Files
2026-05-01 07:18:28 -07:00

210 lines
6.4 KiB
C++

#include "PongActivity.h"
#include <GfxRenderer.h>
#include "MappedInputManager.h"
#include "fontIds.h"
void PongActivity::onEnter() {
Activity::onEnter();
screenW_ = renderer.getScreenWidth();
screenH_ = renderer.getScreenHeight();
playerX_ = (screenW_ - PADDLE_W) / 2.0f;
cpuX_ = (screenW_ - PADDLE_W) / 2.0f;
playerScore_ = 0;
cpuScore_ = 0;
gameOver_ = false;
playerWon_ = false;
lastUpdate_ = millis();
resetBall(true);
renderPending_ = true;
requestUpdate();
}
void PongActivity::onExit() {
Activity::onExit();
}
void PongActivity::resetBall(bool playerServes) {
ballX_ = screenW_ / 2.0f;
ballY_ = screenH_ / 2.0f;
ballDX_ = (playerServes ? 1.0f : -1.0f) * BALL_SPEED_X;
ballDY_ = BALL_SPEED_Y;
}
void PongActivity::moveCpu() {
float cpuCenterX = cpuX_ + PADDLE_W / 2.0f;
float ballCenterX = ballX_ + BALL_SIZE / 2.0f;
if (ballCenterX < cpuCenterX - 4) {
cpuX_ -= CPU_SPEED;
} else if (ballCenterX > cpuCenterX + 4) {
cpuX_ += CPU_SPEED;
}
if (cpuX_ < MARGIN) cpuX_ = MARGIN;
if (cpuX_ + PADDLE_W > screenW_ - MARGIN) cpuX_ = screenW_ - MARGIN - PADDLE_W;
}
void PongActivity::updateGame() {
ballX_ += ballDX_;
ballY_ += ballDY_;
if (ballX_ <= MARGIN) {
ballX_ = MARGIN;
ballDX_ = -ballDX_;
}
if (ballX_ + BALL_SIZE >= screenW_ - MARGIN) {
ballX_ = screenW_ - MARGIN - BALL_SIZE;
ballDX_ = -ballDX_;
}
int playerPaddleY = screenH_ - MARGIN - PADDLE_H;
if (ballDY_ > 0 &&
ballY_ + BALL_SIZE >= playerPaddleY &&
ballY_ + BALL_SIZE <= playerPaddleY + PADDLE_H + 4 &&
ballX_ + BALL_SIZE >= playerX_ &&
ballX_ <= playerX_ + PADDLE_W)
{
ballY_ = playerPaddleY - BALL_SIZE;
ballDY_ = -ballDY_;
float hitPos = (ballX_ + BALL_SIZE / 2.0f) - (playerX_ + PADDLE_W / 2.0f);
ballDX_ = hitPos / (PADDLE_W / 2.0f) * BALL_SPEED_X * 1.5f;
if (ballDX_ > BALL_SPEED_X * 2) ballDX_ = BALL_SPEED_X * 2;
if (ballDX_ < -BALL_SPEED_X * 2) ballDX_ = -BALL_SPEED_X * 2;
}
int cpuPaddleY = MARGIN;
if (ballDY_ < 0 &&
ballY_ <= cpuPaddleY + PADDLE_H &&
ballY_ >= cpuPaddleY - 4 &&
ballX_ + BALL_SIZE >= cpuX_ &&
ballX_ <= cpuX_ + PADDLE_W)
{
ballY_ = cpuPaddleY + PADDLE_H;
ballDY_ = -ballDY_;
float hitPos = (ballX_ + BALL_SIZE / 2.0f) - (cpuX_ + PADDLE_W / 2.0f);
ballDX_ = hitPos / (PADDLE_W / 2.0f) * BALL_SPEED_X * 1.5f;
if (ballDX_ > BALL_SPEED_X * 2) ballDX_ = BALL_SPEED_X * 2;
if (ballDX_ < -BALL_SPEED_X * 2) ballDX_ = -BALL_SPEED_X * 2;
}
if (ballY_ > screenH_) {
cpuScore_++;
if (cpuScore_ >= SCORE_TO_WIN) {
gameOver_ = true;
playerWon_ = false;
} else {
resetBall(false);
}
}
if (ballY_ + BALL_SIZE < 0) {
playerScore_++;
if (playerScore_ >= SCORE_TO_WIN) {
gameOver_ = true;
playerWon_ = true;
} else {
resetBall(true);
}
}
moveCpu();
}
void PongActivity::loop() {
if (gameOver_) {
if (mappedInput.wasPressed(MappedInputManager::Button::Back) ||
mappedInput.wasPressed(MappedInputManager::Button::Confirm) ||
mappedInput.wasPressed(MappedInputManager::Button::Left) ||
mappedInput.wasPressed(MappedInputManager::Button::Right) ||
mappedInput.wasPressed(MappedInputManager::Button::Up) ||
mappedInput.wasPressed(MappedInputManager::Button::Down) ||
mappedInput.wasPressed(MappedInputManager::Button::Power)) {
finish();
}
return;
}
if (mappedInput.wasPressed(MappedInputManager::Button::Power)) {
while (mappedInput.isPressed(MappedInputManager::Button::Power)) {
mappedInput.update();
delay(10);
}
finish();
return;
}
bool moved = false;
bool goLeft = mappedInput.wasPressed(MappedInputManager::Button::Left) ||
mappedInput.wasPressed(MappedInputManager::Button::Up) ||
mappedInput.wasPressed(MappedInputManager::Button::Back);
bool goRight = mappedInput.wasPressed(MappedInputManager::Button::Right) ||
mappedInput.wasPressed(MappedInputManager::Button::Down) ||
mappedInput.wasPressed(MappedInputManager::Button::Confirm);
if (goLeft) {
playerX_ -= PADDLE_W;
if (playerX_ < MARGIN) playerX_ = MARGIN;
moved = true;
}
if (goRight) {
playerX_ += PADDLE_W;
if (playerX_ + PADDLE_W > screenW_ - MARGIN) playerX_ = screenW_ - MARGIN - PADDLE_W;
moved = true;
}
unsigned long now = millis();
if (now - lastUpdate_ >= 33) {
lastUpdate_ = now;
updateGame();
renderPending_ = true;
requestUpdate();
} else if (moved) {
renderPending_ = true;
requestUpdate();
}
}
void PongActivity::render(RenderLock&&) {
renderPending_ = false;
renderer.clearScreen();
renderer.drawLine(MARGIN, MARGIN, screenW_ - MARGIN, MARGIN);
renderer.drawLine(MARGIN, screenH_ - MARGIN, screenW_ - MARGIN, screenH_ - MARGIN);
renderer.drawLine(MARGIN, MARGIN, MARGIN, screenH_ - MARGIN);
renderer.drawLine(screenW_ - MARGIN, MARGIN, screenW_ - MARGIN, screenH_ - MARGIN);
int midY = screenH_ / 2;
for (int x = MARGIN + 4; x < screenW_ - MARGIN; x += 16) {
renderer.drawLine(x, midY, x + 8, midY);
}
int cpuPaddleY = MARGIN;
renderer.fillRect((int)cpuX_, cpuPaddleY, PADDLE_W, PADDLE_H, true);
int playerPaddleY = screenH_ - MARGIN - PADDLE_H;
renderer.fillRect((int)playerX_, playerPaddleY, PADDLE_W, PADDLE_H, true);
renderer.fillRect((int)ballX_, (int)ballY_, BALL_SIZE, BALL_SIZE, true);
char scoreStr[16];
snprintf(scoreStr, sizeof(scoreStr), "%d %d", cpuScore_, playerScore_);
int scoreX = screenW_ / 2 - 20;
renderer.drawText(UI_10_FONT_ID, scoreX, midY - 20, scoreStr, true);
if (gameOver_) {
int quarterY = screenH_ / 4;
const char* msg = playerWon_ ? "YOU WIN!" : "CPU WINS";
renderer.drawText(UI_12_FONT_ID, screenW_ / 2 - 50, quarterY - 20, msg, true, EpdFontFamily::BOLD);
renderer.drawText(UI_10_FONT_ID, screenW_ / 2 - 80, quarterY + 20, "Press any button to exit", true);
}
renderer.displayBuffer();
}