8 Replies - 2795 Views - Last Post: 27 July 2012 - 07:03 AM

#1 Acemanjam  Icon User is offline

  • New D.I.C Head

Reputation: 0
  • View blog
  • Posts: 4
  • Joined: 27-July 12

Having difficulties implementing bullet/enemy collision detection

Posted 27 July 2012 - 05:50 AM

Hey everyone,

I am currently working on a project for school in which I am attempting to make a simple 2d shooter (Using C# 2010/XNA 4.0). Problem is, I don't know how to implement collision detection between my two lists (being bullets and enemies as stated in title). I am very new to programming and have been using various tutorials as a guide, some tutorials say to use a nested for loop and if statement while I have seen others using an if statement, oh and I'm using the rectangle collision method not the pixel by pixel one I think it was called. I know in the do's and don'ts section above it says not to post my project code, but i can't see any other way to show you guys/gals what I need.

Thanks in advance. Jack

MAIN CODE
namespace Software_Design_Major_Project
{
   
    public class Game1 : Microsoft.Xna.Framework.Game
    {
        GraphicsDeviceManager graphics;
        SpriteBatch spriteBatch;

        Texture2D ship; // Declaring the sprite
        Vector2 shipposition = Vector2.Zero; // Creating a vector for the sprite.

        List<bullets> bullets = new List<bullets>(); // a list is created here so that there can be multiple copies of this item at once without writing the extra code.
        Texture2D texture;
        
        KeyboardState pastkey;
        

        //bullet sound effect.
        SoundEffect effect;
        
        List<enemies> Enemies = new List<enemies>();       
        Random random2 = new Random();        
        
        float spawn = 0;

        public enum GameState 
        {
            MainMenu,            
            Playing,
            
        }
        GameState CurrentGameState = GameState.MainMenu;

        int screenWidth = 600, screenHeight = 480;

        cButton play;                    

        public Game1()
        {
            graphics = new GraphicsDeviceManager(this);
            Content.RootDirectory = "Content";
            //changes width of screen to 600px.
            graphics.PreferredBackBufferWidth = 600;
                                   
        }

  

        protected override void Initialize()
        {
                    
            base.Initialize();
        }

 
        protected override void LoadContent()
        {
            
            spriteBatch = new SpriteBatch(GraphicsDevice);
             // This statement positions the ship.
            ship = Content.Load<Texture2D>("ship"); // Loads the ship into the memory.
            shipposition = new Vector2((graphics.GraphicsDevice.Viewport.Width / 2) - (ship.Width / 2), 420); 
            // loads bullet sprite
            texture = Content.Load<Texture2D>("bullet");             

            graphics.PreferredBackBufferWidth = screenWidth;
            graphics.PreferredBackBufferHeight = screenHeight;

            graphics.ApplyChanges();
            IsMouseVisible = true;

            play = new cButton(Content.Load<Texture2D>("play"), graphics.GraphicsDevice);
            play.setPosition(new Vector2(225, 220));

            effect = Content.Load<SoundEffect>("laser");            
                       
            
        }

     
        protected override void UnloadContent()
        {
         
        }


        protected override void Update(GameTime gameTime)
        {
            spawn += (float)gameTime.ElapsedGameTime.TotalSeconds;
            // spawns enemy every second.
            foreach (enemies enemy in Enemies)
                enemy.update(graphics.GraphicsDevice);


            MouseState mouse = Mouse.GetState();

            switch (CurrentGameState)
            {
                case GameState.MainMenu:

                    if (play.isClicked == true)
                        CurrentGameState = GameState.Playing;

                    play.Update(mouse);

                    break;

                case GameState.Playing:

                    if (Keyboard.GetState(PlayerIndex.One).IsKeyDown(Keys.E))
                    {
                        Exit();
                    }

                    break;


            }

            // Allows the ship to move left and stops the ship going off the screen.          
            if (Keyboard.GetState(PlayerIndex.One).IsKeyDown(Keys.Left) && shipposition.X >= 0)
            {
                shipposition.X -= 7;
            }// same as above except for the right direction.
            if (Keyboard.GetState(PlayerIndex.One).IsKeyDown(Keys.Right) && shipposition.X < ((graphics.GraphicsDevice.Viewport.Width) - (ship.Width)))
            {
                shipposition.X += 7;
            }

            // this prevents the player from holding down space to spam bullets.
            if (Keyboard.GetState().IsKeyDown(Keys.Space) && pastkey.IsKeyUp(Keys.Space))
            {
                bullets bullet = new bullets(texture);
                // the ships coordinates are gathered from the top left hand corner of the sprites rectangle therefore 'new Vector2(shipposition.X + 32, shipposition.Y)' had to
                // be added rather than just = 'shipposition' to avoid having the bullets shoot from the wing. 
                bullet.position = new Vector2(shipposition.X + 32, shipposition.Y);
                bullets.Add(bullet);
                effect.Play();

            }



            pastkey = Keyboard.GetState();

            //calls upon the update method from the bullets class.

            foreach (bullets bullet in bullets)
                bullet.update();

            
                LoadEnemies();
            base.Update(gameTime);


        }
            
            public void LoadEnemies() 
            {
                int randX = random2.Next(10, 540);

                if (spawn <= 1) 
                {
                    spawn = 0;
                    //limits amount of enemies on screen to 5.
                    if (Enemies.Count() < 5)
                        Enemies.Add(new enemies(Content.Load<Texture2D>("enemy"), new Vector2(randX, -100)));
                }
                for (int i = 0; i < Enemies.Count; i++) 
                {
                    if (!Enemies[i].enemyVisble)
                    {
                        //removes the enemies when they go off screen.
                        Enemies.RemoveAt(i);
                        i--;
                    }
                    
                }
            }
        
        
      
            protected override void Draw(GameTime gameTime)
            {
                GraphicsDevice.Clear(Color.CornflowerBlue);
                // calls draw method in bullets class
                foreach (bullets bullet in bullets)
                {
                    bullet.Draw(spriteBatch);
                }
                spriteBatch.Begin(SpriteSortMode.BackToFront, BlendState.AlphaBlend);
                spriteBatch.Draw(ship, shipposition, Color.White); // draws ship sprite 
  

                                
                switch (CurrentGameState)
                {
                    case GameState.MainMenu:
                        play.draw(spriteBatch);
                        spriteBatch.Draw(Content.Load<Texture2D>("menu"), new Rectangle(0, 0, screenWidth, screenHeight), Color.White);
                                                                        
                        break;

                    case GameState.Playing:

                       
                        break;

                 
                }
                


                foreach (enemies enemy in Enemies)
                {
                    enemy.draw(spriteBatch);
                }

                 spriteBatch.End();

                base.Draw(gameTime);
            }            
                    

    }
}



BULLETS CLASS
namespace Software_Design_Major_Project
{
   
          class bullets // A new class needs to be created to allow for bullets.
          {
                public Texture2D texture;
                public Vector2 position;     
                public bool isvisible;
                public Rectangle bulletRectangle;   
                
                

                public bullets(Texture2D newtexture) 
                {
                    texture = newtexture;
                    isvisible = false;
                }

                public void update() 
                {
                    position.Y -= 3; // velocity of the bullet                    

                } 
                                   
                
                public void Draw(SpriteBatch spriteBatch) 
                {
                    spriteBatch.Begin();
                    spriteBatch.Draw(texture, position, Color.White);
                    spriteBatch.End();
                }
          }
}


ENEMIES CLASS
namespace Software_Design_Major_Project
{
    class enemies
    {
        public Texture2D enemyTexture;
        public Vector2 enemyPosition;        
        public bool enemyVisble = true;
        public float enemyMoveSpeed;
        public int Value;
        Random random = new Random();
        int randY;
        public Rectangle enemyRectangle 
        {
            get
            {
                return new Rectangle((int)enemyPosition.X, (int)enemyPosition.Y, (int)enemyTexture.Width, (int)enemyTexture.Height);
            }
        }

        public enemies (Texture2D newEnemyTexture, Vector2 newEnemyPosition) 
        {
            enemyTexture = newEnemyTexture;
            enemyPosition = newEnemyPosition;
            randY = random.Next(1, 4);
            enemyMoveSpeed = randY;
            enemyVisble = true;                        
            Value = 100;            

        }       

        
        public void update(GraphicsDevice graphics) 
        {
            enemyPosition.Y += enemyMoveSpeed;

            if (enemyPosition.Y > 500)
                enemyVisble = false;            
            
            
        }

        public void draw(SpriteBatch spriteBatch) 
        {
            
            spriteBatch.Draw(enemyTexture, enemyPosition, Color.White);            
            enemyVisble = true;
            
        }

    }
    
}

Attached image(s)

  • Attached Image


Is This A Good Question/Topic? 0
  • +

Replies To: Having difficulties implementing bullet/enemy collision detection

#2 modi123_1  Icon User is online

  • Suitor #2
  • member icon



Reputation: 9218
  • View blog
  • Posts: 34,619
  • Joined: 12-June 08

Re: Having difficulties implementing bullet/enemy collision detection

Posted 27 July 2012 - 05:56 AM

Typically it's as simple as - after your bullet moves see if it's rectangle over laps/touches another rectangle.. if so the next engine update do the explosion animation and health subtraction.. etc.

Not so shockingly this is a frequent topic and if you search for just "collision" in this subforum you'll get a ton of hits.
Was This Post Helpful? 0
  • +
  • -

#3 Acemanjam  Icon User is offline

  • New D.I.C Head

Reputation: 0
  • View blog
  • Posts: 4
  • Joined: 27-July 12

Re: Having difficulties implementing bullet/enemy collision detection

Posted 27 July 2012 - 06:04 AM

Thanks for the quick reply. Sorry if you see this question a lot, but all of the code I've tried to implement so far hasn't worked T_T. I tried to put something like this in:

public Rectangle bulletRectangle 
{ get {return new rectangle(pos.X, pos.Y, tex.Width, tex.Height);}


but when I put this into my main code the position variable is underlined and I get a message like "this variable doesn't exist in this context". are there any good tutorials you can point me towards?
Was This Post Helpful? 0
  • +
  • -

#4 BBeck  Icon User is offline

  • Here to help.
  • member icon


Reputation: 580
  • View blog
  • Posts: 1,286
  • Joined: 24-April 12

Re: Having difficulties implementing bullet/enemy collision detection

Posted 27 July 2012 - 06:12 AM

This post belongs in the XNA forum. :-)

It seems wrong to me to create a new rectangle object in your get in the last post there. I think you should be returning either a rectangle that is a field in the class, or some other value that's part of the class rather than creating a new object there.

Also, I would be inclined to treat the bullets as points rather than Oriented Bounding Boxes, but that's really up to you.

Essentially, you need to compare every bullet to every enemy's box and determine if that bullet is inside the enemy's box. That would take a loop, such as a for loop.

And since you're using the List object quite a bit, you should get very familiar with it's methods:

http://msdn.microsof...ibrary/s6hkc2c4
Was This Post Helpful? 0
  • +
  • -

#5 BBeck  Icon User is offline

  • Here to help.
  • member icon


Reputation: 580
  • View blog
  • Posts: 1,286
  • Joined: 24-April 12

Re: Having difficulties implementing bullet/enemy collision detection

Posted 27 July 2012 - 06:18 AM

I think what you want is this:

public Rectangle CollisionRectangle 
{ get {return bulletRectangle;}




bulletRectangle is a field in the class. You just need to get it's value here.

(The property here cannot have the same name as the field in the class, I believe.)

This post has been edited by BBeck: 27 July 2012 - 06:20 AM

Was This Post Helpful? 0
  • +
  • -

#6 BBeck  Icon User is offline

  • Here to help.
  • member icon


Reputation: 580
  • View blog
  • Posts: 1,286
  • Joined: 24-April 12

Re: Having difficulties implementing bullet/enemy collision detection

Posted 27 July 2012 - 06:27 AM

You are also not setting a value for bulletRectangle. You need to give it a value somewhere. What about creating a new method in that class called something like "GetBulletRectangle" and build the box in that method. I think that's kind of what you were doing in that post above except you were going about it wrong by doing a property instead of a method. Properties are for giving access to the information in your fields. A Property would be the correct choice if bulletRectangle had something in it, but your code doesn't seem to put anything in it.

I would just go with a method that calculates the box when called, based on the position of the bullet and returns a rectangle object (or point if you use points here).

This post has been edited by BBeck: 27 July 2012 - 06:28 AM

Was This Post Helpful? 0
  • +
  • -

#7 Acemanjam  Icon User is offline

  • New D.I.C Head

Reputation: 0
  • View blog
  • Posts: 4
  • Joined: 27-July 12

Re: Having difficulties implementing bullet/enemy collision detection

Posted 27 July 2012 - 06:32 AM

Thanks BBeck ill give that a go :)
Was This Post Helpful? 0
  • +
  • -

#8 BBeck  Icon User is offline

  • Here to help.
  • member icon


Reputation: 580
  • View blog
  • Posts: 1,286
  • Joined: 24-April 12

Re: Having difficulties implementing bullet/enemy collision detection

Posted 27 July 2012 - 06:35 AM

View PostAcemanjam, on 27 July 2012 - 07:04 AM, said:

public Rectangle bulletRectangle 
{ get {return new rectangle(pos.X, pos.Y, tex.Width, tex.Height);}




This is also wrong because pos and tex are undefined in your bullet class. They are called "position" and "texture" in the class, not "pos" and "tex". If you rename this property (since it conflicts with the bulletRectangle field) and rename those two, this code might work as long as the rectangle class is in scope here.
Was This Post Helpful? 0
  • +
  • -

#9 Acemanjam  Icon User is offline

  • New D.I.C Head

Reputation: 0
  • View blog
  • Posts: 4
  • Joined: 27-July 12

Re: Having difficulties implementing bullet/enemy collision detection

Posted 27 July 2012 - 07:03 AM

Oh sorry I was just shortening them for the sake of a shorter message I was putting the names on correctly before.
Was This Post Helpful? 0
  • +
  • -

Page 1 of 1