From c360aa75ee6fdc4affe6f5cd2242d4770bc83e3a Mon Sep 17 00:00:00 2001 From: Linus Probert Date: Sat, 10 Mar 2018 22:04:03 +0100 Subject: [PATCH] Added dagger throw skill There are still some quirks that could need some love surrounding this skill. Check the reset countdown for example. --- src/defines.h | 3 +- src/main.c | 2 +- src/player.c | 7 +++-- src/player.h | 2 +- src/projectile.c | 75 ++++++++++++++++++++++++++++++++++++++++++++++-- src/projectile.h | 15 ++++++++-- src/skill.c | 42 +++++++++++++++++++++++++++ src/skill.h | 1 + src/sprite.c | 7 +++-- src/sprite.h | 1 + 10 files changed, 143 insertions(+), 12 deletions(-) diff --git a/src/defines.h b/src/defines.h index c96dfca..b5f938a 100644 --- a/src/defines.h +++ b/src/defines.h @@ -50,7 +50,8 @@ /* Quality of life stuff */ #define DEFAULT_DIMENSION (Dimension) { 16, 16 } #define GAME_DIMENSION (Dimension) { TILE_DIMENSION, TILE_DIMENSION } -#define CLIP16(x, y) (SDL_Rect) { x, y, 16, 16 } +#define CLIP16(x, y) (SDL_Rect) { x, y, 16, 16 } +#define CLIP32(x, y) (SDL_Rect) { x, y, 32, 32 } /* Windows and compile crap */ #ifdef _WIN32 diff --git a/src/main.c b/src/main.c index ab3a7b8..aca1537 100644 --- a/src/main.c +++ b/src/main.c @@ -461,7 +461,7 @@ run_game(void) gui_update_player_stats(gGui, gPlayer, gMap, gRenderer); particle_engine_update(deltaTime); - player_update(gPlayer, deltaTime); + player_update(gPlayer, gRoomMatrix, deltaTime); roommatrix_update_with_player(gRoomMatrix, gPlayer); if (currentTurn == PLAYER) { diff --git a/src/player.c b/src/player.c index 5e1238c..32d3b8e 100644 --- a/src/player.c +++ b/src/player.c @@ -31,6 +31,7 @@ #include "random.h" #include "projectile.h" #include "texturecache.h" +#include "vector2d.h" #define ENGINEER_STATS { 12, 12, 5, 7, 2, 2, 1 } #define MAGE_STATS { 12, 12, 5, 7, 1, 2, 1 } @@ -402,6 +403,7 @@ player_create(class_t class, SDL_Renderer *renderer) player->stats = (Stats) WARRIOR_STATS; player->skills[0] = skill_create(FLURRY); player->skills[1] = skill_create(CHARGE); + player->skills[2] = skill_create(DAGGER_THROW); break; } @@ -502,7 +504,7 @@ player_reset_steps(Player *p) player_print(p); } -void player_update(Player *player, float deltatime) +void player_update(Player *player, RoomMatrix *rm, float deltatime) { if (!player->projectiles) return; @@ -514,7 +516,7 @@ void player_update(Player *player, float deltatime) while (current) { Projectile *p = current->data; - projectile_update(p, deltatime); + projectile_update(p, player, rm, deltatime); if (!p->alive) { if (last == NULL) player->projectiles = current->next; @@ -528,6 +530,7 @@ void player_update(Player *player, float deltatime) current->next = NULL; linkedlist_destroy(¤t); current = next; + action_spent(player); } else { last = current; current = current->next; diff --git a/src/player.h b/src/player.h index 8049fa6..f8ca671 100644 --- a/src/player.h +++ b/src/player.h @@ -77,7 +77,7 @@ void player_reset_steps(Player*); void -player_update(Player*, float deltatime); +player_update(Player*, RoomMatrix*, float deltatime); void player_render(Player*, Camera*); diff --git a/src/projectile.c b/src/projectile.c index 9ddfa1d..a85084a 100644 --- a/src/projectile.c +++ b/src/projectile.c @@ -1,5 +1,52 @@ +/* + * BreakHack - A dungeone crawler RPG + * Copyright (C) 2018 Linus Probert + * + * 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 . + */ + #include "projectile.h" #include "util.h" +#include "texturecache.h" +#include "player.h" +#include "monster.h" +#include "mixer.h" + +static void +onDaggerRender(Sprite *s) +{ + if (!timer_started(s->renderTimer)) + timer_start(s->renderTimer); + + if (timer_get_ticks(s->renderTimer) > 100) { + timer_start(s->renderTimer); + s->clip.x += 16; + s->clip.x = s->clip.x % 64; + } +} + +Projectile * +projectile_dagger_create(void) +{ + Projectile *p = projectile_create(); + sprite_set_texture(p->sprite, texturecache_add("Extras/Dagger.png"), 0); + p->sprite->onRender = onDaggerRender; + p->sprite->animate = false; + p->sprite->clip = CLIP16(0, 0); + p->sprite->dim = (Dimension) { 32, 32 }; + return p; +} Projectile * projectile_create(void) @@ -9,23 +56,47 @@ projectile_create(void) p->velocity = VECTOR2D_NODIR; p->alive = true; p->lifetime = timer_create(); + p->onRender = NULL; timer_start(p->lifetime); return p; } void -projectile_update(Projectile *p, float deltatime) +projectile_update(Projectile *p, Player *player, RoomMatrix *rm, float deltatime) { p->sprite->pos.x += (int) (p->velocity.x * deltatime); p->sprite->pos.y += (int) (p->velocity.y * deltatime); if (timer_get_ticks(p->lifetime) > 2000) p->alive = false; + + Position collisionPos = p->sprite->pos; + if (p->velocity.x > 0) + collisionPos.x += TILE_DIMENSION; + else if(p->velocity.y > 0) + collisionPos.y += TILE_DIMENSION; + + Position roomPos = position_to_matrix_coords(&collisionPos); + RoomSpace *space = &rm->spaces[roomPos.x][roomPos.y]; + if (!space->occupied) + return; + + if (space->player) + return; + + if (space->monster) { + Uint32 dmg = stats_fight(&player->stats, &space->monster->stats); + monster_hit(space->monster, dmg); + mixer_play_effect(SWORD_HIT); + } + p->alive = false; } void projectile_render(Projectile *p, Camera *cam) { + if (p->onRender) + p->onRender(p); sprite_render(p->sprite, cam); } @@ -35,4 +106,4 @@ projectile_destroy(Projectile *p) sprite_destroy(p->sprite); timer_destroy(p->lifetime); free(p); -} \ No newline at end of file +} diff --git a/src/projectile.h b/src/projectile.h index c78b00b..41c5895 100644 --- a/src/projectile.h +++ b/src/projectile.h @@ -24,19 +24,28 @@ #include "camera.h" #include "vector2d.h" #include "timer.h" +#include "roommatrix.h" -typedef struct Prjectile_t { +// Forward declare +struct Player_t; + +typedef struct Projectile_t { Sprite *sprite; Vector2d velocity; Timer *lifetime; bool alive; + Timer *animation_timer; + void (*onRender)(struct Projectile_t*); } Projectile; +Projectile * +projectile_dagger_create(void); + Projectile * projectile_create(void); void -projectile_update(Projectile*, float deltatime); +projectile_update(Projectile*, struct Player_t*, RoomMatrix *rm, float deltatime); void projectile_render(Projectile*, Camera*); @@ -44,4 +53,4 @@ projectile_render(Projectile*, Camera*); void projectile_destroy(Projectile*); -#endif // PROJECTILE_H_ \ No newline at end of file +#endif // PROJECTILE_H_ diff --git a/src/skill.c b/src/skill.c index 663c6f2..a533b09 100644 --- a/src/skill.c +++ b/src/skill.c @@ -29,6 +29,8 @@ #include "gui.h" #include "random.h" #include "particle_engine.h" +#include "projectile.h" +#include "linkedlist.h" static void set_player_clip_for_direction(Player *player, Vector2d *direction) @@ -120,6 +122,44 @@ create_flurry(void) return skill; } +static bool +skill_throw_dagger(Skill *skill, SkillData *data) +{ + UNUSED(skill); + UNUSED(data); + + Projectile *p = projectile_dagger_create(); + if (vector2d_equals(VECTOR2D_UP, data->direction)) + p->velocity = (Vector2d) { 0, -300 }; + else if (vector2d_equals(VECTOR2D_DOWN, data->direction)) + p->velocity = (Vector2d) { 0, 300 }; + else if (vector2d_equals(VECTOR2D_RIGHT, data->direction)) + p->velocity = (Vector2d) { 300, 0 }; + else + p->velocity = (Vector2d) { -300, 0 }; + + p->sprite->pos = data->player->sprite->pos; + linkedlist_append(&data->player->projectiles, p); + + return true; +} + +static Skill * +create_throw_dagger(void) +{ + Texture *t = texturecache_add("Extras/Dagger.png"); + Sprite *s = sprite_create(); + sprite_set_texture(s, t, 0); + s->dim = DEFAULT_DIMENSION; + s->clip = CLIP16(0, 0); + s->fixed = true; + Skill *skill = create_default("Throw dagger", s); + skill->instantUse = false; + skill->use = skill_throw_dagger; + skill->actionRequired = false; + return skill; +} + static bool skill_sip_health(Skill *skill, SkillData *data) { @@ -238,6 +278,8 @@ skill_create(enum SkillType t) return create_sip_health(); case CHARGE: return create_charge(); + case DAGGER_THROW: + return create_throw_dagger(); default: fatal("Unknown SkillType %u", (unsigned int) t); return NULL; diff --git a/src/skill.h b/src/skill.h index 0e1ae7b..81325a2 100644 --- a/src/skill.h +++ b/src/skill.h @@ -30,6 +30,7 @@ struct Player_t; enum SkillType { FLURRY, CHARGE, + DAGGER_THROW, SIP_HEALTH }; diff --git a/src/sprite.c b/src/sprite.c index 8a63a85..6c336a9 100644 --- a/src/sprite.c +++ b/src/sprite.c @@ -35,6 +35,7 @@ sprite_create_default(void) s->fixed = false; s->animate = true; s->hidden = false; + s->onRender = NULL; return s; } @@ -90,11 +91,13 @@ sprite_set_texture(Sprite *s, Texture *t, int index) s->textures[index] = t; } -void sprite_render(Sprite *s, Camera *cam) +void +sprite_render(Sprite *s, Camera *cam) { if (s->hidden) return; - + if (s->onRender) + s->onRender(s); if (s->textures[1] && s->animate) { if (!timer_started(s->renderTimer)) timer_start(s->renderTimer); diff --git a/src/sprite.h b/src/sprite.h index 50c6eca..0dde7d1 100644 --- a/src/sprite.h +++ b/src/sprite.h @@ -38,6 +38,7 @@ typedef struct Sprite_t { bool fixed; bool animate; bool hidden; + void (*onRender)(Sprite*); } Sprite; Sprite* sprite_create(void);