I'm currently working on an HTML5 top-down simple RPG game, and as a learning experience I'm building my own little engine from scratch. After reading around a little I decided to go with the Entity Component System pattern because I like the flexibility and reusability it brings.
I have a few questions I hope you could help me with:
First, there seems to be some disagreement as to what an ECS actually is - some articles have it that components are just containers for data and subsystems handling all the logic, and other articles have it that components contain methods in them and communicate via some sort of shared memory or messaging system. What's the most widely accepted model of an ECS?
Secondly, I've been wondering about in-game events. I'll explain:
So I started developing an engine that follows the "components are only data containers" rule, and subsystems operate only on the entities that match their requirements (for example, subsystem A takes all entities that have "physics" and "render" components, and subsystem B takes all entities that have "physics" and "health" components).
I'd like the game to be easily scriptable, so that in the yet-to-exist level editor, I could link a particular item (e.g. vase) to another (e.g. mob spawner) and create some sort of correlation (e.g. when vase is broken the spawner spits out a monster). With that in mind, I added the following to my Entity class (which, until now, was just a container for components):
- Event Trigger - has a "name" field, "predicate" field, and a "data" field. There would be a special subsystem that goes through all entities that have event triggers, check the predicate, and send the event, along with its data if the predicate evaluates to true, to anyone who's listening.
- Event Listener - has a "name" field and a "callback" field. If the entity receives an event it is listening to, it will invoke the event listener's callback (which will be able to do something like changing the "spawner" component to be ready to spawn a monster the next time the appropriate subsystem looks at it).
This pretty much solves the problem I described above (vase + spawner, also allows for scripting events with relative ease). I don't like, however, that there are two ways to "change" components (subsystems and/or events). I usually like that there's only one way to do things, and that one way should be the best way. What do you guys think?
Now, the next problem deals with a different type of event. Say I have a player swinging his sword at a monster; when the "physics" subsystem recognizes that the sword collided with the monster, it should notify the "health" subsystem and the "sound" subsystem of the event, so that health could be decreased for the monster and so that a hit sound could be played.
So the obvious, brute force solution would be to have subsystems sending events to all other subsystems (which is what some ECS articles suggested). The physics system would send an event "entity-A collided with entity-B" every time two things would collide to all other subsystems. Then the health subsystem would check whether it cares about the event and do something about it.
I'm worried about this approach because it seems very computationally intensive and might be a hit for performance. Also, HTML5 doesn't have threads (except web workers but meh...), which would make this easier. I'm just afraid that the sheer amount of messages going between subsystems would be enormous. Also, this approach makes my engine have two completely distinct type of events (one that is inter-entity and one that is inter-subsystem) which is yucky.
What do you guys think? Any suggestions would be very welcome.