Jump to content

  • Log In with Google      Sign In   
  • Create Account


T-Machine Entity Systems : Events, Parent/Child, Networking


Old topic!
Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.

  • You cannot reply to this topic
3 replies to this topic

#1 Farkon   Members   -  Reputation: 192

Like
0Likes
Like

Posted 16 November 2012 - 11:36 AM

After an extensive reading of the T-Machine articles about entity/components design i've decided to move part of my code to that.

It's *working* right now but i still have some questions :

Networking :

Not really a problem here but i'm still wondering if i'm doing it "right", I'm currently having a NetworkSystem which is filling components with network datas and then other systems will do their job. Basically my filling-datas pattern looks like that :

*New data is arriving with item ID*
allNetEntities = getAllEntitiesPossessingComponent(CNet);
for netEntity in allNetEntities {
	net = getComponent(netEntity, CNet)
	if net.id == itemID {
		pos = getComponent(netEntity, CPosition)
		pos.x = itemX
		pos.y = itemY
	}
}

I'm not into performances optimizations yet but it's a bit ugly, i guess the way to go would be add a NetworkSystem method like addNetEntity(entity, ID) populating a collection of some sort and then getting the item through that list. It seems totally logical but i'm mainly trying to see if i'm going to hit a wall of anti-e/s patterns at some point.

Events :

I'm not comfortable with using an event system here and i don't really know how to handle that myself.

Let's say i'm having a CHealthBar component which contains hp datas and i want to add a little animation when a player is losing health.
An idea that come to mind is just to update that hp data and let the system throws an animation when it detects that newHp < oldHp but it means that the system will always check for that condition. Again it looks like premature optimization but i'm more looking for nice habits.
Another idea would be to play with components which might be a bit more elegant : If the client is receiving new hp data he could update the CHealthBar component and adding a new CNewHp component, which will be handled by the HealthBarSystem and then removed. i'm still having that constant check to do in my loop though.

HealthBar parent/child:

Still with that HealthBar i'm wondering how you attach entities together. That's what i'm doing right now.

[source lang="jscript"]// Playervar playerSprite = DrawableSystem.getBitmapFromFile("player_healer_walking1");var player = this.game.em.createEntity();this.game.em.addComponent(player, new CPosition(netx, nety));this.game.em.addComponent(player, new CNet(id, netx, nety));var pdrawable = this.game.em.addComponent(player, new CDrawable(playerSprite, this.game));// Healthbarvar barSprite = new Bar(0x6CF048, 50, 8);var healthbar = this.game.em.createEntity();this.game.em.addComponent(healthbar, new CHealthBar(player)); // Reference to parent player entitythis.game.em.addComponent(healthbar, new CDrawable(barSprite, pdrawable.sprite));this.game.em.addComponent(healthbar, new CPosition(-25, -40));[/source]

Graphically : Right now my CDrawable takes two arguments, the sprite object and the parent sprite object. Here i don't really respect the rule of data-only components since the constructor is actually doing parent.addChild(child), that's an exception I made and i'm not really proud of it since i will eventually need a method to remove that component from the screen; I used to do that differently by just calling drawableSystem.addOnScreen(component), is that better ?

Events/Graphic datas : Since i don't really know how to handle events i'm a bit stuck on where to put initialization code. In the snippet above i'm writing new Bar() and passing it to my CDrawable component but Adam (from T-Machine) doesn't seem to talk about sad and lonely classes going around your code. I want to put that in the component constructor since it doesn't contain any logic code and is actually *datas* even if i'm initializing stuff in it but i'm not sure about that. Or it could be a method in the system but would need to be abstracted IMO.

Relationship : When the client is receiving new hp datas i need to update that component. I'm having an ID for each player so i need to reach that hp entity starting from the player entity. In my example above the player component doesn't know about the hp component whereas the hp component does know who's its owner, it works, but it's a bit weird to update that hp component.

Pseudo-code :
allHpComponents = getComponents(CHealthBar)

for hpComponent in allHpComponents {
	id = getComponentFromEntity(hpComponent.parent, CNet)
	if id == netId {
		hpComponent.hp = newHp
	}
}

I'm having the same kind of code than my network one, the only workaround i can see is to have another component called CHealthBarEntity added to the player entity and redirecting to the healthBar entity, how dirty does that look ?

Sponsor:

#2 BeerNutts   Crossbones+   -  Reputation: 2578

Like
0Likes
Like

Posted 16 November 2012 - 02:47 PM

Hi Farkon,

I've worked with the Component/Entity system, using both the component as data and systems perform the logic on the components, as well as the components handling data and logic. My last work was with a ECS system I created, modeled from the Artemis syste, but for c++. You cna find my journal entry here, and the github for the system itself here.

For your 1st question:

I'm not into performances optimizations yet but it's a bit ugly, i guess the way to go would be add a NetworkSystem method like addNetEntity(entity, ID) populating a collection of some sort and then getting the item through that list. It seems totally logical but i'm mainly trying to see if i'm going to hit a wall of anti-e/s patterns at some point.

My Escape system work by assigning component(s) types to system, so while looping through the entities on Update, if an entity has that component, it calls the system with that entity. It reduces the system to operating on the component, or the entity if multiple components are required, so no retrieving of the objects are required. I don't know if something like that is available in your system.

As for your health bar animation question, you could add an Animation Component (which you set to be the health animation) to your entity when the health changes, and have the Animation system handle that component for you, and remove it when animation is complete.

As far as the Health Bar being it's own entity, can two entities share a common component? If so, you could have the same CHealthBar in Player and HealthBar entities, and updating from the Player would automatically update it in the HealthBar.
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)

#3 Farkon   Members   -  Reputation: 192

Like
0Likes
Like

Posted 17 November 2012 - 04:41 AM

My Escape system work by assigning component(s) types to system, so while looping through the entities on Update, if an entity has that component, it calls the system with that entity. It reduces the system to operating on the component, or the entity if multiple components are required, so no retrieving of the objects are required. I don't know if something like that is available in your system.

I'm not sure how it's directly related to my question and maybe that's because i got your idea wrong. My issue on that example was that i couldn't reach my component easily from just an ID. From what i read of the source your SystemManager handles what system it has to update and while i don't see the link to my issue, i'm also wondering if you are gaining that much resource compare to just iterating over every System which are actually doing nothing because having nothing to iterate to. (Note that it's actually opposite to what i alluded to in my post)

Ps1 : My NetworkSystem is a bit weird in that sense that it doesn't actually manage a really specific type of component, it's basically a dispatcher so the server datas could be about any component type. I'm not sure about the benefit of splitting that into NetworkPlayerSystem NetworkRocketSystem...
Ps2 : I think that your comment would actually fit better for my HP issue.

As for your health bar animation question, you could add an Animation Component (which you set to be the health animation) to your entity when the health changes, and have the Animation system handle that component for you, and remove it when animation is complete.

That's how i would do it as well but i guess it works only with your type of SystemManager or with mine ignoring the pseudo-too-many-systems-to-update-overhead.

As far as the Health Bar being it's own entity, can two entities share a common component? If so, you could have the same CHealthBar in Player and HealthBar entities, and updating from the Player would automatically update it in the HealthBar.

That's a good idea and i might gonna use it for now. But it's a bit dangerous at some point; since i'm iterating over components and not entities if the HpSystem needs to reach CHealthbar AND CPosition handling that position for that specific system meaning the position of the healthbar i might also change the one from the player entity. Now i am not supposed to change the position from the HealthBarSystem but there might be cases where i would be stuck.

Nice framework name :)

Edited by Farkon, 17 November 2012 - 04:44 AM.


#4 BeerNutts   Crossbones+   -  Reputation: 2578

Like
0Likes
Like

Posted 17 November 2012 - 09:39 PM

I'm not sure how it's directly related to my question and maybe that's because i got your idea wrong. My issue on that example was that i couldn't reach my component easily from just an ID. From what i read of the source your SystemManager handles what system it has to update and while i don't see the link to my issue, i'm also wondering if you are gaining that much resource compare to just iterating over every System which are actually doing nothing because having nothing to iterate to. (Note that it's actually opposite to what i alluded to in my post)


Ahh, no, I misunderstood your question. I thought you were saying having your systems grab all entities with a specific component was kind of ugly, so I mentioned how I designed my system to handle components/entities.

FWIW, a System won't run if there are no Entities with that System specific component (or components) available. I believe I've designed it well how it assigns components/entities to systems and they are handle every loop (or on a timer).

IMO, if there's a simple and efficient solution available and it doesn't fit into the Entity/Component framework, you should go ahead and use it. Having the NetworkSystem hold it's own map of entity/ID may be the best solution for you. Whatever you choose, I'm always interested in how people handle these Entity/component systems. In NO WAY do I believe my method is the only right method, or that mine is the best; I'm stil learning all this stuff. Good luck to you!
You're initial question about the system having to request the Entity via a Tag or group
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)




Old topic!
Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.



PARTNERS