From c4b8766a013081f7ecff4fef99bd73132946ad69 Mon Sep 17 00:00:00 2001 From: Linus Probert Date: Fri, 22 Dec 2017 15:15:40 +0100 Subject: [PATCH] Began designing/writing gui. Added states. --- CMakeLists.txt | 1 + TODO.txt | 3 +- src/gamestate.h | 3 +- src/gui.c | 116 ++++++++++++++++++++++++++++++++++++++++++++++++ src/gui.h | 27 +++++++++++ src/main.c | 75 ++++++++++++++++++++++--------- src/map.c | 2 +- src/map_lua.c | 7 +-- src/monster.c | 2 +- src/player.c | 10 ++--- src/sprite.c | 8 +++- src/sprite.h | 1 + src/stats.h | 9 ++-- 13 files changed, 225 insertions(+), 39 deletions(-) create mode 100644 src/gui.c create mode 100644 src/gui.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 95b9aaf..c4265f0 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -58,6 +58,7 @@ add_executable(breakhack src/random src/linkedlist src/hashtable + src/gui ) target_link_libraries(breakhack diff --git a/TODO.txt b/TODO.txt index 939e76c..27820f7 100644 --- a/TODO.txt +++ b/TODO.txt @@ -16,7 +16,8 @@ x Moving enemies x Add hooks to lua x Add movement depending on state (aggro, scared, passive) x Lower dungeon levels -- GUI (lua generated) +o GUI +- Player death - Items (lua generated?) - More GUI o XP diff --git a/src/gamestate.h b/src/gamestate.h index e14a5a1..5d37212 100644 --- a/src/gamestate.h +++ b/src/gamestate.h @@ -4,7 +4,8 @@ typedef enum GameState_t { MENU, PLAYING, - NEXT_LEVEL + IN_GAME_MENU, + GAME_OVER } GameState; #endif // GAMESTATE_H_ diff --git a/src/gui.c b/src/gui.c new file mode 100644 index 0000000..19b147f --- /dev/null +++ b/src/gui.c @@ -0,0 +1,116 @@ +#include + +#include "gui.h" +#include "util.h" + +Gui* +gui_create() +{ + Gui *gui = ec_malloc(sizeof(Gui)); + gui->sprites = linkedlist_create(); + gui->health = linkedlist_create(); + gui->textures = ht_create(5); + return gui; +} + +static void +clear_sprite_list(LinkedList *list) +{ + while (list != NULL) + sprite_destroy(linkedlist_pop(&list)); +} + +void +gui_set_max_health(Gui *gui, int max, SDL_Renderer *renderer) +{ + Sprite *sprite; + Texture *texture; + int i; + + assert(max % 3 == 0); + + if (((unsigned int) max / 3) == (unsigned int) linkedlist_size(gui->health)) + return; + + clear_sprite_list(gui->health); + + texture = gui_add_texture(gui, "assets/GUI/GUI0.png", renderer); + + for (i = 0; i < max/3; ++i) { + sprite = sprite_create(); + sprite->fixed = true; + sprite->clip = (SDL_Rect) { 0, 16, 16, 16 }; + sprite->pos = (Position) { 16 + i*16, 16 }; + sprite_set_texture(sprite, texture, 0); + linkedlist_append(&gui->health, sprite); + } +} + +void +gui_set_current_health(Gui *gui, int current) +{ + Sprite *sprite; + int partial = current % 3; + int full = (current - partial)/3; + int count = 0; + + if (current < 0) + current = 0; + + LinkedList *item = gui->health; + while (item != NULL) { + sprite = (Sprite*) item->data; + if (count < full) { + sprite->clip.x = 0; + } else if (count == full) { + sprite->clip.x = 64 - (partial * 16); + } else { + sprite->clip.x = 64; + } + + ++count; + item = item->next; + } +} + +Texture* +gui_add_texture(Gui *gui, const char *path, SDL_Renderer *renderer) +{ + Texture *t = ht_get(gui->textures, path); + if (t == NULL) { + t = texture_create(); + texture_load_from_file(t, path, renderer); + t->dim = (Dimension) { 16, 16 }; + ht_set(gui->textures, path, t); + } + return t; +} + +void +gui_render(Gui *gui, Camera *cam) +{ + LinkedList *item = gui->health; + while (item != NULL) { + Sprite *s = item->data; + sprite_render(s, cam); + item = item->next; + } + item = gui->sprites; + while (item != NULL) { + Sprite *s = item->data; + sprite_render(s, cam); + item = item->next; + } + +} + +void +gui_destroy(Gui *gui) +{ + while (gui->sprites != NULL) + sprite_destroy(linkedlist_pop(&gui->sprites)); + while (gui->health != NULL) + sprite_destroy(linkedlist_pop(&gui->health)); + ht_destroy_custom(gui->textures, (void (*)(void*)) &texture_destroy); + free(gui); +} diff --git a/src/gui.h b/src/gui.h new file mode 100644 index 0000000..c2bc868 --- /dev/null +++ b/src/gui.h @@ -0,0 +1,27 @@ +#ifndef GUI_H_ +#define GUI_H_ + +#include "linkedlist.h" +#include "hashtable.h" +#include "sprite.h" +#include "camera.h" + +typedef struct { + LinkedList *sprites; + LinkedList *health; + Hashtable *textures; +} Gui; + +Gui* gui_create(void); + +void gui_set_max_health(Gui*, int max, SDL_Renderer*); + +void gui_set_current_health(Gui*, int current); + +Texture* gui_add_texture(Gui*, const char *path, SDL_Renderer*); + +void gui_render(Gui*, Camera*); + +void gui_destroy(Gui*); + +#endif // GUI_H_ diff --git a/src/main.c b/src/main.c index 3df23b4..d7d592d 100644 --- a/src/main.c +++ b/src/main.c @@ -13,6 +13,7 @@ #include "timer.h" #include "roommatrix.h" #include "gamestate.h" +#include "gui.h" static SDL_Window *gWindow = NULL; static SDL_Renderer *gRenderer = NULL; @@ -20,7 +21,8 @@ static Player *gPlayer = NULL; static LinkedList *gSpriteList = NULL; static Map *gMap = NULL; static RoomMatrix *gRoomMatrix = NULL; -static GameState gameState; +static Gui *gGui = NULL; +static GameState gGameState; static Camera gCamera; static @@ -105,9 +107,10 @@ bool init(void) gCamera.pos = (Position) { 0, 0 }; gCamera.renderer = gRenderer; gRoomMatrix = roommatrix_create(); + gGui = gui_create(); } - gameState = PLAYING; + gGameState = PLAYING; return result; } @@ -127,7 +130,7 @@ bool handle_events(void) while (SDL_PollEvent(&event) != 0) { if (event.type == SDL_QUIT) { quit = true; - } else { + } else if (gGameState == PLAYING) { gPlayer->handle_event(gPlayer, gRoomMatrix, &event); @@ -158,6 +161,35 @@ check_next_level(void) } } +static void +run_game(void) +{ + map_clear_dead_monsters(gMap); + roommatrix_populate_from_map(gRoomMatrix, gMap); + roommatrix_add_lightsource(gRoomMatrix, + &gPlayer->sprite->pos); + roommatrix_build_lightmap(gRoomMatrix); + + gui_set_max_health(gGui, gPlayer->stats.maxhp, gRenderer); + gui_set_current_health(gGui, gPlayer->stats.hp); + if (gPlayer->steps == gPlayer->stats.speed) { + player_reset_steps(gPlayer); + roommatrix_update_with_player(gRoomMatrix, gPlayer); + map_move_monsters(gMap, gRoomMatrix); + } + + SDL_RenderClear(gRenderer); + + map_render(gMap, &gCamera); + player_render(gPlayer, &gCamera); + roommatrix_render_lightmap(gRoomMatrix, &gCamera); + gui_render(gGui, &gCamera); + + SDL_RenderPresent(gRenderer); + + check_next_level(); +} + static void run(void) { @@ -169,28 +201,25 @@ void run(void) timer_start(fpsTimer); quit = handle_events(); - map_clear_dead_monsters(gMap); - roommatrix_populate_from_map(gRoomMatrix, gMap); - roommatrix_add_lightsource(gRoomMatrix, - &gPlayer->sprite->pos); - roommatrix_build_lightmap(gRoomMatrix); - if (gPlayer->steps == gPlayer->stats.speed) { - player_reset_steps(gPlayer); - roommatrix_update_with_player(gRoomMatrix, gPlayer); - map_move_monsters(gMap, gRoomMatrix); + switch (gGameState) { + case PLAYING: + run_game(); + break; + case MENU: + fprintf(stderr, "[!!] MENU not implemented\n"); + break; + case IN_GAME_MENU: + fprintf(stderr, + "[!!] IN_GAME_MENU not implemented\n"); + break; + case GAME_OVER: + fprintf(stderr, "[!!] GAME_OVER not implemented\n"); + break; + default: + break; } - SDL_RenderClear(gRenderer); - - map_render(gMap, &gCamera); - player_render(gPlayer, &gCamera); - roommatrix_render_lightmap(gRoomMatrix, &gCamera); - - SDL_RenderPresent(gRenderer); - - check_next_level(); - int ticks = timer_get_ticks(fpsTimer); if (ticks < 1000/60) SDL_Delay((1000/60) - ticks); @@ -206,6 +235,8 @@ void close(void) player_destroy(gPlayer); map_destroy(gMap); roommatrix_destroy(gRoomMatrix); + gui_destroy(gGui); + SDL_DestroyRenderer(gRenderer); SDL_DestroyWindow(gWindow); gWindow = NULL; TTF_Quit(); diff --git a/src/map.c b/src/map.c index b851828..54146ba 100644 --- a/src/map.c +++ b/src/map.c @@ -25,7 +25,7 @@ Map* map_create() Map *map = ec_malloc(sizeof(Map)); map->textures = linkedlist_create(); - map->monsterTextures = ht_create(100); + map->monsterTextures = ht_create(30); map->monsters = linkedlist_create(); map->currentRoom = (Position) { 0, 0 }; map->renderTimer = timer_create(); diff --git a/src/map_lua.c b/src/map_lua.c index cd5cf95..58e91bd 100644 --- a/src/map_lua.c +++ b/src/map_lua.c @@ -191,7 +191,7 @@ l_add_monster(lua_State *L) texture1->dim = (Dimension) { TILE_DIMENSION, TILE_DIMENSION }; texture2->dim = (Dimension) { TILE_DIMENSION, TILE_DIMENSION }; - lua_pop(L, 4); + lua_pop(L, 6); monster = monster_create(renderer); monster->sprite->clip = (SDL_Rect) { clip_x, clip_y, 16, 16 }; @@ -212,12 +212,13 @@ Map* map_lua_generator_run(SDL_Renderer *renderer) int status, result; char file[] = "data/mapgen.lua"; - printf("[**] Running lua script: %s\n", file); + printf("[**] Running lua map script: %s\n", file); lua_State *L = load_lua_state(); status = luaL_loadfile(L, file); if (status) { - fprintf(stderr, "[!!] Couldn't load file: %s\n", lua_tostring(L, -1)); + fprintf(stderr, "[!!] Couldn't load file: %s\n", + lua_tostring(L, -1)); exit(-1); } diff --git a/src/monster.c b/src/monster.c index 6f3257b..26e929b 100644 --- a/src/monster.c +++ b/src/monster.c @@ -30,7 +30,7 @@ monster_create(SDL_Renderer *renderer) Monster *m = ec_malloc(sizeof(Monster)); m->sprite = sprite_create(); m->sprite->clip = (SDL_Rect) { 0, 0, 16, 16 }; - m->stats = (Stats) { 11, 1, 0, 0, 1, 1 }; + m->stats = (Stats) { 12, 12, 1, 0, 0, 1, 1 }; m->state.normal = PASSIVE; m->state.challenge = AGRESSIVE; m->state.current = m->state.normal; diff --git a/src/player.c b/src/player.c index 893f0d6..fa8a431 100644 --- a/src/player.c +++ b/src/player.c @@ -6,11 +6,11 @@ #include "monster.h" #include "util.h" -#define ENGINEER_STATS { 11, 5, 7, 2, 1, 1 } -#define MAGE_STATS { 11, 5, 7, 2, 1, 1 } -#define PALADIN_STATS { 11, 5, 7, 2, 1, 1 } -#define ROGUE_STATS { 11, 5, 7, 2, 2, 1 } -#define WARRIOR_STATS { 11, 5, 7, 2, 1, 1 } +#define ENGINEER_STATS { 12, 12, 5, 7, 2, 1, 1 } +#define MAGE_STATS { 12, 12, 5, 7, 2, 1, 1 } +#define PALADIN_STATS { 12, 12, 5, 7, 2, 1, 1 } +#define ROGUE_STATS { 12, 12, 5, 7, 2, 2, 1 } +#define WARRIOR_STATS { 12, 12, 5, 7, 2, 1, 1 } static bool has_collided(Player *player, RoomMatrix *matrix) diff --git a/src/sprite.c b/src/sprite.c index 13dcc17..de62de5 100644 --- a/src/sprite.c +++ b/src/sprite.c @@ -13,6 +13,7 @@ Sprite* sprite_create_default(void) s->pos = (Position) { 0, 0 }; s->renderTimer = timer_create(); s->texture_index = 0; + s->fixed = false; return s; } @@ -65,7 +66,12 @@ void sprite_render(Sprite *s, Camera *cam) } } - Position cameraPos = camera_to_camera_position(cam, &s->pos); + Position cameraPos; + if (!s->fixed) + cameraPos = camera_to_camera_position(cam, &s->pos); + else + cameraPos = s->pos; + texture_render_clip(s->textures[s->texture_index], &cameraPos, &s->clip, diff --git a/src/sprite.h b/src/sprite.h index 0ad9ee3..66a8ef2 100644 --- a/src/sprite.h +++ b/src/sprite.h @@ -16,6 +16,7 @@ typedef struct Sprite_t { Position pos; Timer *renderTimer; unsigned int texture_index; + bool fixed; } Sprite; Sprite* sprite_create(void); diff --git a/src/stats.h b/src/stats.h index 143920d..caf4a2f 100644 --- a/src/stats.h +++ b/src/stats.h @@ -2,10 +2,11 @@ #define STATS_H_ typedef struct Stats_t { - int hp; /* Hit points */ - int dmg; /* Damage modifier */ - int atk; /* Attack rating */ - int def; /* Defence rating */ + int maxhp; /* Max hitpoints */ + int hp; /* Current hit points */ + int dmg; /* Damage modifier */ + int atk; /* Attack rating */ + int def; /* Defence rating */ unsigned int speed; /* Speed */ unsigned int lvl; /* Level */ } Stats;