2D C++ Collision detection almost perfect, but not quite? - c++

Just to preface this question please note I am not asking 'fix my code', rather what techniques would I employ to fix this problem. I also apologise if my spelling is not very good.
Okay so I have a 2D platformer game which compares the players position with all of the tiles (in a loop), the resolves the collision accordingly. This is pretty much the structure of the main game loop:
Check all collisions (And enable jumping if a collision bellow the
player occurred)
Get input and change player velocity accordingly
Add gravity to the Y velocity
Apply velocity and friction to the players position
Draw the game
repeat
But despite this system working there are two minor, but noticeable problems with the collision system (I have provided images to make it easier). There are two problems, the first is not that bad, but the second renderers the game almost unplayable!
Problem 1. When just moving left and right across the floor in the game, occasionally the player looses all the velocity it has gained and then has to re-accumulate that velocity. I think this is because every now and then my collision detection function does not return properly. here is a image:
I hope that was clear, the problem only really becomes apparent when moving across lots of flat land.
Problem 2 (This one is way worse) The problem is that player can essentially jump up walls, because if you say for example hold down left arrow and hold jump, the player will jump up the wall. I am assuming this is because My collision detection function is returning true if the collision is coming from the side (although it should not). Here is another picture (the text is small, sorry):
So here is my collision detection function, which should take in two 'Objects' then return the direction from the first object at which the collision occurred, I think the problem arouses when It comes to determining the direction as this is causing problems, as shown above:
//Find the collision vectors
float vectorX = (a.Position.x + (a.Scale.x / 2)) - (b.Position.x + (b.Scale.x / 2));
float vectorY = (a.Position.y + (a.Scale.y / 2)) - (b.Position.y + (b.Scale.y / 2));
//Find the distance between the two objects
float deltaWidth = (a.Scale.x / 2) + (b.Scale.x / 2);
float deltaHeight = (a.Scale.y / 2) + (b.Scale.y / 2);
//Stores the direction of collision
Direction collisionDir = Direction::None;
//Check if the two objects are intersecting on the x and y axis
if (fabs(vectorX) < deltaWidth && fabs(vectorY) < deltaHeight)
{
//The direction of collision
float directionX = deltaWidth - fabs(vectorX);
float directionY = deltaHeight - fabs(vectorY);
//Check for vertical collision
if (directionX >= directionY)
{
//Check for collisions from the top
if (vectorY > 0)
{
a.Velocity.y = 0;
a.Position.y += directionY;
collisionDir = Direction::Up;
}
//Collisions form the botttom
else
{
a.Velocity.y = 0;
a.Position.y -= directionY;
collisionDir = Direction::Down;
}
}
else if (directionX < directionY / 2)
{
//Check for collisions from the left
if (vectorX > 0 )
{
a.Velocity.x = 0;
a.Position.x += directionX;
collisionDir = Direction::Left;
}
//Collisions form the right side
else
{
a.Velocity.x = 0;
a.Position.x -= directionX;
collisionDir = Direction::Right;
}
}
}
//Return the direction.
return collisionDir;
This will return a direction, My other code also checks if that direction == Bottom, then it will allow jumping.
Thank-you for any help. I am practising for Ludum Dare, because I plan on (probably) making a platformer and If I cant figure out collision detection I don't know how good my game will be.

First thing I would recommend is make yourself a Vector2D class which holds your x and y coordinates and a few overload some operators to allow for addition and subtraction of two Vector2Ds and multiplication and division by ints, floats and doubles. Trust me it will make your life a lot easier as they can hold all your forces and collision points.
Next when I have used the style of collision you are currently using I have always found that it's:
A)Harder to debug.
B)Harder for other people to follow your code.
So I would recommend creating a Rectangle2D class which handles collisions with other Rectangles and other needed functionality.
As a recommendation have the top left corner and the bottom right corner as a vector from the center of the rectangle which makes scaling and collision detection much easier this also means you can derive the other corners without directly needing to store them.
Here's a code example that will probably help what I'm trying to explain:
bool Intersects(Rectangle2D other)
{
//Checks the right, left, bottom then top of the rectangle
//against the other.
if(other.topLeftCorner.x >= bottomRightCorner.x //Checks the right
|| other.bottomRightCorner.x <= topLeftCorner.x //Checks the left
|| other.topLeftCorner.y >= bottomRightCorner.y //Checks the bottom
|| other.bottomRightCorner.y <= topLeftCorner.y) //Checks the top
return false;
else
return true;
}
You can easily manipulate this code to give you the direction of the collision. Hope this helps.

Related

Collision Detection using D3DXVectors c++, What to do AFTER the collision has been made?

I hope someone out there can answer my question. Currently I am doing some collision detection using D3DXVectors.
I have the collision down, but what I need is what to do AFTER the collision has been made.
I have a player object and the object the player is being collided with and pass these into my function.
Basically, I have this so far (variables names have been changed for clarity):
D3DXVECTOR3 Collision::wallCol(D3DXVECTOR3 player, D3DXVECTOR3 object, float playerWidth, float playerDepth, float objectWidth, float objectDepth)
{
//store the values of the objects into temps
//left hand side of a box
float minX = object.x - (objectWidth / 2);
//right hand side of a box
float maxX = object.x + (objectWidth / 2);
//front of a box
float minZ = object.z - (objectDepth / 2);
//back of a box
float maxZ = object.z + (objectDepth / 2);
//store the players positions into temps
float pminX = player.x - (playerWidth / 2);
float pmaxX = player.x + (playerWidth / 2);
float pminZ = player.z - (playerDepth / 2);
float pmaxZ = player.z + (playerDepth / 2);
//check to see if we are in the box at all
if (pminX <= maxX && pmaxX >= minX &&
pminZ <= maxZ && pmaxZ >= minZ)
{
//x collision for the left side of the block
if (pmaxX >= minX && pmaxX <= maxX)
{
pmaxX = minX - 50;
player.x = pmaxX;
return player;
}
//x collision for the right side of the block
if (pminX <= maxX && pminX >= minX)
{
pminX = maxX + 50;
player.x = pminX;
return player;
}
//z collision for the front
if (pmaxZ >= minZ && pmaxZ <= maxZ)
{
pmaxZ = minZ - 20;
player.z = pmaxZ;
return player;
}
//z collision for the back
if (pminZ <= maxZ && pminZ >= minZ)
{
pminZ = maxZ + 20;
player.z = pminZ;
return player;
}
}
return player;
}
As you can see, I would like to move my player object away from whatever it is that it is bumping into. The problem I am having is that no matter what, my player will always move either to the left or the right on the X axis because it accounts for the X first, it never has the chance to even get to the Z if statements.
I've considered making 2 Booleans to tell if the player makes contact with the X or the Z first, but since the first if statement is to even see if we are in the box, I believe it would trigger them both at the same time and there would be no way to tell which came first.
If anyone could offer some advice on this problem, it would be greatly appreciated! Thank you.
In order to implement more or less realistic bouncing it is not enough to have only positions and bounding boxes of colliding objects. You need to have some kind of kinematic history: to be able to tell how objects move after collision you should also know how they were moving before the collision.
In simplest case, you want to have at least a velocity (speed) vector (direction and magnitude) and, probably, a mass for every object. When collision is detected you may simply invert the direction of the velocity vector of one of the objects (for example, smaller and lighter one).
The pseudocode will be something like:
if have_collided(object1, object2):
if object1.mass > object2.mass:
object2.velocity = -object2.velocity
else:
object1.velocity = -object1.velocity
This would not look very realistic, but is very simple to implement.
For more realism you could use momentum conservation principle or elastic collisions. For even more realistic bouncing, implement acceleration vector and re-calculate both, velocity and acceleration after collision is detected. Having acceleration you may now add arbitrary forces influencing your objects (gravity, friction, maybe even electromagnetic forces etc.). Adding more attributes make it more interesting: for example adding elasticity and viscosity may be used to calculate deformations.
As you see there is more in object interactions involved than just positions.
Additionally, collision detection and bouncing code could (and should) be decoupled. That means that you would want to implement them in different parts of code (different set of functions and classes): collision subsystem will detect the collision event, providing information like: whether collision happened or not and if yes, by how far objects currently intersect with each other. After that, bouncing code, based on this information, will decide how to change objects traveling, while deformation code will decide how to change objects shapes etc. Thus, there will be no silly problems like which "if" statement in collision code came first decides the direction of bouncing.
Overall I would suggest you:
To look up some physics. For example:
Wiki: Inelastic collision
Wiki: Elastic collision
To get this excellent book: Real-Time Collision Detection
To read through some popular questions on gamedev.stackexchange.com, for example on collision (sort by votes)
Finally, you should know that DirectX 9 API is wildly obsolete, not supported and should not be used for new projects. It is notoriously hard to port D3DX* stuff to modern APIs. You may want to take a look at DirectX 11 and OpenGL 4, along with their support library ecosystems, or maybe even a good rendering or game engine. Specifically you may want to use some good math library (with vectors, matrices, linear algebra, geometry).

Isometric Collision - 'Diamond' shape detection

My project uses an isometric perspective for the time being I am showing the co-ordinates in grid-format above them for debugging. However, when it comes to collision/grid-locking of the player, I have an issue.
Due to the nature of sprite drawing, my maths is creating some issues with the 'triangular' corner empty areas of the textures. I think that the issue is something like below (blue is what I think is the way my tiles are being detected, whereas the red is how they ideally should be detected for accurate roaming movement on the tiles:
As you can see, the boolean that checks the tile I am stood on (which takes the pixel central to the player's feet, the player will later be a car and take a pixel based on the direction of movement) is returning false and denying movement in several scenarios, as well as letting the player move in some places that shouldn't be allowed.
I think that it's because the cutoff areas of each texture are (I think) being considered part of the grid area, so when the player is in one of these corner areas it is not truly checking the correct tile, and so returning the wrong results.
The code I'm using for creating the grid is this:
int VisualComponent::TileConversion(Tile* tileToConvert, bool xOrY)
{
int X = (tileToConvert->x - tileToConvert->y) * 64; //change 64 to TILE_WIDTH_HALF
int Y = (tileToConvert->x + tileToConvert->y) * 25;
/*int X = (tileToConvert->x * 128 / 2) + (tileToConvert->y * 128 / 2) + 100;
int Y = (tileToConvert->y * 50 / 2) - (tileToConvert->x * 50 / 2) + 100;*/
if (xOrY)
{
return X;
}
else
{
return Y;
}
}
and the code for checking the player's movement is:
bool Clsentity::CheckMovementTile(int xpos, int ypos, ClsMapData* mapData) //check if the movement will end on a legitimate road tile UNOPTIMISED AS RUNS EVERY FRAME FOR EVERY TILE
{
int x = xpos + 7; //get the center bottom pixel as this is more suitable than the first on an iso grid (more realistic 'foot' placement)
int y = ypos + 45;
int mapX = (x / 64 + y / 25) / 2; //64 is TILE-WIDTH HALF and 25 is TILE HEIGHT
int mapY = (y / 25 - (x / 64)) / 2;
for (int i = 0; i < mapData->tilesList.size(); i++) //for each tile of the map
{
if (mapData->tilesList[i]->x == mapX && mapData->tilesList[i]->y == mapY) //if there is an existing tile that will be entered
{
if (mapData->tilesList[i]->movementTile)
{
HAPI->DebugText(std::to_string(mapX) + " is the x and the y is " + std::to_string(mapY));
return true;
}
}
}
return false;
}​
I'm a little stuck on progression until having this fixed in the game loop aspect of things. If anyone thinks they either know the issue from this or might be able to help it'd be great and I would appreciate it. For reference also, my tile textures are 128x64 pixels and the math behind drawing them to screen treats them as 128x50 (to cleanly link together).
Rather than writing specific routines for rendering and click mapping, seriously consider thinking of these as two views on the data, which can be transformed in terms of matrix transformations of a coordinate space. You can have two coordinate spaces - one is a nice rectangular grid that you use for positioning and logic. The other is the isometric view that you use for display and input.
If you're not familiar with linear algebra, it'll take a little bit to wrap your head around it, but once you do, it makes everything trivial.
So, how does that work? Your isometric view is merely a rotation of a bog standard grid view, right? Well, close. Isometric view also changes the dimensions if you're starting with a square grid. Anyhow: can we just do a simple coordinate transformation?
Logical coordinate system -> display system (e.g. for rendering)
Texture point => Rotate 45 degrees => Scale by sqrt(2) because a 45 degree rotation changes the dimension of the block by sqrt(1 * 1 + 1 * 1)
Display system -> logical coordinate system (e.g. for mapping clicks into logical space)
Click point => descale by sqrt(2) to unsquish => unrotate by 45 degrees
Why?
If you can do coordinate transformations, then you'd be dealing with a pretty bog-standard rectangular grid for everything else you write, which will make your any other logic MUCH simpler. Your calculations there won't involve computing angles or slopes. E.g. now your "can I move 'down'" logic is much simpler.
Let's say you have 64 x 64 tiles, for simplicity. Now transforming a screen space click to a logical tile is simply:
(int, int) whichTile(clickX, clickY) {
logicalX, logicalY = transform(clickX, clickY)
return (logicalX / 64, logicalY / 64)
}
You can do checks like see if x0,y0 and x1,y1 are on the same tile, in the logical space by someting as simple as:
bool isSameTile(x0, y0, x1, y1) {
return floor(x0/64) == floor(x1/64) && floor(y0/64) == floor(y1/64)
}
Everything gets much simpler once you define the transforms and work in the logical space.
http://en.wikipedia.org/wiki/Rotation_matrix
http://en.wikipedia.org/wiki/Scaling_%28geometry%29#Matrix_representation
http://www.alcove-games.com/advanced-tutorials/isometric-tile-picking/
If you don't want to deal with some matrix library, you can do the equivalent math pretty straightforwardly, but if you separate concerns of logic management from display / input through these transformations, I suspect you'll have a much easier time of it.

SDL 2 bullet collision not working?

I'm new to SDL 2 and I've been stuck on a collision detection between a bullet and a spaceship for some time.
I understand what has to happen, but I'm getting confused with what collides with what, and which way around to put the code. The collision detection doesn't work, and some other attempts I've made results in the bullet disappearing at the spaceships y coordinate, even if it is on the opposite side of the screen! I've based it around a lazy foo tutorial.
My whole code is here: http://codepad.org/YaCavBvm
My collision detection based around LazyFoo:
//sides of sprite rectangles
int leftBullet, leftEnemy;
int rightBullet, rightEnemy;
int topBullet, topEnemy;
int bottomBullet, bottomEnemy;
//Calculate the sides of bullet
leftBullet = posBullet.x;
rightBullet = posBullet.x + BULLET_WIDTH;
topBullet = posBullet.y;
bottomBullet = posBullet.y + BULLET_HEIGHT;
//Calculate the sides of enemy
leftEnemy = posEnemy.x;
rightEnemy = posEnemy.x + SPRITE_WIDTH;
topEnemy = posEnemy.y;
bottomEnemy = posEnemy.y + SPRITE_HEIGHT;
for (int i=0; i<MAX_BULLETS; i++)
{
if (topBullet == bottomEnemy)
{
arrayofBullets[i].isActive = false;
}
}
In theory, a bullet grazing the bottom of your foot is a hit but you could regard that as a hit or a miss. Try the following
if (topBullet >= topEnemy &&
bottomBullet <= bottomEnemy &&
leftBullet >= leftEnemy &&
rightBullet <= rightEnemy)
// What happens when the bullet hits
This will take care of the partial hits. The one in lazyfoo is for one particular case which is correct in the context of the example.

Circular collision rebound not working properly

I'm writing a little physics simulation in C++ that basically moves circles across the screen and when two circles collide, they should ricochet in the same manner as billiard balls would. When the circles do collide with each other, most of the time they will practically slow down infinitely/they appear to stick to each other and become static. Sometimes only one ball will rebound in the collision and the other will retain it's trajectory. This is just a simple 2D simulation.
So here's what I have for the detection/ricochet logic:
bool Ball::BallCollision(Ball &b2)
{
if (sqrt(pow(b2.x - x, 2) + pow(b2.y - y, 2)) <= b2.radius + radius) // Test for collision
{
normal[0] = (x - (x + b2.x) / 2) / radius; // Finds normal vector from point of collision to radius
normal[1] = (y - (y + b2.y) / 2) / radius;
xvel = xvel - 2 * (xvel * normal[0]) * normal[0]; // Sets the velocity vector to the reflection vector
yvel = yvel - 2 * (yvel * normal[1]) * normal[1];
////x = xprev; // These just move the circle back a 'frame' so the collision
////y = yprev; // detection doesn't detect collision more than once.
// Not sure if working?
}
}
I can't figure out what is wrong with my function. Thanks for any help in advance!
Edit:
Every variable is declared as a float
The functions:
void Ball::Move()
{
xprev = x;
yprev = y;
x += xvel;
y += yvel;
}
void Ball::DrawCircle()
{
glColor3ub(100, 230, 150);
glBegin(GL_POLYGON);
for (int i = 0; i < 10; i++)
{
angle = i * (2*3.1415/10);
newx = x + r*cos(angle);
newy = y + r*sin(angle);
glVertex2f(newx, newy);
}
glEnd();
}
The loop:
run_prev.clear(); // A vector, cleared every loop, that holds the Ball objects that collided
for (int i = 0; i < num_balls; i++)
{
b[i].Move();
}
for (int i = 0; i < num_balls; i++)
{
b[i].WallCollision(); // Just wall collision detecting, that is working just fine
}
//The loop that checks for collisions... Am I executing this properly?
for (int i = 0; i < num_balls; i++)
{
for (int j = 0; j < num_balls; j++)
{
if (i == j) continue;
if (b[i].BallCollision(b[j]) == true)
{
run_prev.push_back(b[i]);
}
}
}
for (int i = 0; i < num_balls; i++)
{
b[i].DrawCircle();
}
//xprev and yprev are the x and y values of the frame before for each circle
for (int i = 0; i < run_prev.size(); i++)
{
run_prev[i].x = run_prev[i].xprev;
run_prev[i].y = run_prev[i].yprev;
}
Makes balls collide (reflect movement vector) only if they're moving towards each other. Do not process collision if they're moving away from each other. Break this rule, and they'll be glued together.
When processing collision, update both balls at once. Do not update one ball at a time.
Your move vector adjustment is incorrect. Balls don't reflect against each other, because they can be moving at different speeds.
Correct movement adjustment (assuming balls have equal mass) should look something like that:
pos1 and pos2 = positions;
v1 and v2 are movement vector (speed);
n is collision normal == normalize(pos1 - pos2);
collisionSpeed = dot((v2-v1), n);
collisionSpeed *= elasticy; (0.0..1.0);
v1 = v1 - dot(v1, n);
v2 = v2 - dot(v2, n);
v1 -= scale(n, collisionSpeed * 0.5);
v2 += scale(n, collisionSpeed * 0.5);
To understand the formula, check newtons law (impulses in particular). Or check Chris Hecker's papers on game physics.
It's not clear how you're calling this function, but I think I see the problem.
Say you have Ball ballA and Ball ballB, which are colliding in the current frame, and then you run ballA.BallCollision(ballB).
This will update the member variables of ballA, and move it back a frame. But it doesn't update the position or trajectory of ballB.
Even if you call the converse as well (ballB.BallCollision(ballA)), it won't detect the collision because when you called ballA.BallCollision(ballB), it moved ballA back a frame.
I haven't looked at your code in detail, but it doesn't take into consideration that this type of collision can only work in center of momentum frames. Now, I assume your balls are of equal masses. What you do is take the average of the two momentums (or velocities since they have the same masses) and subtract that average from the velocities. Perform your calculations, and add the average back. Here is the question I asked that may relate to this.
I know this question is quite old, but it's still relevant, especially to students. Something that wasn't mentioned in the answers made me want to contribute.
One thing that I ran into when solving a similar problem was overlap. That is, if the moving balls overlap by any amount at all, the collision detection will trigger continuously, giving the sticking behavior the OP referred to.
There was an attempt here to prevent this by moving the balls to the previous frame, but that can occasionally fail if the movement was enough that the balls enmeshed more than a single frame can account for, or if the movement velocity is just right so that the frame before doesn't trigger collision but the frame after is too far overlapped.
Since the original check was for center distance less than or equal to the sum of the radii, the detection triggers on both collision AND overlap.
One way to fix this is to separate the test into checking for collision (equals only) or overlap (less than only). For the collision, proceed as normal. But for the overlap condition, you can physically move one ball or the other (or both by half) the amount of overlap. This positions them at correct "collision" position, which allows for the correct behavior of the bounce function.
An overlap function that only moves one ball at a time might look something like this(not real code):
if (distanceBetweenBallCenters < sumOfRadii){
currentPosition = oldPosition - (distanceBetweenBallCenters - sumOfRadii) * (unitVectorFromSecondBallToFirstBall);
}
One could easily move both balls by half, but I found that moving one at a time gave satisfactory results for my uses, and allowed me to keep the parameter as a const.
I hope this helps future students! (I am also a student, and new to this, so take my advice with the proverbial grain of salt)
Your way of calculating the normal is wrong. (x + b2.x)/2 doesn't have to be the point of collision, if the radii of the balls aren't equal.

2D Platformer Collision Handling

I am trying to create a 2D platformer (Mario-type) game and I am some having some issues with handling collisions properly. I am writing this game in C++, using SDL for input, image loading, font loading, etcetera. I am also using OpenGL via the FreeGLUT library in conjunction with SDL to display graphics.
My method of collision detection is AABB (Axis-Aligned Bounding Box), which is really all I need to start with. What I need is an easy way to both detect which side the collision occurred on and handle the collisions properly. So, basically, if the player collides with the top of the platform, reposition him to the top; if there is a collision to the sides, reposition the player back to the side of the object; if there is a collision to the bottom, reposition the player under the platform.
I have tried many different ways of doing this, such as trying to find the penetration depth and repositioning the player backwards by the penetration depth. Sadly, nothing I've tried seems to work correctly. Player movement ends up being very glitchy and repositions the player when I don't want it to. Part of the reason is probably because I feel like this is something so simple but I'm over-thinking it.
If anyone thinks they can help, please take a look at the code below and help me try to improve on this if you can. I would like to refrain from using a library to handle this (as I want to learn on my own) or the something like the SAT (Separating Axis Theorem) if at all possible. Thank you in advance for your help!
void world1Level1CollisionDetection()
{
for(int i; i < blocks; i++)
{
if (de2dCheckCollision(ball,block[i],0.0f,0.0f)==true)
{
de2dObj ballPrev;
ballPrev.coords[0] = ball.coords[0];
ballPrev.coords[1] = ball.coords[1];
ballPrev.coords[2] = ball.coords[2];
ballPrev.coords[3] = ball.coords[3];
ballPrev.coords[0] -= ball.xspeed;
ballPrev.coords[1] -= ball.yspeed;
ballPrev.coords[2] -= ball.xspeed;
ballPrev.coords[3] -= ball.yspeed;
int up = 0;
int left = 0;
int right = 0;
int down = 0;
if (ballPrev.coords[0] < block[i].coords[0] && ballPrev.coords[2] < block[i].coords[0] && (((ball.coords[1] < block[i].coords[1]) || (ball.coords[3] < ball.coords[1])) || ((ball.coords[1] < block[i].coords[3]) || ball.coords[3] < block[i].coords[3])))
{
left = 1;
}
if (ballPrev.coords[0] > block[i].coords[2] && ballPrev.coords[2] > block[i].coords[2] && (((ball.coords[1] < block[i].coords[1]) || (ball.coords[3] < ball.coords[1])) || ((ball.coords[1] < block[i].coords[3]) || (ball.coords[3] < block[i].coords[3]))))
{
right = 1;
}
if(ballPrev.coords[1] < block[i].coords[1] && block[i].coords[1] < ballPrev.coords[3] && ballPrev.coords[3] < block[i].coords[3])
{
up = 1;
}
if(block[i].coords[1] < ballPrev.coords[1] && ballPrev.coords[1] < block[i].coords[3] && block[i].coords[3] < ballPrev.coords[3])
{
down = 1;
}
cout << left << ", " << right << ", " << up << ", " << down << ", " << endl;
if (left == 1)
{
ball.coords[0] = block[i].coords[0] - 18.0f;
ball.coords[2] = block[i].coords[0] - 2.0f;
}
else if (right == 1)
{
ball.coords[0] = block[i].coords[2] + 2.0f;
ball.coords[2] = block[i].coords[2] + 18.0f;
}
else if (down == 1)
{
ball.coords[1] = block[i].coords[3] + 4.0f;
ball.coords[3] = block[i].coords[3] + 20.0f;
}
else if (up == 1)
{
ball.yspeed = 0.0f;
ball.gravity = 0.0f;
ball.coords[1] = block[i].coords[1] - 17.0f;
ball.coords[3] = block[i].coords[1] - 1.0f;
}
}
if (de2dCheckCollision(ball,block[i],0.0f,0.0f)==false)
{
ball.gravity = -0.5f;
}
}
}
To explain what some of this code means:
The blocks variable is basically an integer that is storing the amount of blocks, or platforms. I am checking all of the blocks using a for loop, and the number that the loop is currently on is represented by integer i.
The coordinate system might seem a little weird, so that's worth explaining.
coords[0] represents the x position (left) of the object (where it starts on the x axis).
coords[1] represents the y position (top) of the object (where it starts on the y axis).
coords[2] represents the width of the object plus coords[0] (right).
coords[3] represents the height of the object plus coords[1] (bottom).
de2dCheckCollision performs an AABB collision detection.
Up is negative y and down is positive y, as it is in most games.
Hopefully I have provided enough information for someone to help me successfully. If there is something I left out that might be crucial, let me know and I'll provide the necessary information. Finally, for anyone who can help, providing code would be very helpful and much appreciated.
Thank you again for your help!
Edit 2: I have updated my code with a new algorithm that checks where the ball was previously before collision. Corner cases work on that single platform correctly now, and when I have a wall of objects, I can slide against it correctly now. The only remaining problem is that there is a small jittering effect that happens when I am on the ground, where the ball is constantly going up and down as if it is being pulled by gravity and then the ball falls back into the object again.
Edit: Here is a URL to an image trying to show the kinds of problems I am having:
http://img8.imageshack.us/img8/4603/collisionproblem.png
In case the explanation in the picture doesn't make too much sense, the ball cannot move left past the corner of an object unless I jump over it. However, the ball can move right, but it gets repositioned to the right of the object while moving, which is not needed. This creates a skipping movement essentially, where it appears as the the ball is skipping over half of the object or so when I move right. If this doesn't make sense, please ask me and I'll try to clarify more.
One problem with your code is that you only detect situations like this:
If the circle happens to be fully inside the block, you don't reposition at all. And that's a problem.
You're trying to think about your simulation as if it were continuous, but keep in mind it's discrete. In general, if you only look at the current state of the ball, you really cannot know which side it collided with. Look at these two possibilities:
The first solution that comes to mind is to look at the last position of the ball as well; more precisely, look at the delta vector. See if the delta vector intersects a wall. If it does, reposition in an axis-aligned direction towards the wall intersected by the delta vector.
Edit: When I said "delta vector", I forgot that you're moving a square and not a single point. So, if you just look at the delta vector of the top-left corner, that's not going to be enough because it may not detect that part of the ball entered a block. Instead, you can look at the delta vectors of all 4 corners.