Added an XP bar. Need some text to go with it next
This commit is contained in:
parent
6dc08b8a6b
commit
5dff9a9452
126
src/gui.c
126
src/gui.c
|
@ -8,6 +8,7 @@
|
|||
#include "util.h"
|
||||
|
||||
#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_right = { 48, 160, 16, 16 };
|
||||
|
@ -26,6 +27,19 @@ static struct LogData_t {
|
|||
unsigned int strlen;
|
||||
} 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
|
||||
gui_malloc_log(void)
|
||||
{
|
||||
|
@ -39,8 +53,56 @@ gui_malloc_log(void)
|
|||
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_create()
|
||||
gui_create(SDL_Renderer *renderer)
|
||||
{
|
||||
Texture *t;
|
||||
unsigned int i;
|
||||
|
@ -48,6 +110,7 @@ gui_create()
|
|||
Gui *gui = ec_malloc(sizeof(Gui));
|
||||
gui->sprites = linkedlist_create();
|
||||
gui->health = linkedlist_create();
|
||||
gui->xp_bar = linkedlist_create();
|
||||
gui->textures = ht_create(5);
|
||||
|
||||
for (i = 0; i < LOG_LINES_COUNT; ++i) {
|
||||
|
@ -58,6 +121,8 @@ gui_create()
|
|||
|
||||
gui_malloc_log();
|
||||
|
||||
init_sprites(gui, renderer);
|
||||
|
||||
return gui;
|
||||
}
|
||||
|
||||
|
@ -76,7 +141,7 @@ gui_set_max_health(Gui *gui, int max, SDL_Renderer *renderer)
|
|||
while (gui->health != NULL)
|
||||
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) {
|
||||
Sprite *sprite = sprite_create();
|
||||
|
@ -114,17 +179,48 @@ gui_set_current_health(Gui *gui, int current)
|
|||
}
|
||||
}
|
||||
|
||||
Texture*
|
||||
gui_add_texture(Gui *gui, const char *path, SDL_Renderer *renderer)
|
||||
void
|
||||
gui_set_current_xp(Gui *gui, ExperienceData data)
|
||||
{
|
||||
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);
|
||||
static unsigned int last_level = 0;
|
||||
unsigned int xp_from_levelup, xp_required_from_last_level;
|
||||
float xp_step, xp_current_step;
|
||||
unsigned int full_xp_blocks, partial_xp_block;
|
||||
LinkedList *xp_bars;
|
||||
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;
|
||||
}
|
||||
return t;
|
||||
|
||||
++i;
|
||||
}
|
||||
|
||||
if (last_level != data.level) {
|
||||
// TODO(Linus): Update the indicators
|
||||
last_level = data.level;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -173,6 +269,12 @@ gui_render_panel(Gui *gui, unsigned int width, unsigned int height, Camera *cam)
|
|||
sprite_render(s, cam);
|
||||
item = item->next;
|
||||
}
|
||||
item = gui->xp_bar;
|
||||
while (item != NULL) {
|
||||
Sprite *s = item->data;
|
||||
sprite_render(s, cam);
|
||||
item = item->next;
|
||||
}
|
||||
item = gui->sprites;
|
||||
while (item != NULL) {
|
||||
Sprite *s = item->data;
|
||||
|
@ -262,6 +364,8 @@ gui_destroy(Gui *gui)
|
|||
sprite_destroy(linkedlist_pop(&gui->sprites));
|
||||
while (gui->health != NULL)
|
||||
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);
|
||||
free(gui);
|
||||
|
|
29
src/gui.h
29
src/gui.h
|
@ -8,28 +8,41 @@
|
|||
#include "hashtable.h"
|
||||
#include "sprite.h"
|
||||
#include "camera.h"
|
||||
#include "player.h"
|
||||
|
||||
typedef struct {
|
||||
LinkedList *sprites;
|
||||
LinkedList *health;
|
||||
LinkedList *xp_bar;
|
||||
Hashtable *textures;
|
||||
Texture *log_lines[LOG_LINES_COUNT];
|
||||
} 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_
|
||||
|
|
20
src/main.c
20
src/main.c
|
@ -115,9 +115,7 @@ initViewports(void)
|
|||
static
|
||||
bool initGame(void)
|
||||
{
|
||||
initViewports();
|
||||
gMap = map_lua_generator_run(cLevel, gRenderer);
|
||||
gPointer = pointer_create(gRenderer);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -129,11 +127,13 @@ bool init(void)
|
|||
result = result && initSDL();
|
||||
result = result && initGame();
|
||||
if (result) {
|
||||
initViewports();
|
||||
gCamera.pos = (Position) { 0, 0 };
|
||||
gCamera.renderer = gRenderer;
|
||||
gRoomMatrix = roommatrix_create();
|
||||
gGui = gui_create();
|
||||
gGui = gui_create(gRenderer);
|
||||
item_builder_init(gRenderer);
|
||||
gPointer = pointer_create(gRenderer);
|
||||
}
|
||||
|
||||
gGameState = PLAYING;
|
||||
|
@ -201,6 +201,10 @@ check_next_level(void)
|
|||
static 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);
|
||||
map_clear_dead_monsters(gMap);
|
||||
map_clear_collected_items(gMap);
|
||||
|
@ -210,8 +214,18 @@ run_game(void)
|
|||
|
||||
roommatrix_build_lightmap(gRoomMatrix);
|
||||
|
||||
if (player_max_hp != gPlayer->stats.maxhp) {
|
||||
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) {
|
||||
player_reset_steps(gPlayer);
|
||||
roommatrix_update_with_player(gRoomMatrix, gPlayer);
|
||||
|
|
30
src/player.c
30
src/player.c
|
@ -22,6 +22,10 @@ player_levelup(Player *player)
|
|||
player->stats.dmg += 5;
|
||||
player->stats.atk += 1;
|
||||
player->stats.def += 1;
|
||||
|
||||
// Limit health to 3 rows of hearts
|
||||
if (player->stats.maxhp > 72)
|
||||
player->stats.maxhp = 72;
|
||||
}
|
||||
|
||||
unsigned int
|
||||
|
@ -115,8 +119,8 @@ move_left(Player *player, RoomMatrix *matrix)
|
|||
player_step(player);
|
||||
}
|
||||
|
||||
static
|
||||
void move_right(Player *player, RoomMatrix *matrix)
|
||||
static void
|
||||
move_right(Player *player, RoomMatrix *matrix)
|
||||
{
|
||||
player->sprite->clip.y = 32;
|
||||
player->sprite->pos.x += TILE_DIMENSION;
|
||||
|
@ -126,8 +130,8 @@ void move_right(Player *player, RoomMatrix *matrix)
|
|||
player_step(player);
|
||||
}
|
||||
|
||||
static
|
||||
void move_up(Player *player, RoomMatrix *matrix)
|
||||
static void
|
||||
move_up(Player *player, RoomMatrix *matrix)
|
||||
{
|
||||
player->sprite->clip.y = 48;
|
||||
player->sprite->pos.y -= TILE_DIMENSION;
|
||||
|
@ -137,8 +141,8 @@ void move_up(Player *player, RoomMatrix *matrix)
|
|||
player_step(player);
|
||||
}
|
||||
|
||||
static
|
||||
void move_down(Player *player, RoomMatrix *matrix)
|
||||
static void
|
||||
move_down(Player *player, RoomMatrix *matrix)
|
||||
{
|
||||
player->sprite->clip.y = 0;
|
||||
player->sprite->pos.y += TILE_DIMENSION;
|
||||
|
@ -148,8 +152,8 @@ void move_down(Player *player, RoomMatrix *matrix)
|
|||
player_step(player);
|
||||
}
|
||||
|
||||
static
|
||||
void handle_player_input(Player *player, RoomMatrix *matrix, SDL_Event *event)
|
||||
static void
|
||||
handle_player_input(Player *player, RoomMatrix *matrix, SDL_Event *event)
|
||||
{
|
||||
static unsigned int step = 1;
|
||||
|
||||
|
@ -251,6 +255,16 @@ player_create(class_t class, SDL_Renderer *renderer)
|
|||
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
|
||||
player_hit(Player *p, unsigned int dmg)
|
||||
{
|
||||
|
|
11
src/player.h
11
src/player.h
|
@ -10,6 +10,14 @@
|
|||
enum PlayerClass { ENGINEER, MAGE, PALADIN, ROGUE, WARRIOR };
|
||||
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 {
|
||||
Sprite *sprite;
|
||||
ActionText *hitText;
|
||||
|
@ -28,6 +36,9 @@ typedef struct Player_t {
|
|||
Player*
|
||||
player_create(class_t, SDL_Renderer*);
|
||||
|
||||
ExperienceData
|
||||
player_get_xp_data(Player*);
|
||||
|
||||
void
|
||||
player_hit(Player*, unsigned int dmg);
|
||||
|
||||
|
|
|
@ -14,6 +14,7 @@ Sprite* sprite_create_default(void)
|
|||
s->renderTimer = timer_create();
|
||||
s->texture_index = 0;
|
||||
s->fixed = false;
|
||||
s->hidden = false;
|
||||
|
||||
return s;
|
||||
}
|
||||
|
@ -55,6 +56,9 @@ sprite_set_texture(Sprite *s, Texture *t, int index)
|
|||
|
||||
void sprite_render(Sprite *s, Camera *cam)
|
||||
{
|
||||
if (s->hidden)
|
||||
return;
|
||||
|
||||
if (s->textures[1]) {
|
||||
if (!timer_started(s->renderTimer))
|
||||
timer_start(s->renderTimer);
|
||||
|
|
|
@ -17,6 +17,7 @@ typedef struct Sprite_t {
|
|||
Timer *renderTimer;
|
||||
unsigned int texture_index;
|
||||
bool fixed;
|
||||
bool hidden;
|
||||
} Sprite;
|
||||
|
||||
Sprite* sprite_create(void);
|
||||
|
|
Loading…
Reference in New Issue