C++ 2D Box-Collision, is this right?
Well I've got a 2D box collision code that basically loops through every bl开发者_开发问答ock in a list called "Blocks" and it checks if I'm near the sides and whatnot.
It works very well except for the bottom of the block. When I'm jumping up towards the bottom I want my player to simply "bounce" off. It does this, but it is very glitchy. It's hard to explain so I was hoping you guys could possibly spot out what's wrong with my bottom collision code.
Here's the entire thing (this is ran in a loop):
for(unsigned int i = 0; i<blocks.size(); i++){
Block &b = blocks.at(i);
if(!b.passable==true){
//Check if we are on the sides
if(y + height + vspeed >= b.worldY+2 && y + vspeed <= b.worldY+b.height)
{
//Right side
if(x + hspeed <= b.worldX+b.width-1 && x + hspeed > b.worldX+b.width + hspeed-2)
{
x = b.worldX + b.width; hspeed = 0;
}
//Left side
if(x + width + hspeed >= b.worldX +1 && x + width + hspeed <= b.worldX + hspeed + 2)
{
x = b.worldX - width; hspeed = 0;
}
}
//Check if we are on the top or the bottom
if(x + width + hspeed >= b.worldX+2 && x + hspeed <= b.worldX+b.width-2)
{
if(y + height + vspeed >= b.worldY && y + height + vspeed <= b.worldY + vspeed + 1 && jumpstate=="falling")
{
y = b.worldY - height; jumpstate.assign("ground"); vspeed = 0;
}
if(y + vspeed <= b.worldY + b.height && y + vspeed >= b.worldY + b.height + vspeed - 1 && jumpstate=="jumping")
{
y = b.worldY + b.height; jumpstate.assign("falling"); vspeed = 0;
}
}
}
}
I'm not sure you'll get it to work like this. I'll explain a solution that I thought of for some collision detection and bouncing that works smoothly. Record the time interval from when you last checked collisions and adjusted position. If Xplayer+Vplayer*deltaT>Xtarget
(if the player would overlap the target) then compute the actual time when it would be touching the target deltaTtouch=(Xtarget-Xplayer)/Vplayer
. Now bounce the player back Xplayer=Xtarget-Vplayer*(deltaT-deltaTtouch)
. You'll have to figure out all the cases when moving forward, backward, up, down.
LE: You can also implement gravity, this involves solving a quadratic equation for finding out the deltaTtouch
.
Well I can see a few little details:
1) In this line the hspeed when checking the old position is quite redundant, best to remove it for clarity.
if(x + hspeed <= b.worldX+b.width-1 && x + hspeed > b.worldX+b.width + hspeed-2)
Becomes:
if(x + hspeed <= b.worldX + b.width - 1 && x > b.worldX + b.width - 2)
Same goes for the other similar lines.
2) The small offsets of -2 and -1 are a bit confusing I presume you are trying to achieve a small buffer such that a slight amount of overlap is required. Especially this line where you have used a < instead of the <= you have used every else:
if(x + hspeed <= b.worldX+b.width-1 && x + hspeed > b.worldX+b.width + hspeed-2)
To keep consistancy with the rest of the program I would probably write:
if(x + hspeed <= b.worldX + b.width - 1 && x >= b.worldX + b.width - 1)
3) You seem to be missing a few of your small offsets in the vert checks:
So this check first:
if(y + height + vspeed >= b.worldY && y + height + vspeed <= b.worldY + vspeed + 1 && jumpstate=="falling")
You seem to have forgotten your small offset:
if(y + height + vspeed >= b.worldY + 1 && y + height <= b.worldY + 1 && jumpstate=="falling")
Then the second check:
if(y + vspeed <= b.worldY + b.height && y + vspeed >= b.worldY + b.height + vspeed - 1 && jumpstate=="jumping")
Offset again:
if(y + vspeed <= b.worldY + b.height - 1 && y >= b.worldY + b.height - 1 && jumpstate=="jumping")
4) You will need to be very careful that vspeed and jumpstate always remain in sync as the sign of vspeed needs to always match jumpstate or you will miss collisions. I imagine this might be where your problem is coming from.
5) In both directions if speed exceeds the block size you will skip collision detection and fire through the block.
if(y + height + vspeed >= b.worldY+2 && y + vspeed <= b.worldY+b.height)
The second check in these lines will be false if speed is higher than b.height and the y coords are similar.
Hope that helps some.
精彩评论