From 67b13ab164abc4dbc5cb0ac2f5c8f0f583d5cbb1 Mon Sep 17 00:00:00 2001 From: DarthMooMancer <107283522+DarthMooMancer@users.noreply.github.com> Date: Wed, 12 Nov 2025 01:22:44 -0500 Subject: [PATCH] complete rewrite of code as unlike snake and tic_tac_toe, this required bigger changes and more volatile changes all at once --- .DS_Store | Bin 0 -> 6148 bytes CMakeLists.txt | 17 +++--- include/elements.hpp | 49 ----------------- include/engine.hpp | 59 ++++++++++++++++++++ include/globals.hpp | 7 --- include/input.hpp | 10 ---- include/window.hpp | 13 ----- src/elements.cpp | 68 ----------------------- src/engine.cpp | 125 +++++++++++++++++++++++++++++++++++++++++++ src/input.cpp | 24 --------- src/main.cpp | 60 ++------------------- src/window.cpp | 31 ----------- 12 files changed, 193 insertions(+), 270 deletions(-) create mode 100644 .DS_Store delete mode 100644 include/elements.hpp create mode 100644 include/engine.hpp delete mode 100644 include/globals.hpp delete mode 100644 include/input.hpp delete mode 100644 include/window.hpp delete mode 100644 src/elements.cpp create mode 100644 src/engine.cpp delete mode 100644 src/input.cpp delete mode 100644 src/window.cpp diff --git a/.DS_Store b/.DS_Store new file mode 100644 index 0000000000000000000000000000000000000000..754fba5f1a103e53413dd0e3091235ee3dc7328e GIT binary patch literal 6148 zcmeHK!AiqG5S_KD7QGZK>M?i|L@541ED<~kJ$Th7(h8|5YL7||9`zsk171}80S_Ma z*rVVt^aGsP9n#$<;;o3x!0g-X%u_-Z%lNW4(M;eGq z&(VX^q}yyqX@5}2mH|;f6!>cj(6_q?I}pJMdg1%sdY+B<(=hBLX$Qw^o0FsM_1(9< zVov;P&Y)-S6C<1gJX}W?&fv=3Lq4wUn9cwA^zeEgYW}>opH8{U;tsF(NxW6)zz}&8 zh#ls}IC7&l_t(qqn7OTbo4q{4;a?jO{}OVaqxuQ1BA(qrtCM1ey^i;TT!Wc;?6v%y z<*Ww|X+0IVgbRoqEnxL-8nO9rhB-gi*}TPQ2_JEa&0hgLv&m{J2Bj4RL;+DCSAg~h zADu8@%na(S0~>t>K=g1}8}{igK{Y;Oz?d1t2%0jbh^AEW6+@YF9QQddV9X4fa!`Ev zP|U3OhN3h(&hP7VP=P^dMFCO3RiI)X>vaC_|9t;K6MZS#>^m&pvjMbmO&a(V6F;$16eDjN&o-= literal 0 HcmV?d00001 diff --git a/CMakeLists.txt b/CMakeLists.txt index 7d0afea..cf4d062 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,21 +1,16 @@ cmake_minimum_required(VERSION 3.16) +set(CMAKE_CXX_STANDARD 23) +set(CMAKE_CXX_STANDARD_REQUIRED ON) +set(CMAKE_EXPORT_COMPILE_COMMANDS ON) project(pong) -set(CMAKE_C_STANDARD 23) -set(CMAKE_C_STANDARD_REQUIRED ON) -include_directories(include) set(SOURCES src/main.cpp - src/input.cpp - src/window.cpp - src/elements.cpp + src/engine.cpp src/timer.cpp ) - add_executable(pong ${SOURCES}) +target_include_directories(pong PRIVATE include) find_package(Curses REQUIRED) -include_directories(${CURSES_INCLUDE_DIR}) -target_link_libraries(pong ${CURSES_LIBRARIES}) - -set(CMAKE_EXPORT_COMPILE_COMMANDS ON) +target_link_libraries(pong PRIVATE ${CURSES_LIBRARIES}) diff --git a/include/elements.hpp b/include/elements.hpp deleted file mode 100644 index bec937c..0000000 --- a/include/elements.hpp +++ /dev/null @@ -1,49 +0,0 @@ -#ifndef ELEMENTS_HPP -#define ELEMENTS_HPP - -#include "globals.hpp" - -enum Direction { - NONE, UP, DOWN -}; - -struct vec2 { - vec2() : y(0), x(0) {}; - vec2(int r, int c, char s) : y(r), x(c), m_symbol(s) {} - int x, y; - char m_symbol; -}; - -struct Ball { - Ball() : m_vx(1), m_vy(-1) {}; - vec2* m_origin; - int m_vx; - int m_vy; - bool determine_next_valid_position(); -}; - -struct Paddle { - Paddle() : m_score(0) {}; - int m_score; - int m_size; - vec2** m_nodes; - enum Direction m_dir; - void determine_new_position(vec2* (*board)[COL]); -}; - -class Engine { -public: - Engine(); - ~Engine(); - void run(); - -private: - - -}; - -void on_collision_with_ball(vec2** segments, Ball &ball, int t_size); -Ball create_ball(vec2** segments, int row, int col, char symbol, int t_size); -Paddle create_paddle(vec2** segments, int starting_index, int ending_index, int column, char symbol); - -#endif diff --git a/include/engine.hpp b/include/engine.hpp new file mode 100644 index 0000000..957ec76 --- /dev/null +++ b/include/engine.hpp @@ -0,0 +1,59 @@ +#ifndef ENGINE_HPP +#define ENGINE_HPP + +#include +#include + +constexpr int ROW = 15; +constexpr int COL = 31; +constexpr int SIZE { 5 }; + +enum class Direction { + NONE, UP, DOWN +}; + +struct vec2 { + int a, b; + vec2() : b(0), a(0) {}; + vec2(int x, int y) : a(x), b(y) {}; + void set(int a1, int b1) { a = a1; b = b1; }; + auto operator <=> (const vec2&) const = default; +}; + +struct Paddle { + Paddle(const vec2 init_pos); + std::array nodes; + const char symbol { '|' }; + enum Direction dir = Direction::NONE; + void move(); +}; + +struct Window { + std::array, ROW> view = {}; + void clear_display(); + void draw_display(); + void update_display(const vec2 &ball, const Paddle &p1, const Paddle &p2); +}; + +class Engine { +public: + Engine(); + ~Engine() { endwin(); }; + void run(); + +private: + Window win; + int time_seconds { 30 }; + vec2 score { 0, 0 }; + vec2 ball { (COL / 2), (ROW / 2) }; + vec2 ball_direction { 1, 1 }; + Paddle p1 { { 1, (ROW / 2) - (SIZE / 2) } }; + Paddle p2 { { COL - 2, (ROW / 2) - (SIZE / 2) } }; + + bool exit_process(); + bool process_input(); + bool move_ball(); + void on_collision_with_ball(); +}; + +#endif diff --git a/include/globals.hpp b/include/globals.hpp deleted file mode 100644 index 7626946..0000000 --- a/include/globals.hpp +++ /dev/null @@ -1,7 +0,0 @@ -#ifndef GLOBALS_HPP -#define GLOBALS_HPP - -constexpr unsigned int ROW = 15; -constexpr unsigned int COL = 31; - -#endif diff --git a/include/input.hpp b/include/input.hpp deleted file mode 100644 index 2baf134..0000000 --- a/include/input.hpp +++ /dev/null @@ -1,10 +0,0 @@ -#ifndef INPUT_HPP -#define INPUT_HPP -#include "elements.hpp" - -struct Input { - int m_getch = 0; - void get_input(enum Direction &left, enum Direction &right, bool &running); -}; - -#endif // INPUT_HPP diff --git a/include/window.hpp b/include/window.hpp deleted file mode 100644 index ef7a8da..0000000 --- a/include/window.hpp +++ /dev/null @@ -1,13 +0,0 @@ -#ifndef WINDOW_HPP -#define WINDOW_HPP - -#include "globals.hpp" -#include "elements.hpp" - -struct Window { - vec2* m_board[ROW][COL] = {}; - void clear_display(); - void draw_display(int milliseconds); - void update_display(vec2** segments); -}; -#endif diff --git a/src/elements.cpp b/src/elements.cpp deleted file mode 100644 index 43db836..0000000 --- a/src/elements.cpp +++ /dev/null @@ -1,68 +0,0 @@ -#include "elements.hpp" -#include "globals.hpp" - -Ball create_ball(vec2** segments, int row, int col, char symbol, int t_size) { - Ball ball; - segments[t_size - 1] = new vec2 { row, col, symbol }; - ball.m_origin = segments[t_size - 1]; - return ball; -} - -Paddle create_paddle(vec2** segments, int starting_index, int ending_index, int column, char symbol) { - Paddle paddle; - paddle.m_size = ending_index - starting_index; - paddle.m_nodes = new vec2*[paddle.m_size]; - int starting_y_index = (ROW / 2) - (paddle.m_size / 2); - for(int i = 0; i < paddle.m_size; i++) { - paddle.m_nodes[i] = new vec2 { starting_y_index + i, column, symbol }; - segments[starting_index + i] = paddle.m_nodes[i]; - } - return paddle; -} - -void Paddle::determine_new_position(vec2* (*board)[COL]) { - if(m_dir == UP) { - if(board[(m_nodes[0]->y) - 1][m_nodes[0]->x] == nullptr) { - for(int i = 0; i < m_size; i++) { - m_nodes[i]->y--; - } - } - } else if(m_dir == DOWN) { - if(board[(m_nodes[m_size - 1]->y) + 1][m_nodes[m_size - 1]->x] == nullptr) { - for(int i = 0; i < m_size; i++) { - m_nodes[i]->y++; - } - } - } - m_dir = NONE; -} - -void on_collision_with_ball(vec2** segments, Ball &ball, int t_size) { - for(int i = 0; i < t_size - 1; i++) { - if(segments[i]->y != ball.m_origin->y) continue; - if(segments[i]->x != ball.m_origin->x) continue; - if (ball.m_vx == 1) ball.m_vx = -1; - else ball.m_vx = 1; - } -} - -bool Ball::determine_next_valid_position() { - if(m_origin->y <= 0 || m_origin->y >= ROW - 1) { - if (m_vy == 1) m_vy = -1; - else m_vy = 1; - } - if(m_origin->x <= 0 || m_origin->x >= COL - 1) return false; - if(m_vx == 1) { - m_origin->x++; - } - else if(m_vx == -1) { - m_origin->x--; - } - if(m_vy == 1) { - m_origin->y++; - } - else if(m_vy == -1) { - m_origin->y--; - } - return true; -} diff --git a/src/engine.cpp b/src/engine.cpp new file mode 100644 index 0000000..0c71e6c --- /dev/null +++ b/src/engine.cpp @@ -0,0 +1,125 @@ +#include +#include +#include +#include +#include + +void Window::clear_display() { + for(auto &row : view) { + row.fill('.'); + } +} + +void Window::draw_display() { + std::cout << "\033[H" << std::flush; // Clear screen + for(const auto &row : view) { + for(const auto val : row) { + if(val == '.') std::cout << ". "; + else std::cout << val << " "; + } + std::cout << "\r\n"; + } +} + +void Window::update_display(const vec2 &ball, const Paddle &p1, const Paddle &p2) { + view[ball.b][ball.a] = '*'; + for(auto &i : p1.nodes) { + view[i.b][i.a] = p1.symbol; + } + for(auto &i : p2.nodes) { + view[i.b][i.a] = p2.symbol; + } +} + +Paddle::Paddle(const vec2 init_pos) { + for(int i : std::ranges::views::iota(0, (int)nodes.size())) { + nodes[i].set(init_pos.a, init_pos.b + i); + } +} + +void Paddle::move() { + if(dir == Direction::UP && nodes.front().b > 0) { + for(auto &i : nodes) { i.b--; } + } else if(dir == Direction::DOWN && nodes.back().b < ROW - 1) { + for(auto &i : nodes) { i.b++; } + } + dir = Direction::NONE; +} + +Engine::Engine() { + initscr(); + cbreak(); + noecho(); + curs_set(0); + nodelay(stdscr, true); +} + +void Engine::on_collision_with_ball() { + for(const auto &i : p1.nodes) { + if(i == ball) { + if (ball_direction.a == 1) ball_direction.a = -1; + else ball_direction.a = 1; + } + } + for(const auto &i : p2.nodes) { + if(i == ball) { + if (ball_direction.a == 1) ball_direction.a = -1; + else ball_direction.a = 1; + } + } +} + +void Engine::run() { + while(process_input() && exit_process()) { + if(!move_ball()) { + if(ball.a < 1) { score.b++; } + else if(ball.a > COL - 2) { score.a++; } + ball.set(COL / 2, ROW / 2); + } + p1.move(); + p2.move(); + on_collision_with_ball(); + win.clear_display(); + win.update_display(ball, p1, p2); + win.draw_display(); + std::cout << "Time left: " << time_seconds << ", Score ( " << score.a << " : " << score.b << " )\n"; + std::this_thread::sleep_for(std::chrono::milliseconds(150)); // 1000 / fps; 200ms = 5fps + } +} + +bool Engine::process_input() { + int ch; + while((ch = getch()) != ERR) { + if(ch == 'q') { return false; } + if(ch == 'w') { p1.dir = Direction::UP; } + else if(ch == 's') { p1.dir = Direction::DOWN; } + + if(ch == 65) { p2.dir = Direction::UP; } + else if(ch == 66) { p2.dir = Direction::DOWN; } + } + return true; +} + + +bool Engine::exit_process() { + if(time_seconds <= 0) { + std::cout << ((score.a > score.b ) ? "Player 1 wins\n" : (score.a == score.b) ? "It's a tie\n" : "Player 2 wins\n"); + std::this_thread::sleep_for(std::chrono::seconds(1)); + return false; + } + return true; +} + +bool Engine::move_ball() { + if(ball.b <= 0 || ball.b >= ROW - 1) { + if (ball_direction.b == 1) ball_direction.b = -1; + else ball_direction.b = 1; + } + if(ball.a <= 0 || ball.a >= COL - 1) return false; + if(ball_direction.a == 1) { ball.a++; } + else if(ball_direction.a == -1) { ball.a--; } + + if(ball_direction.b == 1) { ball.b++; } + else if(ball_direction.b == -1) { ball.b--; } + return true; +} diff --git a/src/input.cpp b/src/input.cpp deleted file mode 100644 index 56948ef..0000000 --- a/src/input.cpp +++ /dev/null @@ -1,24 +0,0 @@ -#include "input.hpp" -#include -#include - -void Input::get_input(enum Direction &left, enum Direction &right, bool &running) { - while(running) { - initscr(); - cbreak(); - noecho(); - - m_getch = getch(); - endwin(); - - if(m_getch == 119) left = UP; - else if(m_getch == 115) left = DOWN; - - if(m_getch == 65) right = UP; - else if(m_getch == 66) right = DOWN; - - if(m_getch == 113) running = false; - - m_getch = 0; - } -} diff --git a/src/main.cpp b/src/main.cpp index 07e2bc3..043e932 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1,61 +1,7 @@ -#include -#include -#include "input.hpp" -#include "timer.hpp" -#include "window.hpp" -#include "elements.hpp" -#include "globals.hpp" +#include int main() { - int time_seconds = 30; - Input input; - Timer timer; - Window window; - bool running = true; - vec2* segments[8] = {}; - - Paddle left = create_paddle(segments, 0, 3, 1, '|'); - Paddle right = create_paddle(segments, 3, 6, COL - 2, '|'); - Ball ball = create_ball(segments, (ROW / 2), (COL / 2), 'o', 8); - - std::thread timer_thread([&] { timer.decrement_time(time_seconds, running); } ); - std::thread input_thread([&] { input.get_input(left.m_dir, right.m_dir, running); } ); - - while (running) { - left.determine_new_position(window.m_board); - right.determine_new_position(window.m_board); - if(!ball.determine_next_valid_position()) { - if(ball.m_origin->x < 1) { - left.m_score++; - } else if(ball.m_origin->x > COL - 2) { - right.m_score++; - } - ball.m_origin->y = ROW / 2; - ball.m_origin->x = COL / 2; - } - on_collision_with_ball(segments, ball, 7); - if(time_seconds <= 0) { - if(left.m_score > right.m_score) { - std::cout << "Player 1 wins!\n"; - } if(left.m_score < right.m_score) { - std::cout << "Player 2 wins!\n"; - } if(left.m_score == right.m_score) { - std::cout << "It's a tie!\n"; - } - running = false; - } - window.clear_display(); - window.update_display(segments); - window.draw_display(130); - std::cout << "Time left: " << time_seconds << ", Score ( " << left.m_score << " : " << right.m_score << " )\n"; - } - - timer_thread.join(); - input_thread.join(); - for(int i = 8; i > 0; i--) { - if(segments[i] != nullptr) { - delete segments[i]; - } - } + Engine engine; + engine.run(); return 0; } diff --git a/src/window.cpp b/src/window.cpp deleted file mode 100644 index 2eae535..0000000 --- a/src/window.cpp +++ /dev/null @@ -1,31 +0,0 @@ -#include "window.hpp" -#include -#include -#include - -void Window::clear_display() { - for(int i = 0; i < ROW; i++) { - for(int j = 0; j < COL; j++) { - m_board[i][j] = nullptr; - } - } -} - -void Window::draw_display(int milliseconds) { - std::cout << "\033[H" << std::flush; // Clear screen - for(int i = 0; i < ROW; i++) { - for(int j = 0; j < COL; j++) { - if(m_board[i][j] == nullptr) std::cout << ". "; - else std::cout << m_board[i][j]->m_symbol << " "; - } - std::cout << "\r\n"; - } - std::this_thread::sleep_for(std::chrono::milliseconds(milliseconds)); // 1000 / fps; 200ms = 5fps -} - -void Window::update_display(vec2** segments) { - for(int i = 10; i >= 0; i--) { - if(segments[i] == nullptr) continue; - m_board[segments[i]->y][segments[i]->x] = segments[i]; - } -}