Component Based Magic System

Started by
8 comments, last by Questioning 9 years, 2 months ago

Ok so this is purely a thought exercise for myself for some possible future work.

I have a system that will have spells, these spells will need to collide and then do whatever their effect is.

The spells:

  • Type - this is an enum as in Fire, Water, Dark, Light, Poison etc
  • A list of components - these are things such as a "damage component" a "timed component" (for damage / heal over time) and an "area of effect component"
    • Note I am not sure I need the AoE and Timed components. Am I over engineering this?
  • It would also have a "collidable" and "render" component to draw and collide

Now this is where I get stuck.

How do I spawn these spells? If I don't want coupling how do I add them to my "projectile list"? How do I process the collisions and then transfer the effects to the effected entities?

I'm new to component / entity based designs so any help would be very appreciated. A point in the right direction to some source code, a blog or even a book would be very appreciated.

Thanks.

PS: If you want to give code example stick to pseudocode, C++, C#, C or Java

EDIT: Also...networking? Any resources on networking a component based system?

Advertisement

For what you've described I can see 2 different entities needed, and I think you might be confusing them.

1) There is a spell entity that is in the user's inventory (or somewhere). This describes the information needed to create the spell (fire the projectile, etc...). It might also contain some sort of sprite component so it can be rendered in the UI. The SpellDescription component might include stuff like damage; or possibly that could be a separate Damage component? Your game's UI somehow uses this information to create a projectile entity when the player casts a spell.

2) So then there is the projectile entity. It will have position data. It might include some sort of Physics component that ties the entity to whatever physics library you're using and allows for collisions with other game entities. There might be a component that represents a particle system. And you need to include some component that indicates damage, damage type, etc... Your physics library will tell you when a collision has occured, and from this you need to be able to get back to the entity that contains the Physics component that collided. If the entity that collided is something that gives damage, then you'll take appropriate action:

3) You'll have code that applies damage to the character, and might possibly apply a timed effect/buff on the game character (which could be a new Component attached to the character entity, or possibly just changing some properties in a "health" component on the entity that was hit).

The above 3 bullet points are completely separate things that happen, and they aren't necessarily related. #2 isn't really even related to spells anymore. So something like this can be very flexible. For instance, maybe you have some volcano in your game that shoots fire projectiles randomly. In that case, only #2 and #3 are involved. Or maybe the character gets poisoned when they walk into a swamp. In that case, of the above list, only #3 is involved.


Note I am not sure I need the AoE and Timed components. Am I over engineering this?

It's hard to give advice on exactly which components are needed (and what data they contain) without knowing a lot more about your game. Think of all the different scenarios that can happen in your game (arrows being fired, spells being cast, things the environment does to people, buffs inventory items might give you, etc...) and try to find common patterns.


How do I spawn these spells? If I don't want coupling how do I add them to my "projectile list"?

Do you need a projectile list? What's a projectile? It's just a game entity that moves and has some handler for when it collides with something. At a minimum, it has position, physics information (which your physics system will use to move the position), and a reference to some handler that reacts to collisions. Those could be 3 separate components, possibly. Or perhaps the handler is part of the physics component.

So there is no projectile list. You just create an entity with the appropriate components and you're good to go.

Gonna piggyback on this thread because I'm at a roadblock with some similar issues while trying to design my game, specifically which systems handle which jobs. For example: my CollisionSystem detects that entity A (a projectile) has collided with entity B (an enemy). At the moment, my CollisionSystem only knows about CollisionNodes, which only contain a PositionComponent and a ColliderComponent. If I want to do damage to entity B, or spawn another entity (say an explosion that damages everything it touches), or any other effect that requires more information than just CollisionNodes, where does that code go? Should I use some kind of observer for the CollisionSystem and call observer::onCollide()? A message queue?

EDIT: Also...networking? Any resources on networking a component based system?

Haven't implemented any of this myself, but this may be a good read. His other articles that I have used have been very helpful: http://gafferongames.com/networking-for-game-programmers/what-every-programmer-needs-to-know-about-game-networking/

OP, be sure and understand what phil said about there not being a "projectile list." that's important in understanding how a component based system works.

In your case, when casting a spell, I'd make an entity that contains your physics component (position, velocity, mass, whatever), your renderable component (sprite, animation, whatever), and, depending on the type of spell, either a spell-component (which does something special when it collides with an entity, for example Freezes a entity, or does a AOE on collision, or AOE after a certain time being fired, like a grenade), a damage component (if your spell does damage), or both the previous 2. You may also want some kind of timer if it's a spell that explodes after a certain time of being cast, and when the timer is triggered, it does the work in the spell component.

To act on these, you'll want to create a SpellSystem that is given entities that have a collided component (I use a separate collided component which has the 2 entitiys that have collided as data), and a spell-component. You'll then know that this entity has collided with something, and you'll know what to do with it (based on the spell component), and you'll know who to do it to (based on the other entity in the collided component).

That's just my way of thinking about it, but I'm sure there are other, possibly better ways to do it.

My Gamedev Journal: 2D Game Making, the Easy Way

---(Old Blog, still has good info): 2dGameMaking
-----
"No one ever posts on that message board; it's too crowded." - Yoga Berra (sorta)

Gonna piggyback on this thread because I'm at a roadblock with some similar issues while trying to design my game, specifically which systems handle which jobs. For example: my CollisionSystem detects that entity A (a projectile) has collided with entity B (an enemy). At the moment, my CollisionSystem only knows about CollisionNodes, which only contain a PositionComponent and a ColliderComponent. If I want to do damage to entity B, or spawn another entity (say an explosion that damages everything it touches), or any other effect that requires more information than just CollisionNodes, where does that code go? Should I use some kind of observer for the CollisionSystem and call observer::onCollide()? A message queue?

See my last response, when 2 objects collided, I create a collision component (CollidedComponent) for both entities, and the collision component holds which 2 entities have collided. Then, you can create systems that act on entities that have the collided component and some other components to do certain things (for example, a collided component and a damage component, the system just modifies the Health Component of the other entity).

My Gamedev Journal: 2D Game Making, the Easy Way

---(Old Blog, still has good info): 2dGameMaking
-----
"No one ever posts on that message board; it's too crowded." - Yoga Berra (sorta)

Hi there, appreciate the responses!

Phil I guess I didn't mention well enough but yes there are a number of components listed.

There is no real game in mind, I was just thinking about how to implement things. My question in regards to a projectile list I guess is...how do I actually handle creation of entities from within another entity without coupling? I want the system to be dynamic, obviously. This is obviously for processing collisions and their appropriate actions.

Also if I have a bunch of physics components I assume that I simply run something like physicsComponent.Update() in the objects update function? Or do I have a physicsCompHandler which stores a list of all components and runs their update functions?

Sorry for all the, probably ridiculous, questions.

Also thanks for the resource Kovaz, will definitely be checking it out.

For me it is easier to generalize the spell component as a weapon component. Then you can have poison-tipped swords or poison arrows, instead of just poison magic. Projectiles also need to have a reference to their owner nearly most of the time, in order to give experience points to the player.

At this point it starts to sound like a fine line between a particle system and projectile system. Which begs the question: can a projectile emitter possibly be its own component that is essentially a spawner for pre-fab particle entities? Maybe weapons should instead have a particle emitter component which defines the behavior of individual projectiles. The point of this is so that all ranged attacks don't have to look like pea shooters or a linear trail of machine gun fire. For instance, more powerful spells that spit out fire or ice balls in a spiral that grows outwards with distance, or a flamethrower-type horizontal spread of particles. Or even put the particle emitter on the target itself (with a delay so that the other character has time to evade, or a healing spell that stays with the player for a limited time).

New game in progress: Project SeedWorld

My development blog: Electronic Meteor


My question in regards to a projectile list I guess is...how do I actually handle creation of entities from within another entity without coupling?

You need to have a mechanism to run specific game logic in response to things like collision events or some UI event (such as the player casting a spell). This logic doesn't exist in a component, it's just off by itself (or it might be in a system that is processing certain components). I can think of two ways this could be handled:

- The Physics component would have a "collision handler" function pointer that is called when the physics/collision detects a collision between this Physics entity and another. Likewise, whatever entity represents the UI element (that the user activates to cast spell) needs to have a component that has some "UI handler" function (assuming the UI is part of your entity/component system... it might not be related at all). Alternately,

- You could use some sort of messaging system. Instead of a function pointer to call, a message is " fired" on the entity that has a collision (or got clicked on, whatever). Presumably your game will have a way to attach arbitrary scripts to entities. One of these scripts could respond to the message and run the appropriate logic.

In either case, you have no unnecessary dependencies. e.g. your UI spell entity's components don't know anything about projectiles. The projectile entity's components don't know anything about applying buffs/effects on a character.


There is no real game in mind, I was just thinking about how to implement things. My question in regards to a projectile list I guess is...how do I actually handle creation of entities from within another entity without coupling? I want the system to be dynamic, obviously. This is obviously for processing collisions and their appropriate actions.

Firstly, you should not be doing anything "within another entity." An entity is just some identifier that has a collection of components. You should be doing everything with the systems that act on the components within each entity.

Whatever framework you are using will be complete enough such that, when you create an entity, that entity is added to it's "world." The "world" holds all the entities in the game. Once an entity is added to the world, it will be included in any list given to specific systems. And, realize, all systems run each update loop. So, if you have a "SpellSystem", in your "SpellSystem::Update()" it might be called with all the entities that have the "SpellComponent" and "CollidedComponent", so you'll know that these entities have a spell, and it has now collided with another entity. At least, that's how I'd do it.

Good luck.

My Gamedev Journal: 2D Game Making, the Easy Way

---(Old Blog, still has good info): 2dGameMaking
-----
"No one ever posts on that message board; it's too crowded." - Yoga Berra (sorta)

Thanks very much both of you. Very informative and I've got a much better understanding of how to approach this now.

This topic is closed to new replies.

Advertisement