Pong: paddle can change angle + top/bottom bounce

This commit is contained in:
Patrick Haßel 2024-12-27 13:55:07 +01:00
parent 89ed7b1c21
commit 7539dbb7b0
3 changed files with 43 additions and 45 deletions

View File

@ -51,26 +51,6 @@ public:
return {x * i, y * i}; return {x * i, y * i};
} }
Vector bounceInBox(uint8_t width, uint8_t height) const {
double x2 = this->x;
double y2 = this->y;
while (x2 < 0 || x2 >= width) {
if (x2 < 0) {
x2 = -x2;
} else if (x2 >= width) {
x2 = 2 * width - x2;
}
}
while (y2 < 0 || y2 >= height) {
if (y2 < 0) {
y2 = -y2;
} else if (y2 >= height) {
y2 = 2 * height - y2;
}
}
return {x2, y2};
}
}; };
#endif #endif

View File

@ -7,7 +7,7 @@ class Player {
public: public:
uint8_t position = 0; uint8_t y = 0;
uint8_t size = 2; uint8_t size = 2;
@ -17,14 +17,14 @@ public:
void randomMove(uint8_t height) { void randomMove(uint8_t height) {
if (moveUp) { if (moveUp) {
position--; y--;
if (position <= 0 || randomBool(20)) { if (y <= 0 || randomBool(20)) {
moveUp = !moveUp; moveUp = false;
} }
} else { } else {
position++; y++;
if (position + size >= height || randomBool(20)) { if (y + size >= height || randomBool(20)) {
moveUp = !moveUp; moveUp = true;
} }
} }
} }

View File

@ -17,7 +17,7 @@ private:
Player player1; Player player1;
Vector position; Vector ball;
Vector velocity; Vector velocity;
@ -29,7 +29,7 @@ public:
explicit Pong(Display &display) : explicit Pong(Display &display) :
Mode(display), Mode(display),
position(width / 2.0, height / 2.0), ball(width / 2.0, height / 2.0),
velocity(Vector::polar(random(360), exp10(1))) { velocity(Vector::polar(random(360), exp10(1))) {
timer(0, 100); timer(0, 100);
spawnBall(random(2) == 0 ? -1 : +1); spawnBall(random(2) == 0 ? -1 : +1);
@ -51,12 +51,12 @@ protected:
} }
break; break;
case PLAY: case PLAY:
position = position.plus(velocity); ball = ball.plus(velocity);
player0.randomMove(height); player0.randomMove(height);
player1.randomMove(height); player1.randomMove(height);
topBottomBounce();
paddleBounce(); paddleBounce();
checkScoring(); checkScoring();
topBottomBounce();
markDirty(); markDirty();
break; break;
@ -80,12 +80,12 @@ protected:
break; break;
case PLAY: case PLAY:
for (int i = 0; i < player0.size; ++i) { for (int i = 0; i < player0.size; ++i) {
display.set(1, (uint8_t) round(player0.position) + i, GREEN); display.set(1, (uint8_t) round(player0.y) + i, GREEN);
} }
for (int i = 0; i < player1.size; ++i) { for (int i = 0; i < player1.size; ++i) {
display.set(width - 2, (uint8_t) round(player1.position) + i, RED); display.set(width - 2, (uint8_t) round(player1.y) + i, RED);
} }
display.set((uint8_t) round(position.x), (uint8_t) round(position.y), WHITE); display.set((uint8_t) round(ball.x), (uint8_t) round(ball.y), WHITE);
break; break;
case OVER: case OVER:
if (player0.score > player1.score) { if (player0.score > player1.score) {
@ -104,22 +104,32 @@ private:
void resetPlayer() { void resetPlayer() {
player0.size = 3; player0.size = 3;
player0.score = 0; player0.score = 0;
player0.position = (height - player0.size) / 2; player0.y = (height - player0.size) / 2;
player1.size = 3; player1.size = 3;
player1.score = 0; player1.score = 0;
player1.position = (height - player1.size) / 2; player1.y = (height - player1.size) / 2;
} }
void topBottomBounce() { void topBottomBounce() {
position = position.bounceInBox(width, height); while (ball.y < 0 || ball.y >= height) {
if (ball.y < 0) {
ball.y = -ball.y;
velocity.y = -velocity.y;
} else if (ball.y >= height) {
ball.y = 2 * height - ball.y - 1;
velocity.y = -velocity.y;
}
}
} }
void checkScoring() { void checkScoring() {
if (position.x < 0) { if (ball.x < 0) {
player1.score++; player1.score++;
Serial.println("Player 1 scored");
spawnBall(+1); spawnBall(+1);
} else if (position.x >= width) { } else if (ball.x >= width) {
player0.score++; player0.score++;
Serial.println("Player 0 scored");
spawnBall(-1); spawnBall(-1);
} }
if (player0.score >= 10 || player1.score >= 10) { if (player0.score >= 10 || player1.score >= 10) {
@ -129,18 +139,26 @@ private:
} }
void paddleBounce() { void paddleBounce() {
if (position.x == 1 && player0.position <= position.y && position.y < player0.position + player0.size) { double paddleHitPosition0 = ball.y - player0.y;
if (ball.x >= 1 && ball.x < 2 && paddleHitPosition0 >= 0 && paddleHitPosition0 < player0.size) {
Serial.printf("Player 0 hit: paddleHitPosition0=%.2f\n", paddleHitPosition0);
velocity.x = -velocity.x; velocity.x = -velocity.x;
position.x = 3; velocity.y = max(-2.0, min(+2.0, velocity.y + paddleHitPosition0 - 1));
} else if (position.x == width - 2 && player1.position <= position.y && position.y < player1.position + player1.size) { ball.x = 3;
return;
}
double paddleHitPosition1 = ball.y - player1.y;
if (ball.x >= width - 2 && ball.x < width - 1 && paddleHitPosition1 >= 0 && paddleHitPosition1 < player1.size) {
Serial.printf("Player 1 hit: paddleHitPosition1=%.2f\n", paddleHitPosition1);
velocity.x = -velocity.x; velocity.x = -velocity.x;
position.x = width - 4; velocity.y = max(-2.0, min(+2.0, velocity.y + paddleHitPosition1 - 1));
ball.x = width - 4;
} }
} }
void spawnBall(int direction) { void spawnBall(int direction) {
position.x = (double) width / 2.0; ball.x = (double) width / 2.0;
position.y = (double) height / 2.0; ball.y = (double) height / 2.0;
velocity.x = direction; velocity.x = direction;
velocity.y = 0; velocity.y = 0;
status = SCORE; status = SCORE;