#include #include #include "keyb.h" #include "vga.h" #include "sound.h" #include "text.h" #include "map.h" #include "data.h" #include "timer.h" #include "entities.h" #include "player.h" #include "game.h" #define GAME_LIVES_START 3 #define GAME_LIVES_MAX 9 #define GAME_TIME_MAX 60 #define GAME_MAX_PICKAXE 3 #define HUD_CLEAN 0 #define HUD_LIVES 1 #define HUD_SCORE 2 #define HUD_STAGE 4 #define HUD_TIME 8 #define HUD_PICKAXE 16 #define HUD_ALL 255 #define GAMEOVER_DELAY 96 static uint32_t hiscore = 15000; static uint8_t hud; static volatile uint8_t clock_updated; /* game variables */ static uint8_t lives; static uint32_t score; static uint8_t stage; static uint8_t time; static uint8_t pickaxe; static uint8_t gameover; static uint8_t pause; static void hud_render() { char b[32]; if (hud & HUD_ALL) { Rect src = { 128, 32, 144, 144}; Rect dst = { 4, 0, 16, 16}; /* lives */ blitrc(binary_sprites_start, &src, &dst); /* pickaxe */ src.x = 112; dst.x = 90; blitrc(binary_sprites_start, &src, &dst); put_text(132, 4, "TIME", 1); put_text(249, 4, "STAGE", 1); } if (hud & HUD_LIVES) { sprintf(b, "%d", lives); put_text(18, 4, b, 1); } if (hud & HUD_SCORE) { sprintf(b, "%06li", score); put_text(34, 4, b, 5); } if (hud & HUD_PICKAXE) { sprintf(b, "%d", pickaxe); put_text(106, 4, b, 1); } if (hud & HUD_TIME) { sprintf(b, "%02d", time); put_text(172, 4, b, time > 10 ? 1 : 15); if (time <= 10) sound_play_efx(EFX_TIME); } if (hud & HUD_STAGE) { sprintf(b, "%02d", stage + 1); put_text(297, 4, b, 1); } hud = HUD_CLEAN; } static void run_gameover() { blit_erase(0); /* restore the HUD after erasing the screen */ hud = HUD_ALL; hud_render(); put_text(124, 90, "GAME OVER", 1); wait_vsync(); blit_update(); /* wait some time */ wait_frames(255); } void run_game() { pause = 0; gameover = 0; lives = GAME_LIVES_START; score = 0; stage = 0; pickaxe = 0; time = GAME_TIME_MAX; hud = HUD_ALL; blit_erase(0); map_init(binary_stage_start); /* render the scene with the READY? text */ map_render(); entities_draw(); player_draw(); hud_render(); put_text(136, 100, "READY?", 1); wait_vsync(); blit_update(); /* wait some time */ wait_frames(96); /* erase the READY? text */ map_render(); entities_draw(); player_draw(); timer_start(GAME_TIME_MAX, &clock_updated); while (!keys[KEY_ESC]) { if (clock_updated) { time = timer_value(); hud |= HUD_TIME; } if (hud) hud_render(); if (keys[KEY_P]) { /* pause / resume */ pause ^= 1; /* wait for the key to be released */ while (keys[KEY_P]) wait_vsync(); if (pause) timer_stop(); else timer_resume(); } if (pause) continue; /* erase first the last we draw */ player_erase(); entities_erase(); player_update(); entities_update(); entities_draw(); player_draw(); wait_vsync(); blit_update(); if (gameover) { gameover--; if (gameover == 1) { run_gameover(); break; } } } /* wait for ESC to be release */ while (keys[KEY_ESC]) wait_vsync(); } void add_score(uint8_t v) { score += v; hud |= HUD_SCORE; } uint32_t get_hiscore() { return hiscore; } uint8_t dec_lives() { lives--; if (lives == 0) { gameover = GAMEOVER_DELAY; timer_stop(); } hud |= HUD_LIVES; return lives; } void reset_time() { time = GAME_TIME_MAX; hud |= HUD_TIME; timer_start(GAME_TIME_MAX, &clock_updated); } void add_pickaxe() { if (pickaxe < GAME_MAX_PICKAXE) { pickaxe++; hud |= HUD_PICKAXE; } } uint8_t use_pickaxe() { if (pickaxe) { pickaxe--; hud |= HUD_PICKAXE; return 1; } return 0; }