Articles of 实体系统

使用实体系统方法的基于回合的游戏的AI

我最近刚刚了解到Entity Systems,想试试一个真实的例子(我最近正在开发一款游戏,并试图通过Entity Systems移植它)。 但是我马上就有问题了。 其实这是一个两个问题。 首先是: 在传统的面向对象的方法中,我有一个游戏循环,每隔100msselect空闲单元的动作(所谓的“转向”)。 但是渲染显然是在每个游戏循环迭代中运行的。 我该怎么做? 也许我需要一些像系统运行的独立时间间隔? 像AI系统运行每个更新时的RenderingSystem一样,每100ms运行一次。 或者,也许有更好的办法,我应该使用? 第二个问题是关于这些AI系统 我知道如何使人工智能,将完全单独管理每个单位。 不过,我有一些同时寻找所有单位的做法: 标记应该开始移动的单位“移动”。 find每个“移动”单位到其目标(基本上最接近的敌人)的path。 所有“移动”单位都不被视为障碍物,而是所有不“移动”的单位视为障碍物。 试着将每一个单位移动一步。 如果不能步(某人已经站在那里),那么将path标记为无效(在下次AI迭代时重新计算),并向目标方向(如果有空闲节点)移动一步。 将所有“移动”单元标记为不“移动” 除此之外,还有以下几点:3.在进行前,我们将检查我们是否有敌人在我们周围,而不是移动,我们会攻击这个敌人。 所以,一个AI迭代需要对每个将要运行的单元进行操作,直到完成。 然后AI应该给下一个行动。 我如何在实体系统方法中做到这一点? 因为在ES中,所有的系统都是一个接一个地运行,我需要在它们之间自由地“跳跃”。 或者,也许我是过于复杂的事情,应该做一些不同的事情,而不是在系统之间“跳跃”?

实体组件系统和二维地图与瓷砖:如何做到这一点?

我有一个问题:我目前正在使用ECS编程范例编写一个roguelike游戏(带有瓷砖),我正在为如何实现地图而苦苦挣扎。 起初,我把每个地形都做成了一个实体(带有一个screenPosition和一个sprite组件),但是这很快就导致了性能问题(一个100×100的地图已经是10k个实体)。 所以现在我想把整个地图作为一个单一的实体来处理,但是我不确定如何去做。 我应该做一个地图组件,这将存储每个地形属性? 这对我来说似乎“不好”。 有没有更好的办法? 谢谢 编辑: 我的实现是这样的: 每个实体都是一个存储一对component_id(一个int)和component_handle(一个int)的列表的结构体。 组件是结构 一个EntityManagerSystem将所有实体存储在一个向量中,并将所有的组件存储在它自己的向量中。 每个向量都是公共的,每个实体的id是它的向量索引,组件的句柄也是组件索引 一个RenderSystem,通过EntityManagerSystem遍历实体向量,绘制出具有相应组件的元素 EngineSystem存储指向所有系统的指针,并按顺序调用它们以更新:这是“主”类 在RenderSystem中,这是循环的罪魁祸首: em是entityManager,CT_HASH是一个编译时间散列。 for (std::vector<GameObject>::iterator it = em->entities.begin(); it != em->entities.end(); ++it) { if (it->HasComponent(CT_HASH("ScreenPosition")) && it->HasComponent(CT_HASH("Sprites"))) { ScreenPosition pos = em->screenPosition[it->GetComponent(CT_HASH("ScreenPosition"))]; if (0 <= pos.x && pos.x < xSize && 0 <= pos.y && pos.y < ySize) { Sprites sprites […]

什么是在libgdx ashley ecs框架中创建子弹的正确方法?

我还在想,如何在libgdx ashley中正确地合并子弹? 因为PooledEngine是可用的, Entities , Components和Systems已经Pooled 。 我做了下面的例子,我只是创建一个生成器模式来产生子弹。 如果不使用ashley ECS框架,我使用这个内存管理参考来创建一个子弹池,结果这让我更加困惑。 class EntityFactory { … public EntityFactory(World world, PooledEngine engine) { this.engine = engine; this.world = world; } public Entity createBullet(float x, float y) { … } } class GunSystem extends IteratingSystem { EntityFactory factory; public GunSystem(EntityFactory factory) { super(Mappers.gunFamily); this.factory = factory; } @Override public […]

如何在libgdx ashley ECS方法中使用子弹?

我有问题在Ashley ECS方法中创建子弹池,因为我使用PooledEngine,一切都合并。 所以我所做的只是使用engine.createEntity() , engine.removeEntity()和engine.removeEntity()来产生子弹。 问题是,子弹行为不正常。 在这个内存管理子弹池的例子中,工作正常,但没有在ECS的方法。 有人可以给我一个简要的解释,我如何在ashley ECS方法中集中子弹?

你如何处理Ashley ECS中的实体亲子关系?

在下面的代码示例中,是一个实体的父子关系。 现在,每个孩子都应该跟随父母的位置,孩子可以在任何地方重新定位。 Entity character; // character is a parent Entity weapon; // weapon is a child of character Entity gun; // gun is a parent Entity bullet; // bullet is a parent Entity bulletShadow; // shadow is a child of bullet 我自己的解决scheme是拥有一个OwnershipComponent Entity owner属性的OwnershipComponent ,但是我怀疑组件应该只有一个数据。 一个Entity是数据的集合,如果我将这些数据传递给组件,这可能会导致迭代过度。 所以我改变了我的想法,使用它的属性int flags ,这可以现在可以作为一个ID来引用子女父母关系。 public class OwnershipComponent implements { public […]

在Farseer XNA中定义碰撞规则

我正在尝试将Farseer整合到我的XNA游戏中。 由于我使用的是EntityComponentSystem方法,因此我在组件中添加了Body,并将其添加到玩家的组件中。 有一件事我挣扎着,我不知道如何控制“碰撞规则”。 例如, 我希望Players可以与 other Players/Walls ,但是不要move them on contact ,当我设置BodyType = BodyType.Dynamic时会发生什么。 我希望玩家能阻挡其他玩家,但现在发生的情况是,如果一个玩家保持不动,如果有另一个玩家遇到他们,他们会身体上移动,这不是我想要的那种行为。 我给他们一个LinearVelocity ,然后当我LinearVelocity World ,我把他们的位置设置到他们Body的位置。 我试着改变BodyType = BodyType.Static ,但是消除了玩家之间的碰撞。 我知道,如果是Unity,我会给对象一个BoxCollision2D和一个RigidBody2D ,它会像我想要的那样。 我想我所缺less的是碰撞的RigidBody部分,但是我怎样才能在Farseer实现呢?

在实体组件系统中逐渐处理大量的实体

LibGDX / Ashley有一个IntervalIteratingSystem类,允许您每X毫秒处理一个特定族的所有实体。 但是,如果你有很多实体要处理,那么一次做所有事情可能是一个坏主意。 例如,如果要每10秒处理一次10,000个实体,则可能不需要等待10秒,然后处理所有实体 – 您希望在多个帧中“分散”这些实体。 也许每100毫秒处理100个实体,全部循环。 换个说法:我想要处理大量的实体,但分散在多个框架,最好: 为所有实体每X秒至less处理一次提供合理的保证, 使您能够跟踪自该实体上次处理以来经过了多less时间, 随机的实体顺序, 所有的实体都被处理相同的次数。 这是我的想法,迄今为止…(一些不好,一些很好) 每次将一个实体添加到Engine ,添加一个Group1,Group2或GroupN组件(随机或顺序),然​​后在我的EntitySystem中,我根据它们的Group#循环遍历各个系列。 每10秒钟,将所有10,000个实体添加到列表中,然后每隔100ms,从该列表中排出并处理100个实体。 (内存密集,可能落后) 每100ms,迭代所有10,000个实体,但是随机跳过99%(使用PRNG或通过检查hashcode mod prime)。 使用Engine#addEntityListener()维护EntitySystem内所有相关实体的列表(实际上是一个副本Engine#addEntityListener() ,然后每100ms按顺序处理1%的列表,并在达到最后时环绕它。 (使用LibGDX的无序数组,所以删除便宜)。 与4.相同,但是依赖Engine#getEntitiesFor ,只是让Ashley处理订单和跟踪实体,而不是保留单独的列表。 目前,#1和#5似乎最有希望。 #1似乎满足我所有的要求,但有点普遍(创建和添加一组组件),#5不太普及,但并不能满足要求(主要是#2和#3)。 思考? 有比这更好的东西吗?

基于组件的基于多态的实体系统:OpenGL不渲染

我想能够从不同的组件集创建实体。 我想调用Entity entity(new StaticObject(modelpath, position)); 我有一个EntityTypes标题: struct EntityType { public: std::vector<Component*> components; }; struct StaticObject :public EntityType { StaticObject(std::string meshPath, glm::vec3 Position = glm::vec3(0.0f, 0.0f, 0.0f), glm::vec3 Orientation = glm::vec3(0.0f, 0.0f, 1.0f), glm::vec3 scale = glm::vec3(1.0f, 1.0f, 1.0f)); Mesh mesh; Space space; }; 在构造函数中,我初始化成员Mesh和Space ,并将它们的地址推送到std::vector<Component*> components;的后面std::vector<Component*> components; 然后,我的实体将指针指向StaticObjecttypes(带有成员向量组件),并将指向组件的指针连同其唯一的实体ID一起插入到多图中( std::multimap<unsigned int, Component*> entityComponents contains all component在我的游戏中的实例,我可以使用实体ID访问它们)。 […]

一个组件如何“触发”另一个组件系统?

在我的游戏中,我有一个MoveComponent和一个ClimbComponent 。 有些角色只能在一个层面上移动,其他角色可以爬到下一层。 我的意图是让角色随机爬上,如果即将弹起的墙壁。 我将如何管理? 如果ClimbComponent被dynamic地添加并且被再次移除,或者随机字符是否总是具有ClimbComponent ,并且它将被dynamic地激活和停用?

具有消息总线的实体组件系统

我目前正在C#中devise一个2D游戏引擎,目前我正专注于实现一个实体组件系统。 这是我到目前为止所实现的: Entity :这个类包含一个名称,一个父Entity ,子实体,一个IEntityComponent的列表,最后,你可以添加,删除和获取子元素。 IEntityComponent :这个接口只包含对它所连接的Entity的引用。 组件只包含数据,没有逻辑。 只要清楚组件的外观,下面是一个'Sprite'组件: public sealed class Sprite : IEntityComponent { public Bitmap Bitmap { get; set; } public Sprite(Bitmap bitmap) { this.Bitmap = bitmap; } // IEntityComponent implementation public Entity Entity { get; set; } } 我想实施的是: ISystem :将用于实现实体逻辑的接口。 Event Aggregator :所以ISystem可以订阅,取消订阅和接收消息,这些消息将简单地使用reflection来调用方法。 有了这个,我有两个问题 这是一个好方法吗? 我将如何去创建一个事件聚合器,我看遍了整个networking,但我似乎无法得到它的窍门。 有人能告诉我一个非常简单的事件聚合器的实现吗? 谢谢。