Sign in to follow this  

Best way of handling enemy projectiles

This topic is 1099 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

I'm working on a fantasy themed Flappy Bird clone, and I'm looking for advice on something. I have a skeleton enemy that throws bones at the player (though my question applies to any enemy that attacks with projectiles). The Skeleton class has a list of Bone objects, and it calls each Bone's update and draw methods within it's own respective methods. The problem is, when the skeleton dies after throwing a bone, the bone "dies" as well. 

 

I ran into a similar problem with the bone's collider, as the main game loop was checking each object belonging to it's class - the hero and all monsters. Because the bones belong to the skeletons, I had to expose a list of the bones colliders through a getter so the main update loop could iterate over those as well. Should I try something similar for the bone objects themselves? If I grab the list of bones from each skeleton in the main loop, I can update and draw them independently of the skeleton - and I'll also have direct access to their colliders. 

 

Typing out this question actually helped me come up with some ideas (don't you love when that happens?), but I'll pose my main question anyway. Should an enemy's projectiles (or any other game object that logically belongs to the enemy, or any other object for that matter) be members of the enemy class itself, or should they exist at the game loop level, next to the enemies? The latter seems like really poor design, and I'm not sure how I would handle the skeleton telling the main class that it should create a new bone. I prefer the former approach, but any input would be appreciated.

 

It shouldn't matter for this question, but I'm using libGDX.

Share this post


Link to post
Share on other sites

I would handle it by having a list of projectile instances at the main game loop layer, and pass that list to a skeleton when it updates. If the skeleton decides to throw a bone, it will create a projectile instance, initialize it with the required data, such as the projectile velocity, direction, gravity scale, sprite image index, starting position, etc. (note: i would make the projectile a simple data struct, which has an updateType variable, which is used to determine if the projectile needs to arc, or move like a sine wave, etc. You could do it by making a lot of derived projectile types for the different types of projectiles, if you so prefer).

 

Then the main loop simply iterates over each projectile, updates it, checks collisions, does the proper response if collision is detected, and draws it later.

 

There is a question if the projectile needs to know who threw it (like if you need to grant experience to the thrower when the projectile kills something or play an animation on a successfull hit). In such a case, give it an entityID by which you can look up it's thrower, and do the proper behaviour.

Share this post


Link to post
Share on other sites

That sounds like a great approach, thanks for the ideas! One question though - all of my enemies subclass Monster, so I can iterate over all types at once. To pass the projectile list in, I'd need to add it to Monster's update method, but not all monsters throw projectiles. Would you suggest simply ignoring the list if I don't need it (easy enough), or separating my Monster list into individual subclass lists, so each monster type can have it's own update signature? 

Share this post


Link to post
Share on other sites

For my (small) games, I usually have an update(World) function. The game object can choose to interact with the world, e.g. query for interesting objects around them or adding new objects to the world, or it can just ignore this parameter if it is "dumb", like the projectiles you mentioned.

Share this post


Link to post
Share on other sites
Hi.

You could try this.
When your object dies leave it in play but don't render it. This way it can still update it's projectiles then in it's process function you can check to see if it's dead and all projectile have reached there target if so then remove the object.

Share this post


Link to post
Share on other sites
For something like projectiles that are frequently created and destroyed while you play the game it is usually better to pre-allocate a cache of projectile objects and re-use them. If you need to fire a projectile, ask the cache for one, set up its data, and let it do its thing. When the projectile dies, give it back to the cache instead of deleting it.

This helps avoid memory fragmentation and frequent allocation/deallocation which is bad even in languages like C++ and worse in languages with garbage collectors (like Java or C#) due to the massive amount of garbage that would be generated. Edited by SmkViper

Share this post


Link to post
Share on other sites

Caching the projectiles is a good idea and even if you have a reasonably high number pre-allocated to the cache (like 1,000 to 10,000) it would be better on the memory performance than to frequently de-allocate every frame.

 

Add projectiles starting from the beginning of the array and keep a variable to track the number of active projectiles. Then the game would know how far into the array it would need to iterate for each frame. When you need to "delete" a projectile, swap the projectile to be deleted with the last active projectile on the array, and reduce the number of active projectiles by one.

Edited by CC Ricers

Share this post


Link to post
Share on other sites

Good call on the caching. I'll definitely do that.

 

For adding projectiles to the list, I ended up going with a modified version of Strewya's idea. Instead of passing the list in to the update method, I just pass it in to the Skeleton's constructor. Now the skeletons can just add the bone to their own list, and it's the same object in memory that the main loop uses so it works out. 

Share this post


Link to post
Share on other sites

Good call on the caching. I'll definitely do that.

 

For adding projectiles to the list, I ended up going with a modified version of Strewya's idea. Instead of passing the list in to the update method, I just pass it in to the Skeleton's constructor. Now the skeletons can just add the bone to their own list, and it's the same object in memory that the main loop uses so it works out. 

That's another way to do it, yes.

Keep in mind that this prevents you from adding bones to a different list of projectiles (without destroying+recreating the skeleton or having a setter for the list), should you ever decide you need another list. Might not happen ever, but just something to be aware of. :)

Share this post


Link to post
Share on other sites

This topic is 1099 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this