# [Solved]Tile Based Collision Detection

This topic is 4100 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

## Recommended Posts

I have a tile based game that im making. The dimensions are 25*16 tiles. Each tile is 32*32 pixels. My character can move to any position(he isnt forced to be in one tile at a a time). He can also jump up(3 tiles high and 5 tiles far). So now ive got my level editor working i need to add collision detection to the game. I can easily get the position and direction of the character(eg Left right up down...) Ive been battling for hours and i really need help. Any links to tutorials or examples will be greatly appreciated! Thanks [Edited by - hahaha on September 28, 2007 9:04:04 AM]

##### Share on other sites
Jump & Run Dev has a good article on tiles in platformers.

##### Share on other sites
Hi,

I battled with this one when I first started out. It's not that complex (surprisingly). Anyways, what you need to do is separate the axis for the player i.e. y and x and check for collisions in those axis alone. For example check the y-axis for a collision first then check the x-axis (but don't do both!) and respond to the collision accordingly. That should be all you need to know.

Good Luck :)

mameman

##### Share on other sites
thanks for the link and the help!
So this is what ive come up with so far to test for collisions and its not working
//CScreen.h#ifndef CSCREEN_H#define CSCREEN_H#include "Main.h"#include "CEntity.h"struct sTile{	bool Transparent;	int Type;};struct sScreen{	CEntity Tiles[25][16];};class CScreen{private:	std::vector<sScreen> m_Screens;	int m_iActiveScreen;	int m_iNumScreens;	int m_iColX[25];	int m_iColY[16];public:	CScreen();	virtual ~CScreen();	bool LoadMap(char *Filename);	void Render();	bool CanMove(sEntityPos Pos,eEntityDirection Direction);};#endif//CScreen.cpp#include "CScreen.h"#include "CPlayer.h"extern CPlayer g_Player;using namespace std;CScreen::CScreen(){	m_iActiveScreen = 0;	m_iNumScreens = 0;	for(int i=0;i<25;i++)	{		m_iColX = i*32;	}	for(int i=15;i!=-1;i--)	{		m_iColY = i*32+44;	}}CScreen::~CScreen(){}bool CScreen::LoadMap(char *Filename){	//Clear Vector of screens	m_Screens.clear();	//Open File for reading	ifstream In(Filename,ios::binary);	if(In.is_open() == false)return false;	//Read the amount of screens	In.read((char *)&m_iNumScreens,sizeof(int));	//Read all tile data	for(int a=0;a<m_iNumScreens;a++)	{		sScreen Screen;		for(int i=0;i<25;i++)		{			for(int b=15;b!=-1;b--)			{				sTile Tile;				In.read((char *)&Tile,sizeof(sTile));				sEntityPos Pos((float)i*32,(float)(b*32)+44);				CEntity Entity;				Entity.SetEntityPos(Pos);				if(Tile.Type == 0) //Blue Brick				{					Entity.SetEntityColor(E_BLUE);					Entity.SetEntityType(E_BRICK);					Entity.SetBaseEntityType(E_COLLIDABLE);				}				else if(Tile.Type == 1) //Blue Diamond				{					Entity.SetEntityColor(E_BLUE);					Entity.SetEntityType(E_DIAMOND);					Entity.SetBaseEntityType(E_COLLECTABLE);				}				else if(Tile.Type == 2) //Blue Platform				{					Entity.SetEntityColor(E_BLUE);					Entity.SetEntityType(E_PLATFORM);					Entity.SetBaseEntityType(E_COLLIDABLE);				}				else if(Tile.Type == 3) //Blue Sphere				{					Entity.SetEntityColor(E_BLUE);					Entity.SetEntityType(E_SPHERE);					Entity.SetBaseEntityType(E_COLLECTABLE);				}				else if(Tile.Type == 4) //Box				{					Entity.SetEntityType(E_BOX);					Entity.SetBaseEntityType(E_COLLIDABLE);				}				else if(Tile.Type == 5) //Crown				{					Entity.SetEntityType(E_CROWN);					Entity.SetBaseEntityType(E_COLLECTABLE);				}				else if(Tile.Type == 6) //Dirt				{					Entity.SetEntityType(E_DIRT);					Entity.SetBaseEntityType(E_COLLIDABLE);				}				else if(Tile.Type == 7) //Door				{					Entity.SetEntityType(E_DOOR);					Entity.SetBaseEntityType(E_OTHER);				}				else if(Tile.Type == 8) // Empty				{					Entity.SetEntityType(E_EMPTY);					Entity.SetBaseEntityType(E_OTHER);				}				else if(Tile.Type == 9) // Fire				{					Entity.SetEntityType(E_FIRE);					Entity.SetBaseEntityType(E_KILLABLE);				}				else if(Tile.Type == 10) //Grass				{					Entity.SetEntityType(E_GRASS);					Entity.SetBaseEntityType(E_COLLIDABLE);				}				else if(Tile.Type == 11) // Ladder				{					Entity.SetEntityType(E_LADDER);					Entity.SetBaseEntityType(E_OTHER);				}				else if(Tile.Type == 12) // Lava				{					Entity.SetEntityType(E_LAVA);					Entity.SetBaseEntityType(E_KILLABLE);				}				else if(Tile.Type == 13) // Mg				{					Entity.SetEntityType(E_MG);					Entity.SetBaseEntityType(E_OTHER);				}				else if(Tile.Type == 14) // Mud				{					Entity.SetEntityType(E_MUD);					Entity.SetBaseEntityType(E_KILLABLE);				}				else if(Tile.Type == 15) // Pistol				{					Entity.SetEntityType(E_PISTOL);					Entity.SetBaseEntityType(E_OTHER);				}				else if(Tile.Type == 16) //Pole				{					Entity.SetEntityType(E_POLE);					Entity.SetBaseEntityType(E_COLLECTABLE);				}				else if(Tile.Type == 17) //Purple Diamond				{					Entity.SetEntityColor(E_PURPLE);					Entity.SetEntityType(E_DIAMOND);					Entity.SetBaseEntityType(E_COLLECTABLE);				}				else if(Tile.Type == 18) //Purple Platform				{					Entity.SetEntityColor(E_PURPLE);					Entity.SetEntityType(E_PLATFORM);					Entity.SetBaseEntityType(E_COLLIDABLE);				}				else if(Tile.Type == 19) //Purple Sphere				{					Entity.SetEntityColor(E_PURPLE);					Entity.SetEntityType(E_SPHERE);					Entity.SetBaseEntityType(E_COLLECTABLE);				}				else if(Tile.Type == 20) //Red Brick				{					Entity.SetEntityColor(E_RED);					Entity.SetEntityType(E_BRICK);					Entity.SetBaseEntityType(E_COLLIDABLE);				}				else if(Tile.Type == 21) //Red Diamond				{					Entity.SetEntityColor(E_RED);					Entity.SetEntityType(E_DIAMOND);					Entity.SetBaseEntityType(E_COLLECTABLE);				}				else if(Tile.Type == 22) //Red Platform				{					Entity.SetEntityColor(E_RED);					Entity.SetEntityType(E_PLATFORM);					Entity.SetBaseEntityType(E_COLLIDABLE);				}				else if(Tile.Type == 23) //Red Sphere				{					Entity.SetEntityColor(E_RED);					Entity.SetEntityType(E_SPHERE);					Entity.SetBaseEntityType(E_COLLECTABLE);				}				else if(Tile.Type == 24) // Reed				{					Entity.SetEntityType(E_REED);					Entity.SetBaseEntityType(E_KILLABLE);				}				else if(Tile.Type == 25) //Sand				{					Entity.SetEntityType(E_SAND);					Entity.SetBaseEntityType(E_COLLIDABLE);				}				else if(Tile.Type == 26) // Smg				{					Entity.SetEntityType(E_SMG);					Entity.SetBaseEntityType(E_OTHER);				}				else if(Tile.Type == 27) // Spikes				{					Entity.SetEntityType(E_SPIKE);					Entity.SetBaseEntityType(E_KILLABLE);				}				else if(Tile.Type == 28) // Start Point				{					Entity.SetEntityType(E_EMPTY);					Entity.SetBaseEntityType(E_OTHER);					Pos.x+=3;					g_Player.SetPos(Pos);				}				else if(Tile.Type == 29) // Water				{					Entity.SetEntityType(E_WATER);					Entity.SetBaseEntityType(E_KILLABLE);				}				else if(Tile.Type == 30) //Weed				{					Entity.SetEntityType(E_WEED);					Entity.SetBaseEntityType(E_COLLECTABLE);				}				Screen.Tiles = Entity;			}		}		m_Screens.push_back(Screen);	}	return true;}void CScreen::Render(){	for(int i=0;i<25;i++)	{		for(int a=0;a<16;a++)		{			m_Screens[m_iActiveScreen].Tiles[a].UpdateAndRender();		}	}}bool CScreen::CanMove(sEntityPos Pos,eEntityDirection Direction){	int PlayerColX = 0;	int PlayerColY = 0;	for(int i=0;i<25;i++)	{		if(Pos.x > m_iColX && Pos.x < m_iColX[i+1]+32)		{			PlayerColX = i;		}	}	for(int i=0;i<16;i++)	{		if(Pos.y >= m_iColY)		{			PlayerColY = i;		}	}		sEntityPos      EntityPos;	eEntityBaseType BaseType;	switch(Direction)	{	case E_LEFT:		BaseType = m_Screens[m_iActiveScreen].Tiles[PlayerColX-1][PlayerColY].GetBaseEntityType();		if(BaseType == E_COLLIDABLE)		{			EntityPos = m_Screens[m_iActiveScreen].Tiles[PlayerColX-1][PlayerColY].GetEntityPos();			if(Pos.x-3 < EntityPos.x+32)return false;		}		break;	case E_RIGHT:		BaseType = m_Screens[m_iActiveScreen].Tiles[PlayerColX+1][PlayerColY].GetBaseEntityType();		if(BaseType == E_COLLIDABLE)		{			EntityPos = m_Screens[m_iActiveScreen].Tiles[PlayerColX+1][PlayerColY].GetEntityPos();			if(Pos.x+35 > EntityPos.x)return false;		}		break;	case E_UP:		BaseType = m_Screens[m_iActiveScreen].Tiles[PlayerColX][PlayerColY+1].GetBaseEntityType();		if(BaseType == E_COLLIDABLE)		{			EntityPos = m_Screens[m_iActiveScreen].Tiles[PlayerColX][PlayerColY+1].GetEntityPos();			if(Pos.y+35 >= EntityPos.y)return false;		}		break;	case E_DOWN:		BaseType = m_Screens[m_iActiveScreen].Tiles[PlayerColX][PlayerColY-1].GetBaseEntityType();		if(BaseType == E_COLLIDABLE)		{			EntityPos = m_Screens[m_iActiveScreen].Tiles[PlayerColX][PlayerColY-1].GetEntityPos();			if(Pos.y-3 <= EntityPos.y)return false;		}		break;	};	return true;}

this is what my players update function is doing
void CPlayer::Update(){	if(m_bLButtonUp == false)	{		m_Direction = E_LEFT;		if(g_Screen.CanMove(m_Pos,m_Direction) == true)		{			m_Pos.x -= 2.5f;		}	}	else if(m_bRButtonUp == false)	{		m_Direction = E_RIGHT;		if(g_Screen.CanMove(m_Pos,m_Direction) == true)		{			m_Pos.x += 2.5f;		}	}	if(m_bUButtonUp == false)m_bJumping = true;	if(m_bJumping == true)	{		if(m_bReverse == false)		{			m_Direction = E_UP;			if(g_Screen.CanMove(m_Pos,m_Direction) == true)			{				m_Pos.y += 3;			}		}		else		{			m_Direction = E_DOWN;			if(g_Screen.CanMove(m_Pos,m_Direction) == true)			{				m_Pos.y -= 3;			}		}		m_iElapsedJump++;		if(m_iElapsedJump == 32)		{			m_bReverse = true;		}		else if(m_iElapsedJump == 64)		{			m_iElapsedJump = 0;			m_bReverse = false;			m_bJumping = false;		}	}	g_Renderer->BindTexture(g_TextureManager.Weed);	g_Renderer->DrawSquare(m_Pos.x,m_Pos.y);}

The collision on the x axis seems to be working except for when i jump. The y axis collision doesnt work. Sometimes on both the x and the y axis when it does seem to work my player seems to be about 2 or 3 pixels into the tile where it was supposed to stop.

Heres a link to the full game source and a built binary to see whats going on (868Kb)

I know this is a lot to go through but i would really appreciate it someone could help me.

Thanks

##### Share on other sites
Thanks for the links they were quite useful! I solved it by calculating which column and row i was in and seeing if i could move before i moved

1. 1
2. 2
Rutin
19
3. 3
khawk
18
4. 4
5. 5
A4L
11

• 9
• 12
• 16
• 26
• 10
• ### Forum Statistics

• Total Topics
633769
• Total Posts
3013754
×