首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
社区首页 >问答首页 >带有C++模板的实体系统

带有C++模板的实体系统
EN

Game Development用户
提问于 2013-06-30 04:59:38
回答 1查看 3.3K关注 0票数 4

我对游戏编程的实体/组件风格很感兴趣,并且我想出了一个C++的设计,我想对此进行评论。

我决定使用一个相当纯的实体系统,其中实体只是一个ID号。组件存储在一系列向量中--每个组件类型一个。

但是,我不想为我添加到游戏中的每一个新组件类型添加样板代码。我也不想使用宏来做这件事,坦率地说,这让我感到害怕。因此,我提出了一个基于模板和类型提示的系统。但是,在我花很长时间写这篇文章之前,我想检查一些潜在的问题(我是一个缓慢的程序员!)

所有组件都是从Component基类派生的。这个基类有一个受保护的构造函数,它接受一个字符串参数。编写新派生组件类时,必须以字符串形式使用新类的名称初始化基。当您第一次实例化一个新的DerivedComponent时,它会将字符串添加到映射到唯一整数id的组件内部的静态哈希映射中。当您随后实例化相同类型的更多组件时,将不采取任何操作。结果(我认为)应该是一个静态hashmap,其中包含至少实例化一次的组件派生的每个类的名称,映射到一个惟一的id,该id可以通过静态方法Component::getTypeId ("DerivedComponent")获得。呼。

下一个重要部分是TypedComponentList<typename PropertyType>。这基本上只是一个带有一些有用方法的std::vector<typename PropertyType>包装器。它还包含一个实体ID号到数组中插槽的哈希映射,这样我们就可以通过它们的实体所有者找到组件。关键的是,TypedComponentList<>是从非模板类ComponentList派生的。

这允许我在我的主ComponentList中维护指向ComponentManager的指针列表,它实际上指向具有不同模板参数的TypedComponentLists (鬼怪)。

组件管理器具有模板功能,如:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
template <typename ComponentType>
void addProperty (ComponentType& component, int componentTypeId, int entityId)

以及:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
template <typename ComponentType>
TypedComponentList<ComponentType>* getComponentList (int componentTypeId)

它处理从ComponentList到正确的TypedComponentList的转换。

因此,要获得您调用的特定类型组件的列表:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
TypedComponentList<MyComponent>* list =  componentManager.getComponentList<MyComponent> (Component::getTypeId("MyComponent"));

我承认看起来很丑。

设计的缺点:

  • 如果代码的用户编写了一个新的组件类,但向基本构造函数提供了错误的字符串,则整个系统将失败。
  • 每次新组件被实例化时,我们都必须检查散列字符串,以查看该组件类型以前是否已被实例化。
  • 由于模板的广泛使用,可能会生成大量的程序集。我不知道编译器能把这个最小化有多好。
  • 你可以认为整个系统有点复杂--也许是过早的优化?但是我想一次又一次地使用这个代码,所以我希望它是可执行的。

设计的优点:

  • 组件存储在类型化向量中,但也可以通过使用它们的实体所有者id作为散列来找到它们。这意味着我们可以快速迭代它们,尽量减少缓存丢失,但如果需要,也可以直接跳到我们需要的组件上。
  • 我们可以自由地将不同类型的组件添加到系统中,而不必手工添加和管理新的组件向量。

你认为如何?好的比坏的重要吗?

EN

回答 1

Game Development用户

回答已采纳

发布于 2013-06-30 05:44:29

我认为这是一个很好的第一次实现,但我要指出一些事情。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
Component::getTypeId ("DerivedComponent")

上面的代码让我担心有几个原因。

  1. 它很容易出现错误,即使我们假设您从未犯过任何明显的错误,比如将它命名为另一种组件类型,这对可维护性来说也是很糟糕的。我在我的系统中所做的是有一个静态函数,它返回类型为did的std::size_t ComponentType;
  2. 性能。即使使用字符串散列方案,思考如何最大限度地提高性能也成了一场噩梦。突然之间,您将不得不在任何地方传递一个字符串,以获取组件类型,这很容易占用大量的帧时间,甚至可以使用const&。

现在,对您来说,这可能是一个“黑客”,但我有许多组件,我可以证明它运行得很好:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
static const ComponentType GetType() 
{ 
    static char uniqueVariable = 0; 
    return reinterpret_cast<ComponentType>(&uniqueVariable); 
}

应该清楚的是,对于每种类型,类型都是唯一的。严格地说,我有时想知道内存分配的某些边缘情况是否会破坏系统,但到目前为止我还没有遇到任何问题。

更有甚者,我知道对于宏的使用有很大的协同努力,但是任何有经验的程序员都会告诉你,在某些情况下,他们是不那么邪恶的。我想这里就是这样的。我将上面的方法封装在宏中,这样我就可以简单地定义类。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
#define COMPONENT_TYPE_INFORMATION static const ComponentType GetType() { static char uniqueVariable = 0; return reinterpret_cast<ComponentType>(&uniqueVariable); }

如果您担心宏,那么请考虑阅读,以便尽可能地保护自己不受bug的影响。上面显示的宏只是为了说明。

下面是一个组件和用法的示例:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
class Component
{
public:
    virtual ComponentType GetType() = NULL;
    //etc etc 
}

class DerivedComponent : public Component
{
public:
    DerivedComponent(/*pass some arguments here perhaps*/) { }

    void MyMethod() { } //do something

    int MyAccessor() { return 1; }

    COMPONENT_TYPE_INFORMATION 
private:
};

//ComponentList stores a list of pointers to Component for the inheritance goodness

template<typename T>
bool DoesComponentMatchExist(ComponentList list) 
{ 
    for(std::size_t i = 0; i < list.size(); i++)
    {
        if(list[i]->GetType() == T::GetType())  
            return true;
    }

    return false;
}

注意,如果T:: GetType ()没有实现纯虚拟组件基类指定的GetType,它将很方便地返回编译器错误。

关于文章的其余部分,虽然我用内存池解决了问题,但在我看来,您的方法似乎很好,尽管不断地传递组件管理器可能会带来麻烦。然而,这取决于你,这样做有好处也有缺点。

不过,我要提到的一件事是,您可能希望将实体中的组件列表从其他实体中分离出来,而不是有一个超级列表。在幕后,您仍然可以将组件存储在一个内存池中,但您可能应该考虑支持它。将父对象的列表传递到每个组件的构造函数中是非常强大的。你可以这样做:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
MyComponent::MyComponent(ComponentList parentContainer)
{
    //we check whether another component exists in the container.
    //in this way we can have dependencies on components
    //without grouping together unnecessary functionality
    //for instance, you may want a renderable to require a graphics core component
}
票数 3
EN
页面原文内容由Game Development提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://gamedev.stackexchange.com/questions/58348

复制
相关文章
jquery slide 幻灯片
因为图片1-5是使用行内块的方式布局,只要控制图片1的div的margin-left改变,就可以跟推箱子一样,实现5个图片的左右滑动。
Devops海洋的渔夫
2019/05/30
3.5K0
javascript 组件
** 最新内容请查看这里** 工具库 javascript底层工具库underscore.js 时间操作库moment 发布订阅 Arbiter.js ---- 以下均依赖jquery 幻灯 wowslider 幻灯切换时各种很炫的效果 cycle2 普通的幻灯 浏览图片 fancybox 弹出查看图片,视屏等等 demo yoxview 弹出查看图片,图片尺寸缩放很自然 图片墙 wookmark 加载资源 imagesLoaded 选取的图片都加载好后执行回调
前端GoGoGo
2018/08/27
1.3K0
jQuery幻灯片插件slick
支持响应式 浏览器支持 CSS3 时,则使用 CSS3 过度/动画 支持移动设备滑动 支持桌面浏览器鼠标拖动 支持循环 支持左右控制 支持动态添加、删除、过滤 支持自动播放、圆点、箭头、回调等等 兼容
李维亮
2021/07/09
3.2K0
【IDEA】同一个应用运行多个测试实例(以不同端口)
一、在idea中写好应用后,正常情况下,选择测试,将启动唯一的服务实例(8080端口默认)
陶然同学
2023/04/02
1.5K0
【IDEA】同一个应用运行多个测试实例(以不同端口)
与视频和图像共同训练 Transformer 以提高动作识别
动作识别已成为研究界的主要关注领域,因为许多应用程序都可以从改进的建模中受益,例如视频检索、视频字幕、视频问答等。基于 Transformer 的方法最近展示了最先进的技术 在多个基准测试中的表现。 虽然与 ConvNet 相比,Transformer 模型需要数据来学习更好的视觉先验,但动作识别数据集的规模相对较小。 大型 Transformer 模型通常首先在图像数据集上进行训练,然后在目标动作识别数据集上进行微调。
从大数据到人工智能
2022/03/07
7970
与视频和图像共同训练 Transformer 以提高动作识别
PS-图像处理:PS抠出图片中的图形轮廓渐变填充
1、打开你要扣出轮廓线的图片素材 2、复制图层Ctrl+j 3、选中副本图层,去色,shift+Ctrl+u 4、滤镜——模糊——特殊模糊 5、在弹出的对话框中,设置它的模式为:仅限边缘,品质选择高,半径阈值自己调,直至图片轮廓清晰,调整半径和阈值时期到适当位置,线条清晰,粗细均匀即可,点击确定 6、这时线条轮廓已经出来,接下来反向选择Ctrl+i 7、这时一幅图片就剩下了轮廓线 8、填充轮廓内渐变颜色
1900
2022/12/05
2.2K0
PS-图像处理:PS抠出图片中的图形轮廓渐变填充
幻灯视频素材怎么剪
把抽象概念形象化。例如化学课上,讲述不同元素发生反应会怎么样,单单语言描述或者静态配图无法把过程完整形象描摹出来,这时候一段化学反应的录像会立即让学生把握全貌。
王树义
2018/08/22
3.3K0
幻灯视频素材怎么剪
医学图像处理教程(二)——医学图像读取,存储和不同对象互相转换
今天将给大家分享医学图像读取,包括dicom图像和非dicom图像,图像的存储以及修改图像信息后产生的变化结果,最后再介绍如何将SimpleITK的图像数据与Numpy的数据进行互相转换。
医学处理分析专家
2020/06/29
5.3K2
在不同电脑上随时打开和修改同一个Power BI模型
有这样一个场景:办公室一楼和二楼分别有一台办公电脑,家里还有一台,有时候出差还得带一台,且模型需要经常性修改,数据是随时需要更新并查看分析的。
陈学谦
2021/09/22
1.2K0
jquery注册事件处理函数常用的几种方式
需要的朋友可以做一下参考,下面就以click事件为例子: 第一种方式: $(document).ready(function(){ $("#button").click(function(){ console.log("yourdomain.net"); }) }); 第二种方式(这种方法不建议使用,新版已废弃了 bind函数): $(document).ready(function(){ $('#button').bind("click", function(){ consol
IT工作者
2022/02/17
6700
深度学习在图像和视频压缩中的应用
本文来自AOMedia 2019 Research Symposium的演讲,演讲者是来自纽约大学Tandon工学院的Yao Wang教授。
用户1324186
2019/12/27
1.4K0
OpenMP基础----以图像处理中的问题为例
1.循环语句中的循环变量必须是有符号整形,如果是无符号整形就无法使用,OpenMP3.0中取消了这个约束
流川疯
2022/05/10
1.2K0
以管道的方式来完成复杂的流程处理
之前参与一个机票价格计算的项目,为他们设计了基本的处理流程,但是由于整个计算流程相当复杂,而且变化非常频繁,导致日常的修改、维护和升级也变得越来越麻烦,当我后来再接手的时候已经看不懂计算逻辑了。为了解决这个问题,我借鉴了“工作流”的思路,试图将整个计算过程设计成一个工作流。但是我又不想引入一个独立的工作流引擎,于是写了一个名为Pipelines的框架。顾名思义,Pipelines通过构建Pipeline的方式完成所需的处理流程,整个处理逻辑被分解并实现在若干Pipe中,这些Pipe按照指定的顺序将完成的Pipeline构建出来。Pipeline本质上就是一个简单的顺序工作流,它仅仅按序执行注册的Pipe。这个简单的Pipelines框架被放在这里,这里我不会介绍它的设计实现,只是简单地介绍它的用法,有兴趣的可以查看源代码。
蒋金楠
2023/07/10
2460
以管道的方式来完成复杂的流程处理
CSS遮罩的过渡效果有趣的幻灯片
今天,我们想向您展示如何使用CSS Masks创建一个有趣而简单却引人注目的过渡效果。与裁剪一起,遮罩是定义可见性和与元素合成的另一种方式。在下面的教程中,我们将向您展示如何在简单的幻灯片上应用现代过渡效果的新属性。我们将使用步骤()计时功能应用动画,并将掩模PNG移动到图像上以实现有趣的过渡效果。 注意:请记住,这种效果是高度实验性的,只有一些现代浏览器(现在的Chrome,Safari和Opera)才支持。 CSS面具 显示部分元素的方法,使用选定的图像作为蒙版 W3C候选推荐 来自caniuse.co
企鹅号小编
2018/01/30
3.3K0
CSS遮罩的过渡效果有趣的幻灯片
企业在云管理和优化方面应该以不同的方式运行
随着越来越多的企业将其重要业务迁移到云平台中,这也成为企业了解云计算如何运作的好时机。当他们这样做时很可能会感到,采用云计算可能会获得更多的价值。
静一
2018/12/29
7740
企业在云管理和优化方面应该以不同的方式运行
10. 图像处理的应用-基于相位的视频处理
前面已经给大家讲了动作放大算法中的一种:欧式视频放大。看起来这种技术非常炫酷,然而它并非毫无缺点。
HawkWang
2020/04/17
1.1K0
10. 图像处理的应用-基于相位的视频处理
图像处理在工程中的应用
传感器 图像处理在工程和科研中都具有广泛的应用,例如:图像处理是机器视觉的基础,能够提高人机交互的效率,扩宽机器人的使用范围;在科研方面,相关学者把图像处理与分子动力学相结合,实现了多晶材料、梯度结构等裂纹扩展路径的预测,具体见深度学习在断裂力学中的应用,以此为契机,偷偷学习一波图像处理相关的技术,近期终于完成了相关程序的调试,还是很不错的,😄~ 程序主要的功能如下:1、通过程序控制摄像头进行手势图像的采集;2、对卷积网络进行训练,得到最优模型参数;3、对采集到的手势进行判断,具体如下图所示: 附:
联远智维
2022/01/20
2.3K0
图像处理在工程中的应用
Photoshop 2023 (ps 2023)
Photoshop是一款强大的图像处理和编辑软件,广泛用于数字艺术、摄影、平面设计等领域。它提供了丰富的工具和功能,包括选择、修饰、涂鸦、绘画、排版等等。同时,Photoshop也支持许多不同的文件格式,如JPG、PNG、EPS、PSD等,使其成为一个非常灵活和全能的图像处理软件。
Mac小小心
2023/03/08
7670
Photoshop 2023 (ps 2023)
Adobe Photoshop 2023 v24.0 for Mac 中文版 PS 2023 强大图像处理软件
Adobe Photoshop 2023 Mac版是功能强大的修图绘图工具,知识兔使用可帮助用户更高效的处理您的图片和照片,自由灵活的编辑和创造激发灵感,灵活高效,功能齐全,一流的软件,激发灵感,知识兔更多的工具和控件辅助您完成创建,全世界数以百万计的设计师、摄影师和艺术家使用Photoshop使不可能成为可能。知识兔从海报到包装,从基本横幅到美丽的网站,从令人难忘的徽标到醒目的图标,Photoshop让创意世界不断前进。凭借直观的工具和易于使用的模板,即使是初学者也可以做出令人惊叹的事!
知识兔
2022/10/22
1.9K0
Python+Pillow+MoviePy合成不同尺寸的图像为视频
任务描述: 给定不同尺寸的多幅图像,合成为一个视频。 参考代码: 结果视频: http://mpvideo.qpic.cn/0bc3baaasaaayaaknpl6orsfacgdbeeaaci
Python小屋屋主
2023/08/29
3450
Python+Pillow+MoviePy合成不同尺寸的图像为视频

相似问题

jquery cycle2视频和图像

21

调整jquery以保持幻灯片中的图像比例

20

jquery幻灯片中心图像?

11

在幻灯片中以内联方式显示图像

112

幻灯片中的jQuery叠加图像

11
添加站长 进交流群

领取专属 10元无门槛券

AI混元助手 在线答疑

扫码加入开发者社群
关注 腾讯云开发者公众号

洞察 腾讯核心技术

剖析业界实践案例

扫码关注腾讯云开发者公众号
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
查看详情【社区公告】 技术创作特训营有奖征文