2018-02-16 18:11:26 +01:00
|
|
|
/*
|
|
|
|
* BreakHack - A dungeone crawler RPG
|
|
|
|
* Copyright (C) 2018 Linus Probert <linus.probert@gmail.com>
|
|
|
|
*
|
|
|
|
* This program is free software: you can redistribute it and/or modify
|
|
|
|
* it under the terms of the GNU General Public License as published by
|
|
|
|
* the Free Software Foundation, either version 3 of the License, or
|
|
|
|
* (at your option) any later version.
|
|
|
|
*
|
|
|
|
* This program is distributed in the hope that it will be useful,
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
* GNU General Public License for more details.
|
|
|
|
*
|
|
|
|
* You should have received a copy of the GNU General Public License
|
|
|
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
*/
|
|
|
|
|
2018-01-23 22:54:02 +01:00
|
|
|
#include <stdio.h>
|
2017-12-22 15:15:40 +01:00
|
|
|
#include <assert.h>
|
2017-12-22 15:19:26 +01:00
|
|
|
#include <stdlib.h>
|
2018-01-23 21:03:43 +01:00
|
|
|
#include <string.h>
|
2018-01-23 22:54:02 +01:00
|
|
|
#include <stdarg.h>
|
2017-12-22 15:15:40 +01:00
|
|
|
|
|
|
|
#include "gui.h"
|
|
|
|
#include "util.h"
|
2018-01-31 20:59:55 +01:00
|
|
|
#include "map.h"
|
2018-02-23 23:53:52 +01:00
|
|
|
#include "texturecache.h"
|
2018-08-19 20:25:31 +02:00
|
|
|
#include "gui_util.h"
|
2018-08-20 14:30:31 +02:00
|
|
|
#include "tooltip.h"
|
2017-12-22 15:15:40 +01:00
|
|
|
|
2018-08-05 12:48:56 +02:00
|
|
|
#define DEFAULT_LOG { NULL, LOG_LINES_COUNT, 0, 200 }
|
2018-03-07 16:02:56 +01:00
|
|
|
#define DEFAULT_EVENT_MESSAGES { NULL, 5, 0, 200 }
|
2018-02-03 13:02:39 +01:00
|
|
|
|
2018-03-13 16:13:54 +01:00
|
|
|
#define POS_Y_COLLECTABLES 64
|
|
|
|
#define POS_Y_XPBAR 128
|
2018-01-23 14:11:03 +01:00
|
|
|
|
|
|
|
static struct LogData_t {
|
|
|
|
char **log;
|
|
|
|
unsigned int len;
|
|
|
|
unsigned int count;
|
|
|
|
unsigned int strlen;
|
|
|
|
} log_data = DEFAULT_LOG;
|
2018-01-23 12:14:44 +01:00
|
|
|
|
2018-08-20 14:30:31 +02:00
|
|
|
static struct GuiEventMsgs {
|
2018-03-07 16:02:56 +01:00
|
|
|
char **messages;
|
|
|
|
unsigned int len;
|
|
|
|
unsigned int count;
|
|
|
|
unsigned int strlen;
|
|
|
|
} event_messages = DEFAULT_EVENT_MESSAGES;
|
|
|
|
|
2018-01-23 12:14:44 +01:00
|
|
|
static void
|
|
|
|
gui_malloc_log(void)
|
|
|
|
{
|
2018-01-23 14:11:03 +01:00
|
|
|
if (log_data.log != NULL)
|
2018-01-23 12:14:44 +01:00
|
|
|
return;
|
|
|
|
|
|
|
|
unsigned int i;
|
|
|
|
|
2018-01-23 14:11:03 +01:00
|
|
|
log_data.log = ec_malloc(log_data.len * sizeof(char*));
|
|
|
|
for (i = 0; i < log_data.len; ++i)
|
|
|
|
log_data.log[i] = NULL;
|
2018-01-23 12:14:44 +01:00
|
|
|
}
|
|
|
|
|
2018-03-07 16:02:56 +01:00
|
|
|
static void
|
|
|
|
gui_malloc_eventmessages(void)
|
|
|
|
{
|
|
|
|
if (event_messages.messages != NULL)
|
|
|
|
return;
|
|
|
|
|
|
|
|
unsigned int i;
|
|
|
|
|
|
|
|
event_messages.messages = ec_malloc(event_messages.len * sizeof(char*));
|
|
|
|
for (i = 0; i < event_messages.len; ++i)
|
|
|
|
event_messages.messages[i] = NULL;
|
|
|
|
}
|
|
|
|
|
2018-01-31 20:59:55 +01:00
|
|
|
static Sprite*
|
|
|
|
create_xp_sprite(Texture *t, SDL_Rect clip, Position pos)
|
|
|
|
{
|
|
|
|
Sprite *s = sprite_create();
|
|
|
|
sprite_set_texture(s, t, 0);
|
|
|
|
s->fixed = true;
|
|
|
|
s->clip = clip;
|
|
|
|
s->pos = pos;
|
|
|
|
return s;
|
|
|
|
}
|
|
|
|
|
|
|
|
static Sprite*
|
|
|
|
create_label_sprite(Position pos)
|
|
|
|
{
|
|
|
|
Sprite *s = sprite_create();
|
|
|
|
s->fixed = true;
|
|
|
|
s->pos = pos;
|
2018-05-15 14:12:38 +02:00
|
|
|
sprite_load_text_texture(s, "GUI/SDS_8x8.ttf", 0, LABEL_FONT_SIZE, 0);
|
2018-01-31 20:59:55 +01:00
|
|
|
return s;
|
|
|
|
}
|
|
|
|
|
2018-01-31 13:52:11 +01:00
|
|
|
static void
|
2018-05-09 00:21:38 +02:00
|
|
|
init_sprites(Gui *gui, Camera *cam)
|
2018-01-31 13:52:11 +01:00
|
|
|
{
|
|
|
|
Texture *t;
|
|
|
|
unsigned int i;
|
|
|
|
|
2018-02-23 23:53:52 +01:00
|
|
|
t = texturecache_add("GUI/GUI0.png");
|
2018-01-31 13:52:11 +01:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Add XP bar decoration
|
|
|
|
*/
|
|
|
|
|
|
|
|
// Left end
|
2018-01-31 20:59:55 +01:00
|
|
|
linkedlist_append(&gui->sprites, create_xp_sprite(
|
|
|
|
t,
|
|
|
|
(SDL_Rect) { 6 * 16, 0, 16, 16 },
|
|
|
|
(Position) { 16, POS_Y_XPBAR }
|
|
|
|
));
|
2018-01-31 13:52:11 +01:00
|
|
|
|
|
|
|
// Right end
|
2018-01-31 20:59:55 +01:00
|
|
|
linkedlist_append(&gui->sprites, create_xp_sprite(
|
|
|
|
t,
|
|
|
|
(SDL_Rect) { 8 * 16, 0, 16, 16 },
|
|
|
|
(Position) { 16 + (16 * 7), POS_Y_XPBAR }
|
|
|
|
));
|
2018-01-31 13:52:11 +01:00
|
|
|
|
|
|
|
for (i = 1; i < 7; ++i) {
|
2018-01-31 20:59:55 +01:00
|
|
|
linkedlist_append(&gui->sprites, create_xp_sprite(
|
|
|
|
t,
|
|
|
|
(SDL_Rect) { 7 * 16, 0, 16, 16 },
|
|
|
|
(Position) { 16 + (i * 16), POS_Y_XPBAR }
|
|
|
|
));
|
2018-01-31 13:52:11 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
for (i = 0; i < 8; ++i) {
|
2018-01-31 20:59:55 +01:00
|
|
|
linkedlist_append(&gui->xp_bar, create_xp_sprite(
|
|
|
|
t,
|
|
|
|
(SDL_Rect) { 6 * 16, 4 * 16, 16, 16 },
|
|
|
|
(Position) { 16 + (i * 16), POS_Y_XPBAR }
|
|
|
|
));
|
2018-01-31 13:52:11 +01:00
|
|
|
}
|
2018-02-03 13:02:39 +01:00
|
|
|
|
|
|
|
Sprite *s;
|
2018-02-23 23:53:52 +01:00
|
|
|
t = texturecache_add("Items/Potion.png");
|
2018-02-03 13:02:39 +01:00
|
|
|
s = sprite_create();
|
|
|
|
s->fixed = true;
|
|
|
|
sprite_set_texture(s, t, 0);
|
2018-03-13 16:13:54 +01:00
|
|
|
s->clip = CLIP16(0, 0);
|
2018-02-03 13:02:39 +01:00
|
|
|
s->pos = (Position) { 16, POS_Y_COLLECTABLES };
|
|
|
|
linkedlist_append(&gui->sprites, s);
|
|
|
|
|
2018-02-23 23:53:52 +01:00
|
|
|
t = texturecache_add("Items/Money.png");
|
2018-02-03 13:02:39 +01:00
|
|
|
s = sprite_create();
|
|
|
|
s->fixed = true;
|
|
|
|
sprite_set_texture(s, t, 0);
|
2018-03-13 16:13:54 +01:00
|
|
|
s->clip = CLIP16(16, 16);
|
2018-02-03 13:02:39 +01:00
|
|
|
s->pos = (Position) { 16, POS_Y_COLLECTABLES + 16 };
|
|
|
|
linkedlist_append(&gui->sprites, s);
|
2018-03-13 16:13:54 +01:00
|
|
|
|
|
|
|
t = texturecache_add("Items/ShortWep.png");
|
|
|
|
s = sprite_create();
|
|
|
|
s->fixed = true;
|
|
|
|
sprite_set_texture(s, t, 0);
|
|
|
|
s->clip = CLIP16(0, 0);
|
|
|
|
s->pos = (Position) { 16, POS_Y_COLLECTABLES + 32 };
|
|
|
|
linkedlist_append(&gui->sprites, s);
|
2018-05-09 00:21:38 +02:00
|
|
|
|
2018-08-21 15:44:12 +02:00
|
|
|
gui->statsFrame = gui_util_create_frame_sprite(RIGHT_GUI_WIDTH/16,
|
|
|
|
STATS_GUI_HEIGHT/16,
|
2018-08-19 20:25:31 +02:00
|
|
|
cam);
|
|
|
|
gui->bottomFrame = gui_util_create_frame_sprite(BOTTOM_GUI_WIDTH/16,
|
|
|
|
BOTTOM_GUI_HEIGHT/16,
|
|
|
|
cam);
|
2018-08-21 15:44:12 +02:00
|
|
|
|
|
|
|
gui->miniMapFrame = gui_util_create_frame_sprite(RIGHT_GUI_WIDTH/16,
|
|
|
|
MINIMAP_GUI_HEIGHT/16,
|
|
|
|
cam);
|
2018-01-31 13:52:11 +01:00
|
|
|
}
|
|
|
|
|
2017-12-22 15:15:40 +01:00
|
|
|
Gui*
|
2018-05-09 00:21:38 +02:00
|
|
|
gui_create(Camera *cam)
|
2017-12-22 15:15:40 +01:00
|
|
|
{
|
2018-01-23 14:11:03 +01:00
|
|
|
Texture *t;
|
|
|
|
unsigned int i;
|
|
|
|
|
2017-12-22 15:15:40 +01:00
|
|
|
Gui *gui = ec_malloc(sizeof(Gui));
|
|
|
|
gui->sprites = linkedlist_create();
|
|
|
|
gui->health = linkedlist_create();
|
2018-01-31 13:52:11 +01:00
|
|
|
gui->xp_bar = linkedlist_create();
|
2018-08-20 14:30:31 +02:00
|
|
|
gui->activeTooltip = NULL;
|
2018-01-23 12:14:44 +01:00
|
|
|
|
2018-01-23 14:11:03 +01:00
|
|
|
for (i = 0; i < LOG_LINES_COUNT; ++i) {
|
|
|
|
t = texture_create();
|
2018-05-15 14:12:38 +02:00
|
|
|
texture_load_font(t, "GUI/SDS_8x8.ttf", LOG_FONT_SIZE, 0);
|
2018-01-23 14:11:03 +01:00
|
|
|
gui->log_lines[i] = t;
|
|
|
|
}
|
|
|
|
|
2018-03-07 16:02:56 +01:00
|
|
|
gui->event_message = texture_create();
|
2018-05-15 14:12:38 +02:00
|
|
|
texture_load_font(gui->event_message, "GUI/SDS_8x8.ttf", EVENT_MESSAGE_FONT_SIZE, 2);
|
2018-03-07 16:02:56 +01:00
|
|
|
gui->event_message_timer = timer_create();
|
|
|
|
|
2018-02-03 13:02:39 +01:00
|
|
|
gui->labels[CURRENT_XP_LABEL] = create_label_sprite((Position) { 16, POS_Y_XPBAR + 18 });
|
|
|
|
gui->labels[LEVEL_LABEL] = create_label_sprite((Position) { 16, POS_Y_XPBAR + 18 + 14 });
|
2018-05-09 00:21:38 +02:00
|
|
|
gui->labels[DUNGEON_LEVEL_LABEL] =
|
|
|
|
create_label_sprite((Position) {
|
|
|
|
16,
|
|
|
|
POS_Y_XPBAR + 18 + (2*14)
|
|
|
|
});
|
|
|
|
gui->labels[HEALTH_POTION_LABEL] =
|
|
|
|
create_label_sprite((Position) {
|
|
|
|
32,
|
|
|
|
POS_Y_COLLECTABLES + 5
|
|
|
|
});
|
|
|
|
gui->labels[GOLD_LABEL] =
|
|
|
|
create_label_sprite((Position) {
|
|
|
|
32,
|
|
|
|
POS_Y_COLLECTABLES + 16 + 5
|
|
|
|
});
|
|
|
|
gui->labels[DAGGER_LABEL] =
|
|
|
|
create_label_sprite((Position) {
|
|
|
|
32,
|
|
|
|
POS_Y_COLLECTABLES + 32 + 5
|
|
|
|
});
|
2018-01-31 20:59:55 +01:00
|
|
|
|
2018-01-23 12:14:44 +01:00
|
|
|
gui_malloc_log();
|
2018-03-07 16:02:56 +01:00
|
|
|
gui_malloc_eventmessages();
|
2018-01-23 12:14:44 +01:00
|
|
|
|
2018-05-09 00:21:38 +02:00
|
|
|
init_sprites(gui, cam);
|
2018-01-31 13:52:11 +01:00
|
|
|
|
2017-12-22 15:15:40 +01:00
|
|
|
return gui;
|
|
|
|
}
|
|
|
|
|
2018-02-01 09:04:19 +01:00
|
|
|
static void
|
2018-02-24 00:29:25 +01:00
|
|
|
set_max_health(Gui *gui, int max)
|
2017-12-22 15:15:40 +01:00
|
|
|
{
|
2018-02-23 11:10:50 +01:00
|
|
|
Texture *texture0, *texture1;
|
2017-12-22 15:15:40 +01:00
|
|
|
int i;
|
|
|
|
|
|
|
|
assert(max % 3 == 0);
|
|
|
|
|
|
|
|
if (((unsigned int) max / 3) == (unsigned int) linkedlist_size(gui->health))
|
|
|
|
return;
|
|
|
|
|
2018-01-30 15:16:14 +01:00
|
|
|
// Clear sprite list
|
|
|
|
while (gui->health != NULL)
|
|
|
|
sprite_destroy(linkedlist_pop(&gui->health));
|
2017-12-22 15:15:40 +01:00
|
|
|
|
2018-02-23 23:53:52 +01:00
|
|
|
texture0 = texturecache_add("GUI/GUI0.png");
|
|
|
|
texture1 = texturecache_add("GUI/GUI1.png");
|
2017-12-22 15:15:40 +01:00
|
|
|
|
|
|
|
for (i = 0; i < max/3; ++i) {
|
2017-12-22 21:33:00 +01:00
|
|
|
Sprite *sprite = sprite_create();
|
2017-12-22 15:15:40 +01:00
|
|
|
sprite->fixed = true;
|
2018-02-23 11:10:50 +01:00
|
|
|
sprite->animate = false;
|
2017-12-22 15:15:40 +01:00
|
|
|
sprite->clip = (SDL_Rect) { 0, 16, 16, 16 };
|
2018-01-30 15:16:14 +01:00
|
|
|
sprite->pos = (Position) { 16 + (i%8)*16, 16 + ((i-(i%8))/8)*16 };
|
2018-02-23 11:10:50 +01:00
|
|
|
sprite_set_texture(sprite, texture0, 0);
|
|
|
|
sprite_set_texture(sprite, texture1, 1);
|
2017-12-22 15:15:40 +01:00
|
|
|
linkedlist_append(&gui->health, sprite);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-02-01 09:04:19 +01:00
|
|
|
static void
|
|
|
|
set_current_health(Gui *gui, int current)
|
2017-12-22 15:15:40 +01:00
|
|
|
{
|
2018-02-15 14:00:59 +01:00
|
|
|
if (current < 0)
|
|
|
|
current = 0;
|
|
|
|
|
2017-12-22 15:15:40 +01:00
|
|
|
int partial = current % 3;
|
|
|
|
int full = (current - partial)/3;
|
|
|
|
int count = 0;
|
|
|
|
|
|
|
|
LinkedList *item = gui->health;
|
|
|
|
while (item != NULL) {
|
2018-01-23 14:45:05 +01:00
|
|
|
Sprite *sprite = (Sprite*) item->data;
|
2017-12-22 15:15:40 +01:00
|
|
|
if (count < full) {
|
|
|
|
sprite->clip.x = 0;
|
|
|
|
} else if (count == full) {
|
|
|
|
sprite->clip.x = 64 - (partial * 16);
|
|
|
|
} else {
|
|
|
|
sprite->clip.x = 64;
|
|
|
|
}
|
|
|
|
|
2018-02-23 11:10:50 +01:00
|
|
|
sprite->animate = current < 9;
|
|
|
|
|
2017-12-22 15:15:40 +01:00
|
|
|
++count;
|
|
|
|
item = item->next;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-02-06 09:11:04 +01:00
|
|
|
static void
|
|
|
|
update_xp_bar(Gui *gui, ExperienceData *data)
|
|
|
|
{
|
|
|
|
unsigned int xp_from_levelup = data->current - data->previousLevel;
|
|
|
|
unsigned int xp_required_from_last_level = data->nextLevel - data->previousLevel;
|
|
|
|
float xp_step = ((float)xp_required_from_last_level) / 32; // 4 * 8
|
2018-02-22 09:44:27 +01:00
|
|
|
float xp_current_step = (float) xp_from_levelup / xp_step;
|
2018-02-06 09:11:04 +01:00
|
|
|
|
|
|
|
unsigned int partial_xp_block = ((unsigned int) xp_current_step) % 4;
|
2018-02-22 09:44:27 +01:00
|
|
|
unsigned int full_xp_blocks =
|
|
|
|
(unsigned int) ((xp_current_step - (float) partial_xp_block) / 4);
|
2018-02-06 09:11:04 +01:00
|
|
|
|
|
|
|
LinkedList *xp_bars = gui->xp_bar;
|
|
|
|
unsigned int 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;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-01-31 13:52:11 +01:00
|
|
|
void
|
2018-01-31 20:59:55 +01:00
|
|
|
gui_update_player_stats(Gui *gui, Player *player, Map *map, SDL_Renderer *renderer)
|
2017-12-22 15:15:40 +01:00
|
|
|
{
|
2018-01-31 20:59:55 +01:00
|
|
|
// TODO(Linus): Perhaps split this up a bit?
|
|
|
|
// some static functions maybe?
|
|
|
|
|
2018-01-31 13:52:11 +01:00
|
|
|
static unsigned int last_level = 0;
|
2018-01-31 20:59:55 +01:00
|
|
|
static int last_xp = -1;
|
|
|
|
static double last_gold = -1;
|
|
|
|
static unsigned int dungeon_level = 0;
|
2018-02-01 09:04:19 +01:00
|
|
|
static int max_health = -1;
|
|
|
|
static int current_health = -1;
|
2018-02-03 13:02:39 +01:00
|
|
|
static int current_potion_sips = -1;
|
2018-03-13 16:13:54 +01:00
|
|
|
static int current_dagger_count = -1;
|
2018-01-31 20:59:55 +01:00
|
|
|
|
|
|
|
char buffer[200];
|
2018-01-31 13:52:11 +01:00
|
|
|
|
2018-01-31 20:59:55 +01:00
|
|
|
ExperienceData data = player_get_xp_data(player);
|
|
|
|
|
2018-02-01 09:04:19 +01:00
|
|
|
if (max_health != player->stats.maxhp) {
|
|
|
|
max_health = player->stats.maxhp;
|
2018-02-24 00:29:25 +01:00
|
|
|
set_max_health(gui, max_health);
|
2018-02-01 09:04:19 +01:00
|
|
|
}
|
|
|
|
if (current_health != player->stats.hp) {
|
|
|
|
current_health = player->stats.hp;
|
|
|
|
set_current_health(gui, current_health);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (last_xp != (int) data.current) {
|
2018-02-06 09:11:04 +01:00
|
|
|
update_xp_bar(gui, &data);
|
2018-01-31 20:59:55 +01:00
|
|
|
}
|
2018-01-31 13:52:11 +01:00
|
|
|
|
2018-02-01 09:04:19 +01:00
|
|
|
if (dungeon_level != (unsigned int) map->level) {
|
2018-01-31 20:59:55 +01:00
|
|
|
m_sprintf(buffer, 200, "Dungeon level: %d", map->level);
|
2018-05-22 15:48:09 +02:00
|
|
|
texture_load_from_text(gui->labels[DUNGEON_LEVEL_LABEL]->textures[0], buffer, C_WHITE, C_BLACK, renderer);
|
2018-02-23 23:53:52 +01:00
|
|
|
gui->labels[DUNGEON_LEVEL_LABEL]->dim = gui->labels[DUNGEON_LEVEL_LABEL]->textures[0]->dim;
|
2018-01-31 20:59:55 +01:00
|
|
|
dungeon_level = (unsigned int) map->level;
|
2017-12-22 15:15:40 +01:00
|
|
|
}
|
2018-01-31 13:52:11 +01:00
|
|
|
|
2018-02-03 13:02:39 +01:00
|
|
|
if (current_potion_sips != (int) player->potion_sips) {
|
|
|
|
m_sprintf(buffer, 200, "x %u", (unsigned int) player->potion_sips);
|
2018-05-22 15:48:09 +02:00
|
|
|
texture_load_from_text(gui->labels[HEALTH_POTION_LABEL]->textures[0], buffer, C_WHITE, C_BLACK, renderer);
|
2018-02-23 23:53:52 +01:00
|
|
|
gui->labels[HEALTH_POTION_LABEL]->dim = gui->labels[HEALTH_POTION_LABEL]->textures[0]->dim;
|
2018-02-03 13:02:39 +01:00
|
|
|
current_potion_sips = player->potion_sips;
|
|
|
|
}
|
|
|
|
|
2018-03-13 16:13:54 +01:00
|
|
|
if (current_dagger_count != (int) player->daggers) {
|
|
|
|
m_sprintf(buffer, 200, "x %u", (unsigned int) player->daggers);
|
2018-05-22 15:48:09 +02:00
|
|
|
texture_load_from_text(gui->labels[DAGGER_LABEL]->textures[0], buffer, C_WHITE, C_BLACK, renderer);
|
2018-03-13 16:13:54 +01:00
|
|
|
gui->labels[DAGGER_LABEL]->dim = gui->labels[DAGGER_LABEL]->textures[0]->dim;
|
|
|
|
current_dagger_count = (int) player->daggers;
|
|
|
|
}
|
|
|
|
|
2018-01-31 20:59:55 +01:00
|
|
|
if (last_gold != player->gold) {
|
2018-02-03 13:02:39 +01:00
|
|
|
m_sprintf(buffer, 200, "x %.2f", player->gold);
|
2018-05-22 15:48:09 +02:00
|
|
|
texture_load_from_text(gui->labels[GOLD_LABEL]->textures[0], buffer, C_WHITE, C_BLACK, renderer);
|
2018-02-23 23:53:52 +01:00
|
|
|
gui->labels[GOLD_LABEL]->dim = gui->labels[GOLD_LABEL]->textures[0]->dim;
|
2018-01-31 20:59:55 +01:00
|
|
|
last_gold = player->gold;
|
2018-01-31 13:52:11 +01:00
|
|
|
}
|
|
|
|
|
2018-02-01 09:04:19 +01:00
|
|
|
if (last_xp != (int) data.current) {
|
2018-01-31 20:59:55 +01:00
|
|
|
m_sprintf(buffer, 200, "XP: %u / %u", data.current, data.nextLevel);
|
2018-05-22 15:48:09 +02:00
|
|
|
texture_load_from_text(gui->labels[CURRENT_XP_LABEL]->textures[0], buffer, C_WHITE, C_BLACK, renderer);
|
2018-02-23 23:53:52 +01:00
|
|
|
gui->labels[CURRENT_XP_LABEL]->dim = gui->labels[CURRENT_XP_LABEL]->textures[0]->dim;
|
2018-01-31 20:59:55 +01:00
|
|
|
last_xp = data.current;
|
|
|
|
}
|
2018-01-31 13:52:11 +01:00
|
|
|
|
2018-01-31 20:59:55 +01:00
|
|
|
if (last_level != data.level) {
|
|
|
|
m_sprintf(buffer, 200, "Level: %u", data.level);
|
2018-05-22 15:48:09 +02:00
|
|
|
texture_load_from_text(gui->labels[LEVEL_LABEL]->textures[0], buffer, C_WHITE, C_BLACK, renderer);
|
2018-02-23 23:53:52 +01:00
|
|
|
gui->labels[LEVEL_LABEL]->dim = gui->labels[LEVEL_LABEL]->textures[0]->dim;
|
2018-01-31 20:59:55 +01:00
|
|
|
last_level = data.level;
|
|
|
|
}
|
2017-12-22 15:15:40 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2018-05-09 00:21:38 +02:00
|
|
|
gui_render_panel(Gui *gui, Camera *cam)
|
2017-12-22 15:15:40 +01:00
|
|
|
{
|
2018-08-21 15:44:12 +02:00
|
|
|
sprite_render(gui->statsFrame, cam);
|
2017-12-22 15:15:40 +01:00
|
|
|
LinkedList *item = gui->health;
|
|
|
|
while (item != NULL) {
|
|
|
|
Sprite *s = item->data;
|
|
|
|
sprite_render(s, cam);
|
|
|
|
item = item->next;
|
|
|
|
}
|
2018-01-31 13:52:11 +01:00
|
|
|
item = gui->xp_bar;
|
|
|
|
while (item != NULL) {
|
|
|
|
Sprite *s = item->data;
|
|
|
|
sprite_render(s, cam);
|
|
|
|
item = item->next;
|
|
|
|
}
|
2017-12-22 15:15:40 +01:00
|
|
|
item = gui->sprites;
|
|
|
|
while (item != NULL) {
|
|
|
|
Sprite *s = item->data;
|
|
|
|
sprite_render(s, cam);
|
|
|
|
item = item->next;
|
|
|
|
}
|
|
|
|
|
2018-01-31 20:59:55 +01:00
|
|
|
for (int i = 0; i < LABEL_COUNT; ++i)
|
|
|
|
sprite_render(gui->labels[i], cam);
|
2017-12-22 15:15:40 +01:00
|
|
|
}
|
|
|
|
|
2018-08-21 15:44:12 +02:00
|
|
|
void
|
|
|
|
gui_render_minimap(Gui *gui, Map *map, Camera *cam)
|
|
|
|
{
|
|
|
|
sprite_render(gui->miniMapFrame, cam);
|
|
|
|
|
|
|
|
SDL_Rect box = { 0, 0, 12, 8 };
|
|
|
|
for (Uint8 i = 0; i < MAP_H_ROOM_COUNT; ++i) {
|
|
|
|
for (Uint8 j = 0; j < MAP_V_ROOM_COUNT; ++j) {
|
|
|
|
Room *room = map->rooms[i][j];
|
|
|
|
box.x = i*14 + 10;
|
|
|
|
box.y = j*10 + 14;
|
|
|
|
if (room && room->visited) {
|
|
|
|
if (map->currentRoom.x == i && map->currentRoom.y == j)
|
|
|
|
SDL_SetRenderDrawColor(cam->renderer, 0, 255, 255, 255);
|
|
|
|
else
|
|
|
|
SDL_SetRenderDrawColor(cam->renderer, 255, 255, 255, 255);
|
|
|
|
SDL_RenderFillRect(cam->renderer, &box);
|
|
|
|
SDL_SetRenderDrawColor(cam->renderer, 60, 134, 252, 255);
|
|
|
|
SDL_RenderDrawRect(cam->renderer, &box);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-01-23 14:11:03 +01:00
|
|
|
void
|
2018-01-23 22:54:02 +01:00
|
|
|
gui_log(const char *fmt, ...)
|
2018-01-23 14:11:03 +01:00
|
|
|
{
|
2018-01-27 23:14:39 +01:00
|
|
|
char buffer[200];
|
2018-01-23 14:11:03 +01:00
|
|
|
char *new_message;
|
2018-01-24 09:35:21 +01:00
|
|
|
char tstamp[10];
|
2018-01-23 22:54:02 +01:00
|
|
|
|
|
|
|
va_list args;
|
2018-01-23 14:11:03 +01:00
|
|
|
|
2018-01-24 09:35:21 +01:00
|
|
|
new_message = ec_malloc(log_data.strlen * sizeof(char));
|
|
|
|
timestamp(tstamp, 10);
|
2018-03-07 16:02:56 +01:00
|
|
|
|
|
|
|
va_start(args, fmt);
|
|
|
|
m_vsprintf(buffer, 200, fmt, args);
|
|
|
|
va_end(args);
|
2018-01-24 09:35:21 +01:00
|
|
|
m_sprintf(new_message, log_data.strlen, "%s > %s", tstamp, buffer);
|
|
|
|
|
2018-01-23 14:11:03 +01:00
|
|
|
log_data.count++;
|
|
|
|
if (log_data.count > log_data.len) {
|
|
|
|
log_data.count = log_data.len;
|
2018-08-05 12:48:56 +02:00
|
|
|
free(log_data.log[0]);
|
|
|
|
log_data.log[0] = NULL;
|
2018-08-12 09:13:18 +02:00
|
|
|
for (size_t i = 0; i < log_data.count - 1; ++i) {
|
2018-08-05 12:48:56 +02:00
|
|
|
log_data.log[i] = log_data.log[i+1];
|
|
|
|
log_data.log[i+1] = NULL;
|
|
|
|
}
|
2018-01-23 14:11:03 +01:00
|
|
|
}
|
2018-08-05 12:48:56 +02:00
|
|
|
log_data.log[log_data.count-1] = new_message;
|
2018-01-23 14:11:03 +01:00
|
|
|
}
|
|
|
|
|
2018-03-07 16:02:56 +01:00
|
|
|
void
|
|
|
|
gui_event_message(const char *fmt, ...)
|
|
|
|
{
|
|
|
|
char *new_message = ec_malloc(sizeof(char) * event_messages.strlen);
|
|
|
|
|
|
|
|
va_list args;
|
|
|
|
va_start(args, fmt);
|
|
|
|
m_vsprintf(new_message, event_messages.strlen, fmt, args);
|
|
|
|
va_end(args);
|
|
|
|
|
|
|
|
if (event_messages.count == event_messages.len) {
|
|
|
|
error("To many event messages");
|
|
|
|
free(new_message);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
event_messages.messages[event_messages.count] = new_message;
|
|
|
|
event_messages.count++;
|
|
|
|
}
|
|
|
|
|
2018-08-20 14:30:31 +02:00
|
|
|
void
|
|
|
|
gui_render_tooltip(Gui *gui, Camera *cam)
|
|
|
|
{
|
|
|
|
if (gui->activeTooltip) {
|
|
|
|
sprite_render(gui->activeTooltip, cam);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-01-23 12:14:44 +01:00
|
|
|
void
|
2018-05-09 00:21:38 +02:00
|
|
|
gui_render_log(Gui *gui, Camera *cam)
|
2018-01-23 12:14:44 +01:00
|
|
|
{
|
2018-02-23 23:53:52 +01:00
|
|
|
SDL_Rect box = { 16, 0, 16, 16 };
|
2018-01-23 14:11:03 +01:00
|
|
|
|
2018-05-09 00:21:38 +02:00
|
|
|
sprite_render(gui->bottomFrame, cam);
|
2018-01-23 14:11:03 +01:00
|
|
|
|
2018-08-05 12:48:56 +02:00
|
|
|
for (Uint32 i = 0; i < log_data.count; ++i) {
|
2018-01-23 14:37:58 +01:00
|
|
|
Texture *t;
|
2018-02-23 23:53:52 +01:00
|
|
|
box.y = 16 + ((LOG_FONT_SIZE+5) * i);
|
2018-01-23 14:11:03 +01:00
|
|
|
t = gui->log_lines[i];
|
2018-05-22 15:48:09 +02:00
|
|
|
texture_load_from_text(t, log_data.log[i], C_WHITE, C_BLACK, cam->renderer);
|
2018-02-23 23:53:52 +01:00
|
|
|
box.w = t->dim.width;
|
|
|
|
box.h = t->dim.height;
|
|
|
|
texture_render(t, &box, cam);
|
2018-01-23 14:11:03 +01:00
|
|
|
}
|
2018-01-23 12:14:44 +01:00
|
|
|
}
|
|
|
|
|
2018-03-07 16:02:56 +01:00
|
|
|
void
|
|
|
|
gui_render_event_message(Gui *gui, Camera *cam)
|
|
|
|
{
|
|
|
|
static SDL_Rect box = { 0, 0, 150, 50 };
|
|
|
|
|
|
|
|
if (timer_started(gui->event_message_timer)
|
|
|
|
&& timer_get_ticks(gui->event_message_timer) < EVENT_MESSAGE_DISPLAY_TIME)
|
|
|
|
{
|
|
|
|
texture_render(gui->event_message, &box, cam);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (event_messages.count > 0) {
|
|
|
|
texture_load_from_text(gui->event_message,
|
|
|
|
event_messages.messages[0],
|
2018-05-22 15:48:09 +02:00
|
|
|
C_WHITE,
|
|
|
|
C_BLACK,
|
2018-03-07 16:02:56 +01:00
|
|
|
cam->renderer);
|
|
|
|
|
|
|
|
box.x = (GAME_VIEW_WIDTH/2) - (gui->event_message->dim.width/2);
|
|
|
|
box.y = (GAME_VIEW_HEIGHT/2) - (gui->event_message->dim.height/2);
|
|
|
|
box.w = gui->event_message->dim.width;
|
|
|
|
box.h = gui->event_message->dim.height;
|
|
|
|
|
|
|
|
free(event_messages.messages[0]);
|
|
|
|
for (size_t i = 1; i < event_messages.count; ++i) {
|
|
|
|
event_messages.messages[i-1] = event_messages.messages[i];
|
|
|
|
}
|
|
|
|
event_messages.count--;
|
|
|
|
|
|
|
|
texture_render(gui->event_message, &box, cam);
|
|
|
|
timer_start(gui->event_message_timer);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
gui_clear_message_log(void)
|
|
|
|
{
|
2018-08-20 14:30:31 +02:00
|
|
|
for (size_t i = 0; i < event_messages.count; ++i) {
|
2018-03-07 16:02:56 +01:00
|
|
|
free(event_messages.messages[i]);
|
2018-08-20 14:30:31 +02:00
|
|
|
}
|
2018-03-07 16:02:56 +01:00
|
|
|
event_messages.count = 0;
|
|
|
|
|
|
|
|
for (size_t i = 0; i < log_data.count; ++i)
|
|
|
|
free(log_data.log[i]);
|
|
|
|
log_data.count = 0;
|
|
|
|
}
|
|
|
|
|
2018-01-23 12:14:44 +01:00
|
|
|
static void
|
|
|
|
destroy_log(void)
|
|
|
|
{
|
2018-01-23 14:11:03 +01:00
|
|
|
if (log_data.log == NULL)
|
2018-01-23 12:14:44 +01:00
|
|
|
return;
|
|
|
|
|
|
|
|
unsigned int i;
|
2018-01-23 14:11:03 +01:00
|
|
|
for (i = 0; i < log_data.count; ++i)
|
|
|
|
free(log_data.log[i]);
|
2018-01-23 12:14:44 +01:00
|
|
|
|
2018-01-23 14:11:03 +01:00
|
|
|
free(log_data.log);
|
|
|
|
log_data.log = NULL;
|
2018-01-23 12:14:44 +01:00
|
|
|
}
|
|
|
|
|
2018-03-07 16:02:56 +01:00
|
|
|
static void
|
|
|
|
destroy_event_messages(void)
|
|
|
|
{
|
|
|
|
if (event_messages.messages == NULL)
|
|
|
|
return;
|
|
|
|
|
2018-08-20 14:30:31 +02:00
|
|
|
for (unsigned int i = 0; i < event_messages.count; ++i) {
|
2018-03-07 16:02:56 +01:00
|
|
|
free(event_messages.messages[i]);
|
2018-08-20 14:30:31 +02:00
|
|
|
}
|
2018-03-07 16:02:56 +01:00
|
|
|
|
|
|
|
free(event_messages.messages);
|
|
|
|
event_messages.messages = NULL;
|
|
|
|
}
|
|
|
|
|
2017-12-22 15:15:40 +01:00
|
|
|
void
|
|
|
|
gui_destroy(Gui *gui)
|
|
|
|
{
|
2018-01-23 12:14:44 +01:00
|
|
|
destroy_log();
|
2018-03-07 16:02:56 +01:00
|
|
|
destroy_event_messages();
|
|
|
|
|
|
|
|
timer_destroy(gui->event_message_timer);
|
|
|
|
texture_destroy(gui->event_message);
|
2018-01-23 12:14:44 +01:00
|
|
|
|
2018-05-09 00:21:38 +02:00
|
|
|
sprite_destroy(gui->bottomFrame);
|
2018-08-21 15:44:12 +02:00
|
|
|
sprite_destroy(gui->statsFrame);
|
|
|
|
sprite_destroy(gui->miniMapFrame);
|
2018-05-09 00:21:38 +02:00
|
|
|
|
2017-12-22 15:15:40 +01:00
|
|
|
while (gui->sprites != NULL)
|
|
|
|
sprite_destroy(linkedlist_pop(&gui->sprites));
|
|
|
|
while (gui->health != NULL)
|
|
|
|
sprite_destroy(linkedlist_pop(&gui->health));
|
2018-01-31 13:52:11 +01:00
|
|
|
while (gui->xp_bar != NULL)
|
|
|
|
sprite_destroy(linkedlist_pop(&gui->xp_bar));
|
2018-01-23 12:14:44 +01:00
|
|
|
|
2018-01-31 16:55:48 +01:00
|
|
|
for (int i = 0; i < LOG_LINES_COUNT; ++i)
|
|
|
|
texture_destroy(gui->log_lines[i]);
|
|
|
|
|
2018-02-03 23:39:49 +01:00
|
|
|
for (int i = 0; i < LABEL_COUNT; ++i)
|
|
|
|
sprite_destroy(gui->labels[i]);
|
|
|
|
|
2017-12-22 15:15:40 +01:00
|
|
|
free(gui);
|
|
|
|
}
|