wip menu
This commit is contained in:
		
							
								
								
									
										381
									
								
								spel.c
									
									
									
									
									
								
							
							
						
						
									
										381
									
								
								spel.c
									
									
									
									
									
								
							| @@ -21,15 +21,24 @@ | ||||
|  */ | ||||
|  | ||||
| #include <assert.h> | ||||
| #include <ctype.h> | ||||
| #include <stdio.h> | ||||
| #include <stdlib.h> | ||||
|  | ||||
| #include <ncurses.h> | ||||
| #include <wchar.h> | ||||
| #include <locale.h> | ||||
| #include <string.h> | ||||
|  | ||||
| #include "rooster.h" | ||||
|  | ||||
| typedef enum { | ||||
|     GAME_QUIT, | ||||
|     GAME_MAZE_RUNNER, | ||||
|     GAME_SNAKE, | ||||
|     GAME_MINESWEEPER | ||||
| } game; | ||||
|  | ||||
| typedef struct { | ||||
|     char name[100]; | ||||
|     rooster *game_map; | ||||
| @@ -66,6 +75,115 @@ void update_grid(rooster *rp, char c, int x, int y) { | ||||
|     } | ||||
| } | ||||
|  | ||||
| void game_error(void) { | ||||
|     endwin(); | ||||
|     exit(EXIT_FAILURE); | ||||
| } | ||||
|  | ||||
| void quit_game(rooster *menu) { | ||||
|     if (menu != NULL) { | ||||
|         rooster_klaar(menu); | ||||
|     } | ||||
|     endwin(); | ||||
|     exit(EXIT_SUCCESS); | ||||
| } | ||||
|  | ||||
| /* | ||||
|  * Toont het victory screen. | ||||
|  * | ||||
|  * Side Effect: | ||||
|  * De victory message wordt op een schone console geprint. | ||||
|  */ | ||||
| void display_victory(void) { | ||||
|     clear(); | ||||
|     mvprintw(2,5, "YOU WON!!!!!"); | ||||
|     refresh(); | ||||
| } | ||||
|  | ||||
| /* | ||||
|  * Toont het loss screen. | ||||
|  * | ||||
|  * Side Effect: | ||||
|  * De loss message wordt op een schone console geprint. | ||||
|  */ | ||||
| void display_loss(void) { | ||||
|     clear(); | ||||
|     mvprintw(2,5, "RIP, YOU DIED..."); | ||||
|     refresh(); | ||||
| } | ||||
|  | ||||
| /* | ||||
|  * Toont het quit screen. | ||||
|  * | ||||
|  * Side Effect: | ||||
|  * De quit message wordt op een schone console geprint. | ||||
|  */ | ||||
| void display_quit(void) { | ||||
|     clear(); | ||||
|     mvprintw(2,5, "You quit the game"); | ||||
|     refresh(); | ||||
| } | ||||
|  | ||||
| /* | ||||
|  * Toont het hackerman screen. | ||||
|  * | ||||
|  * Side Effect: | ||||
|  * De hackerman message wordt op een schone console geprint. | ||||
|  */ | ||||
| void display_hackerman(void) { | ||||
|     clear(); | ||||
|     mvprintw(2,5, "The hacker man strikes again..."); | ||||
|     refresh(); | ||||
| } | ||||
|  | ||||
| /* | ||||
|  * Bepaalt afhankelijk van de eindtoestand van het rooster | ||||
|  * welk afsluitscherm er getoond moet worden en toont dan dat rooster. | ||||
|  * | ||||
|  * Input: Het rooster om de toestand uit af te lezen. | ||||
|  * | ||||
|  * Side Effects: | ||||
|  * Het end-of-game scherm wordt op een blanke console geprint. | ||||
|  */ | ||||
| void game_exit_screen(rooster *rp) { | ||||
|     toestand current_state = rooster_vraag_toestand(rp); | ||||
|     switch (current_state) { | ||||
|         case STATE_GEWONNEN: | ||||
|             display_victory(); | ||||
|             return; | ||||
|         case STATE_VERLOREN: | ||||
|             display_loss(); | ||||
|             return; | ||||
|         case GAME_QUIT: | ||||
|             display_quit(); | ||||
|             return; | ||||
|     } | ||||
|     display_hackerman(); | ||||
| } | ||||
|  | ||||
| /* | ||||
|  * Waits for the user to press an exit key 'q' before continuing. | ||||
|  */ | ||||
| void graceful_exit(void) { | ||||
|     mvprintw(5, 0, "Press 'q' to exit the game."); | ||||
|     while (1) { | ||||
|         switch (getch()) { | ||||
|             case 'q': | ||||
|                 return; | ||||
|         } | ||||
|     } | ||||
| } | ||||
|  | ||||
| void speel_snake(void) { | ||||
|     mvprintw(0,0, "Snake has not yet been created"); | ||||
|     graceful_exit(); | ||||
| } | ||||
|  | ||||
| void speel_minesweeper() { | ||||
|     mvprintw(0,0, "Minesweeper has not yet been created"); | ||||
|     graceful_exit(); | ||||
| } | ||||
|  | ||||
| /* Voert de benodigde veranderingen in het rooster door als de speler in een | ||||
|  * bepaalde richting probeert te bewegen. | ||||
|  * Input: | ||||
| @@ -77,7 +195,7 @@ void update_grid(rooster *rp, char c, int x, int y) { | ||||
|  * Side effect: het rooster wordt aangepast op basis van de handeling van | ||||
|  *              de speler. | ||||
|  */ | ||||
| void beweeg(rooster *rp, int dx, int dy) { | ||||
| void maze_runner_beweeg(rooster *rp, int dx, int dy) { | ||||
|     int playerx; | ||||
|     int playery; | ||||
|     rooster_zoek(rp, '*', &playerx, &playery); | ||||
| @@ -94,7 +212,7 @@ void beweeg(rooster *rp, int dx, int dy) { | ||||
|                 break; | ||||
|             case 'X': | ||||
|                 update_grid(rp, ' ', playerx, playery); | ||||
|                 rooster_zet_toestand(rp, VERLOREN); | ||||
|                 rooster_zet_toestand(rp, STATE_VERLOREN); | ||||
|                 break; | ||||
|             case ' ': | ||||
|                 update_grid(rp, ' ', playerx, playery); | ||||
| @@ -102,7 +220,7 @@ void beweeg(rooster *rp, int dx, int dy) { | ||||
|                 break; | ||||
|             case '$': | ||||
|                 update_grid(rp, ' ', playerx, playery); | ||||
|                 rooster_zet_toestand(rp, GEWONNEN); | ||||
|                 rooster_zet_toestand(rp, STATE_GEWONNEN); | ||||
|                 break; | ||||
|         } | ||||
|         refresh(); | ||||
| @@ -117,133 +235,44 @@ void beweeg(rooster *rp, int dx, int dy) { | ||||
|  * | ||||
|  * Side Effects: | ||||
|  * Met WSAD en arrow keys kun je door het doolhof heen bewegen. | ||||
|  * | ||||
|  */ | ||||
| void run_maze(rooster *rp) { | ||||
|     while (rooster_vraag_toestand(rp) == AAN_HET_SPELEN) | ||||
| void maze_runner(rooster *rp) { | ||||
|     while (rooster_vraag_toestand(rp) == STATE_AAN_HET_SPELEN) | ||||
|     { | ||||
|         switch (getch()) { | ||||
|             case KEY_UP: // fallthrough | ||||
|             case 'w': | ||||
|                 beweeg(rp, 0, -1); | ||||
|                 maze_runner_beweeg(rp, 0, -1); | ||||
|                 break; | ||||
|             case KEY_DOWN: // fallthrough | ||||
|             case 's': | ||||
|                 beweeg(rp, 0, 1); | ||||
|                 maze_runner_beweeg(rp, 0, 1); | ||||
|                 break; | ||||
|             case KEY_LEFT: // fallthrough | ||||
|             case 'a': | ||||
|                 beweeg(rp, -1, 0); | ||||
|                 maze_runner_beweeg(rp, -1, 0); | ||||
|                 break; | ||||
|             case KEY_RIGHT: // fallthrough | ||||
|             case 'd': | ||||
|                 beweeg(rp, 1, 0); | ||||
|                 maze_runner_beweeg(rp, 1, 0); | ||||
|                 break; | ||||
|             case KEY_EXIT: | ||||
|                 rooster_zet_toestand(rp, VERLOREN); | ||||
|             case KEY_BACKSPACE: | ||||
|                 rooster_zet_toestand(rp, STATE_QUIT); | ||||
|                 break; | ||||
|         } | ||||
|     } | ||||
| } | ||||
|  | ||||
| /* | ||||
|  * Toont het maze victory screen. | ||||
|  * | ||||
|  * Side Effect: | ||||
|  * De victory message wordt op een schone console geprint. | ||||
|  */ | ||||
| void display_maze_victory() { | ||||
|     clear(); | ||||
|     mvprintw(2,5, "YOU WON!!!!!"); | ||||
|     refresh(); | ||||
| } | ||||
| rooster *choose_maze(void) { | ||||
|     // TODO: echt opties aanbieden in plaats van hardcoded 1 maze. | ||||
|     // Alternatief is om random een maze te genereren. dit is miss beter. | ||||
|  | ||||
| /* | ||||
|  * Toont het maze loss screen. | ||||
|  * | ||||
|  * Side Effect: | ||||
|  * De loss message wordt op een schone console geprint. | ||||
|  */ | ||||
| void display_maze_loss() { | ||||
|     clear(); | ||||
|     mvprintw(2,5, "RIP, YOU DIED..."); | ||||
|     refresh(); | ||||
| } | ||||
|  | ||||
| /* | ||||
|  * Toont het maze broken screen. | ||||
|  * | ||||
|  * Side Effect: | ||||
|  * De hackerman message wordt op een schone console geprint. | ||||
|  */ | ||||
| void display_hackerman() { | ||||
|     clear(); | ||||
|     mvprintw(2,5, "The hacker man strikes again..."); | ||||
|     refresh(); | ||||
| } | ||||
|  | ||||
| /* | ||||
|  * Bepaalt afhankelijk van de eindtoestand van het rooster | ||||
|  * welk afsluitscherm er getoond moet worden en toont dan dat rooster. | ||||
|  * | ||||
|  * Input: Het rooster om de toestand uit af te lezen. | ||||
|  * | ||||
|  * Side Effects: | ||||
|  * Het end-of-game scherm wordt op een blanke console geprint. | ||||
|  */ | ||||
| void maze_exit_screen(rooster *rp) { | ||||
|     toestand current_state = rooster_vraag_toestand(rp); | ||||
|     switch (current_state) { | ||||
|         case GEWONNEN: | ||||
|             display_maze_victory(); | ||||
|             return; | ||||
|         case VERLOREN: | ||||
|             display_maze_loss(); | ||||
|             return; | ||||
|     } | ||||
|     display_hackerman(); | ||||
| } | ||||
|  | ||||
| /* | ||||
|  * Waits for the user to press an exit key 'q' before continuing. | ||||
|  */ | ||||
| void graceful_exit() { | ||||
|     mvprintw(5, 0, "Press 'q' to exit the game."); | ||||
|     while (1) { | ||||
|         switch (getch()) { | ||||
|             case 'q': | ||||
|                 return; | ||||
|         } | ||||
|     } | ||||
| } | ||||
|  | ||||
| void toon_menu(rooster *rp) { | ||||
|     toon_rooster(rp); | ||||
|     rooster_zet_toestand(rp, AAN_HET_SPELEN); | ||||
|     run_maze(rp); | ||||
|     maze_exit_screen(rp); | ||||
|     graceful_exit(); | ||||
| } | ||||
|  | ||||
| /* | ||||
|  * Speelt het spel met een gegeven rooster tot de toestand niet langer | ||||
|  * AAN_HET_SPELEN is. | ||||
|  */ | ||||
| void speel(rooster *rp) { | ||||
|     toon_menu(rp); | ||||
| } | ||||
|  | ||||
| int main(int argc, char *argv[]) { | ||||
|     // 1. Controleer dat er een doolhofbestand is opgegeven op de command line. | ||||
|     if (argc != 2) { | ||||
|         fprintf(stderr, "gebruik: ./spel assets/voorbeeld_doolhof.txt\n"); | ||||
|         return 1; | ||||
|     } | ||||
|  | ||||
|     // 2. Open het doolhofbestand en lees het rooster. | ||||
|     FILE *fh = fopen(argv[1], "r"); | ||||
|     // 2. Open het doolhof bestand en lees het rooster. | ||||
|     FILE *fh = fopen("assets/voorbeeld_doolhof.txt", "r"); | ||||
|     if (fh == NULL) { | ||||
|         perror("main"); | ||||
|         return 1; | ||||
|         perror("loading maze"); | ||||
|         game_error(); | ||||
|     } | ||||
|     rooster *rp = rooster_lees(fh); | ||||
|     fclose(fh); | ||||
| @@ -251,23 +280,147 @@ int main(int argc, char *argv[]) { | ||||
|     // 3. Bepaal of het lezen van het rooster is gelukt. | ||||
|     if (rp == NULL) { | ||||
|         fprintf(stderr, "Kan rooster niet maken.\n"); | ||||
|         return 1; | ||||
|         game_error(); | ||||
|     } | ||||
|  | ||||
|     return rp; | ||||
| } | ||||
|  | ||||
| /* | ||||
|  * Speelt het spel met een gegeven rooster tot de toestand niet langer | ||||
|  * AAN_HET_SPELEN is. | ||||
|  */ | ||||
| void speel_maze(void) { | ||||
|     // Voorbereiding. | ||||
|     rooster *rp = choose_maze(); | ||||
|     toon_rooster(rp); | ||||
|     rooster_zet_toestand(rp, STATE_AAN_HET_SPELEN); | ||||
|  | ||||
|     // Game zelf. | ||||
|     maze_runner(rp); | ||||
|  | ||||
|     // Exit game. | ||||
|     game_exit_screen(rp); | ||||
|     rooster_klaar(rp); | ||||
|     graceful_exit(); | ||||
| } | ||||
|  | ||||
| void launch_game(rooster *menu, const game game) { | ||||
|     switch (game) { | ||||
|         case GAME_MAZE_RUNNER: | ||||
|             speel_maze(); | ||||
|             return; | ||||
|         case GAME_SNAKE: | ||||
|             speel_snake(); | ||||
|             return; | ||||
|         case GAME_MINESWEEPER: | ||||
|             speel_minesweeper(); | ||||
|             return; | ||||
|         case GAME_QUIT: | ||||
|             quit_game(menu); | ||||
|     } | ||||
| } | ||||
|  | ||||
| void menu_highlight(rooster *rp, const game target, const int offset_x, const int offset_y) { | ||||
|     switch (target) { | ||||
|         case GAME_MAZE_RUNNER: // Fallthrough | ||||
|         case GAME_SNAKE:       // Fallthrough | ||||
|         case GAME_MINESWEEPER: // Fallthrough | ||||
|         case GAME_QUIT:        // Fallthrough | ||||
|             // TODO: Properly highlight this shit. | ||||
|             mvprintw(offset_y + (int)target, offset_x, rooster_vraag_rij(rp, target)); | ||||
|     } | ||||
| } | ||||
|  | ||||
| game menu_try_move(const game selected_game, const int offset) { | ||||
|     switch (selected_game + offset) { | ||||
|         case GAME_MAZE_RUNNER: | ||||
|             return GAME_MAZE_RUNNER; | ||||
|         case GAME_SNAKE: | ||||
|             return GAME_SNAKE; | ||||
|         case GAME_MINESWEEPER: | ||||
|             return GAME_MINESWEEPER; | ||||
|         case GAME_QUIT: | ||||
|             return GAME_QUIT; | ||||
|     } | ||||
|     return selected_game; | ||||
| } | ||||
|  | ||||
| void navigate_menu(rooster *menu, const game default_game, const int offset_x, const int offset_y) { | ||||
|     game selected_game = default_game; | ||||
|     while (true) { | ||||
|         switch (getch()) { | ||||
|             case KEY_UP: // fallthrough | ||||
|             case 'w': | ||||
|                 selected_game = menu_try_move(selected_game, -1); | ||||
|                 menu_highlight(menu, selected_game, offset_x, offset_y); | ||||
|                 break; | ||||
|             case KEY_DOWN: // fallthrough | ||||
|             case 's': | ||||
|                 selected_game = menu_try_move(selected_game, 1); | ||||
|                 menu_highlight(menu, selected_game, offset_x, offset_y); | ||||
|                 break; | ||||
|             case KEY_ENTER: | ||||
|                 // select current game somehow | ||||
|                 launch_game(menu, GAME_QUIT); | ||||
|                 menu_highlight(menu, selected_game, offset_x, offset_y); | ||||
|                 break; | ||||
|             case KEY_BACKSPACE: | ||||
|                 launch_game(menu, GAME_QUIT); | ||||
|                 break; | ||||
|         } | ||||
|     } | ||||
| } | ||||
|  | ||||
| rooster *laad_menu(void) { | ||||
|     char menu[] = "Maze Runner\n" | ||||
|                   "   Snake   \n" | ||||
|                   "Minesweeper\n" | ||||
|                   "   Leave   \n"; | ||||
|     rooster *rp = rooster_maak(menu); | ||||
|     return rp; | ||||
| } | ||||
|  | ||||
| void toon_menu(rooster *menu, const game default_game, const int offset_x, const int offset_y) { | ||||
|     toon_rooster_op_locatie(menu, offset_x, offset_y); | ||||
|     menu_highlight(menu, default_game, offset_x, offset_y); | ||||
|     refresh(); | ||||
| } | ||||
|  | ||||
| void menu(void) { | ||||
|     rooster *menu = laad_menu(); | ||||
|     const game default_game = GAME_MAZE_RUNNER; | ||||
|  | ||||
|     while (true) { | ||||
|         clear(); | ||||
|         const int offset_x = 5; | ||||
|         const int offset_y = 5; | ||||
|         toon_menu(menu, default_game, offset_x, offset_y); | ||||
|         navigate_menu(menu, default_game, offset_x, offset_y); | ||||
|     } | ||||
| } | ||||
|  | ||||
| void startup_sequence(void) { | ||||
|     // TODO: Nice entry screen | ||||
| } | ||||
|  | ||||
| int main(void) { | ||||
|     // 4. Initialiseer ncurses | ||||
|     setlocale(LC_ALL, ""); | ||||
|     initscr(); | ||||
|     cbreak();             // zodat je kunt onderbreken met Ctrl+C | ||||
|     keypad(stdscr, TRUE); // luister ook naar extra toetsen zoals pijltjes | ||||
|     noecho();             // druk niet de letters af die je intypt | ||||
|     curs_set(0);          // hides the cursor | ||||
|     curs_set(0);          // hides the cursor// Don't mask any mouse events | ||||
|  | ||||
|     // mousemask(ALL_MOUSE_EVENTS | REPORT_MOUSE_POSITION, NULL); // Don't mask any mouse events | ||||
|     // printf("\033[?1003h\n"); // Makes the terminal report mouse movement events | ||||
|  | ||||
|  | ||||
|     // 5. Speel het spel. | ||||
|     speel(rp); | ||||
|     startup_sequence(); | ||||
|     menu(); | ||||
|  | ||||
|     // 6. Sluit af. | ||||
|     rooster_klaar(rp); | ||||
|     endwin(); | ||||
|     return 0; | ||||
|     quit_game(NULL); | ||||
| } | ||||
|   | ||||
		Reference in New Issue
	
	Block a user