Fixes #38, Artifact inventory

This commit is contained in:
Linus Probert 2018-08-21 12:30:44 +02:00
parent 358c0c7ddc
commit 9ef97c0897
9 changed files with 268 additions and 66 deletions

View File

@ -26,65 +26,39 @@
static void
artifact_set_effect(Artifact *a, MagicalEffect effect)
{
Texture *t;
a->effect = effect;
switch (effect) {
case IMPROVED_HEARING:
a->info.name = "Potion of ear juice";
a->info.desc = "Your hearing is slightly improved";
t = texturecache_add("Items/Potion.png");
sprite_set_texture(a->sprite, t, 0);
a->sprite->clip = CLIP16(7*16, 4*16);
break;
case TRAP_AVOIDANCE:
a->info.name = "Boot with nails inside";
a->info.desc = "You are lighter on your feet";
t = texturecache_add("Items/Boot.png");
sprite_set_texture(a->sprite, t, 0);
a->sprite->clip = CLIP16(5*16, 0);
break;
case PIERCING_DAGGERS:
a->info.name = "Whetstone";
a->info.desc = "Your daggers are sharper";
t = texturecache_add("Items/Rock.png");
sprite_set_texture(a->sprite, t, 0);
a->sprite->clip = CLIP16(0, 0);
break;
case CHARGE_THROUGH:
a->info.name = "Greasy shield";
a->info.desc = "You glide through obstructions";
t = texturecache_add("Items/Shield.png");
sprite_set_texture(a->sprite, t, 0);
a->sprite->clip = CLIP16(16, 0);
break;
case PUSH_BACK:
a->info.name = "Glove of strength";
a->info.desc = "Your arm is stronger";
t = texturecache_add("Items/Glove.png");
sprite_set_texture(a->sprite, t, 0);
a->sprite->clip = CLIP16(0, 0);
break;
case DAGGER_RECOVERY:
a->info.name = "Forging hammer";
a->info.desc = "Your daggers are more durable";
t = texturecache_add("Items/LongWep.png");
sprite_set_texture(a->sprite, t, 0);
a->sprite->clip = CLIP16(0, 6*16);
break;
case INCREASED_STUN:
a->info.name = "Solid shield";
a->info.desc = "Your shield is harder";
t = texturecache_add("Items/Shield.png");
sprite_set_texture(a->sprite, t, 0);
a->sprite->clip = CLIP16(4*16, 0);
break;
case FEAR_INDUCING:
a->info.name = "Ugly shirt";
a->info.desc = "You look disgusting";
t = texturecache_add("Items/Armor.png");
sprite_set_texture(a->sprite, t, 0);
a->sprite->clip = CLIP16(6*16, 8*16);
break;
default:
break;
@ -107,11 +81,63 @@ artifact_create_random(Player *p, Uint8 level)
return a;
}
Sprite *
artifact_sprite_for(MagicalEffect effect)
{
Sprite *sprite = sprite_create();
Texture *t;
switch (effect) {
case IMPROVED_HEARING:
t = texturecache_add("Items/Potion.png");
sprite_set_texture(sprite, t, 0);
sprite->clip = CLIP16(7*16, 4*16);
break;
case TRAP_AVOIDANCE:
t = texturecache_add("Items/Boot.png");
sprite_set_texture(sprite, t, 0);
sprite->clip = CLIP16(5*16, 0);
break;
case PIERCING_DAGGERS:
t = texturecache_add("Items/Rock.png");
sprite_set_texture(sprite, t, 0);
sprite->clip = CLIP16(0, 0);
break;
case CHARGE_THROUGH:
t = texturecache_add("Items/Shield.png");
sprite_set_texture(sprite, t, 0);
sprite->clip = CLIP16(16, 0);
break;
case PUSH_BACK:
t = texturecache_add("Items/Glove.png");
sprite_set_texture(sprite, t, 0);
sprite->clip = CLIP16(0, 0);
break;
case DAGGER_RECOVERY:
t = texturecache_add("Items/LongWep.png");
sprite_set_texture(sprite, t, 0);
sprite->clip = CLIP16(0, 6*16);
break;
case INCREASED_STUN:
t = texturecache_add("Items/Shield.png");
sprite_set_texture(sprite, t, 0);
sprite->clip = CLIP16(4*16, 0);
break;
case FEAR_INDUCING:
t = texturecache_add("Items/Armor.png");
sprite_set_texture(sprite, t, 0);
sprite->clip = CLIP16(6*16, 8*16);
break;
default:
break;
}
return sprite;
}
Artifact *
artifact_create(MagicalEffect effect)
{
Artifact *a = ec_malloc(sizeof(Artifact));
a->sprite = sprite_create();
a->sprite = artifact_sprite_for(effect);
a->sprite->dim = GAME_DIMENSION;
a->collected = false;
a->level = 1;

View File

@ -45,6 +45,9 @@ typedef struct Artifact {
int level;
} Artifact;
Sprite *
artifact_sprite_for(MagicalEffect);
Artifact *
artifact_create_random(Player*, Uint8 level);

View File

@ -19,6 +19,8 @@
#ifndef DIMENSION_H_
#define DIMENSION_H_
#define DIM(x, y) (Dimension) { x, y }
typedef struct {
unsigned int width;
unsigned int height;

View File

@ -54,6 +54,27 @@
#include "io_util.h"
#include "tooltip.h"
static char *artifacts_tooltip[] = {
"CONGRATULATIONS!",
"",
" You just picked up your first artifact!",
"",
" Your current artifacts and corresponding level are",
" listed next to your skills."
"",
"",
" Artifacts have mystical effects that improve your offensive",
" or defensive advantage in the dungeon. However it is sometimes",
" hard to know what effect an artifact has.",
"",
"",
" Perhaps an experienced dungeoner will know more?",
"",
"",
"Press ESC to close",
NULL
};
static char *skills_tooltip[] = {
"CONGRATULATIONS!",
"",
@ -123,6 +144,7 @@ static Screen *creditsScreen = NULL;
static Screen *scoreScreen = NULL;
static Sprite *new_skill_tooltip = NULL;
static Sprite *howto_tooltip = NULL;
static Sprite *new_artifact_tooltip = NULL;
static unsigned int cLevel = 1;
static float deltaTime = 1.0;
static double renderScale = 1.0;
@ -251,7 +273,7 @@ initGame(void)
gCamera = camera_create(gRenderer);
gRoomMatrix = roommatrix_create();
gGui = gui_create(gCamera);
gSkillBar = skillbar_create(gRenderer);
gSkillBar = skillbar_create(gCamera);
item_builder_init(gRenderer);
gPointer = pointer_create(gRenderer);
particle_engine_init();
@ -452,6 +474,8 @@ resetGame(void)
if (gMap)
map_destroy(gMap);
skillbar_reset(gSkillBar);
particle_engine_clear();
info("Building new map");
@ -480,6 +504,7 @@ init(void)
howto_tooltip = tooltip_create(how_to_play_tooltip, gCamera);
new_skill_tooltip = tooltip_create(skills_tooltip, gCamera);
new_artifact_tooltip = tooltip_create(artifacts_tooltip, gCamera);
gCamera->pos = (Position) { 0, 0 };
@ -600,6 +625,7 @@ populateUpdateData(UpdateData *data, float deltatime)
data->input = &input;
data->gui = gGui;
data->deltatime = deltatime;
data->cam = gCamera;
}
static void
@ -607,6 +633,7 @@ run_game_update(void)
{
static UpdateData updateData;
static unsigned int playerLevel = 1;
static bool artifactTooltipShown = false;
if (gGameState == IN_GAME_MENU)
menu_update(inGameMenu, &input);
@ -621,6 +648,10 @@ run_game_update(void)
if (skillActivated && settings_get()->tooltips_enabled && playerLevel < 5) {
gGui->activeTooltip = new_skill_tooltip;
}
if (!artifactTooltipShown && gPlayer->equipment.hasArtifacts) {
artifactTooltipShown = true;
gGui->activeTooltip = new_artifact_tooltip;
}
map_clear_expired_entities(gMap, gPlayer);
if (gGameState == PLAYING && currentTurn == PLAYER)

View File

@ -450,6 +450,7 @@ player_create(class_t class, Camera *cam)
player->projectiles = linkedlist_create();
player->animationTimer = timer_create();
player->swordAnimation = animation_create(5);
player->equipment.hasArtifacts = false;
build_sword_animation(player, cam->renderer);
@ -624,6 +625,7 @@ player_reset(Player *player)
{
for (size_t i = 0; i < LAST_ARTIFACT_EFFECT; ++i)
player->equipment.artifacts[i].level = 0;
player->equipment.hasArtifacts = false;
while (player->projectiles)
projectile_destroy(linkedlist_pop(&player->projectiles));
@ -677,4 +679,5 @@ player_add_artifact(Player *p, Artifact *a)
gui_log("You pick an ancient %s", ad->name);
gui_log("%s (%u)", ad->desc, ad->level);
p->equipment.hasArtifacts = true;
}

View File

@ -59,6 +59,7 @@ typedef struct ArtifactData {
typedef struct PlayerEquipment {
ArtifactData artifacts[LAST_ARTIFACT_EFFECT];
bool hasArtifacts;
} PlayerEquipment;
typedef struct Player {

View File

@ -53,7 +53,7 @@ load_countdown_sprites(SkillBar *bar)
{
for (int i = 0; i < PLAYER_SKILL_COUNT; ++i) {
Sprite *s = sprite_create();
sprite_load_text_texture(s, "GUI/SDS_8x8.ttf", 0, 16, 0);
sprite_load_text_texture(s, "GUI/SDS_8x8.ttf", 0, 14, 1);
s->fixed = true;
s->pos = (Position) { 8 + (32 * i), 8 };
s->dim = (Dimension) { 16, 16 };
@ -61,47 +61,36 @@ load_countdown_sprites(SkillBar *bar)
}
}
SkillBar *
skillbar_create(SDL_Renderer *renderer)
{
SkillBar *bar = ec_malloc(sizeof(SkillBar));
bar->sprites = linkedlist_create();
bar->activationTimer = timer_create();
bar->skillSparkleTimer = timer_create();
bar->lastActivation = 0;
load_texture(bar, "GUI/GUI0.png", renderer);
load_countdown_sprites(bar);
return bar;
}
bool
skillbar_check_skill_activation(SkillBar *bar, Player *player)
{
for (int i = 0; i < PLAYER_SKILL_COUNT; ++i) {
if (!player->skills[i])
continue;
if (player->skills[i]->levelcap != player->stats.lvl)
continue;
timer_start(bar->skillSparkleTimer);
}
return timer_started(bar->skillSparkleTimer);
}
static void
render_frame(Camera *cam)
static Sprite*
create_frame_sprite(Camera *cam)
{
static SDL_Rect c_top_left = { 1*16, 10*16, 16, 16 };
static SDL_Rect c_top_right = { 3*16, 10*16, 16, 16 };
static SDL_Rect c_center_top = { 2*16, 10*16, 16, 16 };
static SDL_Rect c_center_bottom = { 2*16, 12*16, 16, 16 };
static SDL_Rect c_bottom_left = { 1*16, 12*16, 16, 16 };
static SDL_Rect c_bottom_right = { 3*16, 12*16, 16, 16 };
Sprite *frame = sprite_create();
Texture *texture = texture_create();
texture->dim = (Dimension) { GAME_VIEW_WIDTH, 32 };
frame->textures[0] = texture;
frame->destroyTextures = true;
frame->pos = (Position) { 0, 0 };
frame->dim = (Dimension) { GAME_VIEW_WIDTH, 32 };
frame->fixed = true;
texture_create_blank(texture,
SDL_TEXTUREACCESS_TARGET,
cam->renderer);
SDL_SetRenderTarget(cam->renderer, texture->texture);
SDL_RenderClear(cam->renderer);
Texture *t = texturecache_get("GUI/GUI0.png");
SDL_Rect box = { 0, 0, 16, 16 };
for (unsigned int i = 0; i < MAP_ROOM_WIDTH; ++i) {
// Render skill squares
for (Uint32 i = 0; i < 5; ++i) {
box.x = i*32;
box.y = 0;
texture_render_clip(t, &box, &c_top_left, cam);
@ -114,6 +103,93 @@ render_frame(Camera *cam)
box.y = 16;
texture_render_clip(t, &box, &c_bottom_right, cam);
}
// Render inventory box
box.x = 5 * 32;
box.y = 0;
texture_render_clip(t, &box, &c_top_left, cam);
box.y = 16;
texture_render_clip(t, &box, &c_bottom_left, cam);
box.x = 5 * 32 + 16;
box.y = 0;
texture_render_clip(t, &box, &c_center_top, cam);
box.y = 16;
texture_render_clip(t, &box, &c_center_bottom, cam);
for (Uint32 i = 6; i < MAP_ROOM_WIDTH - 1; ++i) {
box.x = i*32;
box.y = 0;
texture_render_clip(t, &box, &c_center_top, cam);
box.y = 16;
texture_render_clip(t, &box, &c_center_bottom, cam);
box.x = i * 32 + 16;
box.y = 0;
texture_render_clip(t, &box, &c_center_top, cam);
box.y = 16;
texture_render_clip(t, &box, &c_center_bottom, cam);
}
box.x = (MAP_ROOM_WIDTH - 1) * 32;
box.y = 0;
texture_render_clip(t, &box, &c_center_top, cam);
box.y = 16;
texture_render_clip(t, &box, &c_center_bottom, cam);
box.x = (MAP_ROOM_WIDTH - 1) * 32 + 16;
box.y = 0;
texture_render_clip(t, &box, &c_top_right, cam);
box.y = 16;
texture_render_clip(t, &box, &c_bottom_right, cam);
SDL_SetRenderTarget(cam->renderer, NULL);
return frame;
}
SkillBar *
skillbar_create(Camera *cam)
{
SkillBar *bar = ec_malloc(sizeof(SkillBar));
bar->sprites = linkedlist_create();
bar->activationTimer = timer_create();
bar->skillSparkleTimer = timer_create();
bar->lastActivation = 0;
bar->frame = create_frame_sprite(cam);
bar->artifactDisplayOffset = 5 * 32 + 8;
load_texture(bar, "GUI/GUI0.png", cam->renderer);
load_countdown_sprites(bar);
for (Uint32 i = 0; i < LAST_ARTIFACT_EFFECT; ++i) {
bar->artifacts[i].aSprite = artifact_sprite_for(i);
bar->artifacts[i].aSprite->fixed = true;
bar->artifacts[i].lvl = 0;
Sprite *lvlSprite = sprite_create();
lvlSprite->fixed = true;
lvlSprite->dim = DIM(9, 9);
sprite_load_text_texture(lvlSprite, "GUI/SDS_8x8.ttf", 0, 9, 0);
bar->artifacts[i].lvlSprite = lvlSprite;
}
return bar;
}
bool
skillbar_check_skill_activation(SkillBar *bar, Player *player)
{
if (player->stats.lvl == 1)
return false;
for (int i = 0; i < PLAYER_SKILL_COUNT; ++i) {
if (!player->skills[i])
continue;
if (player->skills[i]->levelcap != player->stats.lvl)
continue;
timer_start(bar->skillSparkleTimer);
}
return timer_started(bar->skillSparkleTimer);
}
static void
@ -180,6 +256,18 @@ render_skills(Player *player, Camera *cam)
}
}
static void
render_artifacts(SkillBar *bar, Camera *cam)
{
UNUSED(bar);
for (size_t i = 0; i < LAST_ARTIFACT_EFFECT; ++i) {
if (bar->artifacts[i].lvl == 0)
continue;
sprite_render(bar->artifacts[i].aSprite, cam);
sprite_render(bar->artifacts[i].lvlSprite, cam);
}
}
static void
render_skill_unavailable(SkillBar *bar, Player *player, Camera *cam)
{
@ -245,8 +333,9 @@ render_skill_sparkles(SkillBar *bar, Player *player)
void
skillbar_render(SkillBar *bar, Player *player, Camera *cam)
{
render_frame(cam);
sprite_render(bar->frame, cam);
render_skills(player, cam);
render_artifacts(bar, cam);
render_sprites(bar, cam);
render_skill_unavailable(bar, player, cam);
render_activation_indicator(bar, cam);
@ -280,6 +369,34 @@ skillbar_update(SkillBar *bar, UpdateData *data)
bar->lastActivation = key;
timer_start(bar->activationTimer);
}
for (size_t i = 0; i < LAST_ARTIFACT_EFFECT; ++i) {
if (data->player->equipment.artifacts[i].level == bar->artifacts[i].lvl)
continue;
bar->artifacts[i].lvl = data->player->equipment.artifacts[i].level;
char lvl[4];
m_sprintf(lvl, 4, "%u", bar->artifacts[i].lvl);
texture_load_from_text(bar->artifacts[i].lvlSprite->textures[0],
lvl, C_BLUE, C_WHITE, data->cam->renderer);
// Only update position if this is the first pickup
if (bar->artifacts[i].lvl == 1) {
bar->artifacts[i].lvlSprite->pos.x = bar->artifactDisplayOffset + 12;
bar->artifacts[i].lvlSprite->pos.y = 16;
bar->artifacts[i].aSprite->pos.x = bar->artifactDisplayOffset;
bar->artifacts[i].aSprite->pos.y = 8;
bar->artifactDisplayOffset += 32;
}
}
}
void
skillbar_reset(SkillBar *bar)
{
bar->artifactDisplayOffset = 5 * 32 + 8;
}
void
@ -287,9 +404,14 @@ skillbar_destroy(SkillBar *bar)
{
while (bar->sprites)
sprite_destroy(linkedlist_pop(&bar->sprites));
for (unsigned int i = 0; i < PLAYER_SKILL_COUNT; ++i)
for (Uint32 i = 0; i < PLAYER_SKILL_COUNT; ++i)
if (bar->countdowns[i])
sprite_destroy(bar->countdowns[i]);
for (Uint32 i = 0; i < LAST_ARTIFACT_EFFECT; ++i) {
sprite_destroy(bar->artifacts[i].aSprite);
sprite_destroy(bar->artifacts[i].lvlSprite);
}
sprite_destroy(bar->frame);
timer_destroy(bar->activationTimer);
timer_destroy(bar->skillSparkleTimer);
free(bar);

View File

@ -28,16 +28,25 @@
struct UpdateData;
typedef struct SkillBar_t {
typedef struct ArtifactDisplay {
Sprite *aSprite;
Sprite *lvlSprite;
Uint32 lvl;
} ArtifactDisplay;
typedef struct SkillBar {
LinkedList *sprites;
ArtifactDisplay artifacts[LAST_ARTIFACT_EFFECT];
Uint32 artifactDisplayOffset;
Sprite *countdowns[PLAYER_SKILL_COUNT];
Sprite *frame;
Timer *activationTimer;
Timer *skillSparkleTimer;
unsigned int lastActivation;
Uint32 lastActivation;
} SkillBar;
SkillBar *
skillbar_create(SDL_Renderer*);
skillbar_create(Camera*);
bool
skillbar_check_skill_activation(SkillBar*, Player*);
@ -48,6 +57,9 @@ skillbar_render(SkillBar*, Player*, Camera*);
void
skillbar_update(SkillBar*, struct UpdateData*);
void
skillbar_reset(SkillBar*);
void
skillbar_destroy(SkillBar*);

View File

@ -23,12 +23,14 @@
#include "map.h"
#include "roommatrix.h"
#include "gui.h"
#include "camera.h"
typedef struct UpdateData {
Player *player;
Map *map;
RoomMatrix *matrix;
Gui *gui;
Camera *cam;
Input *input;
float deltatime;
} UpdateData;