Page 1 of 1

Bullet targeting an Enemy

Posted: Sun Sep 20, 2009 2:25 am
by Duncan
Hey everyone. I'm working on making a Tower Defense game. The designer tells me he wants the towers to shoot out bullets that will "follow" an enemy until they collide. He also stated that if two towers fire at one enemy and the enemy is killed before one bullet reaches the enemy, then the bullet that doesn't reach the enemy should just disappear.

I'm having a bit of trouble implementing this. The "following" mechanism is not too bad cuz that's just a matter of some subtraction and whatnot but the tricky bit is how to inform the bullets when their targeted Enemy dies. The only solution I could think of would be to give each Enemy a std::vector of Bullet pointers and then when each bullet is assigned a target have that Push its own "this" pointer into the Enemy's vector... and THEN in the Enemy destructor do something like

Code: Select all

for (int i=0; i < followers.size(); i++)
  followers[i]->cease();
That's the only solution I can think of. I feel like there might be a more efficient/less hackish way? Obviously if this way works then it works but... if you guys can think of anything else I'd be glad to hear it.

Thanks!

Re: Bullet targeting an Enemy

Posted: Sun Sep 20, 2009 3:23 am
by K-Bal
The best way I can think of is giving each bullet a pointer to their target (which could also be used for calculating the target vector) and each frame they ask the target if it is still alive. If not they let themselfs vanish.

I would not just let them disappear, let them fly in the last given direction until they collide with something else ;)

Re: Bullet targeting an Enemy

Posted: Sun Sep 20, 2009 10:11 pm
by MarauderIIC
Duncan wrote: The only solution I could think of would be to give each Enemy a std::vector of Bullet pointers and then when each bullet is assigned a target have that Push its own "this" pointer into the Enemy's vector... and THEN in the Enemy destructor do something like

Code: Select all

for (int i=0; i < followers.size(); i++)
  followers[i]->cease();
This would also work. It'd be more of an event-driven thing, than a polling thing, which is what K-Bal's suggestion was. Event-driven is better than polling from a CPU usage suggestion, but not necessarily from an organizational one. Personally, I sort of like the event-driven way. Although you should use an accessor, really.

You should do the loop this way:

Code: Select all

for (vector<Bullet*>::iterator i = followers.begin(); i != followers.end(); ++i)
    delete *i; //or i->cease(); if you prefer. Syntax might be (*i)->cease, though.
size() is "slow", so you shouldn't use it on every loop iteration. If you wanted to use size, you should save it first:

Code: Select all

unsigned int vecSize = followers.size();
for (int i = 0;i < vecSize; ++i)
    followers[i]->cease();
iterators is "faster" than the [] operator, so you should use the iterator method above, if you can.

Re: Bullet targeting an Enemy

Posted: Mon Sep 21, 2009 9:04 am
by dandymcgee
That's an interesting approach. Personally I would have most likely done it K-Bal's way, but only because I would've never thought of your idea. ;)

Re: Bullet targeting an Enemy

Posted: Mon Sep 21, 2009 11:56 am
by Bakkon
The way I did it for the homing missiles in Ace of Space was each entity held an std::vector point to what it could collide with. During the missiles' update, it would check to see if its target pointer was null or dead, if it wasn't, it would call a method that picked a random object from its collision list.

Re: Bullet targeting an Enemy

Posted: Mon Sep 28, 2009 3:30 am
by internetfx
dandymcgee wrote:That's an interesting approach. Personally I would have most likely done it K-Bal's way, but only because I would've never thought of your idea. ;)
I think the answer involves what happens to this entity that is destroyed. If it is going to be deleted, you don't want any pointers to it hanging around, so storing a linked list of the missiles or players that are targeting it is a simple sort of event-driven model to prevent this from happening and to allow immediate clean-up.

On the other hand, if the programmer wants to persist with running checks and not store the data about what is targeting the entity in the entity itself (per K-Bal), then to be safe from dangling pointer references, the entity could have only a reference count that is updated when another object targets or de-targets it. Even if it is removed from the world, it cannot be deleted from memory until that reference count reaches zero, which would likely happen after the next game logic cycle. Suddenly I smell a garbage collection list, but I am not afraid! On to battle!

Every game designer runs into two-way reference and deletion issues here and there, but the best answer lies in the game engine's model. Most often, you do the simplest thing first until necessity forces you to do otherwise.