Initial game launcher
This commit is contained in:
131
lib/game_launcher.cpp
Normal file
131
lib/game_launcher.cpp
Normal file
@@ -0,0 +1,131 @@
|
||||
// ============================================================================
|
||||
// GAME LAUNCHER IMPLEMENTATION
|
||||
// ============================================================================
|
||||
// Menu system for selecting and launching games
|
||||
|
||||
#include "game_launcher.h"
|
||||
#include "display/low_level_render.h"
|
||||
#include "display/low_level_gui.h"
|
||||
#include <stdio.h>
|
||||
|
||||
GameLauncher::GameLauncher(uint16_t width, uint16_t height,
|
||||
LowLevelRenderer* renderer, LowLevelGUI* gui)
|
||||
: width(width), height(height), renderer(renderer), gui(gui),
|
||||
selected_index(0), selected_game(nullptr) {
|
||||
}
|
||||
|
||||
void GameLauncher::register_game(const char* name, const char* description,
|
||||
Game* (*factory)(uint16_t, uint16_t, LowLevelRenderer*, LowLevelGUI*)) {
|
||||
GameEntry entry;
|
||||
entry.name = name;
|
||||
entry.description = description;
|
||||
entry.factory = factory;
|
||||
games.push_back(entry);
|
||||
|
||||
printf("Registered game: %s - %s\n", name, description);
|
||||
}
|
||||
|
||||
void GameLauncher::draw() {
|
||||
// Draw main window
|
||||
gui->draw_new_window(10, 10, width - 20, height - 20, "Game Launcher");
|
||||
|
||||
// Draw title
|
||||
renderer->draw_string(30, 30, "Select a Game:", true);
|
||||
|
||||
// Draw game list
|
||||
for (size_t i = 0; i < games.size(); i++) {
|
||||
int y = MENU_Y_START + (i * MENU_ITEM_HEIGHT);
|
||||
|
||||
// Highlight selected item
|
||||
if ((int)i == selected_index) {
|
||||
// Draw selection box
|
||||
renderer->draw_rectangle(20, y - 5, width - 40, MENU_ITEM_HEIGHT - 10, true, 2);
|
||||
renderer->draw_string(30, y + 2, ">", true);
|
||||
}
|
||||
|
||||
// Draw game name
|
||||
renderer->draw_string(45, y + 2, games[i].name, true);
|
||||
|
||||
// Draw description (smaller, below name)
|
||||
renderer->draw_string(45, y + 15, games[i].description, true);
|
||||
}
|
||||
|
||||
// Draw instructions at bottom
|
||||
const char* instructions;
|
||||
#ifdef BUTTON_KEY0_PIN
|
||||
instructions = "Touch game or use KEY0/KEY1";
|
||||
#else
|
||||
instructions = "Touch game to play";
|
||||
#endif
|
||||
renderer->draw_string(30, height - 35, instructions, true);
|
||||
}
|
||||
|
||||
bool GameLauncher::update(const InputEvent& event) {
|
||||
bool needs_refresh = false;
|
||||
|
||||
switch (event.type) {
|
||||
case INPUT_TOUCH_DOWN: {
|
||||
printf("Touch at (%d,%d) in launcher\n", event.x, event.y);
|
||||
|
||||
// Check if touch is on a game entry
|
||||
for (size_t i = 0; i < games.size(); i++) {
|
||||
int y = MENU_Y_START + (i * MENU_ITEM_HEIGHT);
|
||||
|
||||
// Touch area is the entire menu item
|
||||
if (event.y >= y - 5 && event.y < y + MENU_ITEM_HEIGHT - 5) {
|
||||
// Game selected - create instance
|
||||
printf("Selected game: %s\n", games[i].name);
|
||||
selected_game = games[i].factory(width, height, renderer, gui);
|
||||
if (selected_game) {
|
||||
selected_game->init();
|
||||
return true; // Signal game selected
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case INPUT_BUTTON_0: {
|
||||
// Navigate menu
|
||||
if (games.size() > 0) {
|
||||
selected_index = (selected_index + 1) % games.size();
|
||||
needs_refresh = true;
|
||||
printf("Menu selection: %d (%s)\n", selected_index, games[selected_index].name);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case INPUT_BUTTON_1: {
|
||||
// Select current game
|
||||
if (selected_index >= 0 && selected_index < (int)games.size()) {
|
||||
printf("Selected game: %s\n", games[selected_index].name);
|
||||
selected_game = games[selected_index].factory(width, height, renderer, gui);
|
||||
if (selected_game) {
|
||||
selected_game->init();
|
||||
return true; // Signal game selected
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return needs_refresh;
|
||||
}
|
||||
|
||||
Game* GameLauncher::get_selected_game() {
|
||||
return selected_game;
|
||||
}
|
||||
|
||||
void GameLauncher::reset() {
|
||||
// Clean up current game if any
|
||||
if (selected_game) {
|
||||
delete selected_game;
|
||||
selected_game = nullptr;
|
||||
}
|
||||
selected_index = 0;
|
||||
printf("Launcher reset - returning to menu\n");
|
||||
}
|
||||
102
lib/game_launcher.h
Normal file
102
lib/game_launcher.h
Normal file
@@ -0,0 +1,102 @@
|
||||
// ============================================================================
|
||||
// GAME LAUNCHER HEADER
|
||||
// ============================================================================
|
||||
// Menu system for selecting and launching games
|
||||
|
||||
#ifndef GAME_LAUNCHER_H
|
||||
#define GAME_LAUNCHER_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include <vector>
|
||||
#include "input_event.h"
|
||||
#include "game.h"
|
||||
|
||||
// Forward declarations
|
||||
class LowLevelRenderer;
|
||||
class LowLevelGUI;
|
||||
|
||||
/**
|
||||
* @brief Game entry in launcher menu
|
||||
*/
|
||||
struct GameEntry {
|
||||
const char* name; // Display name
|
||||
const char* description; // Short description
|
||||
Game* (*factory)(uint16_t width, uint16_t height,
|
||||
LowLevelRenderer* renderer, LowLevelGUI* gui); // Factory function
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Game Launcher - Menu system for game selection
|
||||
*
|
||||
* Displays a list of available games and allows selection via:
|
||||
* - Touch: Tap on game name
|
||||
* - Buttons: KEY0 to navigate, KEY1 to select
|
||||
*
|
||||
* Returns the selected game instance for the main loop to run.
|
||||
*/
|
||||
class GameLauncher {
|
||||
public:
|
||||
/**
|
||||
* @brief Construct GameLauncher
|
||||
* @param width Display width in pixels
|
||||
* @param height Display height in pixels
|
||||
* @param renderer Pointer to low-level rendering interface
|
||||
* @param gui Pointer to GUI drawing primitives
|
||||
*/
|
||||
GameLauncher(uint16_t width, uint16_t height, LowLevelRenderer* renderer, LowLevelGUI* gui);
|
||||
|
||||
/**
|
||||
* @brief Register a game in the launcher
|
||||
* @param name Game display name
|
||||
* @param description Short description
|
||||
* @param factory Function pointer to create game instance
|
||||
*/
|
||||
void register_game(const char* name, const char* description,
|
||||
Game* (*factory)(uint16_t, uint16_t, LowLevelRenderer*, LowLevelGUI*));
|
||||
|
||||
/**
|
||||
* @brief Draw the launcher menu
|
||||
*/
|
||||
void draw();
|
||||
|
||||
/**
|
||||
* @brief Process input event in launcher
|
||||
* @param event Input event from InputManager
|
||||
* @return true if a game was selected (check get_selected_game())
|
||||
*/
|
||||
bool update(const InputEvent& event);
|
||||
|
||||
/**
|
||||
* @brief Get the currently selected game instance
|
||||
* @return Pointer to selected game, or nullptr if none selected
|
||||
*/
|
||||
Game* get_selected_game();
|
||||
|
||||
/**
|
||||
* @brief Reset launcher to show menu again
|
||||
*/
|
||||
void reset();
|
||||
|
||||
/**
|
||||
* @brief Check if a game is currently selected
|
||||
* @return true if game selected, false if in menu
|
||||
*/
|
||||
bool is_game_selected() const { return selected_game != nullptr; }
|
||||
|
||||
private:
|
||||
uint16_t width;
|
||||
uint16_t height;
|
||||
LowLevelRenderer* renderer;
|
||||
LowLevelGUI* gui;
|
||||
|
||||
std::vector<GameEntry> games;
|
||||
int selected_index; // Currently highlighted game
|
||||
Game* selected_game; // Currently running game (nullptr = in menu)
|
||||
|
||||
// Menu layout constants
|
||||
static const int MENU_Y_START = 60;
|
||||
static const int MENU_ITEM_HEIGHT = 40;
|
||||
static const int MENU_PADDING = 10;
|
||||
};
|
||||
|
||||
#endif // GAME_LAUNCHER_H
|
||||
Reference in New Issue
Block a user