Files
minigame-menu/minigame_menu.c

192 lines
4.2 KiB
C

//
// Created by snapshot112 on 10/15/25.
//
#include "minigame_menu.h"
#include <ncurses.h>
#include <stdlib.h>
#include "grid_game_engine.h"
#include "manual.h"
#include "maze_runner.h"
#include "minesweeper.h"
#include "rooster.h"
#include "snake.h"
#define AMOUNT_OF_MENU_OPTIONS 5
typedef enum {
GAME_HELP = 0,
GAME_MAZE_RUNNER = 1,
GAME_SNAKE = 2,
GAME_MINESWEEPER = 3,
GAME_QUIT = 4,
} game;
static game SELECTED_GAME = GAME_HELP;
static int OFFSET_Y = 5;
static int OFFSET_X = 5;
/*
* Launch a game from the menu.
*
* Input:
* menu: A pointer to the menu grid.
* game: The game you want to launch.
*/
static void launch_game(const game game) {
switch (game) {
case GAME_HELP:
manual((coordinate){0,0});
break;
case GAME_MAZE_RUNNER:
maze_runner();
break;
case GAME_SNAKE:
snake();
break;
case GAME_MINESWEEPER:
minesweeper();
break;
}
}
/*
* Highlight a valid menu option.
*
* Input:
* menu: A pointer to the menu grid.
* target: The menu option to highlight.
* offset_x: The x offset of the menu.
* offset_y: The y offset of the menu.
*
* Side effects:
* If a valid menu option is provided: It will be highlighted in green.
* If an invalid menu option is provided: Nothing happens
*/
static void menu_highlight(const rooster *menu) {
switch (SELECTED_GAME) {
case GAME_HELP:
case GAME_MAZE_RUNNER:
case GAME_SNAKE:
case GAME_MINESWEEPER:
case GAME_QUIT:
attron(COLOR_PAIR(GREEN));
char* row = rooster_vraag_rij(menu, SELECTED_GAME);
mvprintw(OFFSET_Y + (int)SELECTED_GAME, OFFSET_X, "%s", row);
free(row);
attroff(COLOR_PAIR(GREEN));
}
}
/*
* Show the menu screen.
*
* Input:
* menu: A pointer to the menu grid.
* default_selection: The starting selection in the menu.
* offset_x: The x offset of the menu.
* offset_y: The y offset of the menu.
*
* Side Effects:
* Displays the menu
*/
static void show_menu(const rooster *menu) {
erase();
show_grid_on_offset(menu, OFFSET_X, OFFSET_Y);
menu_highlight(menu);
refresh();
}
/*
* Select the game on a location determined by a given offset.
* Negative values go up and positive values go down.
* Out of bounds selections loop around.
*
* Input:
* selected_game: The currently selected game.
* offset: The amount offset the current selection by.
*
* Side effect:
* The game on the location of the given offset will be selected.
*/
static void menu_move(const int offset) {
SELECTED_GAME = modulo(SELECTED_GAME + offset, AMOUNT_OF_MENU_OPTIONS);
}
/*
* Navigate through the menu.
*
* Input:
* menu: A pointer to the menu grid.
*
* Output: A code that reflects the current menu state.
* 0: Continue running.
* 1: Exit the menu.
*
*
* Side Effect:
* Changes the SELECTED_GAME as needed and launches selected games on select.
*/
static int navigate_menu(void) {
switch (getch()) {
case KEY_UP:
case 'w':
case 'W':
menu_move(-1);
break;
case KEY_DOWN:
case 's':
case 'S':
menu_move(1);
break;
case KEY_ENTER:
case '\n':
case 'f':
case 'F':
case ' ':
if (SELECTED_GAME == GAME_QUIT) {
return 1;
}
launch_game(SELECTED_GAME);
break;
case 'p':
case KEY_BACKSPACE:
case KEY_ESCAPE:
return 1;
}
return 0;
}
/*
* Create the menu grid.
*
* Output:
* A pointer to the menu grid.
*/
static rooster *initialize_menu(void) {
char menu[] = "How to play\n"
"Maze Runner\n"
" Snake \n"
"Minesweeper\n"
" Leave \n";
rooster *rp = grid_from_string(menu);
return rp;
}
void minigame_menu(void) {
rooster *menu = initialize_menu();
while (true) {
show_menu(menu);
if (navigate_menu() == 1) {
break;
}
}
rooster_klaar(menu);
}