Re: solid rectangle collision
Posted: September 19th, 2020, 10:16 am
Man I miss this project actually.
Learn to program or die trying
https://forum.planetchili.net:443/
Code: Select all
if( a > b )
max_ab = a;
else
max_ab = b;
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;
}
}
}
}
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);
}
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;
}
}