Logic <-> Graphics traversal question

Can’t decide which way is better.
Consider fighting between shielded spaceships (ship and its shield are represented by one logical entity currently, and by two geoms as children of one Node). Shield can take certain amount of hits after which it will disappear (its logical part is still there though). Now some time passed without taking hits and shield recharges. I want it to appear back. Which way would you do this? 1st way obviously is to recreate the whole entity’s appearance (this time both ship and its shield). 2nd way is to split shield and ship into two entities which means synching task (probably another appstate running) to keep their visual representations together, i.e. manual implementation of their relative offset, proper facing etc etc which is default behavior already implemented in case they’re attached as children of Node and are represented in logic by single entity…

If like every ship has a shield, then i’d represent it as one logical entity. Eg. some class Ship contains a field for shield. Then i would have two geoms as well. One for ship another for shield. When the shield goes down i simply detach the shield geom, when it goes back up i attach it.

If not every ship has a shield, or if it has some variable equipment, I would store list of equipments, where each equipment would be composed of some data and geom. Then i would simply attach detach them.

I missed at first that this was a Zay-ES question so that automatically means this is in ES land. :smile:

Whether shields are an entity on their own or a component I guess depends on some other factors that @The_Leo hints at.

The main question is if the shield will have its own “things”, ie: attributes. If it’s just a “ship has a shield” then I’d leave it as a component. As soon as the shield starts to have things more than just a power value then maybe it starts to be better to have a separate entity.

A component is easier though. Give a shield component to an entity and have a shield system in the visualization layer that can add/remove a shield geometry from an existing model. (Bonus points if it takes the model’s bounding shape into consideration and can thus work for any model… but I digress.)

The key here is that adding “shield support” should minimally touch other things. What I described above is just adding another component (the shield component) and probably another app state (the shield visualization state). The latter of which asks the model state for it’s model for some entity ID to which it will attach a shield visual.

It is a component, and separate entity but the problem that immediately arises is proper placement (we don’t assume it’s a sphere centered at ship’s origin, that would be trivial). If it’s just a translated during creation geom, as soon as we want to rotate it by hand (say, it’s orienting according to user input while ship is moving differently) - it will rotate not around ship’s origin as it would if it’d be part of ship’s geometry but around its own origin point. Is there an easy way to compensate this? All other things seem to be better fit a separate entity, I do agree on that. Overriding facing might need one extra boolean (is inherited from ship or not), but in the end it is not that big deal.

Well, if the shields must be artistically aligned with the model then they should be a part of the model and then you just turn them on/off (set cull hint Inheret, Always, whatever).

From a systems standpoint, this is still a separate feature. The shield state will look at the existing model and try to get it’s “shield” child geometry to turn it on/off.

It’s possible to do this with separate shield entities but it’s more complicated. You will have some parent->child relationship and then have to make sure to look up the parent model to attach the shield as a child… using position as an offset or whatever. But given that it sounds like your shields start to be very model specific, making them part of the model still sounds easier to me. In a way, it’s kind of like an animation at that point.

One more example: consider, say, modern tank gun stabilizer. Despite having its “logical” task of being constantly aimed at target point, it’s still moving together with tank, which can be treated as ongoing “pure visual” part. So looks like I will need parent-child relations anyway, the only question where to put the split better. Either way I can do geometry calc in model state, but this way logic will be partially there partially here, or I can put some geometry-related things into logical appstate, this way I will have geometry distributed in many places, so still need to take care of sync. Well, looks like it all will depend on particular case, so will see what I’ll come up with :slight_smile:

For parent child relationships… you will need a parent child relationship.

Imagine a ChildOf(entityId) component that you could attach to your entities. Your model state would then have to be smart about this… or would have to be ok with some other state/system reparenting your models.

Either way, you definitely without a doubt 1000000% want to let the scene graph handle your parent->child model relationships if you can. Your life is a billion times easier that way and you won’t have weird issues with things sliding around on each other.

So far it’s working for me like this:

long eId = Long.parseLong (curColl.getGeometry().getParent().getUserData(“EntityId”).toString() );
EntityId targetId = new EntityId(eId);

However this doesn’t seem “Effective Java” way. I wonder if there is a more “normal” method :slight_smile:

Whoah…

someSpatial.setUserData(“eid”, entityId.getId());

Long id = someSpatial.getUserData(“eid”);
EntityId eid = new EntityId(id);

…but I’m not at all sure what this has to do with this discussion. In our discussion, you should only need to find the spatial for an entity and not the other way around… and your model state should already have a map of entity Id to spatial else it can’t efficiently do its job.

It seems like i need them back and forth to keep the sync. Ray cast gives me nice automatic results to complete the visuals, but i have to retrieve the logic from there, to complete my non-visual tasks… or do i really miss some important concept?

And you’re right, i don’t keep them all in model state, i just retrieve them on demand. Which can be probably wrong but works so far…

Yeah, picking is one example of having to go from spatial to entity… but it’s like the only one.

All of my model states keep a Map<EntityId, Spatial> for the stuff that they are managing. Simple and saves a ton of time… both in performance and in coding, since that’s the direction one goes all the time. Or are you using controls to keep the spatials in synch with the entities? (Also kind of wasteful if so.)

No way, i don’t use controls at all. I keep it all the way you introduced in asteroid panic. However sometimes it’s not easy to decide where exactly this logical part is to go. Some systems are overriding default behavior (for instance, my blast control kills the bursts instead of posting them with TTL component of zero, which would probably be more consistent), but i’m still experimenting not being sure which way is best :slight_smile:

Btw is there any special difference between using Entity or EntityID? For instance,

for( Entity e : entities ) 
           {
               ComponentAiming coma = ed.getComponent(e.getId(), ComponentAiming.class);

isn’t the same as

for( Entity e : entities ) 
           {
               ComponentAiming coma = e.get(ComponentAiming.class);

You use both approaches in AP as far as I can see so I wonder why.

An Entity is a local view and will contain only those components that you request when you grab the entity set. And it only contains the values as of the last applyChanges().

Using the entity ID to retrieve a component directly from EntityData will always get the most current value at the time you call it… and will let you get any component that the entity might have.

Mostly, systems will their Entity objects. Occasionally they need to do more and so can go directly to EntityData in that case. Direct Entity access is always faster.

If it’s still unclear when looking at specific examples then point to them and I’ll explain why I did it in a particular case.

1 Like

Ok, in CollisionState.java you address entities directly and never use ed after init. In, say, ShipControlState.java you address them through ed.setComponents() etc. I wonder which way is for what.

ShipControlState has no real entities (Big E Entity) to deal with (as I recall) because all it has to work with is the EntityId of the player’s ship… and there is no way to get an EntitySet with just one specific Entity in it. (Well not by entity ID anyway.)

…I do want to add something like that but I haven’t. Anyway, in this case where we are only setting a component it makes no difference performance-wise so it’s ok. The case where it would be nice to grab a single Entity view of some EntityId is when you want to watch the state of one specific entity’s set of components (like score display, etc.). I will add that someday.