2

我的游戏实体系统使用模板来展示实体的创建方式。就像是:

EntityTemplateManager.register("zombie",
    new PhysicsComponent(10), // speed
    new SpriteComponent("zombie"), // graphic
    new HealthComponent(100) // health
);

我喜欢系统的这一部分,因为它确保我不会错过任何参数或搞砸它们的类型。

然后我可以像这样创建一个新实体:

entity : Entity = EntityTemplateManager.create("zombie");

很直接。

我现在要做的,实际创建实体,是让 EntityTemplateManager 创建 1 个实体作为默认值,然后我在实体上调用 clone(),它通过并 clone()s 其所有组件并返回结果.

实际代码:

public function clone() : Entity
{
    var components : Vector.<Component> = new Vector.<Component>();

    var length : int = _components.length;

    for (var i : int = 0; i < length; ++i)
        components.push(_components[i].clone()); // copy my local components to the new entity

    return new Entity(_name, _type, components);
}

问题是,每次我创建(设计)一个新组件时,我都必须在其中编写(设计)一个 clone() 方法,并跟踪在构造函数上调用的所有参数以创建一个全新的默认值声明的组件。

所以我最终得到了这样的垃圾:

public class ComponentX
{
    protected var _defaultName : String;
    protected var _defaultStartingAnimation : String;
    protected var _defaultBroadcastAnimationEnded : Boolean;
    protected var _defaultOffsetX : Number;
    protected var _defaultOffsetY : Number;

    // other stuff hidden

    public function ComponentX(name : String, startingAnimation : String, broadcastAnimationEnded : Boolean = false, offsetX : Number = 0, offsetY : Number = 0) : void
    {
        super();

        _defaultName = name;
        _defaultStartingAnimation = startingAnimation;
        _defaultBroadcastAnimationEnded = broadcastAnimationEnded;
        _defaultOffsetX = offsetX;
        _defaultOffsetY = offsetY;
    }

    public function clone() : Component
    {
        return new ComponentX(_defaultName, _defaultStartingAnimation, _defaultBroadcastAnimationEnded, _defaultOffsetX, _defaultOffsetY);
    }

    // other methods
}

我真的不喜欢这样——它很浪费而且容易出错。

我怎样才能最好地存储 EntityTemplateManager.register() 函数的参数(包括组件的构造函数参数)并使用该新存储来创建实体?

我尝试了一些通用的 clone() 方法,例如 ByteArray 或 describeType(),但它们不适用于受保护/私有变量。

想法?

4

1 回答 1

0

几个月前,我也编写了自己的实体组件管理器。我做了这样的事情(在你的情况下):

EntityTemplateManager.register("zombie", [
    {type: PhysicsComponent, attr: {speed: 10}},
    {type: SpriteComponent, attr: {graphic: "zombie"}},
    {type: HealthComponent, attr: {health: 100}}
]);

注册新模板的工作方式如下:

private static var definitions:Dictionary = new Dictionary();

public static function register(templateName:String, componentDefinitions:Array):void
{
    definitions[templateName] = componentDefinitions;
}

create函数检索指定的组件模板并创建组件,如下所示:

var components:Vector.<Component> = new Vector.<Component>();

// Create all components
for each (var definition:Object in componentDefinitions) {
    var componentClass:Class = definition.type;
    var component:Component = new componentClass();

    // Set default parameters
    for (var prop:String in definition.attr) {
        component[prop] = definition.attr[prop];
    }

    components.push(component);
}

// Then create the entity and attach the freshly created components.
// ...
于 2012-07-10T10:31:14.697 回答