solid rectangle collision
-
- Posts: 4373
- Joined: February 28th, 2013, 3:23 am
- Location: Oklahoma, United States
Re: solid rectangle collision
Man I miss this project actually.
If you think paging some data from disk into RAM is slow, try paging it into a simian cerebrum over a pair of optical nerves. - gameprogrammingpatterns.com
-
- Posts: 8
- Joined: September 5th, 2020, 1:01 am
Re: solid rectangle collision
alright i give up thanks alot. i appreciate it. i just dont understand it at all at this point i dont even know what Vec2 is or the ?
i guess ill just wait until im better at coding its just that it seems a lot easier than i thought. and also there is no velocity im moving the square with WASD.
i guess ill just wait until im better at coding its just that it seems a lot easier than i thought. and also there is no velocity im moving the square with WASD.
-
- Posts: 4373
- Joined: February 28th, 2013, 3:23 am
- Location: Oklahoma, United States
Re: solid rectangle collision
Vec2 is just a struct that holds an X and a Y.
A struct is just a way of grouping related data together.
The Vec2 in this case represents a 2D mathematical vector.
While not a true velocity, moving the square using WASD does give the square a direction and the amount you move the square each frame is your speed. So combining those two you get velocity, you just need to keep track of it's previous position before moving it then subtracting the current position and it's previous position gives you it's velocity over the previous frame. Then you can use the steps I provided.
A struct is just a way of grouping related data together.
The Vec2 in this case represents a 2D mathematical vector.
While not a true velocity, moving the square using WASD does give the square a direction and the amount you move the square each frame is your speed. So combining those two you get velocity, you just need to keep track of it's previous position before moving it then subtracting the current position and it's previous position gives you it's velocity over the previous frame. Then you can use the steps I provided.
If you think paging some data from disk into RAM is slow, try paging it into a simian cerebrum over a pair of optical nerves. - gameprogrammingpatterns.com
-
- Posts: 4373
- Joined: February 28th, 2013, 3:23 am
- Location: Oklahoma, United States
Re: solid rectangle collision
Oh, the ? is half of an operator called the ternary operator.
It's used like this:
result = condition ? condition_true : condition_false;
It's short hand for if/else and can be used like so:
int a = 2;
int b = 3;
int max_ab = a>b ? a : b;
Where using if/else would be
It's used like this:
result = condition ? condition_true : condition_false;
It's short hand for if/else and can be used like so:
int a = 2;
int b = 3;
int max_ab = a>b ? a : b;
Where using if/else would be
Code: Select all
if( a > b )
max_ab = a;
else
max_ab = b;
If you think paging some data from disk into RAM is slow, try paging it into a simian cerebrum over a pair of optical nerves. - gameprogrammingpatterns.com
-
- Posts: 4373
- Joined: February 28th, 2013, 3:23 am
- Location: Oklahoma, United States
Re: solid rectangle collision
Code: Select all
// This is how to define a struct
struct CollisionResult{
// To handle position and velocity correction, you'll need to
// return both. A struct or class is the only way of doing
// such a thing using the return statement
int xPosition = 0, yPosition = 0;
int xVelocity = 0, yVelocity = 0;
};
// For simplicity, here's another struct to store the necessary elements for the
// HandleCollision() function
struct PhysicsProperties{
int xPosition = 0, yPosition = 0; // The position of the object
int xVelocity = 0, yVelocity = 0; // The velocity of the object
int width = 0, height = 0; // The dimensions of the object
};
void Game::Update(){
int xPrevPosition = xSquarePosition;
int yPrevPosition = ySquarePosition;
// handle keyboard input
if( /* w pressed */ ){ /*move square up*/ }
else if( /* s pressed */ ){/*move square down*/}
if( /* d pressed */ ){/*move square right*/}
else if( /* a pressed */ ) {/*move square left*/}
if( IsColliding( xSquarePosition, ySquarePosition, squareWidth, squareHeight,
xWallPosition, yWallPosition, wallWidth, wallHeight )
{
PhysicsProperties squareProps;
squareProps.xPosition = xSquarePosition;
squareProps.yPosition = ySquarePosition;
squareProps.xVelocity = xSquarePosition - xPrevPosition;
squareProps.yVelocity = ySquarePosition - yPrevPosition;
squareProps.width = squareWidth;
squareProps.height = squareHeight;
PhysicsProperties wallProps;
wallProps.xPosition = xWallPosition;
wallProps.yPosition = yWallPosition;
wallProps.xVelocity = 0;
wallProps.yVelocity = 0;
wallProps.width = wallWidth;
wallProps.height = wallHeight;
CollisionResult result = HandleCollision( squareProps, wallProps );
// Once we have the corrected results, we need to adjust the squares position
xSquarePosition = result.xPosition;
ySquarePosition = result.yPosition;
}
}
CollisitionResult HandleCollision( PhysicsProperties const& ObjectA, PhysicsProperties const& ObjectB )noexcept
{
// Let's assume here that ObjectA are the square's properties and
// ObjectB are the wall's properties
CollisionResult result;
int xPenetration = 0;
int yPenetration = 0;
if( ObjectA.yVelocity == 0 )
{
// Moving horizontal
if( ObjectA.xVelocity < 0 )
{
// square left, wall right
result.xPosition = ObjectA.xPosition + ( ( ObjectB.xPosition + ObjectB.width ) - ObjectA.xPosition );
result.xVelocity = 0;
}
else if( ObjectA.xVelocity > 0 )
{
// square right, wall left
result.xPosition = ObjectA.xPosition + ( ObjectB.xPosition - ( ObjectA.xPosition + ObjectA.width ) );
result.xVelocity = 0;
}
}
else
{
if( ObjectA.xVelocity < 0 )
{
if( ObjectA.yVelocity > 0 )
{
// Heading left and down
xPenetration = ( ObjectB.xPosition + ObjectB.width ) - ObjectA.xPosition;
yPenetration = ( ObjectA.yPosition + ObjectA.height ) - ObjectB.yPosition;
if( penetration.x * velocity.y > penetration.y * -velocity.x )
{
result.yPosition = ObjectA.yPosition - yPenetration;
result.yVelocity = 0;
}
else
{
result.xPosition = ObjectA.xPosition + xPenetration;
result.xVelocity = 0;
}
}
else
{
// Heading left and up
xPenetration = ( ObjectB.xPosition + ObjectB.width ) - ObjectA.xPosition;
yPenetration = ( OjbectB.yPosition + ObjectB.height ) - ObjectA.yPosition;
if( penetration.x * -velocity.y > penetration.y * -velocity.x )
{
result.yPosition = ObjectA.yPosition + yPenetration;
result.yVelocity = 0;
}
else
{
result.xPosition = ObjectA.xPosition + xPenetration;
result.xVelocity = 0;
}
}
}
else if( ObjectA.xVelocity > 0 )
{
if( ObjectA.yVelocity > 0 )
{
// Heading right and down
xPenetration = ObjectA.xPosition + ObjectA.width - ObjectB.xPosition;
yPenetration = ObjectA.yPosition + ObjectA.height - ObjectB.yPosition;
if( xPenetration * ObjectA.yVelocity > yPenetration * ObjectA.xVelocity )
{
// square bottom, wall top
result.yPosition = ObjectA.yPosition - yPenetration;
result.yVelocity = 0;
}
else
{
// square right, wall left
result.xPosition = ObjectA.xPosition - xPenetration;
result.xVelocity = 0;
}
}
else if( ObjectA.yVelocity < 0 )
{
// Heading right and up
xPenetration = ( ObjectA.xPosition + ObjectA.width ) - ObjectB.xPosition;
yPenetration = ( ObjectB.xPosition + ObjectB.height ) - ObjectA.yPosition;
if( xPenetration * -ObjectA.yVelocity > yPenetration * ObjectA.xVelocity )
{
// square top, wall bottom
result.yPosition = ObjectA.yPosition + yPenetration;
result.yVelocity = 0;
}
else
{
// square right, wall left
result.xPosition = ObjectA.xPosition - xPenetration;
result.xVvelocity = 0;
}
}
}
else
{
// Moving vertical
if( ObjectA.yVelocity < 0.f )
{
// hero top, wall bottom
result.yPosition = ObjectA.yPosition + ( ( ObjectB.yPosition + ObjectB.height ) - ObjectA.yPosition );
result.yVelocity = 0;
}
else
{
// hero bottom, wall top
result.yPosition = ObjectA.yPosition + ( ObjectB.yPosition - ( ObjectA.yPosition + ObjectA.height ) );
velocity.y = 0;
}
}
}
}
If you think paging some data from disk into RAM is slow, try paging it into a simian cerebrum over a pair of optical nerves. - gameprogrammingpatterns.com
-
- Posts: 8
- Joined: September 5th, 2020, 1:01 am
Re: solid rectangle collision
thanks for that last post i dont even know what a struct either lol. i dont wanna discredit your help but i think i figured it out almost so what i did was make a bool for detection (isColliding) this is just a bool variable that holds the result for the collision detection ( IsColliding() ). then what i did is once the isColliding returns true (meaning it hit the side of the wall) i set the player position to the wall thats colliding. but now the issue is when i press another key since isColliding is still true it jumps to that corresponding side if the wall. i found out that when i move the player to the wall sometimes itll be placed 1 pixel from the wall preventing the collison, but sometime itll place the player on the wall causing a collision which means when i try to press the oposite key it snaps to the other side completely going throught the wall.
Code: Select all
void Game::UpdateModel()
{
if (wnd.kbd.KeyIsPressed('W'))
{
if (isColliding)
{
playerY = (wallY + wallHeight) + 1;
}
else if (!isColliding)
{
playerY -= 3;
}
}
if (wnd.kbd.KeyIsPressed('A'))
{
if (isColliding)
{
playerX = (wallX + wallWidth) + 1;
}
else if (!isColliding)
{
playerX -= 3;
}
}
if (wnd.kbd.KeyIsPressed('S'))
{
if (isColliding)
{
playerY = (wallY - playerHeight) - 1;
}
else if (!isColliding)
{
playerY += 3;
}
}
if (wnd.kbd.KeyIsPressed('D'))
{
if (isColliding)
{
playerX = (wallX - playerWidth) - 1;
}
else if(!isColliding)
{
playerX += 3;
}
}
playerX = ClampScreenX(playerX, playerWidth);
playerY = ClampScreenY(playerY, playerHeight);
isColliding = IsColliding(playerX, playerY, playerWidth, playerHeight, wallX, wallY, wallWidth, wallHeight);
}
-
- Posts: 4373
- Joined: February 28th, 2013, 3:23 am
- Location: Oklahoma, United States
Re: solid rectangle collision
This may or may not help your situation, but it's worth a shot:
The main differences are updating the position first using the direction, testing for collision AFTER moving and the if else for the two axes.
Without the if else for each axis, pressing 'up' and 'down' ( w,s ) means both are true and both blocks are executed. So moving into the wall from the top, then pressing 'W' means that the moving up block is run and moves the player to the bottom.
Code: Select all
void Game::UpdateModel()
{
int vx = 0;
int vy = 0;
if (wnd.kbd.KeyIsPressed('W'))
{
vy = -3;
}
else if (wnd.kbd.KeyIsPressed('S'))
{
vy = 3;
}
if (wnd.kbd.KeyIsPressed('A'))
{
vx = -3;
}
else if (wnd.kbd.KeyIsPressed('D'))
{
vx = 3;
}
playerX += vx;
playerY += vy;
playerX = ClampScreenX(playerX, playerWidth);
playerY = ClampScreenY(playerY, playerHeight);
isColliding = IsColliding(playerX, playerY, playerWidth, playerHeight, wallX, wallY, wallWidth, wallHeight);
if (isColliding)
{
if( vy < 0 )
playerY = (wallY + wallHeight) + 1;
else if( vy > 0 )
playerY = (wallY - playerHeight) - 1;
if( vx < 0 )
playerX = (wallX + wallWidth) + 1;
else if( vx > 0 )
playerX = (wallX - playerWidth) - 1;
}
}
Without the if else for each axis, pressing 'up' and 'down' ( w,s ) means both are true and both blocks are executed. So moving into the wall from the top, then pressing 'W' means that the moving up block is run and moves the player to the bottom.
If you think paging some data from disk into RAM is slow, try paging it into a simian cerebrum over a pair of optical nerves. - gameprogrammingpatterns.com