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"
|
#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);
|
||||||
|
|
29
src/gui.h
29
src/gui.h
|
@ -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_
|
||||||
|
|
26
src/main.c
26
src/main.c
|
@ -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);
|
||||||
|
|
30
src/player.c
30
src/player.c
|
@ -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)
|
||||||
{
|
{
|
||||||
|
|
11
src/player.h
11
src/player.h
|
@ -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);
|
||||||
|
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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);
|
||||||
|
|
Loading…
Reference in New Issue