Jump to content
  • Advertisement
Sign in to follow this  
Hannibal111111

collision detection

This topic is 4697 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

I'm working on a pacman clone but having some problems with collision detection between pacman and the walls. I will post the code I have below. Currently, it will work fine as long as I don't turn the speed of pacman up to much, then it he has trouble moving around. Thanks, Han

void HandleGameInput() 
{
	static bool moving_up = false;
	static bool moving_down = false;
	static bool moving_left = false;
	static bool moving_right = false;

	// Fill our event structure with event information. //
	if ( SDL_PollEvent(&g_Event) )
	{
		// Handle keyboard input here //
		Uint8 *keys;
		keys = SDL_GetKeyState(NULL);
		if(keys[SDLK_UP]) {
			moving_up = true;
			moving_down = false;
			moving_left = false;
			moving_right = false;
		}
		if(keys[SDLK_DOWN]) {
			moving_down = true;
			moving_up = false;
			moving_left = false;
			moving_right = false;
		}
		if (keys[SDLK_ESCAPE])
		{
			Done = 1;
			//return;  // this state is done, exit the function 
		}	
   		if (keys[SDLK_SPACE])
		{
				
		}
		if (keys[SDLK_RIGHT])
		{
			moving_right = true;
			moving_up = false;
			moving_left = false;
			moving_down = false;
		}
		if (keys[SDLK_LEFT])
		{
			moving_left = true;
			moving_up = false;
			moving_down = false;
			moving_right = false;
		}	
	}

	// This is where we actually move the player //
	if (moving_up)
	{
		if(CheckWallCollisions(UP) == false && Player1.posy != TOPWALL)
		{
			CheckPellotCollisions(UP);
			Player1.posy = Player1.posy - PLAYER_SPEED;
			
			if(Player1.posy % 32 == 0)
			{
				//moving_up = false;
			}
		}
		else
		{
			//move him back to where they were before
			Player1.posy = Player1.posy + PLAYER_SPEED;
			moving_up = false;
		}
	}
	if (moving_down)
	{
		if(CheckWallCollisions(DOWN) == false && Player1.posy != BOTTOMWALL)
		{
			CheckPellotCollisions(DOWN);
			Player1.posy=Player1.posy + PLAYER_SPEED;		

			if(Player1.posy % 32 == 0)
			{
				//moving_down = false;
			}
		}
		else
		{
			//move him back to where he was before
			Player1.posy=Player1.posy - PLAYER_SPEED;
			moving_down = false;
		}
	}
	if (moving_right)
	{
		if(CheckWallCollisions(RIGHT) == false && Player1.posx != RIGHTWALL)
		{
			CheckPellotCollisions(RIGHT);
			Player1.posx=Player1.posx + PLAYER_SPEED;

			if(Player1.posx % 32 == 0)
			{
				//moving_right = false;
			}
		}
		else
		{
			//move him back to where he was before
			Player1.posx=Player1.posx - PLAYER_SPEED;
			moving_right = false;
		}
	}
	if (moving_left)
	{
		if(CheckWallCollisions(LEFT) == false && Player1.posx != LEFTWALL)
		{
			CheckPellotCollisions(LEFT);
			Player1.posx=Player1.posx - PLAYER_SPEED;

			if(Player1.posx % 32 == 0)
			{
				//moving_left = false;
			}
		}
		else
		{
			//move him back to where he was before
			Player1.posx=Player1.posx + PLAYER_SPEED;
			moving_left = false;
		}
	}
}

// Check to see if a game object is going to hit a wall //
bool CheckWallCollisions(Direction dir)
{
	int downY = 0;
	int upY = 0;
	int leftX = 0;
	int rightX = 0;

	int upLeft = 0;
	int upRight = 0;
	int downLeft = 0;
	int downRight = 0;

	//get current positions of 4 corners of pacman
	int currentPosRightX = Player1.posx + TILE_SIZE - 1;
	int currentPosLeftX = Player1.posx;
	int currentPosTopY = Player1.posy;
	int currentPosBottomY = Player1.posy + TILE_SIZE - 1;

	downY = currentPosBottomY / TILE_SIZE;
	upY = currentPosTopY / TILE_SIZE;
	leftX = currentPosLeftX / TILE_SIZE;
	rightX = currentPosRightX / TILE_SIZE;

	//get either blocked or not blocked of the 4 tiles around pacman
	upLeft = Level[leftX][upY].blocked;
	downLeft = Level[leftX][downY].blocked;
	upRight = Level[rightX][upY].blocked;
	downRight = Level[rightX][downY].blocked;

	switch(dir)
	{
	case(UP):
		//check topright and topleft to see if pacman can move up
		if(upRight == 0 && upLeft == 0)
		{
			return false;
		}
		else
		{
			return true;
		}

		break;
	case(DOWN):
		//check topright and topleft to see if pacman can move up
		if(downRight == 0 && downLeft == 0)
		{
			return false;
		}
		else
		{
			return true;
		}

		break;
	case(LEFT):
		//check topright and topleft to see if pacman can move up
		if(upLeft == 0 && downLeft == 0)
		{
			return false;
		}
		else
		{
			return true;
		}

		break;
	case(RIGHT):
		//check topright and topleft to see if pacman can move up
		if(upRight == 0 && downRight == 0)
		{
			return false;
		}
		else
		{
			return true;
		}

		break;
	}
}


Share this post


Link to post
Share on other sites
Advertisement
You didn't give the Exact problem... only that it has something to do with collision detection and speed.
Let me guess, if you let pacman move too fast, sometimes he can walk through walls?
need to be more specific

Anyhow, if that is indeed the problem.
I'd point out that, pacman's movement is Discrete tile(game grid) based motion. His animation shows him smoothly sliding along, but at any given time he is really in one tile at a time.
This greatly simplifies collision detection, you only need to check and see if the tile in the direction he is trying to move in is a wall tile or not.
I reccomend, that you track his current tile, in addition to the x and y position of the graphic image. And when moving, rather than do %32 to find his tile, you actually add +1 -1 to his tile position, This way it can only change by single spaces and you don't have the issue of skipping over walls.

Share this post


Link to post
Share on other sites
Its not that pacman can move through walls. Lets say that I have a wall tile, an open space tile that pacman can move through, and another wall tile. These are all above him as he is moving left. If I want to move him up through the open space, that is where I have trouble unless the speed is set really low (like 1-2 pixels per frame). I'll post my latest movement and collision code below.



void HandleGameInput()
{
static bool moving_up = false;
static bool moving_down = false;
static bool moving_left = false;
static bool moving_right = false;

// Fill our event structure with event information. //
if ( SDL_PollEvent(&g_Event) )
{
// Handle keyboard input here //
Uint8 *keys;
keys = SDL_GetKeyState(NULL);
if(keys[SDLK_UP]) {
moving_up = true;
moving_down = false;
moving_left = false;
moving_right = false;
}
if(keys[SDLK_DOWN]) {
moving_down = true;
moving_up = false;
moving_left = false;
moving_right = false;
}
if (keys[SDLK_ESCAPE])
{
Done = 1;
//return; // this state is done, exit the function
}
if (keys[SDLK_SPACE])
{

}
if (keys[SDLK_RIGHT])
{
moving_right = true;
moving_up = false;
moving_left = false;
moving_down = false;
}
if (keys[SDLK_LEFT])
{
moving_left = true;
moving_up = false;
moving_down = false;
moving_right = false;
}
}

// This is where we actually move the player //
if (moving_up)
{
if(CheckWallCollisions(UP) == false && Player1.posy != TOPWALL)
{
CheckPellotCollisions(UP);
Player1.posy = Player1.posy - PLAYER_SPEED;
}
else
{
//get the current y tile that the player is in
Player1.tiley = Player1.posy / TILE_SIZE;

//move player next to wall
Player1.posy = Player1.tiley * TILE_SIZE;
moving_up = false;
}
}
if (moving_down)
{
if(CheckWallCollisions(DOWN) == false && Player1.posy != BOTTOMWALL)
{
CheckPellotCollisions(DOWN);
Player1.posy=Player1.posy + PLAYER_SPEED;
}
else
{
//get the current y tile that the player is in
Player1.tiley = divideRoundUp(Player1.posy,TILE_SIZE);

//move player next to wall
Player1.posy = Player1.tiley * TILE_SIZE;
moving_down = false;
}
}
if (moving_right)
{
if(CheckWallCollisions(RIGHT) == false && Player1.posx != RIGHTWALL)
{
CheckPellotCollisions(RIGHT);
Player1.posx=Player1.posx + PLAYER_SPEED;
}
else
{
//get the current x tile that the player is in
Player1.tilex = divideRoundUp(Player1.posx,TILE_SIZE);

//move player next to wall
Player1.posx = Player1.tilex * TILE_SIZE;
moving_right = false;
}
}
if (moving_left)
{
if(CheckWallCollisions(LEFT) == false && Player1.posx != LEFTWALL)
{
CheckPellotCollisions(LEFT);
Player1.posx=Player1.posx - PLAYER_SPEED;
}
else
{
//get the current x tile that the player is in
Player1.tilex = Player1.posx / TILE_SIZE;

//move player next to wall
Player1.posx = Player1.tilex * TILE_SIZE;
moving_left = false;
}
}
}

// Check to see if a game object is going to hit a wall //
bool CheckWallCollisions(Direction dir)
{
int downY = 0;
int upY = 0;
int leftX = 0;
int rightX = 0;

int upLeft = 0;
int upRight = 0;
int downLeft = 0;
int downRight = 0;

int currentPosTopY = 0;
int currentPosBottomY = 0;
int currentPosRightX = 0;
int currentPosLeftX = 0;

//get current positions of 4 corners of pacman if he were to move
switch(dir)
{
case(UP):
currentPosTopY = Player1.posy - PLAYER_SPEED;
currentPosBottomY = Player1.posy + TILE_SIZE - 1 - PLAYER_SPEED;
currentPosRightX = Player1.posx + TILE_SIZE - 1;
currentPosLeftX = Player1.posx;
break;
case(DOWN):
currentPosTopY = Player1.posy + PLAYER_SPEED;
currentPosBottomY = Player1.posy + TILE_SIZE - 1 + PLAYER_SPEED;
currentPosRightX = Player1.posx + TILE_SIZE - 1;
currentPosLeftX = Player1.posx;
break;
case(LEFT):
currentPosRightX = Player1.posx + TILE_SIZE - 1 - PLAYER_SPEED;
currentPosLeftX = Player1.posx - PLAYER_SPEED;
currentPosTopY = Player1.posy;
currentPosBottomY = Player1.posy + TILE_SIZE - 1;
break;
case(RIGHT):
currentPosRightX = Player1.posx + TILE_SIZE - 1 + PLAYER_SPEED;
currentPosLeftX = Player1.posx + PLAYER_SPEED;
currentPosTopY = Player1.posy;
currentPosBottomY = Player1.posy + TILE_SIZE - 1;
break;
}

//get current positions of 4 corners of pacman
//int currentPosRightX = Player1.posx + TILE_SIZE - 1;
//int currentPosLeftX = Player1.posx;
//int currentPosTopY = Player1.posy;
//int currentPosBottomY = Player1.posy + TILE_SIZE - 1;

downY = currentPosBottomY / TILE_SIZE;
upY = currentPosTopY / TILE_SIZE;
leftX = currentPosLeftX / TILE_SIZE;
rightX = currentPosRightX / TILE_SIZE;

//get either blocked or not blocked of the 4 tiles around pacman
upLeft = Level[leftX][upY].blocked;
downLeft = Level[leftX][downY].blocked;
upRight = Level[rightX][upY].blocked;
downRight = Level[rightX][downY].blocked;

switch(dir)
{
case(UP):
//check topright and topleft to see if pacman can move up
if(upRight == 0 && upLeft == 0)
{
return false;
}
else
{
return true;
}

break;
case(DOWN):
//check topright and topleft to see if pacman can move up
if(downRight == 0 && downLeft == 0)
{
return false;
}
else
{
return true;
}

break;
case(LEFT):
//check topright and topleft to see if pacman can move up
if(upLeft == 0 && downLeft == 0)
{
return false;
}
else
{
return true;
}

break;
case(RIGHT):
//check topright and topleft to see if pacman can move up
if(upRight == 0 && downRight == 0)
{
return false;
}
else
{
return true;
}

break;
}
}


Share this post


Link to post
Share on other sites
So, you're saying that Pacman has a hard time turning and squeezing between the walls 'just right'. Unless he is moving really slow, it is hard to time it and he ends up bumping against one of the walls instead of going between them.
Is that the problem?

If I remember the origonal PacMan right, what they did is have him shift a little to line up with the 'hallway' before walking through it.
Maybe you should do that too:
If you tell PacMan to go Up, but his nose is already sticking out past the open spot, have him automatically go backwards to line up with the open tile before moving up.



otherwise, you could just make PacMan really skinny :)

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!