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:


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);
}
}
}
view raw Game1.cs hosted with ❤ by GitHub
/*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();
}
}
}
view raw player.cs hosted with ❤ by GitHub

Comments

Popular posts from this blog

Introduction

Loading the tile map