diff --git a/src/game.cpp b/src/game.cpp index 8be1f75..abc3550 100644 --- a/src/game.cpp +++ b/src/game.cpp @@ -1,5 +1,8 @@ #include "game.h" #include +#include + +typedef std::tuple 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); } \ No newline at end of file diff --git a/src/game.h b/src/game.h index d19b7c6..9618955 100644 --- a/src/game.h +++ b/src/game.h @@ -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(); + };