tank-dev / tank

A 2D C++ game engine taking inspiration from FlashPunk
Boost Software License 1.0
12 stars 3 forks source link

onRemoved and onAdded functions in Entity #37

Closed Anstow closed 11 years ago

Anstow commented 11 years ago

These should be called when the entity is removed from the world or added to it. The removed one is especially important, for networking.

For example: take a bomb which explodes when a player is near it, or can be click on a removed by the player. Without an onRemoved function (which will happen at the end of the frame) there could be inconstancies in whether click actions or explode actions take place first. If the onRemoved is at the end of the frame the player will be able to override the explode action if it has happen before the click. (Although there are other problems these should be deal-able with in game.)

qualiaa commented 11 years ago

Yeah, I was thinking we need even more than that. We should just copy Flashpunk - it has entity and state onActivated and onDeactivated stuff, as well as a load of other virtual functions that make it easy for the user to set up their own behaviour.

Edit: Of course, this wasn't a problem when the Engine just removed things immediately :P. Not that we should go back to that. If we're going with @DavidTruby's suggestion for #31 then can also resolve some of the issues you alluded to by checking against the isDeleted() boolean.

DavidTruby commented 11 years ago

There's probably a really obvious answer to this question but... Surely an object is constructed and added to the world at the same time (at least the way we're doing it currently)? Do we really need onAdded in that case? Also, you can have the default delete() function (see #31) call a virtual onDelete when it gets deleted :-)

Anstow commented 11 years ago

I think the answers are: When we create the object it isn't added to the State in the constructor, and the entity may want to affect its State in some way when its added. (For example making a sub entity or increasing score.) Your second point was exactly how I was intending it to be implemented.

Anstow commented 11 years ago

Also checking against the isDeleted boolean isn't sufficient in the above case. The order of being deleted matters and it shouldn't.

qualiaa commented 11 years ago

@DavidTruby The real reason is that an Entity can be moved between States. If we were just worried about the constructor, the answer would be to pass an Entity's parent State in at construction, but the reason I've opted against that is exactly because an Entity doesn't necessarily exist in only one State for its entire lifetime.

@Anstow As for checking isDeleted, I specifically didn't say the case you mentioned, because yes, it doesn't work in that or many other cases. I was just saying that if we're worried about deletion, we also need to check the flag, and it seems nice that it coincides with a possible solution to the other issue.

As for delete() and onDelete(), yes. I was also considering perhaps doing the same with update, so update calls a virtual function onUpdate, which the user overrides. This way, update() could check isDeleted and the user wouldn't have to worry about it.

qualiaa commented 11 years ago

Also, on that note, we need both onRemoved and onDeleted, because an entity can be removed from a State and then added to another.

DavidTruby commented 11 years ago

How do we move an entity between states with the current system though? I thought we only had a makeEntity variadic perfect forwarder... :-P

qualiaa commented 11 years ago

State::moveEntity(Entity, State)

DavidTruby commented 11 years ago

Should that be State::moveEntity(Entity&, State&)? ;-)

Anstow commented 11 years ago

@Gazok are you proposing that something isn't updated if it has been deleted earlier in the frame? Or have I misunderstood.

qualiaa commented 11 years ago

@DavidTruby Unfortunately not :octocat: @Anstow Yep. Do you think that's wrong?

Anstow commented 11 years ago

@Gazok Yes, it creates a dependency on what order the code is ran.

For example if you had an enemy which shot at you. But you shot at it and killed it. If you happened to be updated before the enemy, you'd shoot and kill it and it wouldn't get a chance to shoot and kill you. But if it got updated before you the exact opposite would happen.

Really we should update them "simultaneously". In other words they should all be updated whether the deleted flag is set or not.

We want to avoid any such dependency for networking reasons.

qualiaa commented 11 years ago

Yes, sorry, I was being silly, you're right, we should let them update that frame, because otherwise it depends on the z-layer of the entities, which is completely stupid.

DavidTruby commented 11 years ago

Done for entities. Will do for state if necessary :octocat: