2024-01-19 15:06:48 +01:00
|
|
|
//
|
|
|
|
// Created by love on 2024-01-18.
|
|
|
|
//
|
|
|
|
#pragma once
|
|
|
|
|
|
|
|
#include "../Vec2d/Vec2d.h"
|
|
|
|
#include "PlayerPaddle.h"
|
|
|
|
#include <SDL2/SDL2_gfxPrimitives.h>
|
|
|
|
#include <iostream>
|
|
|
|
#include "optional"
|
2024-01-19 18:41:26 +01:00
|
|
|
#include "Score.h"
|
2024-01-19 15:06:48 +01:00
|
|
|
|
|
|
|
class Ball {
|
|
|
|
private:
|
|
|
|
static const uint8_t RADIUS = 15;
|
|
|
|
const SDL_Point *screen;
|
|
|
|
Sint16 x, y;
|
|
|
|
Vec2d *vec2d;
|
|
|
|
static const uint32_t color = 0xCD5C5CFF;
|
|
|
|
const PlayerPaddle *leftPaddle, *rightPaddle;
|
2024-01-19 18:41:26 +01:00
|
|
|
Score *score;
|
2024-01-19 15:06:48 +01:00
|
|
|
|
|
|
|
public:
|
2024-01-19 18:41:26 +01:00
|
|
|
explicit Ball(const SDL_Point *screen, const PlayerPaddle *leftPaddle, const PlayerPaddle *rightPaddle,
|
|
|
|
Score *score) {
|
|
|
|
this->score = score;
|
2024-01-19 15:06:48 +01:00
|
|
|
this->screen = screen;
|
|
|
|
this->leftPaddle = leftPaddle;
|
|
|
|
this->rightPaddle = rightPaddle;
|
2024-01-19 18:41:26 +01:00
|
|
|
this->x = screen->x / 2;
|
|
|
|
this->y = screen->y / 2;
|
2024-01-19 19:10:03 +01:00
|
|
|
vec2d = new Vec2d(6);
|
2024-01-19 18:41:26 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
void resetPosition() {
|
|
|
|
this->x = screen->x / 2;
|
|
|
|
this->y = screen->y / 2;
|
|
|
|
|
|
|
|
delete vec2d;
|
2024-01-19 19:10:03 +01:00
|
|
|
vec2d = new Vec2d(6);
|
2024-01-19 15:06:48 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
void draw(SDL_Renderer *renderer) const {
|
|
|
|
filledCircleColor(renderer, x, y, RADIUS, color);
|
|
|
|
}
|
|
|
|
|
|
|
|
void update() {
|
|
|
|
std::optional<Side> paddleSide = collidedPaddle();
|
|
|
|
bool screenEdgeVertical = collidedScreenEdgeVertical();
|
2024-01-19 18:41:26 +01:00
|
|
|
std::optional<Side> scoreSide = collidedScreenEdgeHorizontal();
|
|
|
|
|
2024-01-19 15:06:48 +01:00
|
|
|
if (screenEdgeVertical && paddleSide.has_value()) {
|
|
|
|
vec2d->bump(BumpType::BOTH, PaddleDirection::NONE);
|
|
|
|
} else if (screenEdgeVertical) {
|
|
|
|
vec2d->bump(BumpType::WALL, PaddleDirection::NONE);
|
2024-01-19 18:41:26 +01:00
|
|
|
} else if (scoreSide.has_value()) {
|
|
|
|
score->incrementScore(scoreSide.value());
|
|
|
|
resetPosition();
|
2024-01-19 15:06:48 +01:00
|
|
|
}
|
|
|
|
if (paddleSide.has_value()) {
|
|
|
|
const PlayerPaddle *paddle = paddleSide.value() == Side::LEFT ? leftPaddle : rightPaddle;
|
|
|
|
vec2d->bump(BumpType::PADDLE, paddle->getPaddleDirection());
|
|
|
|
}
|
|
|
|
vec2d->applyVector(&x, &y);
|
|
|
|
}
|
|
|
|
|
|
|
|
private:
|
|
|
|
bool collidedScreenEdgeVertical() {
|
|
|
|
return y - RADIUS <= 0 || y + RADIUS >= screen->y;
|
|
|
|
}
|
|
|
|
|
2024-01-19 18:41:26 +01:00
|
|
|
std::optional<Side> collidedScreenEdgeHorizontal() {
|
|
|
|
if (x + RADIUS >= screen->x)
|
|
|
|
return Side::RIGHT;
|
|
|
|
else if (x - RADIUS <= 0)
|
|
|
|
return Side::LEFT;
|
|
|
|
return std::nullopt;
|
2024-01-19 15:06:48 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
std::optional<Side> collidedPaddle() {
|
2024-01-19 18:41:26 +01:00
|
|
|
// Right paddle
|
2024-01-19 15:06:48 +01:00
|
|
|
if (x + RADIUS >= rightPaddle->x &&
|
|
|
|
y >= rightPaddle->y &&
|
|
|
|
y <= rightPaddle->y + rightPaddle->h) {
|
|
|
|
return Side::RIGHT;
|
|
|
|
}
|
2024-01-19 18:41:26 +01:00
|
|
|
// Left paddle
|
|
|
|
if (x - RADIUS <= leftPaddle->x + leftPaddle->w &&
|
|
|
|
y >= leftPaddle->y &&
|
|
|
|
y <= leftPaddle->y + leftPaddle->h) {
|
2024-01-19 15:06:48 +01:00
|
|
|
return Side::LEFT;
|
|
|
|
}
|
|
|
|
return std::nullopt;
|
|
|
|
}
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|