Skip to content
This repository has been archived by the owner on Aug 5, 2024. It is now read-only.

Commit

Permalink
init commit
Browse files Browse the repository at this point in the history
  • Loading branch information
Davenchy committed Sep 24, 2023
0 parents commit 899d9e8
Show file tree
Hide file tree
Showing 15 changed files with 362 additions and 0 deletions.
19 changes: 19 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
SRC := components/
BUILD := build/

SOURCE := $(wildcard $(SRC)/*.cpp)
OBJECT := $(patsubst $(SRC)/%.cpp, $(BUILD)/%.o, $(SOURCE))

.PHONY: run

cping_pong: $(OBJECT) $(BUILD)/main.o
gcc -Wall -lraylib -lm -o $@ $^

$(BUILD)/main.o: main.cpp
gcc -Wall -c $< -o $@

$(BUILD)/%.o: $(SRC)/%.cpp
gcc -Wall -c $< -o $@

run: cping_pong
@./cping_pong
30 changes: 30 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
# Ping Pong CPP

- A ping pong game written in Cpp using RayLib

<center>
![In-Game screenshot](screens/screen.png)
</center>

## How To Play

- Use the keys `K/Up` and `J/Down` to move **Up** and **Down**

## Build

- Make sure that RayLib is installed on your system then compile the project.

1. Create directory `build/`

```sh
$ mkdir -p build/
```

2. Compile the project by running `make` or `make run` to compile and run the project.

```sh
$ make
$ ./cping_pong
# OR
$ make run
```
Binary file added build/ball.o
Binary file not shown.
Binary file added build/game_manager.o
Binary file not shown.
Binary file added build/main.o
Binary file not shown.
Binary file added build/paddle.o
Binary file not shown.
46 changes: 46 additions & 0 deletions components/ball.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
#include "../include/ball.hpp"
#include <raymath.h>

void Game::Ball::draw() { DrawCircle(position.x, position.y, radius, color); }

void Game::Ball::gotoCenter() {
position.x = static_cast<float>(GetScreenWidth()) / 2;
position.y = static_cast<float>(GetScreenHeight()) / 2;
}

void Game::Ball::update() {
// limit ball speed
float speed = Vector2Length(velocity);
if (speed > 8)
velocity = Vector2Scale(velocity, 0.95f);
else if (speed < 6)
velocity = Vector2Scale(velocity, 1.1f);

// update ball position based on velocity
position.x += velocity.x;
position.y += velocity.y;

// collide with top wall
if (position.y - radius < 0) {
position.y = radius;
velocity.y *= -1;
}

// collide with bottom wall
if (position.y + radius > GetScreenHeight()) {
position.y = GetScreenHeight() - radius;
velocity.y *= -1;
}
}

void Game::Ball::shoot(Vector2 force) {
velocity.x += force.x;
velocity.y += force.y;
}

void Game::Ball::shoot(Vector2 direction, float force) {
direction = Vector2Normalize(direction);

velocity.x += direction.x * force;
velocity.y += direction.y * force;
}
86 changes: 86 additions & 0 deletions components/game_manager.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
#include "../include/game_manager.hpp"
#include <cmath>
#include <raylib.h>
#include <raymath.h>

void Game::GameManager::draw() {
const char *human_score_text = TextFormat("%u", human_score);
const char *cpu_score_text = TextFormat("%u", cpu_score);

int human_text_length = MeasureText(human_score_text, font_size);
int cpu_text_length = MeasureText(cpu_score_text, font_size);
int x_value = GetScreenWidth() / 4;
int y_value = GetScreenHeight() / 2 - font_size / 2;

DrawText(human_score_text, x_value - human_text_length / 2, y_value,
font_size, RAYWHITE);

DrawText(cpu_score_text, GetScreenWidth() - x_value - cpu_text_length / 2,
y_value, font_size, RAYWHITE);

DrawLine(x_value * 2, 0, x_value * 2, GetScreenHeight(), RAYWHITE);
DrawCircleLines(x_value * 2, GetScreenHeight() / 2, 80, RAYWHITE);
}

void Game::GameManager::update() {
// if ball hits left wall then score goal for CPU and reset ball
if (ball.position.x + ball.radius <= 0) {
ball.gotoCenter();
ball.velocity = {0, 0};
ball.shoot({1, 0}, 6);
cpu_score++;
}

// if ball hits right wall then score goal for human and reset ball
if (ball.position.x - ball.radius >= GetScreenWidth()) {
ball.gotoCenter();
ball.velocity = {0, 0};
ball.shoot({-1, 0}, 6);
human_score++;
}

if (IsKeyPressed(KEY_SPACE) && human_score > 0) {
ball.gotoCenter();
ball.velocity = {0, 0};
ball.shoot({-1, 0}, 6);
human_score--;
}

// change ball direction on collision with any paddle
if (CheckCollisionCircleRec(ball.position, ball.radius, human_paddle.rect))
onBallPaddleCollision(human_paddle);
if (CheckCollisionCircleRec(ball.position, ball.radius, cpu_paddle.rect))
onBallPaddleCollision(cpu_paddle);
}

void Game::GameManager::onBallPaddleCollision(const Paddle &paddle) {
static float timeA = -1, timer = 0;
float time;

float paddle_speed_ratio = paddle.velocity / paddle.max_velocity;
float ball_speed = Vector2Length(ball.velocity);
float y_touch =
(ball.position.y - paddle.rect.y) / paddle.rect.height * 2 - 1;
Vector2 normal = Vector2Normalize(ball.velocity);

normal.y = (y_touch + paddle_speed_ratio) / 2;
normal.x *= -1;
ball.velocity = Vector2Scale(normal, ball_speed);

// fix ball stuck glitch
time = GetTime();

if (time - timeA < 0.05)
timer += GetFrameTime();
else
timer = 0;

if (timer > 2) {
ball.gotoCenter();
ball.velocity = {0, 0};
ball.shoot({-1, 0}, 6);
timer = 0;
TraceLog(LOG_INFO, "Glitch Detected!!");
}
timeA = GetTime();
}
34 changes: 34 additions & 0 deletions components/paddle.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
#include "../include/paddle.hpp"
#include <cmath>

float Game::Paddle::window_padding = 10;

void Game::Paddle::gotoCenter() {
rect.y = static_cast<float>(GetScreenHeight()) / 2 - rect.height / 2;
}

void Game::Paddle::draw() { DrawRectangleRec(rect, color); }

void Game::Paddle::update() {
// if velocity is too small set it to 0
if (std::abs(velocity) < 0.01)
velocity = 0;
// if velocity is too big set it to maximum velocity
if (std::abs(velocity) > max_velocity)
velocity = velocity > 0 ? max_velocity : -max_velocity;

// update the position of the paddle based on the velocity
rect.y += velocity;
// decrease the velocity over time, so the paddle stops after a while
velocity *= drag;

// limit the paddle to the screen edges
if (rect.y < 0)
rect.y = 0;
if (rect.y > GetScreenHeight() - rect.height)
rect.y = GetScreenHeight() - rect.height;
}

void Game::Paddle::moveUp() { velocity -= speed; }

void Game::Paddle::moveDown() { velocity += speed; }
Binary file added cping_pong
Binary file not shown.
24 changes: 24 additions & 0 deletions include/ball.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
#ifndef BALL_HPP
#define BALL_HPP

#include <raylib.h>

namespace Game {
class Ball {
public:
Vector2 position = {0, 0};
Vector2 velocity = {0, 0};
Color color = RED;
float radius = 10;

void gotoCenter();

void draw();
void update();

void shoot(Vector2 force);
void shoot(Vector2 direction, float force);
};
} // namespace Game

#endif
31 changes: 31 additions & 0 deletions include/game_manager.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
#ifndef GAME_MANAGER_HPP
#define GAME_MANAGER_HPP

#include "ball.hpp"
#include "paddle.hpp"

namespace Game {

class GameManager {
Ball &ball;
const Paddle &human_paddle;
const Paddle &cpu_paddle;

void onBallPaddleCollision(const Paddle &paddle);

public:
unsigned int human_score = 0;
unsigned int cpu_score = 0;

int font_size = 164;

GameManager(Ball &ball, const Paddle &human_paddle, const Paddle &cpu_paddle)
: ball(ball), human_paddle(human_paddle), cpu_paddle(cpu_paddle) {}

void update();
void draw();
};

} // namespace Game

#endif
28 changes: 28 additions & 0 deletions include/paddle.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
#ifndef PADDLE_HPP
#define PADDLE_HPP

#include <raylib.h>

namespace Game {
class Paddle {
public:
Rectangle rect = {0, 0, 15, 100};
Color color = RAYWHITE;
float speed = 2;
float velocity = 0;
float max_velocity = 5;
float drag = 0.88;
static float window_padding;

void gotoCenter();

void draw();
void update();

void moveUp();
void moveDown();
};

} // namespace Game

#endif
64 changes: 64 additions & 0 deletions main.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
#include "include/ball.hpp"
#include "include/game_manager.hpp"
#include "include/paddle.hpp"
#include <raylib.h>

void cpu_paddle(Game::Paddle &paddle, const Game::Ball &ball) {
float diff = ball.position.y - paddle.rect.y - paddle.rect.height / 2;

if (diff < 0)
paddle.moveUp();
else
paddle.moveDown();
}

void human_paddle(Game::Paddle &paddle) {
if (IsKeyDown(KEY_UP) || IsKeyDown(KEY_K))
paddle.moveUp();
else if (IsKeyDown(KEY_DOWN) || IsKeyDown(KEY_J))
paddle.moveDown();
}

int main() {
Game::Ball ball;
Game::Paddle p1, p2;
Game::GameManager gm(ball, p2, p1);

InitWindow(800, 500, "PingPongCpp");
SetTargetFPS(60);

ball.gotoCenter();
ball.shoot({1, -1}, 6);

p1.rect.x = GetScreenWidth() - p1.rect.width - Game::Paddle::window_padding;
p1.gotoCenter();

p2.rect.x = Game::Paddle::window_padding;
p2.gotoCenter();

while (!WindowShouldClose()) {
ball.update();

p1.update();
cpu_paddle(p1, ball);

p2.update();
human_paddle(p2);

gm.update();

BeginDrawing();
ClearBackground(BLACK);

gm.draw();
ball.draw();
p1.draw();
p2.draw();

EndDrawing();
}

CloseWindow();

return 0;
}
Binary file added screens/screen.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.

0 comments on commit 899d9e8

Please sign in to comment.