You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
netpong/main.cpp

172 lines
5.7 KiB
C++

11 months ago
#include <iostream>
#include <cmath>
#include <ctime>
#include "raylib-cpp/raylib-cpp.hpp"
#include "paddle.hpp"
#include "ball.hpp"
#include "math-helpers.hpp"
#include "client.hpp"
11 months ago
/* Global variables used to instantiate structs */
const int WIDTH = 1500;
const int HEIGHT = 600;
const int RECT_H = HEIGHT / 3;
const int RECT_W = 30;
const int PADDLE_SPEED = 8;
const int CIRC_RAD = 10;
const float BASE_BOUNCE_DEG = 60;
const float BASE_BOUNCE_RAD = (BASE_BOUNCE_DEG / 180.0) * M_PI;
const float BASE_SPEED_COMPONENTS = 18;
const float BASE_SPEED = sqrt(powf(BASE_SPEED_COMPONENTS, 2) * 2);
raylib::Vector2 changeVelocityAfterCollision(Paddle paddle, Ball ball) {
float paddle_mid_y = (paddle.getRect().y + paddle.getRect().GetHeight()) / 2.0; /* Middle y value of rectangle */
float ball_y = ball.pos.y; /* Y co-ordinate of ball */
float offset = paddle_mid_y - ball_y; /* Subtracting the ball coordinate will give us a value between -paddle_mid_y (represents bottom of paddle) and +paddle_mid_y (represents top of paddle) */
offset /= (paddle.getRect().GetHeight()); /* Normalize the value, by dividing it by its maximum magnitude. It is now a value between -1 and 1. */
offset *= 0.8 + (float)(std::rand()) / (float) (RAND_MAX / ( 1.2 - 0.8)); // Generate a random float from 0.8 to 1.2
float bounce_angle = offset * BASE_BOUNCE_RAD; /* Calculate the actual bounce angle from the base bounce angle. */
/* Calculate new velocities as multiples of the original velocity. I use sine and cosine, because when the ball hits the paddle
perpendicular to it (bounce angle is 0), the y_velocity should be 0 (i.e. It should bounce straight back). The sin function does
this for us. A similar reasoning was employed for the use of cosine */
float new_x_vel = abs(BASE_SPEED * cosf(bounce_angle)) * (-1 * signum(ball.vel.x)); /* Reverse the sign of the x-velocity */
float new_y_vel = abs(BASE_SPEED * sinf(bounce_angle)) * signum(ball.vel.y); /* Keep the sign of the y-velocity */
11 months ago
return raylib::Vector2(new_x_vel, new_y_vel);
}
int main(int argc, char** argv) {
/* Initialize window and other variables */
SetTraceLogLevel(LOG_NONE);
11 months ago
raylib::Window window = raylib::Window(WIDTH, HEIGHT, "Pong");
window.ClearBackground(BLACK);
SetTargetFPS(60);
SetExitKey(KEY_Q);
std::string points_str = std::string("0\t\t0");
bool game_started = false;
srand(std::time(NULL));
bool in_server_mode = false;
Client client;
if (argc > 1 && strcmp(argv[1],"server") == 0) {
try {
client = Client(4,'T',"127.0.0.1",6500);
in_server_mode = true;
}
catch (int e) {
std::cout << "Unable to connect to the given address." << std::endl;
return -1;
}
}
11 months ago
/* Instantiate Paddle and Ball objects */
Paddle pad1 = Paddle(10, (HEIGHT / 2) - (RECT_H / 2), RECT_W, RECT_H);
Paddle pad2 = Paddle(window.GetWidth() - RECT_W - 10, (HEIGHT / 2) - (RECT_H / 2), RECT_W, RECT_H);
Ball ball = Ball(window.GetWidth()/2, window.GetHeight()/2, CIRC_RAD, BASE_SPEED, 0);
11 months ago
window.BeginDrawing();
pad1.draw();
pad2.draw();
ball.draw();
window.EndDrawing();
11 months ago
/* Main loop */
while (!window.ShouldClose()) {
if (!game_started) {
if (IsKeyDown(KEY_SPACE)) {
game_started = true;
}
11 months ago
}
if (game_started) {
/* Update paddle velocity */
if (IsKeyPressed(KEY_S)) {
pad1.velocity.y = PADDLE_SPEED; /* Set positive (downward) velocity, since (0,0) is top-left */
}
if (IsKeyPressed(KEY_W)) {
pad1.velocity.y = (-1) * PADDLE_SPEED; /* Set negative (upward) velocity */
}
if (IsKeyReleased(KEY_S) || IsKeyReleased(KEY_W)) {
pad1.velocity.y = 0;
}
if (IsKeyPressed(KEY_UP)) {
if(in_server_mode) {
client.sendAll(std::string("U"));
}
pad2.velocity.y = (-1) * PADDLE_SPEED;
}
if (IsKeyPressed(KEY_DOWN)) {
if (in_server_mode) {
client.sendAll(std::string("D"));
}
pad2.velocity.y = PADDLE_SPEED;
}
if (IsKeyReleased(KEY_UP) || IsKeyReleased(KEY_DOWN)) {
if (in_server_mode) {
client.sendAll(std::string("S"));
}
pad2.velocity.y = 0;
}
/* Update ball velocity based on collision detection */
if (pad1.getRect().CheckCollision(ball.pos, ball.radius)) { /* Collision with paddle 1 */
ball.pos.x = pad1.getRect().x + pad1.getRect().GetWidth() + ball.radius + 1; /* Ensuring that the ball doesn't get stuck inside the paddle */
ball.vel = changeVelocityAfterCollision(pad1, ball);
}
if (pad2.getRect().CheckCollision(ball.pos, ball.radius)) { /* Collision with paddle 2 */
ball.pos.x = pad2.getRect().x - ball.radius - 1;
ball.vel = changeVelocityAfterCollision(pad2, ball);
}
if (ball.pos.x + ball.radius >= window.GetWidth()) { /* Collision with right wall */
pad1.incrementPoints();
game_started = false;
ball.reset();
pad1.reset();
pad2.reset();
}
if (ball.pos.x - ball.radius <= 0) { /* Collision with left wall */
pad2.incrementPoints();
game_started = false;
ball.reset();
pad1.reset();
pad2.reset();
}
if (ball.pos.y - ball.radius <= 0) { /* Collision with top wall */
ball.pos.y = ball.radius + 1;
ball.vel.y = ball.vel.y * -1;
}
if (ball.pos.y + ball.radius >= window.GetHeight()) { /* Collision with bottom wall */
ball.pos.y = HEIGHT - ball.radius - 1;
ball.vel.y = ball.vel.y * -1;
}
/* Update positions based on velocities */
pad1.updatePosition();
pad2.updatePosition();
ball.updatePosition();
11 months ago
}
/* Draw objects */
window.BeginDrawing();
window.ClearBackground(BLACK);
points_str = std::to_string(pad1.getPoints()) + "\t\t" + std::to_string(pad2.getPoints());
raylib::Text::Draw( points_str, (WIDTH / 2) - 30, HEIGHT / 10, 30, raylib::Color::White() );
11 months ago
pad1.draw();
pad2.draw();
ball.draw();
window.EndDrawing();
}
window.Close();
return 0;
}