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};
}
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

View File

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

View File

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