Jump to content
  • Advertisement
Sign in to follow this  
dzeligman

World/directors, entity management

This topic is 3771 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've been trying to get a better grasp on some simple ways of improving my basic architecture and a few things I'm really unsure of. I'm making a 2d shooter, and its not that complex. I have different kind of ships (player,alien,etc) they have different weapons with different shots. A few other things like powerups, particle emitters and other classes exist, but they're more independent. Currently my "World" class is also my director class, and I think it is becoming kind of a blob. I create the enemies inside it and remove them if they are inactive, the enemies themselves change themselves to inactive if they go outside the bounds of the camera or are destroyed. The world has separate lists for each class that is loops through during update calls, IE powerUPS,enemyList, etc. Each weapon has a list of shots that it produced. One thing I'm unsure of is a better way of managing the collisions between shots and ships and then the object removal. Currently in my World I do things like
foreach(Enemy enemy in Enemylist)
{
  foreach(Shot shot in player.Shots)
   {
     if(collision detected)
       {  
         shot.reverseCollide(enemy);
         enemy.reverseCollide(shot)  
  
and then an example of clean up...
List<Enemy> enemiesToRemove = ...
foreach(Enemy enemy in Enemylist)
{
     if(!enemy.isActive)
         enemiesToRemove.add(enemy)

foreach(Enemy enemy in enemiesToRemove)
         EnemyList.remove(enemy)
 
Thanks in advance.

Share this post


Link to post
Share on other sites
Advertisement
Here's one suggestion (for optimisation/speed): don't delete enemies. Create as many as you'll need and either tag them as active or inactive...inactive ones are "dead", and active ones aren't. If you need more onscreen/interacting with the environment, activate some inactive ones.

Constantly constructing and destructing objects eats up a lot of effort you could put elsewhere.

Do the same thing with "shots" (bullets). Especially shots. @_@ They usually travel much faster than enemies, so they go inactive much faster/much more frequently. And spawn much more frequently. You'd be constantly calling new and delete. Don't do this. <3 Make a static list and activate/deactive them as you need them.

EDIT: I don't feel that answers your question, however valid a recommendation it may be. Post some more of your code, if you would, so we can look over it. At least the class(es) you are concerned with.

Share this post


Link to post
Share on other sites
Quote:
Original post by dzeligman
Currently my "World" class is also my director class, and I think it is becoming kind of a blob. I create the enemies inside it and remove them if they are inactive, the enemies themselves change themselves to inactive if they go outside the bounds of the camera or are destroyed.

Sounds ok to me, but if you feel it's getting unwieldy, perhaps separate it into Game (for logic) and World (for the setting).

I also wouldn't have the entities set themselves as inactive. They shouldn't know anything about the camera bounds. Have your director/world/game/whatever make that decision.

Quote:
The world has separate lists for each class that is loops through during update calls, IE powerUPS,enemyList, etc.

Sometimes it's better to put all these things in the same list, especially if they have a lot in common, such as an on-screen representation, a position in the world, etc.

Quote:
One thing I'm unsure of is a better way of managing the collisions between shots and ships and then the object removal.


What language are you using? Many languages will make it possible for you to remove all things from a list that match a certain criteria, and to do that in one call.

The actual collision detection looks fine. You can speed it up with spatial hashes and the like, but I doubt that will be important for a 2D shooter.

Share this post


Link to post
Share on other sites
Quote:
Original post by serratemplar
Here's one suggestion (for optimisation/speed): don't delete enemies. Create as many as you'll need and either tag them as active or inactive...inactive ones are "dead", and active ones aren't. If you need more onscreen/interacting with the environment, activate some inactive ones.


By doing so, you create a lot of objects which are neither short nor long living.
Pooling is unnecessary in .net, it just makes things worse for the GC, which makes quick gen 0 sweeps.

Moreover, allocations are fast, so that's not an issue. Having objects staying on the heap in an inactive state doesn't sound particularly efficient either. It is true that GCs kick in upon allocation, but since the objects are short lived, they should be collected quickly, thus not impacting the performance of the app.

This is what I've gathered from a Rico Mariani's post. However, since the "pooling or not" question has bugged me for quite some time, I'd love to hear your point of view on the matter. :)

And as Kylotan said, List<T>'s (I assume the OP is using C# looking at the example's objects and syntax) have a RemoveAll method accepting a Predicate<T>, might come in handy.

Share this post


Link to post
Share on other sites
Thanks for the replies, here's some code for some more specific reference =D

I considered making a pool for each needed set of objects, but I haven't noticed any drops in performance between my good comp at home and my shitty laptop here at work.

[qupte]What language are you using? Many languages will make it possible for you to remove all things from a list that match a certain criteria, and to do that in one call.[/quote]
The language is C#, using XNA framework.

Here's an example of updating of enemies :

foreach (Enemy enemy in enemyList)
{
if (camera.View.Contains((int)enemy.worldPosition.X, (int)enemy.worldPosition.Y))
{
//this could be moved to inside enemy, static calculation method.... enemy.setDrawPosition(Camera2D.ApplyTransformations(enemy.worldPosition));
enemy.isActive = true;
enemy.Update(gameTime);
}
}


With my collision detection/handling originally I was trying for a double dispatch approach, but alas C# doesnt really support it and I havent really got around to trying a different method. Currently I just see if the given objects rectangle contains the other Vector. It's basically just a broad phase test, but it works in my context.

The actual collision handling is pretty gross right now since I didnt mess more with the double dispatch/visitor approach. I do type checking ><.
I have to do the exact class checking instead of top level this way, thus I cant put everything into one list. (eg: enemy.reverseCollide(shot), instead of entity1.reverseCollide(entity2) )

I'll post some as an example for what I do:

Top-level entity:

public void reverseCollide(GameObject entity)
{
entity.collide(this);
}


foreach (Enemy enemy in enemyLists)
{
foreach (Shot shot in player1.Weapon.Shots)
{
if (enemy.isActive)
{
if (CollisionSystem.CollideVector(enemy, shot.drawPosition))
{
enemy.reverseCollide(shot);
shot.reverseCollide(enemy);

bulletHitEmitter.Trigger(shot.drawPosition);

if (enemy.HitPoints <= 0)
{
if (RandomHelper.Random.Next(100) <= 20)
{
powerUPs.Add(PowerUPCreator.create(enemy.worldPosition));
}
doEnemyDeathStuff(enemy.drawPosition, enemy.worldPosition);
}
}
}
}
}

Enemy :
protected override void collide(Entity entity)
{
if (entity is Shot)
{
Shot shot = (Shot)entity;
if (shot.element == EnumFinder.getElementCounter(element))
{

HitPoints -= (int)(100 * shot.Damage);
if (HitPoints <= 0)
{
isDead = true;
}
}
else
{
HitPoints -= (int)(34 * shot.Damage);
if (HitPoints <= 0)
{
isDead = true;
}
}
}
else if (entity is PlayerShip)
{
isDead = true;
}

}



Another thing I'm not sure about that I kind of asked in another thread, is how the spritebatch handles drawing out of "bounds." This may be a more specific XNA oriented thread, but would the spriteBatch call automatically cull the 2d objects whose draw coordinates are outside the viewport coordinates?

The entities use isActive to determine if they should draw themselves or not. The isDead isused if they were shot down in some manner.

A changed example of the "object cleanup" is here:

List<Enemy> enemiesToRemove = new List<Enemy>();
foreach (Enemy enemy in enemyList)
{
if (enemy.isDead || camera.View.Bottom < (int)enemy.worldPosition.Y)
{
enemiesToRemove.Add(enemy);
}
}

foreach (Enemy enemy in enemiesToRemove)
{
enemyList.Remove(enemy);

}


Quote:
And as Kylotan said, List<T>'s (I assume the OP is using C# looking at the example's objects and syntax) have a RemoveAll method accepting a Predicate<T>, might come in handy


How does that work ? :O

I also have each "ship" in the game have its own weapon which tracks its own shots. I'm considering moving all the shots into two separate lists in the world, eg an enemyShots and Playershots. The weapon would just create them and add them to the world lists.




Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!