#include "gui_game.h" #include "game.h" #include "scene.h" #include "../common/log.h" #include "../common/memory_utils.h" #include "../system/platform.h" #include "event.h" #include "input.h" #include "texture.h" #include "door.h" #define SKIN_TEXTURE_WIDTH 256 #define SKIN_TEXTURE_HEIGHT 256 static void gui_game_pause_menu(struct nk_context* context); static void gui_game_next_level_dialog(struct nk_context* context); static void gui_game_restart_level_dialog(struct nk_context* context); static void gui_game_on_player_death(struct Event* event); static void gui_game_on_scene_cleared(struct Event* event); static void gui_game_end_dialog(struct nk_context* context); void gui_game_init(struct Game_Gui* game_gui) { game_gui->gui = memory_allocate_and_clear(1, sizeof(*game_gui->gui)); gui_init(game_gui->gui); game_gui->show_next_level_dialog = false; game_gui->show_restart_level_dialog = false; game_gui->skin.skin_texture = texture_create_from_file("gui_skin.tga", TU_DIFFUSE); game_gui->skin.button = nk_subimage_id(game_gui->skin.skin_texture, SKIN_TEXTURE_WIDTH, SKIN_TEXTURE_HEIGHT, nk_recti(32, 32, 128, 48)); game_gui->skin.button_active = nk_subimage_id(game_gui->skin.skin_texture, SKIN_TEXTURE_WIDTH, SKIN_TEXTURE_HEIGHT, nk_recti(32, 32, 128, 48)); game_gui->skin.button_hover = nk_subimage_id(game_gui->skin.skin_texture, SKIN_TEXTURE_WIDTH, SKIN_TEXTURE_HEIGHT, nk_recti(32, 32, 128, 48)); game_gui->skin.hp = nk_subimage_id(game_gui->skin.skin_texture, SKIN_TEXTURE_WIDTH, SKIN_TEXTURE_HEIGHT, nk_recti(32, 0, 32, 32)); game_gui->skin.key = nk_subimage_id(game_gui->skin.skin_texture, SKIN_TEXTURE_WIDTH, SKIN_TEXTURE_HEIGHT, nk_recti(0, 32, 32, 32)); game_gui->skin.crosshair = nk_subimage_id(game_gui->skin.skin_texture, SKIN_TEXTURE_WIDTH, SKIN_TEXTURE_HEIGHT, nk_recti(112, 0, 32, 32)); struct nk_context* context = &game_gui->gui->context; context->style.button.normal = nk_style_item_image(game_gui->skin.button); context->style.button.active = nk_style_item_image(game_gui->skin.button_active); context->style.button.hover = nk_style_item_image(game_gui->skin.button_hover); context->style.window.border_color = nk_rgba_f(0.f, 0.f, 0.f, 1.f); context->style.window.background = nk_rgba_f(0.f, 0.f, 0.f, 1.f); game_gui->skin.hud_background = nk_style_item_image(nk_subimage_id(game_gui->skin.skin_texture, SKIN_TEXTURE_WIDTH, SKIN_TEXTURE_HEIGHT, nk_recti(32, 32, 128, 48))); game_gui->skin.menu_background = nk_style_item_color(nk_rgba_f(0.2f, 0.2f, 0.2f, 0.6f)); //context->style.window.fixed_background = nk_style_item_color(nk_rgba_f(0.f, 0.f, 0.f, 0.05f)); gui_font_set(game_gui->gui, "6809_chargen.ttf", 30.f); struct Event_Manager* event_manager = game_state_get()->event_manager; event_manager_subscribe(event_manager, EVT_PLAYER_DIED, &gui_game_on_player_death); event_manager_subscribe(event_manager, EVT_SCENE_CLEARED, &gui_game_on_scene_cleared); } void gui_game_cleanup(struct Game_Gui* game_gui) { texture_remove(game_gui->skin.skin_texture); gui_cleanup(game_gui->gui); memory_free(game_gui->gui); struct Event_Manager* event_manager = game_state_get()->event_manager; event_manager_unsubscribe(event_manager, EVT_PLAYER_DIED, &gui_game_on_player_death); event_manager_unsubscribe(event_manager, EVT_SCENE_CLEARED, &gui_game_on_scene_cleared); } void gui_game_update(struct Game_Gui* game_gui, float dt) { struct nk_context* context = &game_gui->gui->context; struct Game_State* game_state = game_state_get(); if(game_state->game_mode == GAME_MODE_GAME) { // HUD context->style.window.fixed_background = game_gui->skin.hud_background; const float key_opacity_full = 1.f; const float key_opacity_reduced = 0.3f; int hud_offset_x = 50; int hud_offset_y = 50; int hp_gui_width = 130; int hp_gui_height = 48; struct Player* player = &game_state->scene->player; if(nk_begin(context, "HP Gui", nk_recti(hud_offset_x, hud_offset_y, hp_gui_width, hp_gui_height), NK_WINDOW_BACKGROUND | NK_WINDOW_NO_SCROLLBAR)) { nk_layout_row_dynamic(context, 40, 2); nk_image_color(context, game_gui->skin.hp, nk_rgba_f(1.f, 1.f, 1.f, 1.f)); nk_labelf(context, NK_TEXT_ALIGN_CENTERED | NK_TEXT_ALIGN_MIDDLE, "%d", player->health); nk_end(context); } int key_gui_width = 192; int key_gui_height = 48; int display_width = 0; int display_height = 0; window_get_drawable_size(game_state_get()->window, &display_width, &display_height); int key_gui_pos_x = display_width - (key_gui_width + hud_offset_x); int key_gui_pos_y = hud_offset_y; if(nk_begin(context, "Key Gui", nk_recti(key_gui_pos_x, key_gui_pos_y, key_gui_width, key_gui_height), NK_WINDOW_BACKGROUND | NK_WINDOW_NO_SCROLLBAR)) { nk_layout_row_dynamic(context, 40, 3); nk_image_color(context, game_gui->skin.key, nk_rgba_f(KEY_INDICATOR_COLOR_RED.x, KEY_INDICATOR_COLOR_RED.y, KEY_INDICATOR_COLOR_RED.z, (player->key_mask & DOOR_KEY_MASK_RED) == DOOR_KEY_MASK_RED ? key_opacity_full : key_opacity_reduced)); nk_image_color(context, game_gui->skin.key, nk_rgba_f(KEY_INDICATOR_COLOR_GREEN.x, KEY_INDICATOR_COLOR_GREEN.y, KEY_INDICATOR_COLOR_GREEN.z, (player->key_mask & DOOR_KEY_MASK_GREEN) == DOOR_KEY_MASK_GREEN ? key_opacity_full : key_opacity_reduced)); nk_image_color(context, game_gui->skin.key, nk_rgba_f(KEY_INDICATOR_COLOR_BLUE.x, KEY_INDICATOR_COLOR_BLUE.y, KEY_INDICATOR_COLOR_BLUE.z, (player->key_mask & DOOR_KEY_MASK_BLUE) == DOOR_KEY_MASK_BLUE ? key_opacity_full : key_opacity_reduced)); nk_end(context); } int crosshair_width = 50; int crosshair_height = 32; int crosshair_x = (display_width / 2) - (crosshair_width / 2); int crosshair_y = (display_height / 2) - (crosshair_height / 2); context->style.window.fixed_background = nk_style_item_hide(); if(nk_begin(context, "Crosshair", nk_recti(crosshair_x, crosshair_y, crosshair_width, crosshair_height), NK_WINDOW_BACKGROUND | NK_WINDOW_NO_SCROLLBAR)) { nk_layout_row_dynamic(context, crosshair_height, 1); nk_image_color(context, game_gui->skin.crosshair, nk_rgba_f(1.f, 1.f, 1.f, 0.3f)); nk_end(context); } if(game_gui->show_next_level_dialog) gui_game_next_level_dialog(context); if(game_gui->show_restart_level_dialog) gui_game_restart_level_dialog(context); if(game_gui->show_game_end_dialog) gui_game_end_dialog(context); } else if(game_state->game_mode == GAME_MODE_PAUSE) { gui_game_pause_menu(context); } } void gui_game_show_door_locked_dialog(struct Game_Gui* game_gui, struct Door* door) { struct nk_context* context = &game_gui->gui->context; struct Game_State* game_state = game_state_get(); if(game_state->game_mode == GAME_MODE_GAME) { struct Player* player = &game_state->scene->player; int label_flags = NK_TEXT_ALIGN_CENTERED | NK_TEXT_ALIGN_MIDDLE; int key_needed_gui_width = 350; int key_needed_gui_height = 48; int display_width = 0; int display_height = 0; window_get_drawable_size(game_state->window, &display_width, &display_height); int key_needed_gui_y = 50; int keys_needed = 0; bool red_needed = false; bool green_needed = false; bool blue_needed = false; float starting_ratio = 0.65f; if((player->key_mask & DOOR_KEY_MASK_RED) != DOOR_KEY_MASK_RED && (door->mask & DOOR_KEY_MASK_RED) == DOOR_KEY_MASK_RED) { red_needed = true; keys_needed++; key_needed_gui_width += 100; starting_ratio -= 0.1f; } if((player->key_mask & DOOR_KEY_MASK_GREEN) != DOOR_KEY_MASK_GREEN && (door->mask & DOOR_KEY_MASK_GREEN) == DOOR_KEY_MASK_GREEN) { green_needed = true; keys_needed++; key_needed_gui_width += 100; starting_ratio -= 0.1f; } if((player->key_mask & DOOR_KEY_MASK_BLUE) != DOOR_KEY_MASK_BLUE && (door->mask & DOOR_KEY_MASK_BLUE) == DOOR_KEY_MASK_BLUE) { blue_needed = true; keys_needed++; key_needed_gui_width += 100; starting_ratio -= 0.1f; } int key_needed_gui_x = (display_width / 2) - (key_needed_gui_width / 2); if(nk_begin(context, "Key Needed Gui", nk_recti(key_needed_gui_x, key_needed_gui_y, key_needed_gui_width, key_needed_gui_height), NK_WINDOW_BACKGROUND | NK_WINDOW_NO_SCROLLBAR)) { context->style.window.fixed_background = game_gui->skin.menu_background; nk_layout_row_begin(context, NK_DYNAMIC, 40, keys_needed + 2); nk_layout_row_push(context, starting_ratio); nk_label(context, "YOU NEED THE", label_flags); if(red_needed) { nk_layout_row_push(context, 0.15f); nk_label_colored(context, "RED", label_flags, nk_rgba_fv(&KEY_INDICATOR_COLOR_RED)); } if(green_needed) { nk_layout_row_push(context, 0.15f); nk_label_colored(context, "GREEN", label_flags, nk_rgba_fv(&KEY_INDICATOR_COLOR_GREEN)); } if(blue_needed) { nk_layout_row_push(context, 0.15f); nk_label_colored(context, "BLUE", label_flags, nk_rgba_fv(&KEY_INDICATOR_COLOR_BLUE)); } nk_layout_row_push(context, 0.25f); nk_label(context, keys_needed > 1 ? "KEYS" : "KEY", label_flags); nk_end(context); } } } void gui_game_pause_menu(struct nk_context* context) { struct Game_State* game_state = game_state_get(); struct Game_Gui* game_gui = game_state->gui_game; int row_height = 30; int popup_x = 0; int popup_y = 0; int popup_width = 300; int popup_height = 200; int display_width = 0; int display_height = 0; int popup_flags = NK_WINDOW_TITLE | NK_WINDOW_BORDER; window_get_drawable_size(game_state_get()->window, &display_width, &display_height); popup_x = (display_width / 2) - (popup_width / 2); popup_y = (display_height / 2) - (popup_height / 2); int background_window_flags = NK_WINDOW_BACKGROUND; if(nk_begin(context, "Pause Gui", nk_rect(0, 0, display_width, display_height), background_window_flags)) { context->style.window.fixed_background = game_gui->skin.menu_background; nk_window_set_focus(context, "Pause Gui"); if(nk_popup_begin(context, NK_POPUP_DYNAMIC, "Game Paused", popup_flags, nk_recti(popup_x, popup_y, popup_width, popup_height))) { nk_layout_row_dynamic(context, row_height, 1); int fullscreen = window_fullscreen_get(game_state->window) ? 1 : 0; if(nk_checkbox_label(context, "Fullscreen", &fullscreen)) window_fullscreen_set(game_state->window, (bool)fullscreen); nk_label(context, "Resolution", NK_TEXT_ALIGN_LEFT | NK_TEXT_ALIGN_MIDDLE); if(nk_button_label(context, "Restart Level")) { char filename[MAX_FILENAME_LEN]; strncpy(filename, game_state->scene->filename, MAX_FILENAME_LEN); if(!scene_load(game_state->scene, filename, DIRT_INSTALL)) log_error("gui_game:pause_menu", "Failed to reload Level"); } if(nk_button_label(context, "Quit")) game_state->quit = true; nk_popup_end(context); } nk_end(context); } } static void gui_game_next_level_dialog(struct nk_context* context) { struct Game_State* game_state = game_state_get(); struct Game_Gui* game_gui = game_state->gui_game; struct Scene* scene = game_state->scene; int row_height = 30; int popup_x = 0; int popup_y = 0; int popup_width = 300; int popup_height = 200; int display_width = 0; int display_height = 0; int popup_flags = NK_WINDOW_TITLE | NK_WINDOW_BORDER; window_get_drawable_size(game_state_get()->window, &display_width, &display_height); popup_x = (display_width / 2) - (popup_width / 2); popup_y = (display_height / 2) - (popup_height / 2); int background_window_flags = NK_WINDOW_BACKGROUND; if(nk_begin(context, "Scene Cleared", nk_rect(0, 0, display_width, display_height), background_window_flags)) { context->style.window.fixed_background = game_gui->skin.menu_background; nk_window_set_focus(context, "Scene Cleared"); if(nk_popup_begin(context, NK_POPUP_DYNAMIC, "Scene Cleared!", popup_flags, nk_recti(popup_x, popup_y, popup_width, popup_height))) { nk_layout_row_dynamic(context, row_height, 1); if(nk_button_label(context, "Restart Level")) { char filename[MAX_FILENAME_LEN]; strncpy(filename, game_state->scene->filename, MAX_FILENAME_LEN); if(!scene_load(game_state->scene, filename, DIRT_INSTALL)) log_error("gui_game:next_level_dialog", "Failed to reload Level"); else game_gui->show_next_level_dialog = false; } if(nk_button_label(context, "Next Level")) { if(strncmp(scene->next_level_filename, "\0", MAX_FILENAME_LEN) != 0) { char filename[MAX_FILENAME_LEN]; strncpy(filename, game_state->scene->next_level_filename, MAX_FILENAME_LEN); if(!scene_load(game_state->scene, filename, DIRT_INSTALL)) log_error("gui_game:next_level_dialog", "Failed to load new Level"); else game_gui->show_next_level_dialog = false; } else { log_error("gui_game:next_level_dialog", "No name provided for next scene"); } } if(nk_button_label(context, "Quit")) game_state->quit = true; nk_popup_end(context); } nk_end(context); } } void gui_game_restart_level_dialog(struct nk_context* context) { struct Game_State* game_state = game_state_get(); struct Game_Gui* game_gui = game_state->gui_game; int row_height = 30; int popup_x = 0; int popup_y = 0; int popup_width = 300; int popup_height = 200; int display_width = 0; int display_height = 0; int popup_flags = NK_WINDOW_TITLE | NK_WINDOW_BORDER; window_get_drawable_size(game_state_get()->window, &display_width, &display_height); popup_x = (display_width / 2) - (popup_width / 2); popup_y = (display_height / 2) - (popup_height / 2); int background_window_flags = NK_WINDOW_BACKGROUND; if(nk_begin(context, "Player Died Gui", nk_rect(0, 0, display_width, display_height), background_window_flags)) { context->style.window.fixed_background = game_gui->skin.menu_background; nk_window_set_focus(context, "Player Died Gui"); if(nk_popup_begin(context, NK_POPUP_DYNAMIC, "You Died", popup_flags, nk_recti(popup_x, popup_y, popup_width, popup_height))) { nk_layout_row_dynamic(context, row_height, 1); if(nk_button_label(context, "Restart Level")) { char filename[MAX_FILENAME_LEN]; strncpy(filename, game_state->scene->filename, MAX_FILENAME_LEN); if(!scene_load(game_state->scene, filename, DIRT_INSTALL)) log_error("gui_game:pause_menu", "Failed to reload Level"); else game_gui->show_restart_level_dialog = false; } if(nk_button_label(context, "Quit")) game_state->quit = true; nk_popup_end(context); } nk_end(context); } } void gui_game_on_player_death(struct Event* event) { struct Player_Death_Event* player_death_event = (struct Player_Death_Event*)event; game_state_get()->gui_game->show_restart_level_dialog = true; input_mouse_mode_set(MM_NORMAL); } void gui_game_on_scene_cleared(struct Event* event) { struct Game_State* game_state = game_state_get(); if(!game_state->gui_game->show_game_end_dialog) game_state->gui_game->show_next_level_dialog = true; input_mouse_mode_set(MM_NORMAL); } void gui_game_show_game_end_dialog(struct Game_Gui* game_gui) { game_gui->show_game_end_dialog = true; game_gui->show_next_level_dialog = false; } void gui_game_end_dialog(struct nk_context* context) { struct Game_State* game_state = game_state_get(); struct Game_Gui* game_gui = game_state->gui_game; int row_height = 30; int popup_x = 0; int popup_y = 0; int popup_width = 300; int popup_height = 200; int display_width = 0; int display_height = 0; int popup_flags = NK_WINDOW_TITLE | NK_WINDOW_BORDER; window_get_drawable_size(game_state_get()->window, &display_width, &display_height); popup_x = (display_width / 2) - (popup_width / 2); popup_y = (display_height / 2) - (popup_height / 2); int background_window_flags = NK_WINDOW_BACKGROUND; if(nk_begin(context, "Game End Dialog", nk_rect(0, 0, display_width, display_height), background_window_flags)) { context->style.window.fixed_background = game_gui->skin.menu_background; nk_window_set_focus(context, "Game End Dialog"); if(nk_popup_begin(context, NK_POPUP_DYNAMIC, "Congratulations!", popup_flags, nk_recti(popup_x, popup_y, popup_width, popup_height))) { nk_layout_row_dynamic(context, row_height, 1); nk_label(context, "YOU BEAT THE GAME!", NK_TEXT_ALIGN_CENTERED | NK_TEXT_ALIGN_MIDDLE); if(nk_button_label(context, "Restart Level")) { char filename[MAX_FILENAME_LEN]; strncpy(filename, game_state->scene->filename, MAX_FILENAME_LEN); if(!scene_load(game_state->scene, filename, DIRT_INSTALL)) log_error("gui_game:end_dialog", "Failed to reload Level"); else game_gui->show_game_end_dialog = false; } if(nk_button_label(context, "Restart from first Level")) { if(scene_load(game_state->scene, "scene_1", DIRT_INSTALL)) game_gui->show_game_end_dialog = false; else log_error("gui_game:end_dialog", "Failed to load first level"); } if(nk_button_label(context, "Quit")) game_state->quit = true; nk_popup_end(context); } nk_end(context); } }