XNA Creators Club Online
Page 1 of 1 (9 items)
Sort Posts: Previous Next

Components List Problem

Last post 11/28/2009 7:58 PM by Gizoku. 8 replies.
  • 11/20/2009 4:33 PM

    Components List Problem

    Hi all,

    I'm using XNA to make an asteroids clone (asteroids meets Geometry Wars, original I know...) and I'm having trouble initiating new waves of asteroids. When an asteroid is destroyed it is removed from the game components list. I basically need something like this:

    if(Components.ASTEROIDS.Count == 0)
    {

    wave += 1

    }

    I'm just not sure of the syntax...

    Any help anyone can offer would be greatly appreciated :D

    Thanks!
  • 11/20/2009 5:15 PM In reply to

    Re: Components List Problem

    I personally would have a single object that holds all the asteroids and work with that object, so if you had 500 asteroids, you would still only be adding 1 object to the components list (which would contain all those asteroids in itself).


    That being said - I would probably do something like this - somewhat simplified since I dont know how you have your code currently set up, organized etc...but hopefully it can point you in the right direction.

    1     class Asteroid 
    2     { 
    3         //whatever makes up an ansteroid, etc 
    4     } 
    5     class AsteroidManager:DrawableGameComponent 
    6     { 
    7         private List<Asteroid> asteroids; 
    8  
    9         public AsteroidManager(Game game):base(game) 
    10         { 
    11             asteroids = new List<Asteroid>(); 
    12             //do whatever to load this list... 
    13         } 
    14  
    15         public override void  Draw(GameTime gameTime) 
    16         { 
    17             //most likely go through and draw the asteroids that are still in the list 
    18             base.Draw(gameTime); 
    19         } 
    20  
    21         public bool TargetsLeft() 
    22         { 
    23             if (asteroids != null
    24                 return asteroids.Count > 0; 
    25             else 
    26                 return false
    27         } 
    28  
    29     } 
    30  
    31 class Game1 : Microsoft.Xna.Framework.Game 
    32     { 
    33         private GraphicsDeviceManager graphics; 
    34         private SpriteBatch spriteBatch; 
    35         private int wave; 
    36  
    37         private AsteroidManager asteroidManager; 
    38  
    39         public Game1() 
    40         { 
    41             graphics = new GraphicsDeviceManager(this); 
    42             Content.RootDirectory = "Content"
    43  
    44         } 
    45  
    46         protected override void Initialize() 
    47         { 
    48             // TODO: Add your initialization logic here 
    49             asteroidManager = new AsteroidManager(this); 
    50             Components.Add(asteroidManager); 
    51  
    52             wave = 1; 
    53             base.Initialize(); 
    54         } 
    67  
    68         protected override void Update(GameTime gameTime) 
    69         { 
    70             //check if we have anything left on this wave.. 
    71             if (!asteroidManager.TargetsLeft()) 
    72                 wave++; 
    73  
    74         } 
    75     } 
    76  

  • 11/20/2009 5:42 PM In reply to

    Re: Components List Problem

    Using a List manager class is good. What you don't want to do is remove and add items to the list. Have a member of the Asteroid class that tells if the asteroid is not destroyed and only draw and calculate collision with the ones that aren't destroyed.
    Jim Perry - Microsoft XNA MVP
    If people spent a minute searching the forums and reading the FAQs before posting I'd be out of a job.
      Got some XNA Game Studio/XNA Framework development info to share with the community? Put it on the XNA Wiki.
        Please mark posts as Answers or Good Feedback when appropriate.
  • 11/20/2009 5:57 PM In reply to

    Re: Components List Problem

    agreed with jim, I usually would have (in this example) the asteroids having a property of IsValid, IsAlive, something to that effect to indicate if it should be included in drawing, collision, and also the if their are any asteroids left for the current wave - so that section would be adjusted a bit  to something like this for example

    if (asteroids != null)  
      foreach(Asteroid a in asteroids) 
      { 
        //as soon as we find one that is alive, no need to continue. 
        if(a.IsAlive) 
          return true
      } 
      //we didnt return so we have nothing alive... 
      return false
    else 
      return false

  • 11/20/2009 6:19 PM In reply to

    Re: Components List Problem

    Okay, thanks Jim and squidpunch :) This is my first game using C#/XNA, so at the minute all the code for my collision detection is held in game1 (which I now realise is a sloppy way of doing things..), would it still work okay using the asteroid manager in this way, or would I have to transfer the collision detection code somewhere else (in the Asteroid Manager class?). I also have mini-asteroids the branch off when a regular asteroid is shot... how should I deal with those? =/


    This is my collision code, doGameLogic detects collision between the player and an asteroid, and ShotAstCollide detects collision between a bullet and an asteroid(and mini-asteroid):
    private void doGameLogic() 
            { 
                bool hasCollision = false
                 
                Rectangle shipRectangle = player.GetBounds(); 
                Rectangle shotRect = shot.GetShotBounds(); 
                foreach (GameComponent gc in Components) 
                { 
                    if (gc is Asteroid) 
                    { 
                        hasCollision = ((Asteroid)gc).CheckCollision(shipRectangle); 
                        if (hasCollision) 
                        { 
                            vibrate.AddVibration(0.8f, 0.8f, 3000); 
                            audio.Explosion.Play(); 
                            RemoveAllAsteroids(); 
                            multiplier = 0; 
                            lives -= 1; 
                             
                            Start(); 
     
                            break
                        } 
                        else 
                            GamePad.SetVibration(PlayerIndex.One, 0f, 0f); 
                    } 
     
                    if (gc is MiniAst1) 
                    { 
                        hasCollision = ((MiniAst1)gc).CheckCollision(shipRectangle); 
                        if (hasCollision) 
                        { 
                            vibrate.AddVibration(0.8f, 0.8f, 3000); 
                            audio.Explosion.Play(); 
                            RemoveAllAsteroids(); 
                            multiplier = 0; 
                            lives -= 1; 
     
                            Start(); 
     
                            break
                        } 
                    } 
     
                    if (gc is MiniAst2) 
                    { 
                        hasCollision = ((MiniAst2)gc).CheckCollision(shipRectangle); 
                        if (hasCollision) 
                        { 
                            vibrate.AddVibration(0.8f, 0.8f, 3000); 
                            audio.Explosion.Play(); 
                            RemoveAllAsteroids(); 
                            multiplier = 0; 
                            lives -= 1; 
     
                            Start(); 
     
                            break
                        } 
                    } 
                     
                } 
            } 
     
            
     
            private void ShotAstCollide() 
            { 
                bool hasCollision = false
     
                foreach (GameComponent gc in Components) 
                { 
                    if (gc is Shot) 
                    { 
                        Shot shot = (Shot)gc; 
                        foreach (GameComponent Ast in Components) 
                        { 
                             
                            if (Ast is Asteroid) 
                            { 
                                Asteroid asteroid = (Asteroid)Ast; 
                                hasCollision = asteroid.CheckCollision(shot.GetBounds()); 
                                if (hasCollision) 
                                { 
                                    if (asteroid.hit == false
                                    { 
     
                                        asteroid.Split(); 
                                        score += 1 * multiplier; 
                                        multiplier++; 
                                        asteroid.hit = true
                                        Components.Remove(asteroid); 
                                         
                                        Shot shotToKill = (Shot)gc; 
                                        Components.Remove(shotToKill); 
                                        shotToKill = null
                                        return
                                    } 
                                } 
                            } 
                            if (Ast is MiniAst1) 
                            { 
                                MiniAst1 miniAst1 = (MiniAst1)Ast; 
                                hasCollision = miniAst1.CheckCollision(shot.GetBounds()); 
                                if (hasCollision) 
                                { 
                                    if (miniAst1.hit == false
                                    { 
                                        score += 2 * multiplier; 
                                        multiplier++; 
                                        miniAst1.hit = true
                                        Components.Remove(miniAst1); 
                                        Shot shotToKill = (Shot)gc; 
                                        Components.Remove(shotToKill); 
                                        shotToKill = null
                                        return
                                    } 
                                } 
                            } 
                            if (Ast is MiniAst2) 
                            { 
                                MiniAst2 miniAst2 = (MiniAst2)Ast; 
     
                              
                                hasCollision = miniAst2.CheckCollision(shot.GetBounds()); 
                                if (hasCollision) 
                                { 
                                    if (miniAst2.hit == false
                                    { 
                                        score += 2 * multiplier; 
                                        multiplier++; 
                                        miniAst2.hit = true
                                        Components.Remove(miniAst2); 
                                        Shot shotToKill = (Shot)gc; 
                                        Components.Remove(shotToKill); 
                                        shotToKill = null
                                        return
                                    } 
                                } 
                            } 
                        } 
                    } 
                } 
            } 
     

    Here is RemoveAllAsteroids:

    private void RemoveAllAsteroids() 
            { 
                for (int i = 0; i < Components.Count; i++) 
                { 
                    if (Components[i] is Asteroid) 
                    { 
                        Components.RemoveAt(i); 
                        i--; 
                    } 
     
                    if (Components[i] is MiniAst1) 
                    { 
                        Components.RemoveAt(i); 
                        i--; 
                    } 
     
                    if (Components[i] is MiniAst2) 
                    { 
                        Components.RemoveAt(i); 
                        i--; 
                    } 
                } 
            } 


    I already have a boolean in the Asteroid called "hit" this can do the same thing as "IsAlive" yeah?

    Sorry, I'm not quite 100% on how to inegrate the asteroid manager with my current code.
    Obviously I'd change everything to do with removing asteroids from the components list but could I keep the basic collision code the same?

    The code I currently use to load the asteroids at the start of the game is this:
    private void Start() 
            { 
                //STARTASTCOUNT is a constant integer with a value of 10 
                for (int i = 0; i < STARTASTCOUNT; i++) 
                { 
                    Components.Add(new Asteroid(thisref asteroidTexture)); 
                } 
     
                //create and put player in position 
                if (player == null
                { 
                    player = new Ship(thisref asteroidTexture); 
                    Components.Add(player); 
                } 
                player.PutinStartPosition(); 
                 
            } 


    Thanks for the help so far guys :)
  • 11/23/2009 2:22 AM In reply to

    Re: Components List Problem

    If you are going to take the direction of having a manager class to handle your asteroids then I yeah I would suggest refactoring your collision logic into the manager, you still might end up with some code in the game class to interface with your player (unless your asteroid manager has some sort of interaction with the your player object)

    You could also refactor the mini-asteroid branching into the asteroid manager as well.

    you could modify the game class a bit to do the collision detection - instead of looping through the game components you could loop through the asteroidmanagers list of asteroids.

    or you could possibly take it a step further and push all the collision into the asteroid manager - of course in that case, you would need to have a way to interface with your player, and the bullet objects...etc

    I could probably slap together some code to show you how to migrate to an asteroid manager - but you would learn a ton more by approaching the problem yourself, and seeking help if needed along the way.  You can work in steps too, you dont have to go all out to start.  So things like keeping the collision detection in the game class to start, and then if you feel like pushing it off to the manager at a later time if you wish :)

    Just think of what you are trying to do and work down the list
  • 11/27/2009 3:35 PM In reply to

    Re: Components List Problem

    Okay, I've got the AsteroidManager going, the asteroids in it now draw, move and collide with the player. I'm having some trouble with sorting the collision with shots however. I tried using a shot manager too, but got a bit lost, so I decided to use my Game1 code for the time being, so I changed it like you said to test against each asteroid in my Asteroid Manager. When I do this I get the following error:

    "Error 1 foreach statement cannot operate on variables of type 'Astrevolution.AsteroidManager' because 'Astrevolution.AsteroidManager' does not contain a public definition for 'GetEnumerator'"

    I've searched the error and it seem like a pretty complex thing to fix :S

    Thanks for the advice squidpunch, has been very helpful thus far :)
  • 11/27/2009 3:45 PM In reply to

    Re: Components List Problem

    You can only use foreach with an IEnumerable instance - it sounds like your manager does not implement that interface. From the code above I'm assuming that you have a List within your AsteroidManager, which will be an IEnumerable. So you likely want:

      foreach(Asteroidasteriod in AsteroidManager.YourList)
      {
      }


    This assumes that your list is publicly available outside the manager class (which it may not be). Another option would be to implement the IEnumerable interface in your manager, simply returning the List.GetEnumerator - this is more complicated and depends on the design of your code.
  • 11/28/2009 7:58 PM In reply to

    Re: Components List Problem

    That did the trick! Thank you very much :) My game is nearly finished now.
Page 1 of 1 (9 items) Previous Next