Is it a bad idea to store functions inside components in ECS?
Say I have three entities: Player
, Spikes
, and Zombie
. All of them are just rectangles and they can collide with each other. All of them have the BoxCollision
component.
So, the BoxCollison
system would look something like this:
function detectCollisions () {
// for each entity with box collision
// check if they collide
// then do something
}
The issue is, the sole purpose of the BoxCollision
component is to detect collision, and that's it. Where should I put the game rules, such as "if the Player collided with Spikes, diminish its health" or "if the Zombie collided with Spikes, instantly kill the Zombie"?
I came up with the idea that each Entity
should have its onCollision
function.
Programming languages such as Javascript and F# have high-order functions, so I can easily pass functions around. So when assembling my Player
entity, I could do something like:
function onPlayerCollision (player) {
return function (entity) {
if (entity.tag === 'Zombie') {
player.getComponent('Health').hp -= 1
} else if (entity.tag === 'Spikes') {
player.getComponent('Health').hp -= 5
}
}
}
const player = new Entity()
player.addComponent('Health', { hp: 100 })
player.addComponent('BoxCollision', { onCollision: onPlayerCollision(player) }
// notice I store a reference to a function here, so now the BoxCollision component will execute this passing the entity the player has collided with
function detectCollisions () {
// for each entity with box collision
// check if they collide
onCollision(entity)
onPlayerCollision
is a curried/closure function that receives a player, and then returns a new function that wants another Entity.
Are there any flaws with this? Is it okay for components to store references to functions? What are other ways of avoiding game rules in components? Events?
Thanks!