Tile map collisions
Tile map collisions:
In the previous part we finished up our tile map loader class.
In this one we will be finishing up the tilemap collisions.
Want a video version?
The implementation:
For the implementation of the tilemap I have used the object layer functionality of the Tiled editor.
An object layer allows us to create shapes like rectangle(which we will be using for our collisions),
polygons, etc.
The rectangles created by us are they passed on into a list of rectangles from which we can then check
if our player is colliding with one of them.
The Code:
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using Microsoft.Xna.Framework; | |
using Microsoft.Xna.Framework.Graphics; | |
using Microsoft.Xna.Framework.Input; | |
using MonoGame.Extended.Serialization; | |
using MonoGame.Extended.Sprites; | |
using MonoGame.Extended.Content; | |
using TiledSharp; | |
using System.Collections.Generic; | |
namespace RPG_1 | |
{ | |
public class Game1 : Game | |
{ | |
private GraphicsDeviceManager _graphics; | |
private SpriteBatch _spriteBatch; | |
private Player player; | |
private TmxMap map; | |
private TileMapManager mapManager; | |
private List<Rectangle> collisionObjects;//Creating a list of rectangles | |
public Game1() | |
{ | |
_graphics = new GraphicsDeviceManager(this); | |
Content.RootDirectory = "Content"; | |
IsMouseVisible = true; | |
} | |
protected override void Initialize() | |
{ | |
// TODO: Add your initialization logic here | |
player = new Player(); | |
base.Initialize(); | |
} | |
protected override void LoadContent() | |
{ | |
_spriteBatch = new SpriteBatch(GraphicsDevice); | |
//Tile map loader start | |
map = new TmxMap("Content/map.tmx"); | |
var tileset = Content.Load<Texture2D>("Tiny Adventure Pack/"+map.Tilesets[0].Name.ToString()); | |
var tileWidth = map.Tilesets[0].TileWidth; | |
var tileHeight = map.Tilesets[0].TileHeight; | |
var TileSetTilesWide = tileset.Width / tileWidth; | |
mapManager = new TileMapManager(_spriteBatch,map,tileset,TileSetTilesWide,tileWidth,tileHeight); | |
//Tile map loader END | |
//Init Collision Area START | |
collisionObjects = new List<Rectangle>();//Initializing the list | |
foreach(var o in map.ObjectGroups["Collisions"].Objects)//Looping through all the rectangles in the Object layer named Collisions | |
{ | |
collisionObjects.Add(new Rectangle((int)o.X,(int)o.Y,(int)o.Width,(int)o.Height));//Adding the rectangles to the list | |
} | |
//Init Collision Area END | |
SpriteSheet[] sheets = { Content.Load<SpriteSheet>("Tiny Adventure Pack/Character/char_two/Idle/playerSheetIdle.sf",new JsonContentLoader()), | |
Content.Load<SpriteSheet>("Tiny Adventure Pack/Character/char_two/Walk/playerSheetWalk.sf",new JsonContentLoader())}; | |
player.Load(sheets); | |
// TODO: use this.Content to load your game content here | |
} | |
protected override void Update(GameTime gameTime) | |
{ | |
if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed || Keyboard.GetState().IsKeyDown(Keys.Escape)) | |
Exit(); | |
var initpos = player.pos; | |
player.Update(gameTime); | |
//collision Check code START | |
foreach(var rect in collisionObjects)//Looping through the rectangles in our list | |
{ | |
if(rect.Intersects(player.playerBounds))//Check if the player is colliding | |
{ | |
player.pos = initpos; | |
player.isIdle = true; | |
} | |
} | |
//Collision code End | |
// TODO: Add your update logic here | |
base.Update(gameTime); | |
} | |
protected override void Draw(GameTime gameTime) | |
{ | |
GraphicsDevice.Clear(Color.CornflowerBlue); | |
mapManager.Draw(); | |
player.Draw(_spriteBatch); | |
// TODO: Add your drawing code here | |
base.Draw(gameTime); | |
} | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/*Note: | |
In the player.cs class you will need to add | |
public Rectangle playerBounds; | |
and then in the update | |
change the x and y to the current position | |
Hence the full code will become like this: | |
*/ | |
using Microsoft.Xna.Framework; | |
using Microsoft.Xna.Framework.Graphics; | |
using Microsoft.Xna.Framework.Input; | |
using MonoGame.Extended.Sprites; | |
using System; | |
using System.Collections.Generic; | |
using System.Text; | |
namespace RPG_1 | |
{ | |
public class Player | |
{ | |
public Vector2 pos; | |
private AnimatedSprite[] playerSprite; | |
private SpriteSheet sheet; | |
private float moveSpeed = 1.5f; | |
public Rectangle playerBounds;//Create the player bounds | |
public bool isIdle=false; | |
public Player() | |
{ | |
playerSprite = new AnimatedSprite[10]; | |
pos = new Vector2(100, 50); | |
playerBounds = new Rectangle((int)pos.X-8/*centered at centre*/,(int)pos.Y-8,16,17);//Initialize the rectangle | |
} | |
public void Load(SpriteSheet[] spriteSheets) | |
{ | |
for (int i =0; i<spriteSheets.Length;i++) | |
{ | |
sheet = spriteSheets[i]; | |
playerSprite[i] = new AnimatedSprite(sheet); | |
} | |
} | |
public void Update(GameTime gameTime) | |
{ | |
isIdle = true; | |
playerSprite[0].Play("idleDown"); | |
string animation = ""; | |
var keyboardstate = Keyboard.GetState(); | |
if(keyboardstate.IsKeyDown(Keys.D))//Move right | |
{ | |
animation = "walkRight"; | |
pos.X += moveSpeed; | |
isIdle = false; | |
} | |
if (keyboardstate.IsKeyDown(Keys.A))//Move right | |
{ | |
animation = "walkLeft"; | |
pos.X -= moveSpeed; | |
isIdle = false; | |
} | |
if (keyboardstate.IsKeyDown(Keys.W))//Move right | |
{ | |
animation = "walkUp"; | |
pos.Y -= moveSpeed; | |
isIdle = false; | |
} | |
if (keyboardstate.IsKeyDown(Keys.S))//Move right | |
{ | |
animation = "walkDown"; | |
pos.Y += moveSpeed; | |
isIdle = false; | |
} | |
if (!isIdle) | |
{ | |
playerSprite[1].Play(animation); | |
playerSprite[1].Update(gameTime); | |
} | |
//Update the player bounds | |
playerBounds.X = (int)pos.X-8;//Apparently by default the rectangle gets centred at the player's centre when using monogame extended's draw function. | |
playerBounds.Y = (int)pos.Y-8; | |
playerSprite[0].Update(gameTime); | |
} | |
public void Draw(SpriteBatch spriteBatch) | |
{ | |
spriteBatch.Begin(); | |
if (isIdle) | |
spriteBatch.Draw(playerSprite[0], pos); | |
else | |
spriteBatch.Draw(playerSprite[1], pos); | |
spriteBatch.End(); | |
} | |
} | |
} |
Comments
Post a Comment