9 Replies - 18880 Views - Last Post: 13 February 2009 - 07:19 AM Rate Topic: -----

#1 stayscrisp  Icon User is offline

  • フカユ
  • member icon

Reputation: 1009
  • View blog
  • Posts: 4,197
  • Joined: 14-February 08

Platform game collision detection, Not tile based

Posted 11 February 2009 - 02:39 PM

Hi

I'm currently developing a 2D platform game and have almost everything in place, but the collision detection is really taking some time, basically I can detect the collision happening between 2 objects using a intersecting rectangles function

bool Game::CheckCollision(GameObject p1, GameObject p2)
{
   
   int leftp1, leftp2;
   int rightp1, rightp2;
   int topp1, topp2;
   int bottomp1, bottomp2;
   
   leftp1 = p1.m_x;
   rightp1 = p1.m_x + p1.m_width;
   topp1 = p1.m_y;
   bottomp1 = p1.m_y + p1.m_height;
   
   leftp2 = p2.m_x;
   rightp2 = p2.m_x + p2.m_width;
   topp2 = p2.m_y;
   bottomp2 = p2.m_y + p2.m_height;
   
   //If any of the sides from A are outside of B
	if( bottomp1 <= topp2 )
	{
		return false;
	}
	
	if(bottomp2 < topp1)
	{
	   return false;
	}
	
	if(bottomp1 >= topp2 && rightp1 <= leftp2 && leftp1 >= rightp2)
	{
	   return false;
	}
	if( topp1 >= bottomp2 )
	{
		return false;
	}

	if( rightp1 <= leftp2 )
	{
		return false;
	}

	if( leftp1 >= rightp2 )
	{
		return false;
	}
	
	//If none of the sides from A are outside B
	return true;
   
}



this is basically the same as the tutorial on lazyfoo website.

so then I have the game loop check for collision between the platform and the player and if it returns true then set a bool in the player class to true

if(CheckCollision(platform, player))
{
	 player.Colliding = true;
}




then in the movement function it only moves if the object is not colliding

if(!Colliding)
{	
	m_x += m_newX;
}
		
if(!Colliding)
{
	m_y += m_newY;
}



but as you can probably guess, now when the player is on top of a platform he cannot move left or right as it counts as a collision, i attempted trying to break up into sections like top collision, side collision and such but could not implement it properly. Anyone have any ideas of how to do this?

Is This A Good Question/Topic? 0
  • +

Replies To: Platform game collision detection, Not tile based

#2 Lillefix  Icon User is offline

  • D.I.C Head
  • member icon

Reputation: 37
  • View blog
  • Posts: 204
  • Joined: 19-September 08

Re: Platform game collision detection, Not tile based

Posted 11 February 2009 - 02:46 PM

I am not sure if I understood your question, but you might try this:

* Add x-movement
* If collision, then backtrace the x-movement
* Add y-movement
* If collision, then backtrace the y-movement
* Add z-movement
* If collision, then backtrace the z-movement

You can then move along the x and z axis even if you collide at the y-axis.

If this was not what you needed, maybe you can give elaborate your problem a bit?

This post has been edited by Lillefix: 11 February 2009 - 02:47 PM

Was This Post Helpful? 0
  • +
  • -

#3 stayscrisp  Icon User is offline

  • フカユ
  • member icon

Reputation: 1009
  • View blog
  • Posts: 4,197
  • Joined: 14-February 08

Re: Platform game collision detection, Not tile based

Posted 11 February 2009 - 03:40 PM

My game is 2d so it doesn't have a Z value, I don't understand what you mean by backtrack the value, do you mean set to value before the collision?

what I want is a way to check for each type of collision top,side,bottom.
Was This Post Helpful? 0
  • +
  • -

#4 pr4y  Icon User is offline

  • Location: 127.0.0.1
  • member icon

Reputation: 35
  • View blog
  • Posts: 621
  • Joined: 19-September 08

Re: Platform game collision detection, Not tile based

Posted 11 February 2009 - 04:03 PM

View Poststayscrisp, on 11 Feb, 2009 - 01:39 PM, said:

then in the movement function it only moves if the object is not colliding

if(!Colliding)
{	
	m_x += m_newX;
}
		
if(!Colliding)
{
	m_y += m_newY;
}





Isn't it redundant to have two of the same conditionals preforming seperate tasks? I'm not sure if this was an example or an actual snipplet of your code, but a quick tip might be to condense your if statements to reduce redundancy and execution time.

Just a tip though :)
Was This Post Helpful? 0
  • +
  • -

#5 mocker  Icon User is offline

  • D.I.C Regular
  • member icon

Reputation: 50
  • View blog
  • Posts: 466
  • Joined: 14-October 07

Re: Platform game collision detection, Not tile based

Posted 11 February 2009 - 04:46 PM

Add a second check to your conditional:

if(!Colliding || (m_newY <= 0) )



Assuming 0,0 is the top left and the platform you are colliding with is below you, it blocks movement only when you are falling, not when going sideways or up. You need to combine the two if's though in order to make sure it doesn't continue to move you horizontal when you stop falling.
Was This Post Helpful? 0
  • +
  • -

#6 WolfCoder  Icon User is offline

  • Isn't a volcano just an angry hill?
  • member icon


Reputation: 786
  • View blog
  • Posts: 7,618
  • Joined: 05-May 05

Re: Platform game collision detection, Not tile based

Posted 11 February 2009 - 08:15 PM

Here's my very simple solution.

move(vx,0);
move(0,vy);



You move the character in the y direction so them falling on the platform cancels the move(0,vy) command. Then, the move(vx,0) command only pays attention to what's left and right of the player. This is what makes my character slide across the item boxes even though you're pushing up against then if you press the diagonals. You can poke around either wshull.c or battlefield.c in my NovaForce source code to see the part of my code that looks like this:

action player_prog()
{
}



or something like that. You'll see I use two different move commands to achieve the effect so that the player doesn't stick to walls and the like. The game is in 3D space despite being drawn in 2D and stuff does have a Z vector (I'm trying to figure out a simple way to allow the user to jump without crowding the controls, but it actually handles collisions in 3D).

If you want the player to slide down slopes, you will have to then either make a slope collision object that pushes the player to the side when the player impacts it, or make the player aware of what kind of surface it is hitting. Or you could go nuts and implement a 2D polygon collision system to describe the shape of the level.

I separate level collisions with object collisions so I can take advantage of the fact that my maps are stuck on a grid layout, allowing me to check for entity<>level collisions much much faster than entity<>entity collisions. You should implement a system like that if your current system just spawns solid invisible blocks on every part of the map that's solid. A map collision detection is a matter of arithmetically shifting values to the right (masking zeros to be safe) to reduce all 4 corners of the collision square to map tile coordinates. Then check the collision layer for a hit. Much faster than having to go through the entire list of 1000+ collision squares for a hit because entity<>entity collision involves comparing one entity that issued a move command to every other solid entity in existence.

If you later implement complicated geometry detection (like pixel detection) on entities and level geometry, you can write an elimination case using simple square checking or map index checking to see if the entity is even anywhere near the target to get incredible speed yet have much more detailed collision detection. I separated all my IF statements so that even square detection is explicitly defined so that the compiler treats each axis in order, having an elimination case to help speed it up even further (if your compiler is not smart enough to do this on it's own).

A final note, don't forget to normalize velocity vectors to a safe length. This will slow things down, but prevents entities from passing through hulls when they're moving really fast. For example, if your player falls off a cliff, instead falling painfully on the ground, it may pass through the ground if the ground is thin enough. Same goes for flying projectiles and walls or enemies that are moving really fast (like motorcycles and the like). However you could also set a limit for the time factor variable you should be using for getting correct movement in any frame rate so that people running really slow systems won't be able to walk through walls.

This post has been edited by WolfCoder: 11 February 2009 - 08:31 PM

Was This Post Helpful? 0
  • +
  • -

#7 stayscrisp  Icon User is offline

  • フカユ
  • member icon

Reputation: 1009
  • View blog
  • Posts: 4,197
  • Joined: 14-February 08

Re: Platform game collision detection, Not tile based

Posted 12 February 2009 - 10:37 AM

@wolfcoder
Hmm why do you use 3d collision detection with a 2d game, seems excessive. I see where you are coming from but i do not want to use a tile based system.


@mocker
if(!Colliding || (m_newY <= 0) )

this doesnt seem to make much of a difference, i tried this and for some reason it works walking left but not right

i also tried if(m_newX != Colliding)
{
// move
}

to no avail, anymore ideas? this is really starting to annoy me :s

thanks for all the replies
Was This Post Helpful? 0
  • +
  • -

#8 Lillefix  Icon User is offline

  • D.I.C Head
  • member icon

Reputation: 37
  • View blog
  • Posts: 204
  • Joined: 19-September 08

Re: Platform game collision detection, Not tile based

Posted 12 February 2009 - 01:41 PM

This is actually not as hard as you make it.
See this little snippet:

xPosition += xSpeed;
if(Collision()) //We have obviously collided
{
	xPosition -= xSpeed; //Going back to our previous position
	if (xSpeed > 0) // We have obviously moved right
		cout << "Oh, no, I hit the left side of something" << endl;
	else if (xSpeed < 0) // We have obviously moved left
		cout << "Oh, no, I hit the right side of something" << endl;
}



This is for one dimension, but is easy expandable to both two and three dimensions.
Was This Post Helpful? 1

#9 stayscrisp  Icon User is offline

  • フカユ
  • member icon

Reputation: 1009
  • View blog
  • Posts: 4,197
  • Joined: 14-February 08

Re: Platform game collision detection, Not tile based

Posted 12 February 2009 - 02:43 PM

View PostLillefix, on 12 Feb, 2009 - 12:41 PM, said:

This is actually not as hard as you make it.
See this little snippet:

xPosition += xSpeed;
if(Collision()) //We have obviously collided
{
	xPosition -= xSpeed; //Going back to our previous position
	if (xSpeed > 0) // We have obviously moved right
		cout << "Oh, no, I hit the left side of something" << endl;
	else if (xSpeed < 0) // We have obviously moved left
		cout << "Oh, no, I hit the right side of something" << endl;
}



This is for one dimension, but is easy expandable to both two and three dimensions.


you are a genius :) ill try implement this now! :^:
Was This Post Helpful? 0
  • +
  • -

#10 WolfCoder  Icon User is offline

  • Isn't a volcano just an angry hill?
  • member icon


Reputation: 786
  • View blog
  • Posts: 7,618
  • Joined: 05-May 05

Re: Platform game collision detection, Not tile based

Posted 13 February 2009 - 07:19 AM

View Poststayscrisp, on 12 Feb, 2009 - 10:37 AM, said:

@wolfcoder
Hmm why do you use 3d collision detection with a 2d game, seems excessive. I see where you are coming from but i do not want to use a tile based system.
...


I didn't say you had to, I eluded to objects you can pass through and detailed geometry collision. Also there's some pitfalls you may or may not encounter with his solution. I just told you to move the object on separate axis instead of one move at once.

I use 3D collision because it actually make things easier, such as jumping over pits (because I am using a top-down perspective) or handling enemies that can fly. Also, the engine is later supposed to be in 3D.

This post has been edited by WolfCoder: 13 February 2009 - 07:21 AM

Was This Post Helpful? 0
  • +
  • -

Page 1 of 1