gcardozo Posted July 1, 2017 Share Posted July 1, 2017 Hi, Phaser devs! I'm developing a game using Phaser with TypeScript and what I'm trying to achieve is this:var component:AwesomeComponent = actor.getComponent<AwesomeComponent>(); I know there's a workaround by constructing objects of type T. But I don't like it because I'd probably need to define tons of different constructors to represent all differents kinds of components. What I'm doing so far is passing a string with the type (of course a number would be better, but I'm still prototyping): 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; } It works, but the result is not good, you have to type the class name twice:var animComp = actor.getComponent<AnimationComponent>("AnimationComponent"); Any suggestions on how to solve it? I know there`s a way to do it, because Unity does exactly that in JavaScript. Thank you for your time! Link to comment Share on other sites More sharing options...
flyovergames Posted July 1, 2017 Share Posted July 1, 2017 I'm using something similar to this in my project. It uses the Component constructors then casts up to the type after verifying it's an instance of the type. Here's a minimal example... What? No TypeScript support in code snippets? 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(); gcardozo 1 Link to comment Share on other sites More sharing options...
gcardozo Posted July 3, 2017 Author Share Posted July 3, 2017 @flyovergames that's exactly what I was looking for, thank you! Link to comment Share on other sites More sharing options...
chatrano Posted July 26, 2017 Share Posted July 26, 2017 You could try this https://github.com/francoagusto/entities There is an example also in my github https://francoagusto.github.io/entities-example/build/index.html Link to comment Share on other sites More sharing options...
Recommended Posts