Difference between revisions of "Simple Platform"
(→Alternatives to Check Right / Left) |
(→Alternatives to Check Right / Left) |
||
Line 534: | Line 534: | ||
You could also check each of the tiles around the centertile using two for loops, this way you can check the right and left at the same time. The code, if (x != 0 && y != 0) is to not check the center tile because this will obviously collide with the player : | You could also check each of the tiles around the centertile using two for loops, this way you can check the right and left at the same time. The code, if (x != 0 && y != 0) is to not check the center tile because this will obviously collide with the player : | ||
<syntaxhighlight lang=c#> | <syntaxhighlight lang=c#> | ||
− | public bool | + | public bool CheckBounds() |
{ | { | ||
bool check = false; | bool check = false; | ||
Line 579: | Line 579: | ||
<syntaxhighlight lang=c#> | <syntaxhighlight lang=c#> | ||
− | public bool | + | public bool CheckBounds() |
{ | { | ||
bool check = false; | bool check = false; |
Revision as of 11:00, 21 January 2018
This will show you how to create a platform game using a tiled map, and tile based collision detection.
Contents
- 1 Create Map
- 1.1 Tiled
- 1.2 MonoGame Project
- 1.3 Code to Display Map
- 1.4 Falling
- 1.5 Other Check Ground ideas
- 1.6 Jumping
- 1.7 Moving Left or Right
- 1.8 Alternatives to Check Right / Left
- 1.9 Collectables
- 1.10 Checking Collectables
- 1.11 CheckCoin Improvements
- 1.12 Key & Door
- 1.13 Check Collision for Key
- 1.14 Check Collision for Door
Create Map
Tiled
You will firstly need to install the Tiled program from the website and link below. In college the Tiled executeables are on moodle, under project, technical skill, monogame, and tiled. I have also added links to other tutorials for using Tiled.
Tiled Website and Download
Tutorials for using Tiled
Written Version of Above Tutorials
New Tiled Map
You will need a new tiled map, the tile size in the screen shot is 128 pixels, in the end i actually changed this to 32 x 32 and resized the tiles accordingly:
It is important to change the format of the map to Base64 gzip compressed:
File:Plat tile layer format.gif
Add Tile Set
Now your map is created we need to add a tile set:
In creating this tutorial i first tried a tileset based upon a collection of images, this seemed fine in Tiled but failed to draw using Square.Tiled. So make sure you choose embed and based on tileset image:
Draw Your Level
Now you have a tile set build a simple set of platforms. You should rename the layer to something like Tiles:
Add Player Object
Now you have a section of platforms, we can now set the position of the player. This will also be the object moved by the code and player input. So insert an object layer, and then use the rectangle tool to create the object. My final player was 60 pixels high and 40 pixels wide:
MonoGame Project
Create a new MonoGame project, mine is a Windows project.
Setup Square.Tiled
If you have a project ready, create a new class in your project. Click project and new class and call it Tiled.cs, then copy the code from this document over the code in your new class: Square.Tiled Class
Remember to set the name space to Squared.Tiled.
You will need to add references in the using section for the following:
using System.IO;
using Squared.Tiled;
Code to Display Map
Map Variables
At the top of your Game1 class add these additional variables:
Map map;
Layer collision;
Vector2 viewportPosition;
int tilePixel;
LoadContent for map
In the LoadContent method add the following lines to load the map, the collision layer and to set the texture of the player. The variable tilepixel assumes your tiles are square, the number of pixels is taken from the map:
map = Map.Load(Path.Combine(Content.RootDirectory, "SimplePlatform.tmx"), Content);
collision = map.Layers["Tiles"];
tilePixel = map.TileWidth;
map.ObjectGroups["objects"].Objects["Player"].Texture = Content.Load<Texture2D>("hero");
The Update Method
You will also need to update the viewportPosition, this will center the map onto the player:
viewportPosition= new Vector2(map.ObjectGroups["objects"].Objects["Player"].X - (graphics.PreferredBackBufferWidth/2), map.ObjectGroups["objects"].Objects["Player"].Y - (graphics.PreferredBackBufferHeight/2));
The Draw Method
Add the following to the draw method to draw the map and hero to the screen.
If you already have spriteBatch.Begin() or spriteBatch.End() then just place the middle line inbetween your lines.
spriteBatch.Begin();
map.Draw(spriteBatch, new Rectangle(0, 0, GraphicsDevice.Viewport.Width, GraphicsDevice.Viewport.Height), viewportPosition);
spriteBatch.End();
At this point your project should run an display your map centered onto the player.
Falling
In a platformer, the first thing you want to program is the falling logic, because you need to be able to land on a platform. To do this create a new method called CheckGround. This method should accept an integer for speed, because i want to check ground only when the player is falling and not jumping up. This method will return an integer for the number of overlapping pixels, we can then adjust the players position:
public int CheckGround(int speed)
{
int temp = 0, temp1 = 0;
if (speed > 0)
{
}
//return largest y collision overlap
if (temp < temp1)
return temp;
else
return temp1;
}
The if statement above is to only check for ground when the player is falling, speed would be negative if the player was moving up the screen. The two variables temp & temp1 will be used to calculate the number of pixels the player overlaps the tile on the bottom left and bottom right corners. So we first need to get the exact coordinates for these corners:
public int CheckGround(int speed)
{
int temp = 0, temp1 = 0;
if (speed > 0)
{
//get exact coordinates for each corner
Vector2 lb = new Vector2(map.ObjectGroups["Objects"].Objects["Player"].X,
map.ObjectGroups["Objects"].Objects["Player"].Y + map.ObjectGroups["Objects"].Objects["Player"].Height);
Vector2 rb = lb+ new Vector2( map.ObjectGroups["Objects"].Objects["Player"].Width,0);
}
//return largest y collision overlap
if (temp < temp1)
return temp;
else
return temp1;
}
Now we need to work out which tile the player is on, this can be done by dividing the X & Y by the tilePixel. We can use these to get the tile value for this tile. If the tile value is 0 then no tile exists on that part of the map. If a tile is present, we need to workout how much the player overlaps the tile, this is then passed back to move the player this number of pixels:
public int CheckGround(int speed)
{
int temp = 0, temp1 = 0;
if (speed > 0)
{
//get exact coordinates for each corner
Vector2 lb = new Vector2(map.ObjectGroups["Objects"].Objects["Player"].X,
map.ObjectGroups["Objects"].Objects["Player"].Y + map.ObjectGroups["Objects"].Objects["Player"].Height);
Vector2 rb = lb+ new Vector2( map.ObjectGroups["Objects"].Objects["Player"].Width,0);
//check left bottom
int tile = collision.GetTile((int)lb.X / tilePixel, (int)lb.Y / tilePixel);
if (tile != 0)
{
temp = (((int)lb.Y / tilePixel) * tilePixel) - (int)lb.Y;
}
}
//return largest y collision overlap
if (temp < temp1)
return temp;
else
return temp1;
}
The temp calculation above works out the top position of the tile, the (int) casting removes any partial tiles in the calculation.
Finally we need to check the other corner, to complete our CheckGround method:
public int CheckGround(int speed)
{
int temp = 0, temp1 = 0;
if (speed > 0)
{
//get exact coordinates for each corner
Vector2 lb = new Vector2(map.ObjectGroups["Objects"].Objects["Player"].X,
map.ObjectGroups["Objects"].Objects["Player"].Y + map.ObjectGroups["Objects"].Objects["Player"].Height);
Vector2 rb = lb+ new Vector2( map.ObjectGroups["Objects"].Objects["Player"].Width,0);
//check left bottom
int tile = collision.GetTile((int)lb.X / tilePixel, (int)lb.Y / tilePixel);
if (tile != 0)
{
temp = (((int)lb.Y / tilePixel) * tilePixel) - (int)lb.Y;
}
//check right bottom
tile = collision.GetTile((int)rb.X / tilePixel, (int)rb.Y / tilePixel);
if (tile != 0)
{
temp1 = (((int)rb.Y / tilePixel) * tilePixel) - (int)rb.Y;
}
}
//return largest y collision overlap
if (temp < temp1)
return temp;
else
return temp1;
}
Using CheckGround
In the Game1.cs create the following variables:
int speed = 4;
bool onGround = false;
Now in the update method add the following code:
if (!onGround)
{
speed++;
}
map.ObjectGroups["Objects"].Objects["Player"].Y = map.ObjectGroups["Objects"].Objects["Player"].Y + (speed);
int CheckY = CheckGround(speed);
if (CheckY != 0)
{
onGround = true;
map.ObjectGroups["Objects"].Objects["Player"].Y = map.ObjectGroups["Objects"].Objects["Player"].Y + CheckY;
}
else
onGround = false;
This code keeps adding to the speed to make the player fall faster, the movement is applied by adding speed to the current Y value. We then check if we have collided with a tile. If we have collided with a tile we set onGround to be true and correct the Y coordinate of the player.
At this point you should be able to test your game, the playing character should fall to the platform below and stay on top of the platform.
Other Check Ground ideas
Everyone will need to be careful regarding just copying and pasting code, especially from key areas such has checking the bounds of the player. I have therefore identified other ways to check the bounds.
Find the center tile and then check the tile below:
public bool CheckGround()
{
bool check = false;
Vector2 centertile = new Vector2(
(map.ObjectGroups["Objects"].Objects["Player"].X + (map.ObjectGroups["Objects"].Objects["Player"].Width / 2))/tilepixel,
(map.ObjectGroups["Objects"].Objects["Player"].Y + (map.ObjectGroups["Objects"].Objects["Player"].Height / 2))/tilepixel
);
if (collision.GetTile((int)centertile.X + 1, (int)centertile.Y) != 0)
check = true;
return check;
}
The method above doesn't allow you to get very close to the actual bounds. Instead we can also create a rectangle for the player and the tile to see if they intersect:
public bool CheckGround()
{
bool check = false;
Rectangle playrec = new Rectangle(
map.ObjectGroups["Objects"].Objects["Player"].X,
map.ObjectGroups["Objects"].Objects["Player"].Y,
map.ObjectGroups["Objects"].Objects["Player"].Width,
map.ObjectGroups["Objects"].Objects["Player"].Height
);
Vector2 centertile = new Vector2(
(map.ObjectGroups["Objects"].Objects["Player"].X + (map.ObjectGroups["Objects"].Objects["Player"].Width / 2)) / tilepixel,
(map.ObjectGroups["Objects"].Objects["Player"].Y + (map.ObjectGroups["Objects"].Objects["Player"].Height / 2)) / tilepixel
);
if (collision.GetTile((int)centertile.X + 1, (int)centertile.Y)!=0)
{
Rectangle right = new Rectangle(
(int)(centertile.X + 1) * tilepixel,
(int)centertile.Y * tilepixel,
tilepixel,
tilepixel
);
if (playrec.Intersects(right))
check = true;
}
return check;
}
Jumping
Jumping should be straight forward, we are going to prevent multiple jumps by counting how many times the player has jumped since the player was last on the ground. To do this we need to declare a new variable in the Game1.cs:
int jumpCount = 0;
Now in the update method add the following to jump everytime the space bar is pressed:
if (Keyboard.GetState().IsKeyDown(Keys.Space))
{
if (jumpCount <= 1)
{
speed = -16;
jumpCount++;
}
}
The jump works by setting speed to a minus value, the previous code will keep adding 1 to this so that the jump will eventually be a fall. The jumpCount should restrict you to a double jump.
Now we need to change the if statement in the update method to:
if (CheckY != 0)
{
onGround = true;
jumpCount = 0;
}
else
onGround = false;
This resets the jumpCount everytime we land on a tile.
Moving Left or Right
To move left or right add the following to the update method of Game1.cs:
if (Keyboard.GetState().IsKeyDown(Keys.Z))
{
map.ObjectGroups["Objects"].Objects["Player"].X -= 3;
}
if (Keyboard.GetState().IsKeyDown(Keys.X))
{
map.ObjectGroups["Objects"].Objects["Player"].X += 3;
}
This should work at this point, however we don't check for collisions with any tiles, this will not be blocked by any tiles. So we need to check if we have collided with a tile on the left and right.
I have used the same logic as CheckGround, ie to check each corner and work out how many pixels the character overlaps by. This can then be used to adjust the X position of the player.
public int CheckLeft()
{
int temp = 0, temp1 = 0;
//get exact coordinates for each corner
Vector2 lt = new Vector2(map.ObjectGroups["Objects"].Objects["Player"].X, map.ObjectGroups["Objects"].Objects["Player"].Y);
Vector2 lb = lt + new Vector2(0, map.ObjectGroups["Objects"].Objects["Player"].Height -1);
//check left Top
int tile = collision.GetTile((int)lt.X / tilePixel, (int)lt.Y / tilePixel);
if (tile != 0)
{
temp = (((int)lt.X / tilePixel) * tilePixel) - (int)lt.X;
}
//check left bottom
tile = collision.GetTile((int)lb.X / tilePixel, (int)lb.Y / tilePixel);
if (tile != 0)
{
temp1 = (((int)lb.X / tilePixel) * tilePixel) - (int)lb.X;
}
if (temp < temp1)
return temp;
else
return temp1;
}
And also this for the CheckRight:
public int CheckRight()
{
int temp = 0, temp1 = 0;
//get exact coordinates for each corner
Vector2 rt = new Vector2(map.ObjectGroups["Objects"].Objects["Player"].X + map.ObjectGroups["Objects"].Objects["Player"].Width,
map.ObjectGroups["Objects"].Objects["Player"].Y);
Vector2 rb = rt + new Vector2(0, map.ObjectGroups["Objects"].Objects["Player"].Height-1);
//check Right Top
int tile = collision.GetTile((int)rt.X / tilePixel, (int)rt.Y / tilePixel);
if (tile != 0)
{
temp = (((int)rt.X / tilePixel) * tilePixel) - (int)rt.X;
}
//check right bottom
tile = collision.GetTile((int)rb.X / tilePixel, (int)rb.Y / tilePixel);
if (tile != 0)
{
temp1 = (((int)rb.X / tilePixel) * tilePixel) - (int)rb.X;
}
if (temp<temp1)
return temp;
else
return temp1;
}
Using CheckRight & CheckLeft
In the Update method of Game1.cs, change the code to move the player left and right to make it the following:
int CheckX = 0;
if (Keyboard.GetState().IsKeyDown(Keys.Z))
{
map.ObjectGroups["Objects"].Objects["Player"].X -= 3;
if (CheckLeft() != 0)
CheckX = 3;
}
if (Keyboard.GetState().IsKeyDown(Keys.X))
{
map.ObjectGroups["Objects"].Objects["Player"].X += 3;
if (CheckRight()!=0)
CheckX = -3;
}
We move the player by 3 pixels, so once moved check if this overlaps the tile. If it does set checkX which is then used to undo the move by adding this code after the two if statements above:
map.ObjectGroups["Objects"].Objects["Player"].X = map.ObjectGroups["Objects"].Objects["Player"].X + CheckX;
You should now have a game which allows you to move, jump and land on platforms, test it and try out the movement.
Alternatives to Check Right / Left
Everyone will need to be careful regarding just copying and pasting code, especially from key areas such has checking the bounds of the player. I have therefore identified other ways to check the bounds.
Find the center tile and then check the tile to the left and right:
public bool CheckRightLeft()
{
bool check = false;
Vector2 centertile = new Vector2(
(map.ObjectGroups["Objects"].Objects["Player"].X + (map.ObjectGroups["Objects"].Objects["Player"].Width / 2))/tilepixel,
(map.ObjectGroups["Objects"].Objects["Player"].Y + (map.ObjectGroups["Objects"].Objects["Player"].Height / 2))/tilepixel
);
if (collision.GetTile((int)centertile.X, (int)centertile.Y - 1) != 0)
check = true;
if (collision.GetTile((int)centertile.X, (int)centertile.Y + 1) != 0)
check = true;
return check;
}
The method above doesn't allow you to get very close to the actual bounds. Instead we can also create a rectangle for the player and the tile to see if they intersect:
public bool CheckLeftRight()
{
bool check = false;
Rectangle playrec = new Rectangle(
map.ObjectGroups["Objects"].Objects["Player"].X,
map.ObjectGroups["Objects"].Objects["Player"].Y,
map.ObjectGroups["Objects"].Objects["Player"].Width,
map.ObjectGroups["Objects"].Objects["Player"].Height
);
Vector2 centertile = new Vector2(
(map.ObjectGroups["Objects"].Objects["Player"].X + (map.ObjectGroups["Objects"].Objects["Player"].Width / 2)) / tilepixel,
(map.ObjectGroups["Objects"].Objects["Player"].Y + (map.ObjectGroups["Objects"].Objects["Player"].Height / 2)) / tilepixel
);
if (collision.GetTile((int)centertile.X, (int)centertile.Y - 1)!=0)
{
Rectangle left = new Rectangle(
(int)(centertile.X + 1) * tilepixel,
(int)centertile.Y * tilepixel,
tilepixel,
tilepixel
);
if (playrec.Intersects(left))
check = true;
}
if (collision.GetTile((int)centertile.X, (int)centertile.Y + 1)!=0)
{
Rectangle right = new Rectangle(
(int)(centertile.X + 1) * tilepixel,
(int)centertile.Y * tilepixel,
tilepixel,
tilepixel
);
if (playrec.Intersects(right))
check = true;
}
return check;
}
You could also check each of the tiles around the centertile using two for loops, this way you can check the right and left at the same time. The code, if (x != 0 && y != 0) is to not check the center tile because this will obviously collide with the player :
public bool CheckBounds()
{
bool check = false;
Rectangle playrec = new Rectangle(
map.ObjectGroups["Objects"].Objects["Player"].X,
map.ObjectGroups["Objects"].Objects["Player"].Y,
map.ObjectGroups["Objects"].Objects["Player"].Width,
map.ObjectGroups["Objects"].Objects["Player"].Height
);
Vector2 centertile = new Vector2(
(map.ObjectGroups["Objects"].Objects["Player"].X + (map.ObjectGroups["Objects"].Objects["Player"].Width / 2))/tilepixel,
(map.ObjectGroups["Objects"].Objects["Player"].Y + (map.ObjectGroups["Objects"].Objects["Player"].Height / 2))/tilepixel
);
for (int x=-1; x<=1; x++)
{
for (int y = -1; y <=1; y++)
{
Vector2 tempv = centertile + new Vector2(x, y);
if (x != 0 && y != 0)
{
if (collision.GetTile((int)tempv.X, (int)tempv.Y) != 0)
{
Rectangle temp = new Rectangle(
(int)tempv.X * tilepixel,
(int)tempv.Y * tilepixel,
tilepixel,
tilepixel
);
if (playrec.Intersects(temp))
check = true;
}
}
}
}
return check;
}
Another approach could be to check every tile on the map to see if it collides with the player. This might be a good approach if your map is small, or if each of your levels are a separate map:
public bool CheckBounds()
{
bool check = false;
Rectangle playrec = new Rectangle(
map.ObjectGroups["Objects"].Objects["Player"].X,
map.ObjectGroups["Objects"].Objects["Player"].Y,
map.ObjectGroups["Objects"].Objects["Player"].Width,
map.ObjectGroups["Objects"].Objects["Player"].Height
);
for (int x = 0; x < map.Width; x++)
{
for (int y = 0; y < map.Height; y++)
{
if (collision.GetTile(x,y) != 0)
{
Rectangle tile = new Rectangle(
(int)x * tilepixel,
(int)y * tilepixel,
tilepixel,
tilepixel
);
if (playrec.Intersects(tile))
check = true;
}
}
}
return check;
}
Collectables
Load your map again in Tiled, this time within the objects layer create 3 new objects for the coins. I have created 3 new objects called Coin1 , Coin2 , and Coin 3. I have also set the type to Coin and the height & width of each object to 16 pixels:
Now, click on the Object layer and in the properties panel add a custom property (+ symbol in bottom left corner). Make an integer called Coin_Count:
Texture2D Declarations
We need to declare two Texture2D variables in the declaration section of Game1.cs:
Texture2D coinTexture, blankTexture;
LoadContent
Now we can add the code to load the texture and to apply the texture to each object. We use the Coin_Count custom property to loop through each coin. The naming for the coins use the prefix "Coin_" followed by a number, so we can create the names within the loop:
coinTexture = Content.Load<Texture2D>("Coin");
blankTexture = Content.Load<Texture2D>("Transparent");
int coinCount = Convert.ToInt32(map.ObjectGroups["Objects"].Properties["CoinCount"]);
for (int i = 1; i <= coinCount; i++)
{
map.ObjectGroups["Objects"].Objects["Coin"+i].Texture = coinTexture;
}
A blank texture is required so that it can be used to remove the coin texture once it has been collected. You can use this image for your blank texture:
<--- it is here, remember its transparent.
Now your collectables should be visible when you run your project.
Checking Collectables
Create a new method called CheckCoins, this method will need to accept a rectangle to represent the bounds of the player:
public void CheckCoins(Rectangle player)
{
}
we need to get the number of coins from the Coin_Count property in the map. We can then use this in a for loop. The loop gets the coin from the map, and then creates a rectangle to represent its bounds:
public void CheckCoins(Rectangle player)
{
int coinCount = Convert.ToInt32(map.ObjectGroups["Objects"].Properties["CoinCount"]);
for (int i = 1; i <= coinCount; i++)
{
var coin = map.ObjectGroups[Objects"].Objects["Coin" + i];
Rectangle coinRec = new Rectangle(coin.X, coin.Y, coin.Width, coin.Height);
}
}
Now we have the two rectangles required to check for a collision between the player & the coin. If a collision occurs the code writes the output to the console and sets the texture of the coin to the blank texture.
public void CheckCoins(Rectangle player)
{
int coinCount = Convert.ToInt32(map.ObjectGroups["Objects"].Properties["CoinCount"]);
for (int i = 1; i <= coinCount; i++)
{
var coin = map.ObjectGroups["Objects"].Objects["Coin" + i];
Rectangle coinRec = new Rectangle(coin.X, coin.Y, coin.Width, coin.Height);
if (player.Intersects(coinRec))
{
coin.Texture = blankTexure;
}
}
}
Now add the code to run CheckCoins in the Update method of Game1.cs, This gets the player, creates a rectangle for the player, and then pass this rectangle to CheckCoins:
var p = map.ObjectGroups["Objects"].Objects["Player"];
Rectangle playerRec = new Rectangle(p.X, p.Y, p.Width, p.Height);
CheckCoins(playerRec);
You should now be able to collide with the coins, and they will then dissappear.
CheckCoin Improvements
The CheckCoin method should ignore coins with a texture set to the blankTexture so:
public void CheckCoins(Rectangle player)
{
int coinCount = Convert.ToInt32(map.ObjectGroups["Objects"].Properties["CoinCount"]);
for (int i = 1; i <= coinCount; i++)
{
var coin = map.ObjectGroups["Objects"].Objects["Coin" + i];
if (coin.Texture != blankTexture)
{
Rectangle coinRec = new Rectangle(coin.X, coin.Y, coin.Width, coin.Height);
if (player.Intersects(coinRec))
{
coin.Texture = blankTexture;
}
}
}
}
Key & Door
Edit your tiled map by adding a key object into the objects layer, and also place a door object in your main layer which represents your door:
We will need to add another Texture2D to the declaration section, so:
Texture2D blankTexture, coinTexture;
becomes:
Texture2D blankTexture, coinTexture, keyTexture, doorTexture;
In the LoadContent method we will need to load in the keyTexture:
keyTexture = Content.Load<Texture2D>("Key");
doorTexture = Content.Load<Texture2D>("Door");
Now in the CheckCoins method, we will change the code so that collecting the coins will give you the key. We need to create a new integer to count the number of keys collected. We can do this by adding the else onto the existing if statement in CheckCoins:
public void CheckCoins(Rectangle player)
{
int coinCount = Convert.ToInt32(map.ObjectGroups["Objects"].Properties["CoinCount"]);
int collectCount = 0;
for (int i = 1; i <= coinCount; i++)
{
var coin = map.ObjectGroups["Objects"].Objects["Coin" + i];
if (coin.Texture != blankTexture)
{
Rectangle coinRec = new Rectangle(coin.X, coin.Y, coin.Width, coin.Height);
if (player.Intersects(coinRec))
{
Console.WriteLine("collision - " + i);
coin.Texture = blankTexture;
}
}
else
{
collectCount++;
}
}
}
Finally if the coins have been collected we can display the key:
public void CheckCoins(Rectangle player)
{
int coinCount = Convert.ToInt32(map.ObjectGroups["Objects"].Properties["CoinCount"]);
int collectCount = 0;
for (int i = 1; i <= coinCount; i++)
{
var coin = map.ObjectGroups["Objects"].Objects["Coin" + i];
if (coin.Texture != blankTexture)
{
Rectangle coinRec = new Rectangle(coin.X, coin.Y, coin.Width, coin.Height);
if (player.Intersects(coinRec))
{
Console.WriteLine("collision - " + i);
coin.Texture = blankTexture;
}
}
else
{
collectCount++;
}
}
var key = map.ObjectGroups["Objects"].Objects["Key"].Texture;
if (collectCount == coinCount && key !=blankTexture)
map.ObjectGroups["Objects"].Objects["Key"].Texture = keyTexture;
}
Check Collision for Key
We need to create a method called CheckKey, this should accept a rectangle to represent the player bounds. This method gets the key object from the map and checks if the texture applied is the keyTexture (this will mean it has been drawn to the screen, other wise it will be empty or the blankTexture). The method creates a rectangle to represent the bounds of the key and then finally checks if the player intersects this rectangle:
public void CheckKey(Rectangle player)
{
var key = map.ObjectGroups["Objects"].Objects["Key"];
if (key.Texture == keyTexture)
{
Rectangle keyRec = new Rectangle(key.X, key.Y, key.Width, key.Height);
if (player.Intersects(keyRec))
{
}
}
Now we have detected the collision we need to program what to do. The code below will apply the doorTexture to the door object, and set the key texture to the blankTexture:
public void CheckKey(Rectangle player)
{
var key = map.ObjectGroups["Objects"].Objects["Key"];
if (key.Texture == keyTexture)
{
Rectangle keyRec = new Rectangle(key.X, key.Y, key.Width, key.Height);
if (player.Intersects(keyRec))
{
map.ObjectGroups["Objects"].Objects["Door"].Texture = doorTexture;
map.ObjectGroups["Objects"].Objects["Key"].Texture = blankTexture;
}
}
Finally we need to add CheckKey to the update method, i have added the code below after the CheckCoin(playerRec) line:
CheckKey(playerRec);
Check Collision for Door
We need to create a method called CheckDoor, this should accept a rectangle to represent the player bounds. This method gets the door object from the map and checks if the texture applied is the doorTexture (this will mean it has been drawn to the screen, other wise it will be empty or the blankTexture). The method creates a rectangle to represent the bounds of the door and then finally checks if the player intersects this rectangle:
public void CheckDoor(Rectangle player)
{
var door = map.ObjectGroups["Objects"].Objects["Door"];
if (door.Texture == doorTexture)
{
Rectangle doorRec = new Rectangle(door.X, door.Y, door.Width, door.Height);
if (player.Intersects(doorRec))
{
Console.WriteLine("door collision, do something");
}
}
Now we have detected the collision we need to program what to do. Your game could set the current state of the game, or it could add the item to an inventory list, or it could display a message.
Finally we need to add CheckDoor to the update method, i have added the code below after the CheckKey(playerRec) line:
CheckDoor(playerRec);