HaxeFlixel / flixel

Free, cross-platform 2D game engine powered by Haxe and OpenFL
https://haxeflixel.com/
MIT License
1.97k stars 434 forks source link

Composition system #3053

Open Geokureli opened 7 months ago

Geokureli commented 7 months ago

Rather than the current inheritance based system, I think we need to move to a more composition based one, this has been asked a lot, and I think it's doable, without making flixel less accessible to newcomers. I'll be inviting people to this discussion but if you have experience or insight in composition patterns or component systems, feel free to join in, because, unfortunately, I do not.

Main Goals:

47rooks commented 7 months ago

Ok, been puzzling over this a bit. The key things I wonder about at the moment are:

  1. do you plan to support adding and removing components from a basic at runtime ?
  2. will all the invocations turn into: if obj.hasComponent(X) obj.processComponent(X) and so on or is there a better way ?
  3. can macros make any of this easier and in particular if this is a compile time feature would adding components via metadata help ?
itulau commented 6 months ago

I second the truly needed move from inheritance towards composition :+1:

Rather than FlxObject being a FlxBasic with collision fields, perhaps it can be a Basic with collision and position components

I'd vouch for just having position as a first-class component. If not it would automatically bloat games that don't need physics at all, which is not good since I suppose one of the goals of this is to prevent that.

Graphics is a complicated one. Forcing a graphic component onto all objects might be troublesome when you only need objects for pure reference points / anchors / pivots / checkpoint / sound emitter / etc that might not need graphics at all, so I'm not entirely sure about that. But at the same time, this could be mitigated if the graphic is just a "debug graphic" type that is only visible on Debug mode.

  1. will all the invocations turn into: if obj.hasComponent(X) obj.processComponent(X) and so on or is there a better way ?

I like Unity's approach of having a getComponent<Null<T>>() method to obtain a reference to any component, and then you can do whatever you need with it:

getComponent<FlxPhysics>()?.update(elapsed);
01010111 commented 6 months ago

will all the invocations turn into: if obj.hasComponent(X) obj.processComponent(X) and so on or is there a better way ?

I think this is a cool opportunity to give newcomers the classic flixel experience by using getters and setters to help. So both easing that onboarding developer experience and attempting to make as few breaking changes as possible, a FlxSprite would have getters and equivalent functions that calls whatever sprite.getComponent() function it needs under the hood.