#include #include #include #include #include "game.h" #include "engine.h" /* All maps */ extern struct map map_lv1; struct map *maps[] = { &map_lv1, }; /* Phases of a turn in the game */ enum turn_phase { PHASE_IDLE = 0, PHASE_MOVE = 1, PHASE_UPDATE = 2, }; /* Returns a direction to move in */ static int get_inputs(void) { int opt = GETKEY_DEFAULT & ~GETKEY_REP_ARROWS; int timeout = 1; while(1) { key_event_t ev = getkey_opt(opt, &timeout); if(ev.type == KEYEV_NONE) return -1; int key = ev.key; if(key == KEY_DOWN) return DIR_DOWN; if(key == KEY_RIGHT) return DIR_RIGHT; if(key == KEY_UP) return DIR_UP; if(key == KEY_LEFT) return DIR_LEFT; } } /* Notify play_level() that the next frame is due soon */ static int callback_tick(volatile int *tick) { *tick = 1; return TIMER_CONTINUE; } bool play_level(int level) { if(level < 1 || level > 8) return false; /* Load the map */ struct game game; engine_load(&game, maps[level-1]); /* Create and spawn a solo player */ struct player singleplayer; game.players[0] = &singleplayer; engine_spawn(&game); /* Start the frame timer */ static volatile int tick = 1; int t = timer_setup(TIMER_ANY, ENGINE_TICK*1000, callback_tick, &tick); if(t < 0) return false; timer_start(t); enum turn_phase phase = PHASE_IDLE; bool succeeded = false; while(1) { while(!tick) sleep(); tick = 0; engine_draw(&game); dupdate(); int dir = get_inputs(); /* If the player inputs a control during IDLE, move them */ if(phase == PHASE_IDLE && dir >= 0) { if(engine_move(&game, &singleplayer, dir)) phase = PHASE_MOVE; } /* When the move is finished, perform a map update */ else if(phase == PHASE_MOVE && engine_all_players_idle(&game)) { /* TODO: Winning condition */ if(engine_wins(&game, &singleplayer)) { succeeded = true; break; } phase = PHASE_UPDATE; engine_finish_turn(&game); } /* When update finishes, start another turn */ else if(phase == PHASE_UPDATE && engine_all_dynamic_tiles_idle(&game)) { phase = PHASE_IDLE; } engine_tick(&game, ENGINE_TICK); } timer_stop(t); return succeeded; }