116 lines
2.2 KiB
C
116 lines
2.2 KiB
C
|
#include <gint/display.h>
|
||
|
#include <gint/keyboard.h>
|
||
|
#include <gint/timer.h>
|
||
|
#include <gint/clock.h>
|
||
|
|
||
|
#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;
|
||
|
}
|