Archived

This topic is now archived and is closed to further replies.

collision detection with a 2d tile map?

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

If you intended to correct an error in the post then please contact us.

Recommended Posts

hi. i am trying to implement some sort of collision detection for my little tile map using opengl. However it doesn''t want to work for me! at the moment i am just testing the right movement of a quad and it goes over to the right off my map by 2 or 3 tiles before stopping. Here is my rendering and keyboard checking stuff. Maybe someone could help me out ??
  
#define NUMBER_OF_ANIMATIONS 4

using namespace std;
extern Texture texture[3];
extern int mapdata[28][25];

double playerx = -15.0;
double playery = 11.0;
int playerposx = 1;
int playerposy = 1;

float plyx = 0;
float plyy = 0;

double current_anim = 1;

int DrawMap()
{
	//glPolygonMode(GL_FRONT_AND_BACK,GL_LINE);

	glDisable(GL_ALPHA_TEST);
	for (int x=0;x < 28;x++)
		{
		for (int y=0;y<25;y++)
			{
			glLoadIdentity();
			glTranslatef(-16.0f+x,12.0f-y,-30.0f);			
			glBindTexture(GL_TEXTURE_2D, texture[(mapdata[x][y])].texID);
			glBegin(GL_QUADS);
				glTexCoord2d(0.0,1.0);
				glVertex3f(-0.5f, 0.5f, 0.0f);
				glTexCoord2d(1.0,1.0);
				glVertex3f(0.5f, 0.5f, 0.0f);
				glTexCoord2d(1.0,0.0);
				glVertex3f(0.5f, -0.5f, 0.0f);
				glTexCoord2d(0.0,0.0);
				glVertex3f(-0.5f, -0.5f, 0.0f);
			glEnd();
			}
		}
	glEnable(GL_ALPHA_TEST);
return true;
}

int DrawPlayer(double anim)
{
			// need to add player x and y pos to translatef command

			// also need to incorporate the anim in the function header

			// aswell as the timer.

	//	angle += (float)(milliseconds) / 5.0f;						// Update angle Based On The Clock


			glLoadIdentity();
			glTranslatef(playerx,playery,-30.0f);			
			glBindTexture(GL_TEXTURE_2D,texture[2].texID);

			float sprite = (anim/NUMBER_OF_ANIMATIONS);
			float sprite2 = sprite-(0.25);

			glBegin(GL_QUADS);
				glTexCoord2d(0.0,1.0-sprite2);
				glVertex3f(-0.5f, 0.5f, 0.0f);
				glTexCoord2d(1.0,1.0-sprite2);
				glVertex3f(0.5f, 0.5f, 0.0f);
				glTexCoord2d(1.0,1.0-sprite);
				glVertex3f(0.5f, -0.5f, 0.0f);
				glTexCoord2d(0.0,1.0-sprite);
				glVertex3f(-0.5f, -0.5f, 0.0f);
			glEnd();

return true;
}

int DrawGLScene(GLvoid)								// Here''s Where We Do All The Drawing

{
	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);			// Clear The Screen And The Depth Buffer

	glLoadIdentity();							// Reset The Current Modelview Matrix


	DrawMap();
	DrawPlayer(current_anim);


	return true;								// Everything Went OK



}

int MoveAi()
{
return true;
}

int CheckKeyboardInput(DWORD milliseconds)
{
	double werd = (milliseconds*0.001);
		
	if (keys[VK_ESCAPE])				// Was ESC Pressed?

	{
		done=TRUE;				// ESC Signalled A Quit

	}
	if (keys[VK_F1])					// Is F1 Being Pressed?

	{
		keys[VK_F1]=FALSE;				// If So Make Key FALSE

		KillGLWindow();					// Kill Our Current Window

		fullscreen=!fullscreen;				// Toggle Fullscreen / Windowed Mode

		// Recreate Our OpenGL Window

		if (!CreateGLWindow("Opengl Basecode v0.25",SCREENWIDTH,SCREENHEIGHT,BITSPERPIXEL,fullscreen))
		{
			return 0;				// Quit If Window Was Not Created

		}
	}
	if (keys[VK_LEFT])
	{
	//	keys[VK_LEFT] = false;

		//playerx -= (float) (milliseconds) / 200.0f;

		playerx -= (float) (werd) *5;
		current_anim = 4;
	}
	if (keys[VK_RIGHT])
	{
	//	keys[VK_RIGHT] = false;

		//playerx += (float) (milliseconds) / 200.0f;

		playerx += (werd) *5;
		current_anim = 3;
		plyx += (werd) *5;
		if (mapdata[playerposx][playerposy] == 0)
			{
			playerx -= (werd) *5;
			current_anim = 3;
			plyx -= (werd) *5;
			}
			
		if  (plyx >=1.0f)
			{
			plyx = 0.0f;
			playerposx++;
			}
		
	}
	if (keys[VK_UP])
	{
		//keys[VK_UP] = false;

		//playerx -= (float) (milliseconds) / 200.0f;

		playery += (float) (werd) *5;
		current_anim = 4;
	}
	if (keys[VK_DOWN])
	{
	//	keys[VK_DOWN] = false;

		//playerx += (float) (milliseconds) / 200.0f;

		playery -= (float) (werd) *5;
		current_anim = 3;
	}

return true;
}

void Update (DWORD milliseconds)								// Perform Motion Updates Here

{
	CheckKeyboardInput(milliseconds);
	MoveAi();
	DrawGLScene();
//	angle += (float)(milliseconds) / 5.0f;						// Update angle Based On The Clock

}

  

Share this post


Link to post
Share on other sites
ok i have managed to get some sort of collision detection happenning but its not perfect. sometimes i can move left and i walk right through the wall if i am not right in line with it, and i can''t fit through some small gaps!

here is my revised drawing and keyboard input functions


  
#define NUMBER_OF_ANIMATIONS 4

using namespace std;
extern Texture texture[3];
extern int mapdata[28][25];

double playerx = -15.0;
double playery = 11.0;

double county = 1;
double countx = 1;

double current_anim = 1;

int DrawMap()
{
glDisable(GL_ALPHA_TEST);
for (int x=0;x < 28;x++)
{
for (int y=0;y<25;y++)
{
glLoadIdentity();
glTranslatef(-16.0f+x,12.0f-y,-30.0f);
glBindTexture(GL_TEXTURE_2D, texture[(mapdata[x][y])].texID);
glBegin(GL_QUADS);
glTexCoord2d(0.0,1.0);
glVertex3f(-0.5f, 0.5f, 0.0f);
glTexCoord2d(1.0,1.0);
glVertex3f(0.5f, 0.5f, 0.0f);
glTexCoord2d(1.0,0.0);
glVertex3f(0.5f, -0.5f, 0.0f);
glTexCoord2d(0.0,0.0);
glVertex3f(-0.5f, -0.5f, 0.0f);
glEnd();
}
}
glEnable(GL_ALPHA_TEST);
return true;
}

int DrawPlayer(double anim)
{
glLoadIdentity();
glTranslatef(playerx,playery,-30.0f);
glBindTexture(GL_TEXTURE_2D,texture[2].texID);

float sprite = (anim/NUMBER_OF_ANIMATIONS);
float sprite2 = sprite-(0.25);

glBegin(GL_QUADS);
glTexCoord2d(0.0,1.0-sprite2);
glVertex3f(-0.5f, 0.5f, 0.0f);
glTexCoord2d(1.0,1.0-sprite2);
glVertex3f(0.5f, 0.5f, 0.0f);
glTexCoord2d(1.0,1.0-sprite);
glVertex3f(0.5f, -0.5f, 0.0f);
glTexCoord2d(0.0,1.0-sprite);
glVertex3f(-0.5f, -0.5f, 0.0f);
glEnd();

return true;
}

int DrawGLScene(GLvoid) // Here''s Where We Do All The Drawing

{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // Clear The Screen And The Depth Buffer

glLoadIdentity(); // Reset The Current Modelview Matrix


DrawMap();
DrawPlayer(current_anim);


return true; // Everything Went OK



}

int MoveAi()
{
return true;
}

int CheckKeyboardInput(DWORD milliseconds)
{
double werd = (milliseconds*0.001);

if (keys[VK_ESCAPE]) // Was ESC Pressed?

{
done=TRUE; // ESC Signalled A Quit

}
if (keys[VK_F1]) // Is F1 Being Pressed?

{
keys[VK_F1]=FALSE; // If So Make Key FALSE

KillGLWindow(); // Kill Our Current Window

fullscreen=!fullscreen; // Toggle Fullscreen / Windowed Mode

// Recreate Our OpenGL Window

if (!CreateGLWindow("Opengl Basecode v0.25",SCREENWIDTH,SCREENHEIGHT,BITSPERPIXEL,fullscreen))
{
return 0; // Quit If Window Was Not Created

}
}
if (keys[VK_LEFT])
{

playerx -= .1;
current_anim = 4;
countx-=.1;
if ( (mapdata[(int)countx][(int)county] == 0) )
{
playerx += 0.1;
countx+=.1;
}
}
if (keys[VK_RIGHT])
{
playerx += 0.1;
current_anim = 3;
countx+=0.1;
if ( (mapdata[(int)countx][(int)county] == 0) || (mapdata[(int)countx+1][(int)county] == 0))
{
playerx -= 0.1;
countx-=.1;
}
}
if (keys[VK_UP])
{
playery += .1;
current_anim = 2;
county-=.1;
if ( mapdata[(int)countx][(int)county] == 0)
{
playery -= .1;
county+=.1;
}
}
if (keys[VK_DOWN])
{
playery -= .1;
current_anim = 1;
county+=.1;
if ( (mapdata[(int)countx][(int)county] == 0) || (mapdata[(int)countx][(int)county+1] == 0))
{
playery += .1;
county-=.1;
}
}

return true;
}

void Update (DWORD milliseconds) // Perform Motion Updates Here

{
CheckKeyboardInput(milliseconds);
MoveAi();
DrawGLScene();
}



And if u would like the complete program go here http://werdy666.20megsfree.com

Share this post


Link to post
Share on other sites
Im, not exactly sure about this sort of game, never spent too much time thinking tile based, but I had a similar broblem with a tetris clone i was making.

Firstly are u sure u need to be using an OR clause in the collision check? I assume the code says, "if the tile im on is clear OR the next tile is clear, then walk...". I would have thought that you would only want to move if the tile your on AND the next tile were clear.

The way I managed to get round this was, to slice the space up into squares (your tiles) and then decide which square the player co-ords were in. Looking at ur code I think u shouldn''t rely on the conversion of float to int to convert from point to square... calculate it ur self. Id be more help but I can''t look at my own code now, and that was years ago...

Share this post


Link to post
Share on other sites
Thanks for your input TheSyan.

The main reason for the OR instead of AND is that cause i only move my player 0.1 at a time, if i was moving left and had just moved into the last tile before a wall, wouldn''t it stop me straight away without allowing me to move right up against the wall? But it is something i will put more thought into.

I am a beginner, so could you maybe give me some hints or point me to a website that will help me understand converting a float such as 1.245 to an int?

again thanks for your input!




Werdy666

My Homepage : http://werdy666.20megsfree.com/

Share this post


Link to post
Share on other sites
Ok... the conversion method... there''s no garentee this is correct, its all from memory...

U know the size of your tile grid, say 100.0f gl co-ordinates square, and your player co-ords, say for example ( 20.3f, 10.2f ). Oh and your tile size, Ill say 10.0f by 10.0f.

So you start by finding the player co-ords relative to the grid, say the grids 0,0 cell starts at gl(10.0f,0.0f,0.0f). The player co-ords relative would be ( 10.3f, 10.2f ).

Then you round up/down the player co-ords to the nearest integer. Theres a function somewhere in the C++ math libs, look in the help files for that. It goes something like,


int player_tile_x = rounddown( player_x );
int player_tile_y = rounddown( player_y );
[CODE]

This gives you a player tile of (10, 10) if u round down. Whether you round up or down, I think changes whether the player_tile_ values start from 0 or 1...

Example:

|0 | 1 | 2 | 3 | ...
-----|---|---|---| ...
0 | | | | | ...
-----|---|---|---| ...
1 | | | | | ...
-----|---|---|---| ...
2 | | | | | ...
-----|---|---|---| ...
3 | | | P | | ...
-----|---|---|---| ...

Now u can use these co-ords to check against your tile grid (but get the start point right or u end up going off the grid''n''stuff).

That was a bit messy and I confused my self halfway throught writing, when I get home, If you still have problems ill look at my code and post some of my solutions...

Share this post


Link to post
Share on other sites
I havn''t been able to find the rounding down method in the msdn for c++. So any extra info u can provide would be great!

My only other idea was to increase the size of my map array. So like if i move 10 points to go from 1 tile to the next, then increase the array 10x to [280][250] and basically fill in the first tile by filling the array 10 times instead of 1. so like when i have my original array of [28][25] the first array would be [0][0] would say equal 1, where as with the new [280][250] from [0][0] to [9][0] would all equal 1. Would this work too? but it does take quite a bit of extra memory!

Thanks for helping me TheSyan!



Werdy666

My Homepage : http://werdy666.20megsfree.com/

Share this post


Link to post
Share on other sites