1
0

Collision Resolution

This commit is contained in:
2022-10-20 12:17:14 +02:00
parent 80fa82f618
commit 6b68fcc84c
2 changed files with 108 additions and 4 deletions

View File

@@ -1,5 +1,8 @@
#include "game.h"
#include <iostream>
#include <tuple>
typedef std::tuple<bool, Direction,glm::vec2> Collision;
SpriteRenderer* Renderer;
@@ -16,6 +19,30 @@ const float BALL_RADIUS = 12.5f;
BallObject* ball;
Direction VectorDirection(glm::vec2 target)
{
glm::vec2 compass[] = {
glm::vec2(0.0f, 1.0f), // up
glm::vec2(1.0f, 0.0f), // right
glm::vec2(0.0f,-1.0f), // down
glm::vec2(-1.0f, 0.0f) //left
};
float max = 0.0f;
unsigned int best_match = -1;
for (unsigned int i = 0; i < 4; i++)
{
float dot_product = glm::dot(glm::normalize(target), compass[i]);
if( dot_product > max )
{
max = dot_product;
best_match = i;
}
}
return (Direction) best_match;
}
// AABB with AABB collision detection
bool CheckCollisions(GameObject& one, GameObject& two)
{
@@ -30,7 +57,7 @@ bool CheckCollisions(GameObject& one, GameObject& two)
}
// AABB with circle collision detection
bool CheckCollisions(BallObject& one, GameObject& two)
Collision CheckCollisions(BallObject& one, GameObject& two)
{
// Calculate the closest point on two's border to the center point of one
glm::vec2 center (one.Position + one.Radius);
@@ -44,11 +71,16 @@ bool CheckCollisions(BallObject& one, GameObject& two)
// Calculate the distance and check if it is less then two's radius
difference = closest - center;
return glm::length(difference) < one.Radius;
if( glm::length(difference) < one.Radius)
{
return std::make_tuple(true, VectorDirection(difference), difference);
} else
{
return std::make_tuple(false, UP, glm::vec2(0.0f, 0.0f));
}
}
Game::~Game()
{
delete Renderer;
@@ -106,15 +138,52 @@ void Game::DoCollisions()
{
if(!box.Destroyed)
{
if(CheckCollisions(*ball, box))
Collision collision = CheckCollisions(*ball, box);
if(std::get<0>(collision)) // If we have collided
{
if(!box.IsSolid)
{
box.Destroyed = true;
}
// Collision resolution
Direction dir = std::get<1>(collision);
glm::vec2 diff_vector = std::get<2>(collision);
if (dir == LEFT || dir == RIGHT )
{
ball->Velocity.x = -ball->Velocity.x;
// relocate
float penetration = ball->Radius - std::abs(diff_vector.x);
if(dir == LEFT)
ball->Position.x += penetration;
else
ball->Position.x -= penetration;
}
else
{
ball->Velocity.y = -ball->Velocity.y;
float penetration = ball->Radius - std::abs(diff_vector.y);
if(dir == UP)
ball->Position.y -= penetration;
else
ball->Position.y += penetration;
}
}
}
}
Collision result = CheckCollisions(*ball, *player);
if(!ball->Stuck && std::get<0>(result)) // if we collided with player paddle
{
float centerBoard = player->Position.x + player->Size.x /2.0f;
float distance = (ball->Position.x + ball->Radius) - centerBoard;
float percentage = distance/ (player->Size.x / 2.0f);
float strength = 2.0f;
glm::vec2 oldVelocity = ball->Velocity;
ball->Velocity.x = INITIAL_BALL_VELOCITY.x * percentage * strength;
ball->Velocity.y = -1.0f * abs(ball->Velocity.y);
ball->Velocity = glm::normalize(ball->Velocity) * glm::length(oldVelocity);
}
}
@@ -157,6 +226,12 @@ void Game::Update(float dt)
{
ball->Move(dt, this->Width);
this->DoCollisions();
if(ball->Position.y >= this->Height)
{
this->ResetLevel();
this->ResetPlayer();
}
}
void Game::Render()
@@ -173,4 +248,23 @@ void Game::Render()
player->Draw(*Renderer);
ball->Draw(*Renderer);
}
}
void Game::ResetLevel()
{
if(this->Level == 0)
this->Levels[0].Load("levels/one.lvl", this->Width, this->Height /2 );
if(this->Level == 1)
this->Levels[1].Load("levels/two.lvl", this->Width, this->Height /2 );
if(this->Level == 2)
this->Levels[2].Load("levels/three.lvl", this->Width, this->Height /2 );
if(this->Level == 3)
this->Levels[3].Load("levels/four.lvl", this->Width, this->Height /2 );
}
void Game::ResetPlayer()
{
player->Size = PLAYER_SIZE;
player->Position = glm::vec2(this->Width / 2.0f - PLAYER_SIZE.x /2.0f, this->Height - PLAYER_SIZE.y);
ball->Reset(player->Position + glm::vec2(PLAYER_SIZE.x / 2.0f - BALL_RADIUS,-(BALL_RADIUS * 2.0f) ), INITIAL_BALL_VELOCITY);
}

View File

@@ -14,6 +14,12 @@ enum GameState {
GAME_MENU,
GAME_WIN
};
enum Direction {
UP,
RIGHT,
DOWN,
LEFT
};
class Game {
public:
// game state
@@ -36,6 +42,10 @@ class Game {
void Update(float dt);
void Render();
void DoCollisions();
void ResetLevel();
void ResetPlayer();
};