【问题标题】:Component based architecture in TypeScriptTypeScript 中基于组件的架构
【发布时间】:2023-03-09 04:40:02
【问题描述】:

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

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

我知道有一个 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");

有什么解决方法的建议吗?

感谢您的宝贵时间!

【问题讨论】:

    标签: typescript components phaser-framework


    【解决方案1】:

    我在 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

    【讨论】:

      猜你喜欢
      • 2015-01-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-11-29
      • 2011-05-19
      • 2017-01-11
      • 2019-07-19
      • 1970-01-01
      相关资源
      最近更新 更多