Jump to content
  • Advertisement
Sign in to follow this  
CustomDrive

[C++]Mario Bros Collision?[SOLVED]

This topic is 3799 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 trying to make a box collision system similar to the ones used by the Nes Mario Bros. Basically, I want my character to stop moving towards a block when it collides with it. Also, my character can be pushed around by moving blocks. Currently, my program has no problem handling stationary blocks. However, once I put in moving blocks, things start getting a bit weird. For example, if my character tries to jump up towards the bottom of a block moving downwards, he will sometimes get stuck inside the block. Also if the character jumps towards the left of the block while the block is moving right, he will instantly move the the right side of the block. Here my code. It's extremely messy and I've tried my best to make everything as readable as possible: Note: the function move is called every time the program loops
void move(double x, double y)
{
	//If collide is true, Man won't move.
	bool collide = false;
	
	//Checks whether Man is out of bound
	if((Man.posX+x) < 0 || (Man.posX+Man.sizeX+x) > SCREEN_WIDTH || (Man.posY+Man.sizeY+y) > SCREEN_HEIGHT){
		collide = true;
	}
	else
		//Checks whether Man is standing on the ground.
		if((Man.posY+y) < 0){
			collide = true;
			Ground = true;
		}
		else
			//Checks collision for all walls
			if(WalMAP.begin() != WalMAP.end()){
				for(vector<Object>::iterator it = WalMAP.begin(); it < WalMAP.end(); it++){
					//Checks if Man collides with wall in the x direction
					if(collisionCheck(Man.posX + x, Man.posY, Man.sizeX, Man.sizeY,
					   (*it).posX-(*it).speedX, (*it).posY-(*it).speedY, (*it).sizeX, (*it).sizeY) == 1)
					{
						collide = true;
						//If Man's speed in x direction is positive, then it is assumed he collides from the left
						if(x>0){
							//Moves Man to the left side of block
							Man.posX += ((*it).posX - (Man.posX+Man.sizeX));
							//Stops Man's speed in x direction
							Man.speedX = 0;
						}
						else
							//If Man's speed in x direction is positive, then it is assumed he collides from the right
							if(x<0){
								//Moves Man to the right side of block
								Man.posX += (((*it).posX+(*it).sizeX) - Man.posX);
								//Stops Man's speed in x direction
								Man.speedX = 0;
							}
							else
								//If Man's speed is 0 in x direction, while wall's speed is negative, it is assumed that
								//the block is pushing the Man from the right.
								if((*it).speedX<0){
									//Moves Man to the left side of block
									Man.posX += ((*it).posX - (Man.posX+Man.sizeX));
									//Stops Man's speed in x direction
									Man.speedX = 0;
								}
								else
									if((*it).speedX>0){
										//Moves Man to the right side of block
										Man.posX += (((*it).posX+(*it).sizeX) - Man.posX);
										//Stops Man's speed in x direction
										Man.speedX = 0;
									}

					}
					//Checks if Man collides with wall in the y direction
					if(collisionCheck(Man.posX, Man.posY + y, Man.sizeX, Man.sizeY,
					   (*it).posX-(*it).speedX, (*it).posY-(*it).speedY, (*it).sizeX, (*it).sizeY) == 1)
					{
						collide = true;
						//If Man's speed in y direction is positive, then it is assumed he collides from the bottom
						if(y>0){
							//Moves Man to the bottom of the block
							Man.posY += ((*it).posY - (Man.posY+Man.sizeY));
							//Stops Man's speed in y direction
							Man.speedY = 0;
						}
						else
							//If Man's speed in y direction is negative, then it is assumed he collides from the top
							if(y<0){
								//Moves Man to the top of the block
								Man.posY += (((*it).posY+(*it).sizeY) - Man.posY);
								//Stops Man's speed in y direction
								Man.speedY = 0;
								//Set Man's speed to the speed of the moving block.
								Man.speedX = (*it).speedX;
								Ground = true;
							}
					}
				}
			}
	
	//If no collisions occured, then Man moves in given direction
	if( collide == false ){
		Man.posX = (Man.posX+x);
		Man.posY = (Man.posY+y);
	}

}

//Returns true if collision happened between the two boxes
int collisionCheck(double x, double y, double sizex, double sizey,
				   double X, double Y, double sizeX, double sizeY)
{
	if(((x+sizex)>X)&&(x<(X+sizeX))&&((y+sizey)>Y)&&(y<(Y+sizeY)))
		return 1;
	else
		return 0;
}




Any help will be greatly appreciated! [Edited by - CustomDrive on July 23, 2008 10:10:04 AM]

Share this post


Link to post
Share on other sites
Advertisement
I know I practically wrote a novel here (took me over half an hour), but I felt you code needed a lot of scrutiny.

Lines that urk me:
void move(double x, double y)

No documentation. Is this what moves the player, enemies, the background? What's x? What's y? It should be documented above the function.

                //Checks whether Man is standing on the ground.
if((Man.posY+y) < 0){
collide = true;
Ground = true;
}

This doesn't make sense. You say, earlier, that if he's colliding with something, he won't move, but the ground is obviously an exception? Either bad documentation or design.

And you use y here, but I have no idea what y is! Why should (Man.posY+y) < 0?

		else
//Checks collision for all walls

So, he can't possibly collide with a wall if he's colliding with the ground?

			if(WalMAP.begin() != WalMAP.end()){

Should I know what WalMAP is? (When you post code that uses globals, you have to tell us what those globals are.) I'm guessing it's a map of the wall, or foreground. So, if there exists a foreground, check for collision? Does there ever not exist a foreground?

					//Checks if Man collides with wall in the x direction
if(collisionCheck(Man.posX + x, Man.posY, Man.sizeX, Man.sizeY,
(*it).posX-(*it).speedX, (*it).posY-(*it).speedY, (*it).sizeX, (*it).sizeY) == 1)

This is a bit more understandable, but if you're only checking for collision in the x direction, why does collisionCheck accept y directions? Maybe that's a problem in the comment (out of date?), but realize that I read the comment THEN I read the code in reference to the comment.

Also, I'm GUESSING (better documentation would make it so I don't have to) that you are using the speedx and y of (*it) because you want to check collision for where it WILL be. It would be more intuitive if you wrote (*it).posY+(*it).speedY. Subtracting by speed has the connotation of going backwards. I can't really comment on beyond that, though.

						//If Man's speed in x direction is positive, then it is assumed he collides from the left
if(x>0){

Is that what the x means? Well, you can't assume that. He could be moving right and an object comes up faster than him and hits him in the back (especially if you're talking about moving blocks).

							//Moves Man to the left side of block
Man.posX += ((*it).posX - (Man.posX+Man.sizeX));
//Stops Man's speed in x direction
Man.speedX = 0;

What if the man's speed was set equal to the block's speed? It's just, when I imagine in my head jumping up in Mario and hitting a block moving the same slower, but in the same direction, I don't want my horizontal speed suddenly zeroing, and if the block is moving against me, it'll push me and my speed will be zeroed the moment it stops, which doesn't make sense.

Also, this MIGHT be the code that's causing him to get stuck in the box because he MIGHT still be colliding with the box, even after you shunt him to the right. Try making adding man.posX += 1; and see what happens.

Also: There's NO reason to use += here.
Man.posX += (((*it).posX+(*it).sizeX) - Man.posX);
could be
Man.posX = (*it).posX + (*it).sizeX;

								//If Man's speed is 0 in x direction, while wall's speed is negative, it is assumed that
//the block is pushing the Man from the right. if((*it).speedX<0){

HUGE logical error. This if checks if the wall's speed is negative, but doesn't check if the Man's speed is zero! This is in the else from the if(x<0), so all you know is the x is 0 OR GREATER.

 								//If Man's speed is 0 in x direction, while wall's speed is negative, it is assumed that
//the block is pushing the Man from the right.
if((*it).speedX<0){
//Moves Man to the left side of block
Man.posX += ((*it).posX - (Man.posX+Man.sizeX));
//Stops Man's speed in x direction
Man.speedX = 0;
}
else
if((*it).speedX>0){
//Moves Man to the right side of block
Man.posX += (((*it).posX+(*it).sizeX) - Man.posX);
//Stops Man's speed in x direction
Man.speedX = 0;
}

What if (*it) is not moving?

					//Checks if Man collides with wall in the y direction
if(collisionCheck(Man.posX, Man.posY + y, Man.sizeX, Man.sizeY,
(*it).posX-(*it).speedX, (*it).posY-(*it).speedY, (*it).sizeX, (*it).sizeY) == 1)

NOW you're checking for collision in the Y direction with the EXACT SAME CHECK? You run the same function with the same arguments (unless I missed something). Before either if, you could set the result to a boolean and just if(that) two times, or you could combine the two ifs, which is my suggestion. You COULD keep it the way it is, it's just not what I'd recommend.

							//If Man's speed in y direction is negative, then it is assumed he collides from the top
if(y<0){

In any graphics library I've worked with (SDL and OpenGL) -y is up, so he'd be colliding with the bottom of things. I'm going to assume you were correct to make this how you did, but what if he does collide from the bottom?

								//Stops Man's speed in y direction
Man.speedY = 0;

What if the block is moving up or down?

	//If no collisions occured, then Man moves in given direction
if( collide == false ){
Man.posX = (Man.posX+x);
Man.posY = (Man.posY+y);
}

Ironically, the GOOD place to use +=, you didn't.

//Returns true if collision happened between the two boxes
int collisionCheck(double x, double y, double sizex, double sizey,
double X, double Y, double sizeX, double sizeY)
{
if(((x+sizex)>X)&&(x<(X+sizeX))&&((y+sizey)>Y)&&(y<(Y+sizeY)))
return 1;
else
return 0;
}

Again, no documentation. I don't know the difference between x, y, and X, Y. That if statement is just cryptic and hard to read.

I'm hoping that just cleaning up your code, documenting better, and looking at the things I mentioned will reveal the problem. Good luck.

Share this post


Link to post
Share on other sites
Quote:
Original post by Splinter of Chaos
I know I practically wrote a novel here (took me over half an hour), but I felt you code needed a lot of scrutiny.


First of all, I would like to thank you for the detailed feedback you've provided. Not many people would bother reading the long junk I wrote, and you were being very kind to actually go through the entire code and pick out all mistakes that I might have and provide helpful suggestions for them.

So I ended up rewriting the entire code from scratch and was able to solve most of the problems I had. Once I found out what my mistake was, I felt like a moron... to sum up my problem, here's a quote:

Quote:
There are two groups of people in this world.

1) Those who don't fully understand all of the details about performing
== and != on floating points values. They should never use == or != on
floating point values (not being mean or anything, they just shouldn't).

2) Those who do understand all the details about performing == and != on
floating point values. They don't use == and !=, so don't have to be
told not to :)

Chris


Again, thanks alot for your help Splinter, and sorry I've wasted half an hour of your time.. I was in a little hurry to get my program working so my code got a bit messy...

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.

GameDev.net is your game development community. Create an account for your GameDev Portfolio and participate in the largest developer community in the games industry.

Sign me up!