Wednesday 21 March 2012

Allowing for One Time collisions of sprites

This post is specifically for 1st Game Design students in IT Sligo 2012. We have two animated sprites in a game. One is an enemy moving around randomly by itself – the randomEnemy, one is controlled by a player – the player. Both have common attributes and methods (they are both animated and Drawn at their position) hence we have a sprite class to handle this. This is all placed in the Sprite class (sometimes called the base class). For convenience as we have other types of Enemies to be used later that share attributes we have an Enemy class in between RandomEnemy and the Sprite class.

Now the Sprite, Enemy, Player, randomEnemy classes are pre-written and can be found here.

In order to use them in a new game don’t forget to use the name space which in which all these objects reside

using AnimatedSprite;


Now I’m using the default Game1 class here for speed. But the example that the current assignment is based on uses a chase engine class that I have written. All actions happen in the Update of the Game and would happen in the Update of the Chase Engine.



Here are the classes involved in this post.



image



So onto the problem to be solved



The sprite class has a method called CollisionDetect which will check if one sprite collides with another.



public bool collisionDetect(Sprite otherSprite)
{
Rectangle myBound = new Rectangle((int)this.position.X,
(int)this.position.Y, this.spriteWidth, this.spriteHeight);
Rectangle otherBound = new Rectangle((int)otherSprite.position.X,
(int)otherSprite.position.Y, otherSprite.spriteWidth, this.spriteHeight);
if (myBound.Intersects(otherBound))
return true;
return false;
}


 



As it’s in the Sprite Class the Player and all the subclasses inherit it. So when the player object collides with the Random Enemy object we want to update a score for the player. The problem is that the score keeps increasing during the collision event which will happen 60 times a second while colliding. This gives unpredictable scoring. So we need 2  Boolean variables to make sure we only update the score one collision at a time.



So to the Variables to represent the score, the player, the random enemy, a Boolean variable to record if there is currently a collision and if there was a collision on the previous call to the update



int score = 0;
Player player;
RandomEnemy randomEnemy;
bool colliding = false;
SpriteFont scoreFont;



The player,enemy and font to draw the score can then be created in the Load Content method.



player = new Player(this, 
Content.Load<Texture2D>("PlayerDot"), new Vector2(10, 10), 2);
randomEnemy = new RandomEnemy(this,
Content.Load<Texture2D>("EnemyDot"), new Vector2(200, 200), 1);
scoreFont = Content.Load<SpriteFont>("scoreFont");


and so to the Update logic



protected override void Update(GameTime gameTime)
{
player.Update(gameTime);
randomEnemy.Update(gameTime);
if (player.collisionDetect(randomEnemy) && !colliding)
{
score += 10;
colliding = true;
}
else if(!player.collisionDetect(randomEnemy))
colliding = false;

base.Update(gameTime);
}


colliding protects the score from being updated many times in the one collision. colliding is false to begin so !colliding will be true and so if the player successfully detects a collision then we update the score but we set the colliding value to true. This makes !colliding false on the next Update call and hence it will not update the score.



colliding is set to false if the player is not colliding which will happen quite a bit actually.



Then it just remains to draw the score and update the new positions of the player and the Random Enemy



 


protected override void Draw(GameTime gameTime)
{
GraphicsDevice.Clear(Color.CornflowerBlue);
player.Draw(spriteBatch);
randomEnemy.Draw(spriteBatch);


            spriteBatch.Begin();
spriteBatch.DrawString(scoreFont, "Score: " + score.ToString(),
new Vector2(10, 10), Color.White);
spriteBatch.End();

base.Draw(gameTime);
}


and that’s it. The same would apply for a decrease in the Lives of a player and you would need an additional different Boolean variable to protect the lives variable. Until next time.



The final coded solution is here. Any problems give me a shout.

No comments:

Post a Comment