Files
roro9stack/src/apps/games_app.h
T
twislaandClaude Opus 5.5 b1e6242b29 Games App: Minesweeper and 2048
Two more Games in the row of icons, which now holds five. Minesweeper
moves a cursor (a held arrow runs it along), digs with Enter, flags with
f, shows where the mines were when it is lost, and keeps the fastest
cleared field. 2048 slides with the arrows and keeps the best score; it
has no clock, so nothing to pause. Neither keeps the screen lit.

Played on the device: Minesweeper's cells went from 8 to 12 pixels to be
read, and its field to 20 x 9.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0162FokPdvY2KsS4NBfwyWPk
2026-10-14 18:46:49 +02:00

95 lines
3.7 KiB
C++

#pragma once
#include <memory>
#include <string>
#include "app.h"
#include "key_mapper.h"
#include "key_value_store.h"
#include "mines.h"
#include "pong.h"
#include "settings.h"
#include "snake.h"
#include "tetris.h"
#include "tune.h"
#include "twenty48.h"
namespace roro {
// The Games App (issue #101): three Games as a row of icons, and the one being played. The rules are in
// lib/games; this draws them, gives them the keys and the time, beeps, and keeps the best of each.
// A Game left in the middle, for the list or for another App, is found again paused.
class GamesApp : public App {
public:
GamesApp(const KeyMapper& keys, const Settings& settings, KeyValueStore& store) : keys_(keys), settings_(settings), store_(store) {}
void onEnter() override;
void onExit() override;
bool onKey(const KeyEvent& e) override;
void update(uint32_t nowMs) override;
void draw(Canvas& c) override;
void help(std::vector<KeyHelp>& out) const override;
const char* helpTitle() const override;
// A Game being played is the device in use, key or no key: the screen stays lit.
// Not for the two that wait for a move: there a key is pressed, or nobody is playing.
bool keepsScreenOn() const override { return which_ <= Tetris && state_[which_] == State::Playing; }
private:
enum Which { Pong, Snake, Tetris, Mines, Twenty48, Menu }; // all but the last index the arrays
static constexpr int kGames = 5;
enum class State : uint8_t { Ready, Playing, Paused, Over };
void begin(); // a new game of the one chosen
void pause();
void ended(int score);
void beep(int hz, int ms);
bool musicOn();
int volume(); // of the tune, 1 to kLoudest
void setVolume(int level);
void quiet(); // the tune stops where it is
void loud(bool on); // the speaker turned up for the tune, or back as it was
int best(Which w);
bool pongKey(const KeyEvent& e);
bool snakeKey(const KeyEvent& e);
bool tetrisKey(const KeyEvent& e);
bool minesKey(const KeyEvent& e);
bool twenty48Key(const KeyEvent& e);
void moveCursor(int dc, int dr);
void drawMines(Canvas& c);
void drawTwenty48(Canvas& c);
void drawMenu(Canvas& c);
void drawPong(Canvas& c);
void drawSnake(Canvas& c);
void drawTetris(Canvas& c);
void drawBanner(Canvas& c, const std::string& title, const std::string& detail);
const KeyMapper& keys_;
const Settings& settings_;
KeyValueStore& store_;
int chosen_ = 0; // in the row of games
Which which_ = Menu;
State state_[kGames] = {State::Ready, State::Ready, State::Ready, State::Ready, State::Ready};
int best_[kGames] = {-1, -1, -1, -1, -1}; // -1: not read from the store yet
bool newBest_ = false;
std::unique_ptr<games::Pong> pong_;
std::unique_ptr<games::Snake> snake_;
std::unique_ptr<games::Tetris> tetris_;
std::unique_ptr<games::Mines> mines_;
std::unique_ptr<games::Twenty48> twenty48_;
// Minesweeper's cursor, and the arrow held to run it along.
int cursorCol_ = 0, cursorRow_ = 0, runDir_ = -1;
uint32_t runMs_ = 0, shownSeconds_ = 0;
bool running_ = false;
uint32_t lastMs_ = 0, lastDrawMs_ = 0;
// Keys that came as presses since the last step: a tap moves too, held or not.
int tapMove_ = 0;
uint32_t tapUntilMs_ = 0;
games::TetrisInput tapped_;
// Tetris's tune (Korobeiniki), switched with 0 and remembered.
games::TunePlayer tune_{games::korobeiniki::at, games::korobeiniki::kCount, games::korobeiniki::kEighthMs};
int music_ = -1, volume_ = -1; // -1: not read from the store yet
int masterWas_ = -1; // the speaker's own volume, while the tune has it turned up
};
} // namespace roro