Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[feat] Fix endless falling, enable jump, enable computer player, add score system #92

Open
wants to merge 8 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
42 changes: 42 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -1 +1,43 @@
# GameX

## Game Controls:

#### Movement

- **W:** Move the ball forward
- **A:** Move the ball left
- **S:** Move the ball backward
- **D:** Move the ball right
- **R:** Rotate the ball with angular velocity in the z-direction
- **J:** Jump, perform a double jump while falling

#### Difficulty Modes

- **0:** Switch to original mode
- **1:** Switch to easy mode
- **2:** Switch to medium mode
- **3:** Switch to difficult mode

## Gameplay:

Welcome to the ball game!

Your mission is to navigate your ball strategically to defeat the stationary enemy. Master the controls to adjust direction, rotation, and execute jumps to defeat your enemy in a more fantasy way. When starting the game, your adversary remains motionless, providing you with an opportunity to plan your moves. Choose the level of challenge that suits you by pressing the corresponding number key.

## End of Game:

The game concludes when the ball falls from the platform. At this point, the results of your game will be displayed in a new window. The results may include your score. A new game will restart automatically after falling down for a few seconds.

### Known Issues:

After the results window closes, the mouse focus may not automatically return to the game window. To resume playing, simply click the mouse once within the game window. In addition, if you have any suggestions to enhance the visual appeal of the window, I would greatly appreciate hearing them.

## Tips:

* Experiment with the controls to get comfortable with the ball's movement and rotation.
* Timing is crucial, especially when performing jumps and double jumps.
* Pay attention to the environment and adapt your strategy to overcome different challenges.

Have a great time playing the Ball Game! If you encounter any issues or have suggestions for improvements, feel free to provide feedback.

#### Enjoy the game and have fun rolling your way to victory!
Binary file added external/.DS_Store
Binary file not shown.
2 changes: 2 additions & 0 deletions src/GameBall/core/game_ball.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,8 @@ void GameBall::OnInit() {

auto primary_player = world->CreatePlayer();
auto enemy_player = world->CreatePlayer();
primary_player->is_enemy = false;
enemy_player->is_enemy = true;
auto primary_unit = world->CreateUnit<Logic::Units::RegularBall>(
primary_player->PlayerId(), glm::vec3{0.0f, 1.0f, 0.0f}, 1.0f, 1.0f);
auto enemy_unit = world->CreateUnit<Logic::Units::RegularBall>(
Expand Down
2 changes: 2 additions & 0 deletions src/GameBall/logic/player.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@ class Player {

PlayerInput TakePlayerInput();

bool is_enemy;

private:
World *world_;
uint64_t player_id_{};
Expand Down
6 changes: 6 additions & 0 deletions src/GameBall/logic/player_input.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,12 @@ PlayerInput PlayerInputController::GetInput() {
input_.move_backward = (glfwGetKey(window, GLFW_KEY_S) == GLFW_PRESS);
input_.move_left = (glfwGetKey(window, GLFW_KEY_A) == GLFW_PRESS);
input_.move_right = (glfwGetKey(window, GLFW_KEY_D) == GLFW_PRESS);
input_.rotate_z = (glfwGetKey(window, GLFW_KEY_R) == GLFW_PRESS);
input_.move_up = (glfwGetKey(window, GLFW_KEY_J) == GLFW_PRESS);
input_.easy_mode = (glfwGetKey(window, GLFW_KEY_1) == GLFW_PRESS);
input_.medium_mode = (glfwGetKey(window, GLFW_KEY_2) == GLFW_PRESS);
input_.difficult_mode = (glfwGetKey(window, GLFW_KEY_3) == GLFW_PRESS);
input_.original_mode = (glfwGetKey(window, GLFW_KEY_0) == GLFW_PRESS);
input_.brake = (glfwGetKey(window, GLFW_KEY_SPACE) == GLFW_PRESS);
auto camera_controller = app_->CameraController();
auto pitch_yaw = camera_controller->GetPitchYaw();
Expand Down
6 changes: 6 additions & 0 deletions src/GameBall/logic/player_input.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,12 @@ struct PlayerInput {
bool move_backward{false};
bool move_left{false};
bool move_right{false};
bool rotate_z{false};
bool move_up{false};
bool easy_mode{false};
bool medium_mode{false};
bool difficult_mode{false};
bool original_mode{false};
bool brake{false};
glm::vec3 orientation{0.0f, 0.0f, 1.0f};
};
Expand Down
143 changes: 105 additions & 38 deletions src/GameBall/logic/units/regular_ball.cpp
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
#include "GameBall/logic/units/regular_ball.h"

#include "GameBall/core/game_ball.h"
#include "GameBall/logic/units/settlement.h"
#include "GameBall/logic/world.h"

namespace GameBall::Logic::Units {
Expand Down Expand Up @@ -45,47 +46,113 @@ void RegularBall::UpdateTick() {
auto physics_world = world_->PhysicsWorld();
auto &sphere = physics_world->GetSphere(sphere_id_);

// auto owner = world_->GetPlayer(player_id_);
// if (owner) {
// if (UnitId() == owner->PrimaryUnitId()) {
// auto input = owner->TakePlayerInput();
//
// glm::vec3 forward = glm::normalize(glm::vec3{input.orientation});
// glm::vec3 right =
// glm::normalize(glm::cross(forward, glm::vec3{0.0f, 1.0f, 0.0f}));
//
// glm::vec3 moving_direction{};
//
// float angular_acceleration = glm::radians(2880.0f);
//
// if (input.move_forward) {
// moving_direction -= right;
// }
// if (input.move_backward) {
// moving_direction += right;
// }
// if (input.move_left) {
// moving_direction -= forward;
// }
// if (input.move_right) {
// moving_direction += forward;
// }
//
// if (glm::length(moving_direction) > 0.0f) {
// moving_direction = glm::normalize(moving_direction);
// sphere.angular_velocity +=
// moving_direction * angular_acceleration * delta_time;
// }
//
// if (input.brake) {
// sphere.angular_velocity = glm::vec3{0.0f};
// }
// }
// }

auto owner = world_->GetPlayer(player_id_);
sphere.velocity *= std::pow(0.5f, delta_time);
sphere.angular_velocity *= std::pow(0.2f, delta_time);

if (owner) {
auto input = owner->TakePlayerInput();
if (input.original_mode) {
std::cout << "Switch to original mode\n";
world_->difficulty = 0;
}
if (input.easy_mode) {
std::cout << "Switch to easy mode\n";
world_->difficulty = 2;
}
if (input.medium_mode) {
std::cout << "Switch to medium mode\n";
world_->difficulty = 4;
}
if (input.difficult_mode) {
std::cout << "Switch to difficult mode\n";
world_->difficulty = 6;
}
if (UnitId() == owner->PrimaryUnitId()) {
glm::vec3 forward = glm::normalize(glm::vec3{input.orientation});
glm::vec3 right =
glm::normalize(glm::cross(forward, glm::vec3{0.0f, 1.0f, 0.0f}));
glm::vec3 z_rotate_speed =
glm::normalize(glm::cross(forward, glm::vec3{0.0f, 0.0f, 1.0f}));

glm::vec3 moving_direction{};

float angular_acceleration = glm::radians(2880.0f);

if (input.move_forward) {
moving_direction -= right;
}
if (input.move_backward) {
moving_direction += right;
}
if (input.move_left) {
moving_direction -= forward;
}
if (input.move_right) {
moving_direction += forward;
}
if (input.rotate_z) {
moving_direction += z_rotate_speed;
}
if (input.move_up) {
if (jump == 1 && sphere.velocity.y < 0) {
sphere.velocity.y = 5;
jump++;
// std::cout << "double jump" << std::endl;
} else if (jump == 0) {
sphere.velocity.y += 3.5;
jump++;
// std::cout << "first jump" << std::endl;
}
// std::cout << sphere.velocity.y << " " << sphere.position.y <<
// std::endl;
}
if (glm::length(moving_direction) > 0.0f) {
moving_direction = glm::normalize(moving_direction);
sphere.angular_velocity +=
moving_direction * angular_acceleration * delta_time;
}

if (input.brake) {
sphere.angular_velocity = glm::vec3{0.0f};
}
world_->owner_place = sphere.position;
}
else {
glm::vec3 relative_pos = glm::normalize(sphere.position - world_->owner_place);
sphere.velocity -= 0.01f * world_->difficulty * relative_pos;
}
}

position_ = sphere.position;
if (position_.y < -30) {
std::string result;
if (owner->is_enemy) {
result = "you win";
sphere.position = glm::vec3{-5.0f, 1.0f, 0.0f};
world_->restart = 1;
world_->score[0]++;
} else {
result = "you lose";
sphere.position = glm::vec3{0.0f, 1.0f, 0.0f};
world_->restart = 2;
world_->score[1]++;
}
result += "\t\tSCORE: " + std::to_string(world_->score[0]) + " : " +
std::to_string(world_->score[1]);
showWindow(result);
// std::cout << "SCORE: " << world_->score[0] << " " << world_->score[1]
// << std::endl;
} else if (position_.y > 0 && position_.y < 1) {
jump = 0;
}
if (world_->restart == 1 && !owner->is_enemy) {
sphere.position = glm::vec3{0.0f, 1.0f, 0.0f};
world_->restart = 0;
} else if (world_->restart == 2 && owner->is_enemy) {
sphere.position = glm::vec3{-5.0f, 1.0f, 0.0f};
world_->restart = 0;
}
position_ = sphere.position;
velocity_ = sphere.velocity;
orientation_ = sphere.orientation;
Expand Down
1 change: 1 addition & 0 deletions src/GameBall/logic/units/regular_ball.h
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ class RegularBall : public Unit {
private:
float radius_{1.0f};
float mass_{1.0f};
int jump;
glm::vec3 position_{};
glm::vec3 velocity_{};
glm::mat3 orientation_{1.0f};
Expand Down
45 changes: 45 additions & 0 deletions src/GameBall/logic/units/settlement.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
#include <string>
#ifdef __APPLE__
#include <GLFW/glfw3.h>
#include <dispatch/dispatch.h>

void renderLoop(GLFWwindow* window) {
// Set the start time
double startTime = glfwGetTime();

while (glfwGetTime() - startTime <= 2.0) {
glfwSwapBuffers(window);
glfwPollEvents();
}
glfwSetWindowShouldClose(window, true);
glfwDestroyWindow(window);
}

void createWindowAndRunLoop(std::string str) {
GLFWwindow* window = glfwCreateWindow(600, 50, "window", NULL, NULL);
if (!window) {
glfwTerminate();
// Handle error appropriately
return;
}
glfwSetWindowTitle(window, str.c_str());
glfwMakeContextCurrent(window);

// Run the rendering loop on the main thread
renderLoop(window);
}

void showWindow(std::string str) {
if (!glfwInit()) {
return;
}
// Use dispatch_async to execute window creation on the main thread
dispatch_async(dispatch_get_main_queue(), ^{
createWindowAndRunLoop(str);
});
}
#else
void showWindow(std::string str) {
std::cout << str << std::endl;
}
#endif
8 changes: 8 additions & 0 deletions src/GameBall/logic/world.h
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,14 @@ class World {

void UpdateTick();

int restart = 0;

int score[2] = {0, 0};

glm::vec3 owner_place = {0.0f, 1.0f, 0.0f};

int difficulty = 0;

private:
friend ::GameBall::GameBall;
friend ::GameBall::Logic::Manager;
Expand Down