TypeScript

时间:2017-06-26 12:52:00

标签: typescript components phaser-framework

我正在使用带有TypeScript的Phaser进行游戏。我想为Actors实现一个基于组件的架构。 我想要实现的目标是:

var component:AwesomeComponent = actor.getComponent<AwesomeComponent>();

我知道&#39; sa workaround通过构建T类型的对象。但是我不喜欢它,因为我可能需要定义大量不同的构造函数来表示所有不同类型的对象组件。

我到目前为止所做的是传递一个字符串类型(当然数字会更好,但我仍然是原型):

getComponent<T>(componentType:string): T 
{
    for (let i = 0; i < this.components.length; i++) 
    {
        if (componentType == this.components[i].componentType)
        {
            return <T><any>this.components[i];
        }
    }
    return undefined;
}

它有效,但结果不好,你必须输入两次类名:

var animComp = actor.getComponent<AnimationComponent>("AnimationComponent");

关于如何解决它的任何建议?

感谢您的时间!

1 个答案:

答案 0 :(得分:0)

我在Phaser论坛上得到了一些很好的建议,用户@flyovergames显示的解决方案就是我想要的:

<script src="https://raw.githubusercontent.com/photonstorm/phaser/master/v2/src/Phaser.js"></script>
class Component {
    public actor: Actor;
}

interface ComponentType<T extends Component> { new(...args: any[]): T }

class Actor {
    public components: Component[] = [];

    private getComponentIndex<T extends Component>(type: ComponentType<T>): number {
        for (let i = 0; i < this.components.length; ++i) {
            const component: Component = this.components[i];
            if (component instanceof type) {
                return i;
            }
        }
        return -1;
    }

    public hasComponent<T extends Component>(type: ComponentType<T>): boolean {
        return this.getComponentIndex(type) !== -1;
    }

    public getComponent<T extends Component>(type: ComponentType<T>, ...args: any[]): T {
        const index: number = this.getComponentIndex(type);
        if (index !== -1) {
            return this.components[index] as T;
        }
        return this.addComponent(type, ...args);
    }

    public addComponent<T extends Component>(type: ComponentType<T>, ...args: any[]): T {
        if (this.hasComponent(type)) { return this.getComponent(type); }
        const component: T = new type(...args); // this needs ES5
        component.actor = this;
        this.components.push(component);
        return component;
    }

    public delComponent<T extends Component>(type: ComponentType<T>): T {
        const component: Component = this.getComponent(type);
        this.components.splice(this.components.indexOf(component), 1);
        component.actor = undefined;
        return component as T;
    }
}

class AwesomeComponent extends Component {
    public message: string;
    constructor(message: string) {
        super();
        this.message = message;
    }
    public alert(): void {
        console.log(this.message);
    }
}

function test(): void {
    const actor: Actor = new Actor();
    if (actor.hasComponent(AwesomeComponent)) { throw new Error(); }
    actor.addComponent(AwesomeComponent, "awesome!");
    const awesome: AwesomeComponent = actor.getComponent(AwesomeComponent); // automatic cast!
    awesome.alert();
    actor.delComponent(AwesomeComponent);
    if (actor.hasComponent(AwesomeComponent)) { throw new Error(); }
}

test();

链接到完整主题: Solution