Public Group

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

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

## 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 on other sites
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 boxesint 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 on other sites
Quote:
 Original post by Splinter of ChaosI 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 != onfloating point values (not being mean or anything, they just shouldn't).2) Those who do understand all the details about performing == and != onfloating point values. They don't use == and !=, so don't have to betold 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 on other sites
My time wasn't wasted if it helped you, which is the whole point of a forum.

1. 1
2. 2
Rutin
19
3. 3
4. 4
5. 5

• 15
• 13
• 9
• 12
• 10
• ### Forum Statistics

• Total Topics
631442
• Total Posts
3000082
×