#include "asset.h" #include "enemy.h" #include "game.h" #include "input.h" #include "platform.h" #include "sprite.h" #include "standard.h" #include "systems.h" void gameplay_new(Game* game) { World* world; world = &game->world; seed_rng(platform_get_time()); init_world(&game->world); init_map(&world->map, world); init_player(&world->player, world); init_waver(&world->waver); world->gmemory = gmemory_max; } void gameplay_next_wave(Game* game) { World* world; world = &game->world; next_wave(&world->waver); game_change_state(game, game_state_game); } static void menu_start(Menu* menu) { Game* game; game = menu->ptr; gameplay_new(game); game_change_state(game, game_state_game); } static void menu_restart(Menu* menu) { Game* game; game = menu->ptr; gameplay_new(game); game_change_state(game, game_state_game); } static void menu_main_menu(Menu* menu) { Game* game; game = menu->ptr; game_change_state(game, game_state_menu); } static void menu_quit(Menu* menu) { (void)menu; platform_quit(); } static void menu_credits(Menu* menu) { Game* game; game = menu->ptr; game_change_state(game, game_state_credits); } static void menu_init(Game* game) { const BM_Font* font; font = get_default_font(); init_menu(&game->menu, game); menu_add(&game->menu, "Play", menu_start, font); menu_add(&game->menu, "Credits", menu_credits, font); menu_add(&game->menu, "Quit", menu_quit, font); } static void menu_update(Game* game) { const Sprite* msg; const Bitmap* bmp; int y; update_menu(&game->menu); y = game->menu.y; msg = get_sprite(sprite_author); bmp = get_bitmap(msg->bitmap); render_bitmap( bmp, renderer_w / 2 - msg->rect.w / 2, renderer_h - 26, &msg->rect ); msg = get_sprite(sprite_free); bmp = get_bitmap(msg->bitmap); render_bitmap( bmp, renderer_w / 2 - msg->rect.w / 2, renderer_h - 15, &msg->rect ); /* Logo. */ msg = get_sprite(sprite_logo); bmp = get_bitmap(msg->bitmap); render_bitmap( bmp, renderer_w / 2 - msg->rect.w / 2, y - msg->rect.h - 8, &msg->rect ); render_menu(&game->menu, get_default_font()); } static void menu_deinit(Game* game) { } static void gameplay_init(Game* game) { start_wave(&game->world); game->want_next = 0; game->wave_timer = 0; game->display_wave_text = 100; } static void render_hud(Game* game) { int i, g; const Sprite* sprite; const Bitmap* bitmap; World* world; Player* player; world = &game->world; player = &world->player; sprite = get_sprite(sprite_heart_full); bitmap = get_bitmap(sprite->bitmap); for (i = 0; i < player->hp; i++) { render_bitmap( bitmap, 1 + i * (sprite->rect.w + 1), 1, &sprite->rect ); } sprite = get_sprite(sprite_heart_empty); bitmap = get_bitmap(sprite->bitmap); for (; i < player_max_hp; i++) { render_bitmap( bitmap, 1 + i * (sprite->rect.w + 1), 1, &sprite->rect ); } sprite = get_sprite(sprite_ram_full); bitmap = get_bitmap(sprite->bitmap); g = world->gmemory / gmemory_units; for (i = 0; i < g; i++) { render_bitmap( bitmap, 1 + i * (sprite->rect.w + 1), 8, &sprite->rect ); } sprite = get_sprite(sprite_ram_empty); bitmap = get_bitmap(sprite->bitmap); g = gmemory_max / gmemory_units; for (; i < g; i++) { render_bitmap( bitmap, 1 + i * (sprite->rect.w + 1), 8, &sprite->rect ); } } static void gameplay_update(Game* game) { int cx, cy, ec, l; World* world; Player* player; const Waver* waver; const BM_Font* font; Colour col; char buf[32]; world = &game->world; player = &world->player; waver = &world->waver; cx = world->cam_x; cy = world->cam_y; font = get_default_font(); update_waver(&world->waver, world); ec = wave_enemy_count(&world->waver); if ( world->enemies_killed >= ec && !game->want_next ) { if (waver->idx >= get_wave_count() - 1) { world->oom = -1; game_change_state(game, game_state_dead); } game->wave_timer = 0; game->want_next = 1; } if (game->want_next && game->wave_timer > 200) { gameplay_next_wave(game); } update_player(player, world); enemy_system(world); debris_system(world); bullet_system(world); collision_system(world); spawner_system(world); animation_system(world); update_camera(player, world); render_map(&world->map, cx, cy); sprite_system(world); if (game->display_wave_text) { col = make_colour(0x7f8dcf, 255); buf[0] = 'W'; buf[1] = 'a'; buf[2] = 'v'; buf[3] = 'e'; buf[4] = ' '; l = 5 + int_to_buf(world->waver.idx + 1, buf + 5); rfont_text_col( font, renderer_w / 2 - (l * font->char_w) / 2, renderer_h / 2, buf, col ); game->display_wave_text--; } game->wave_timer++; render_hud(game); if (world->gmemory <= 0) { world->oom = 1; game_change_state(game, game_state_dead); } } static void gameplay_deinit(Game* game) { } static void credits_init(Game* game) { } static void credits_update(Game* game) { Colour colour; const BM_Font* font; font = get_default_font(); if ( button_just_pressed(btn_shoot) || button_just_pressed(btn_jump) ) { game_change_state(game, game_state_menu); } rfont_text(font, 0, 0, "Programming: quou"); rfont_text(font, 0, 10, "Design: quou"); rfont_text(font, 0, 20, "Sound: quou"); rfont_text(font, 0, 30, "Graphics: quou"); rfont_text(font, 0, 40, "Music: drummyfish"); rfont_text(font, 0, 50, "Source Code: git.quou.xyz"); } static void credits_deinit(Game* game) { } static void dead_init(Game* game) { const BM_Font* font; Menu* menu; menu = &game->menu; font = get_default_font(); init_menu(menu, game); menu_add(menu, "Restart", menu_restart, font); menu_add(menu, "Main Menu", menu_main_menu, font); } static void dead_update(Game* game) { const BM_Font* font; int cx, cy; World* world; font = get_default_font(); world = &game->world; update_menu(&game->menu); cx = game->world.cam_x; cy = game->world.cam_y; render_map(&game->world.map, cx, cy); sprite_system(&game->world); render_hud(game); if (world->oom == 1) { rfont_text( font, renderer_w / 2 - 65, game->menu.y - 15, "Out of Memory" ); } else if (world->oom == -1) { rfont_text( font, renderer_w / 2 - 35, game->menu.y - 15, "You win" ); } else { rfont_text( font, renderer_w / 2 - 40, game->menu.y - 15, "You died" ); } render_menu(&game->menu, get_default_font()); } static void dead_deinit(Game* game) { } static const Game_State_Fns game_state_fns[] = { /* game_state_menu */ { menu_init, menu_update, menu_deinit }, /* game_state_game */ { gameplay_init, gameplay_update, gameplay_deinit }, /* game_state_credits */ { credits_init, credits_update, credits_deinit }, /* game_state_dead */ { dead_init, dead_update, dead_deinit } }; static const Game_State_Fns* get_state_fns(Game_State state) { return &game_state_fns[state]; } void game_init(Game* game, Game_State state) { game->state = state; game->fns = get_state_fns(state); game->fns->state_init(game); } void game_update(Game* game) { game->fns->state_update(game); } void game_deinit(Game* game) { game->fns->state_deinit(game); } void game_change_state(Game* game, Game_State state) { game->fns->state_deinit(game); game->state = state; game->fns = get_state_fns(state); game->fns->state_init(game); }