Added an XP bar. Need some text to go with it next

This commit is contained in:
Linus Probert 2018-01-31 13:52:11 +01:00
parent 6dc08b8a6b
commit 5dff9a9452
7 changed files with 194 additions and 33 deletions

126
src/gui.c
View File

@ -8,6 +8,7 @@
#include "util.h" #include "util.h"
#define DEFAULT_LOG { NULL, 50, 0, 200 } #define DEFAULT_LOG { NULL, 50, 0, 200 }
#define POS_Y_XPBAR 96
static SDL_Rect frame_top_left = { 16, 160, 16, 16 }; static SDL_Rect frame_top_left = { 16, 160, 16, 16 };
static SDL_Rect frame_top_right = { 48, 160, 16, 16 }; static SDL_Rect frame_top_right = { 48, 160, 16, 16 };
@ -26,6 +27,19 @@ static struct LogData_t {
unsigned int strlen; unsigned int strlen;
} log_data = DEFAULT_LOG; } log_data = DEFAULT_LOG;
static Texture*
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;
}
static void static void
gui_malloc_log(void) gui_malloc_log(void)
{ {
@ -39,8 +53,56 @@ gui_malloc_log(void)
log_data.log[i] = NULL; log_data.log[i] = NULL;
} }
static void
init_sprites(Gui *gui, SDL_Renderer *renderer)
{
Texture *t;
Sprite *s;
unsigned int i;
t = add_texture(gui, "assets/GUI/GUI0.png", renderer);
/*
* Add XP bar decoration
*/
// Left end
s = sprite_create();
sprite_set_texture(s, t, 0);
s->fixed = true;
s->clip = (SDL_Rect) { 6 * 16, 0, 16, 16 };
s->pos = (Position) { 16 , POS_Y_XPBAR };
linkedlist_append(&gui->sprites, s);
// Right end
s = sprite_create();
sprite_set_texture(s, t, 0);
s->fixed = true;
s->clip = (SDL_Rect) { 8 * 16, 0, 16, 16 };
s->pos = (Position) { 16 + (16 * 7), POS_Y_XPBAR };
linkedlist_append(&gui->sprites, s);
for (i = 1; i < 7; ++i) {
s = sprite_create();
sprite_set_texture(s, t, 0);
s->fixed = true;
s->clip = (SDL_Rect) { 7 * 16, 0, 16, 16 };
s->pos = (Position) { 16 + (i * 16), POS_Y_XPBAR };
linkedlist_append(&gui->sprites, s);
}
for (i = 0; i < 8; ++i) {
s = sprite_create();
sprite_set_texture(s, t, 0);
s->fixed = true;
s->clip = (SDL_Rect) { 6 * 16, 4 * 16, 16, 16 };
s->pos = (Position) { 16 + (i * 16), POS_Y_XPBAR };
linkedlist_append(&gui->xp_bar, s);
}
}
Gui* Gui*
gui_create() gui_create(SDL_Renderer *renderer)
{ {
Texture *t; Texture *t;
unsigned int i; unsigned int i;
@ -48,6 +110,7 @@ gui_create()
Gui *gui = ec_malloc(sizeof(Gui)); Gui *gui = ec_malloc(sizeof(Gui));
gui->sprites = linkedlist_create(); gui->sprites = linkedlist_create();
gui->health = linkedlist_create(); gui->health = linkedlist_create();
gui->xp_bar = linkedlist_create();
gui->textures = ht_create(5); gui->textures = ht_create(5);
for (i = 0; i < LOG_LINES_COUNT; ++i) { for (i = 0; i < LOG_LINES_COUNT; ++i) {
@ -58,6 +121,8 @@ gui_create()
gui_malloc_log(); gui_malloc_log();
init_sprites(gui, renderer);
return gui; return gui;
} }
@ -76,7 +141,7 @@ gui_set_max_health(Gui *gui, int max, SDL_Renderer *renderer)
while (gui->health != NULL) while (gui->health != NULL)
sprite_destroy(linkedlist_pop(&gui->health)); sprite_destroy(linkedlist_pop(&gui->health));
texture = gui_add_texture(gui, "assets/GUI/GUI0.png", renderer); texture = add_texture(gui, "assets/GUI/GUI0.png", renderer);
for (i = 0; i < max/3; ++i) { for (i = 0; i < max/3; ++i) {
Sprite *sprite = sprite_create(); Sprite *sprite = sprite_create();
@ -114,17 +179,48 @@ gui_set_current_health(Gui *gui, int current)
} }
} }
Texture* void
gui_add_texture(Gui *gui, const char *path, SDL_Renderer *renderer) gui_set_current_xp(Gui *gui, ExperienceData data)
{ {
Texture *t = ht_get(gui->textures, path); static unsigned int last_level = 0;
if (t == NULL) { unsigned int xp_from_levelup, xp_required_from_last_level;
t = texture_create(); float xp_step, xp_current_step;
texture_load_from_file(t, path, renderer); unsigned int full_xp_blocks, partial_xp_block;
t->dim = (Dimension) { 16, 16 }; LinkedList *xp_bars;
ht_set(gui->textures, path, t); unsigned int i;
xp_from_levelup = data.current - data.previousLevel;
xp_required_from_last_level = data.nextLevel - data.previousLevel;
xp_step = ((float) xp_required_from_last_level) / 32; // 4 * 8
xp_current_step = xp_from_levelup / xp_step;
partial_xp_block = ((unsigned int) xp_current_step) % 4;
full_xp_blocks = (unsigned int)((xp_current_step - partial_xp_block) / 4);
xp_bars = gui->xp_bar;
i = 0;
while (xp_bars != NULL) {
Sprite *s = xp_bars->data;
s->hidden = false;
xp_bars = xp_bars->next;
if (i < full_xp_blocks) {
s->clip.x = 6 * 16;
} else if (i == full_xp_blocks && partial_xp_block != 0) {
s->clip.x = (6 * 16) + (16 * (4 - partial_xp_block));
} else {
s->hidden = true;
}
++i;
} }
return t;
if (last_level != data.level) {
// TODO(Linus): Update the indicators
last_level = data.level;
}
} }
static void static void
@ -173,6 +269,12 @@ gui_render_panel(Gui *gui, unsigned int width, unsigned int height, Camera *cam)
sprite_render(s, cam); sprite_render(s, cam);
item = item->next; item = item->next;
} }
item = gui->xp_bar;
while (item != NULL) {
Sprite *s = item->data;
sprite_render(s, cam);
item = item->next;
}
item = gui->sprites; item = gui->sprites;
while (item != NULL) { while (item != NULL) {
Sprite *s = item->data; Sprite *s = item->data;
@ -262,6 +364,8 @@ gui_destroy(Gui *gui)
sprite_destroy(linkedlist_pop(&gui->sprites)); sprite_destroy(linkedlist_pop(&gui->sprites));
while (gui->health != NULL) while (gui->health != NULL)
sprite_destroy(linkedlist_pop(&gui->health)); sprite_destroy(linkedlist_pop(&gui->health));
while (gui->xp_bar != NULL)
sprite_destroy(linkedlist_pop(&gui->xp_bar));
ht_destroy_custom(gui->textures, (void (*)(void*)) &texture_destroy); ht_destroy_custom(gui->textures, (void (*)(void*)) &texture_destroy);
free(gui); free(gui);

View File

@ -8,28 +8,41 @@
#include "hashtable.h" #include "hashtable.h"
#include "sprite.h" #include "sprite.h"
#include "camera.h" #include "camera.h"
#include "player.h"
typedef struct { typedef struct {
LinkedList *sprites; LinkedList *sprites;
LinkedList *health; LinkedList *health;
LinkedList *xp_bar;
Hashtable *textures; Hashtable *textures;
Texture *log_lines[LOG_LINES_COUNT]; Texture *log_lines[LOG_LINES_COUNT];
} Gui; } Gui;
Gui* gui_create(void); Gui*
gui_create(SDL_Renderer *renderer);
void gui_set_max_health(Gui*, int max, SDL_Renderer*); void
gui_set_max_health(Gui*, int max, SDL_Renderer*);
void gui_set_current_health(Gui*, int current); void
gui_set_current_health(Gui*, int current);
Texture* gui_add_texture(Gui*, const char *path, SDL_Renderer*); void
gui_set_current_xp(Gui*, ExperienceData);
void gui_render_panel(Gui*, unsigned int width, unsigned int height, Camera*); void
gui_set_xp_data(Gui*, ExperienceData);
void gui_render_log(Gui*, unsigned int width, unsigned int height, Camera*); void
gui_render_panel(Gui*, unsigned int width, unsigned int height, Camera*);
void gui_log(const char *fmt, ...); void
gui_render_log(Gui*, unsigned int width, unsigned int height, Camera*);
void gui_destroy(Gui*); void
gui_log(const char *fmt, ...);
void
gui_destroy(Gui*);
#endif // GUI_H_ #endif // GUI_H_

View File

@ -115,9 +115,7 @@ initViewports(void)
static static
bool initGame(void) bool initGame(void)
{ {
initViewports();
gMap = map_lua_generator_run(cLevel, gRenderer); gMap = map_lua_generator_run(cLevel, gRenderer);
gPointer = pointer_create(gRenderer);
return true; return true;
} }
@ -129,11 +127,13 @@ bool init(void)
result = result && initSDL(); result = result && initSDL();
result = result && initGame(); result = result && initGame();
if (result) { if (result) {
initViewports();
gCamera.pos = (Position) { 0, 0 }; gCamera.pos = (Position) { 0, 0 };
gCamera.renderer = gRenderer; gCamera.renderer = gRenderer;
gRoomMatrix = roommatrix_create(); gRoomMatrix = roommatrix_create();
gGui = gui_create(); gGui = gui_create(gRenderer);
item_builder_init(gRenderer); item_builder_init(gRenderer);
gPointer = pointer_create(gRenderer);
} }
gGameState = PLAYING; gGameState = PLAYING;
@ -201,17 +201,31 @@ check_next_level(void)
static void static void
run_game(void) run_game(void)
{ {
static unsigned int player_max_hp = 0;
static unsigned int player_current_hp = 0;
static unsigned int player_current_xp = 0;
SDL_RenderSetViewport(gRenderer, NULL); SDL_RenderSetViewport(gRenderer, NULL);
map_clear_dead_monsters(gMap); map_clear_dead_monsters(gMap);
map_clear_collected_items(gMap); map_clear_collected_items(gMap);
roommatrix_populate_from_map(gRoomMatrix, gMap); roommatrix_populate_from_map(gRoomMatrix, gMap);
roommatrix_add_lightsource(gRoomMatrix, roommatrix_add_lightsource(gRoomMatrix,
&gPlayer->sprite->pos); &gPlayer->sprite->pos);
roommatrix_build_lightmap(gRoomMatrix); roommatrix_build_lightmap(gRoomMatrix);
gui_set_max_health(gGui, gPlayer->stats.maxhp, gRenderer); if (player_max_hp != gPlayer->stats.maxhp) {
gui_set_current_health(gGui, gPlayer->stats.hp); gui_set_max_health(gGui, gPlayer->stats.maxhp, gRenderer);
player_max_hp = gPlayer->stats.maxhp;
}
if (player_current_hp != gPlayer->stats.hp) {
gui_set_current_health(gGui, gPlayer->stats.hp);
player_current_hp = gPlayer->stats.hp;
}
if (player_current_xp != gPlayer->xp) {
gui_set_current_xp(gGui, player_get_xp_data(gPlayer));
player_current_xp = gPlayer->xp;
}
if (gPlayer->steps == gPlayer->stats.speed) { if (gPlayer->steps == gPlayer->stats.speed) {
player_reset_steps(gPlayer); player_reset_steps(gPlayer);
roommatrix_update_with_player(gRoomMatrix, gPlayer); roommatrix_update_with_player(gRoomMatrix, gPlayer);

View File

@ -22,6 +22,10 @@ player_levelup(Player *player)
player->stats.dmg += 5; player->stats.dmg += 5;
player->stats.atk += 1; player->stats.atk += 1;
player->stats.def += 1; player->stats.def += 1;
// Limit health to 3 rows of hearts
if (player->stats.maxhp > 72)
player->stats.maxhp = 72;
} }
unsigned int unsigned int
@ -115,8 +119,8 @@ move_left(Player *player, RoomMatrix *matrix)
player_step(player); player_step(player);
} }
static static void
void move_right(Player *player, RoomMatrix *matrix) move_right(Player *player, RoomMatrix *matrix)
{ {
player->sprite->clip.y = 32; player->sprite->clip.y = 32;
player->sprite->pos.x += TILE_DIMENSION; player->sprite->pos.x += TILE_DIMENSION;
@ -126,8 +130,8 @@ void move_right(Player *player, RoomMatrix *matrix)
player_step(player); player_step(player);
} }
static static void
void move_up(Player *player, RoomMatrix *matrix) move_up(Player *player, RoomMatrix *matrix)
{ {
player->sprite->clip.y = 48; player->sprite->clip.y = 48;
player->sprite->pos.y -= TILE_DIMENSION; player->sprite->pos.y -= TILE_DIMENSION;
@ -137,8 +141,8 @@ void move_up(Player *player, RoomMatrix *matrix)
player_step(player); player_step(player);
} }
static static void
void move_down(Player *player, RoomMatrix *matrix) move_down(Player *player, RoomMatrix *matrix)
{ {
player->sprite->clip.y = 0; player->sprite->clip.y = 0;
player->sprite->pos.y += TILE_DIMENSION; player->sprite->pos.y += TILE_DIMENSION;
@ -148,8 +152,8 @@ void move_down(Player *player, RoomMatrix *matrix)
player_step(player); player_step(player);
} }
static static void
void handle_player_input(Player *player, RoomMatrix *matrix, SDL_Event *event) handle_player_input(Player *player, RoomMatrix *matrix, SDL_Event *event)
{ {
static unsigned int step = 1; static unsigned int step = 1;
@ -251,6 +255,16 @@ player_create(class_t class, SDL_Renderer *renderer)
return player; return player;
} }
ExperienceData player_get_xp_data(Player *p)
{
ExperienceData data;
data.previousLevel = next_level_threshold(p->stats.lvl - 1);
data.current = p->xp;
data.nextLevel = next_level_threshold(p->stats.lvl);
data.level = p->stats.lvl;
return data;
}
void void
player_hit(Player *p, unsigned int dmg) player_hit(Player *p, unsigned int dmg)
{ {

View File

@ -10,6 +10,14 @@
enum PlayerClass { ENGINEER, MAGE, PALADIN, ROGUE, WARRIOR }; enum PlayerClass { ENGINEER, MAGE, PALADIN, ROGUE, WARRIOR };
typedef enum PlayerClass class_t; typedef enum PlayerClass class_t;
typedef struct ExperienceData_t {
unsigned int previousLevel;
unsigned int current;
unsigned int nextLevel;
unsigned int level;
} ExperienceData;
typedef struct Player_t { typedef struct Player_t {
Sprite *sprite; Sprite *sprite;
ActionText *hitText; ActionText *hitText;
@ -28,6 +36,9 @@ typedef struct Player_t {
Player* Player*
player_create(class_t, SDL_Renderer*); player_create(class_t, SDL_Renderer*);
ExperienceData
player_get_xp_data(Player*);
void void
player_hit(Player*, unsigned int dmg); player_hit(Player*, unsigned int dmg);

View File

@ -14,6 +14,7 @@ Sprite* sprite_create_default(void)
s->renderTimer = timer_create(); s->renderTimer = timer_create();
s->texture_index = 0; s->texture_index = 0;
s->fixed = false; s->fixed = false;
s->hidden = false;
return s; return s;
} }
@ -55,6 +56,9 @@ sprite_set_texture(Sprite *s, Texture *t, int index)
void sprite_render(Sprite *s, Camera *cam) void sprite_render(Sprite *s, Camera *cam)
{ {
if (s->hidden)
return;
if (s->textures[1]) { if (s->textures[1]) {
if (!timer_started(s->renderTimer)) if (!timer_started(s->renderTimer))
timer_start(s->renderTimer); timer_start(s->renderTimer);

View File

@ -17,6 +17,7 @@ typedef struct Sprite_t {
Timer *renderTimer; Timer *renderTimer;
unsigned int texture_index; unsigned int texture_index;
bool fixed; bool fixed;
bool hidden;
} Sprite; } Sprite;
Sprite* sprite_create(void); Sprite* sprite_create(void);