Implemented the sword swing effect.
This adds the animation type for future use. Not super happy with the animation png. Will look over it in the future.
This commit is contained in:
parent
79b0869974
commit
988d6c5cac
|
@ -171,6 +171,7 @@ add_executable(breakhack
|
||||||
src/db
|
src/db
|
||||||
src/settings
|
src/settings
|
||||||
src/actiontextbuilder
|
src/actiontextbuilder
|
||||||
|
src/animation
|
||||||
)
|
)
|
||||||
|
|
||||||
# Sqlite has some warnings that I we don't need to see
|
# Sqlite has some warnings that I we don't need to see
|
||||||
|
|
Before Width: | Height: | Size: 297 B After Width: | Height: | Size: 297 B |
|
@ -0,0 +1,117 @@
|
||||||
|
/*
|
||||||
|
* 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/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "animation.h"
|
||||||
|
#include "timer.h"
|
||||||
|
#include "camera.h"
|
||||||
|
#include "sprite.h"
|
||||||
|
#include "util.h"
|
||||||
|
|
||||||
|
Animation *
|
||||||
|
animation_create(unsigned int clipCount)
|
||||||
|
{
|
||||||
|
Animation *animation = ec_malloc(sizeof(Animation)
|
||||||
|
+ clipCount * sizeof(AnimationClip));
|
||||||
|
animation->clipTimer = timer_create();
|
||||||
|
animation->clipCount = clipCount;
|
||||||
|
animation->currentClip = 0;
|
||||||
|
animation->loop = true;
|
||||||
|
animation->running = false;
|
||||||
|
animation->sprite = sprite_create();
|
||||||
|
return animation;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
animation_load_texture(Animation *animation, const char *path, SDL_Renderer *renderer)
|
||||||
|
{
|
||||||
|
sprite_load_texture(animation->sprite, path, 0, renderer);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
animation_update(Animation *animation)
|
||||||
|
{
|
||||||
|
if (!animation->running) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!timer_started(animation->clipTimer)) {
|
||||||
|
timer_start(animation->clipTimer);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (timer_get_ticks(animation->clipTimer)
|
||||||
|
> animation->clips[animation->currentClip].renderTime)
|
||||||
|
{
|
||||||
|
animation->currentClip++;
|
||||||
|
if (animation->currentClip >= animation->clipCount) {
|
||||||
|
animation->currentClip = 0;
|
||||||
|
if (!animation->loop) {
|
||||||
|
animation_stop(animation);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
timer_start(animation->clipTimer);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
animation->sprite->clip = (SDL_Rect) {
|
||||||
|
animation->clips[animation->currentClip].x,
|
||||||
|
animation->clips[animation->currentClip].y,
|
||||||
|
animation->clips[animation->currentClip].w,
|
||||||
|
animation->clips[animation->currentClip].h
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
animation_render(Animation *animation, Camera *camera)
|
||||||
|
{
|
||||||
|
if (!animation->running) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
sprite_render(animation->sprite, camera);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
animation_set_frames(Animation *animation, AnimationClip clips[])
|
||||||
|
{
|
||||||
|
for (size_t i = 0; i < animation->clipCount; i++) {
|
||||||
|
animation->clips[i] = clips[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
animation_run(Animation *a)
|
||||||
|
{
|
||||||
|
a->running = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
animation_stop(Animation *a)
|
||||||
|
{
|
||||||
|
a->running = false;
|
||||||
|
a->currentClip = 0;
|
||||||
|
timer_stop(a->clipTimer);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
animation_destroy(Animation *animation)
|
||||||
|
{
|
||||||
|
timer_destroy(animation->clipTimer);
|
||||||
|
sprite_destroy(animation->sprite);
|
||||||
|
free(animation);
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,75 @@
|
||||||
|
/*
|
||||||
|
* 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/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _ANIMATION_H
|
||||||
|
#define _ANIMATION_H
|
||||||
|
|
||||||
|
#include <SDL.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
|
||||||
|
typedef struct Timer Timer;
|
||||||
|
typedef struct Camera Camera;
|
||||||
|
typedef struct Sprite Sprite;
|
||||||
|
|
||||||
|
typedef struct AnimationClip
|
||||||
|
{
|
||||||
|
unsigned int x;
|
||||||
|
unsigned int y;
|
||||||
|
unsigned int w;
|
||||||
|
unsigned int h;
|
||||||
|
unsigned int renderTime;
|
||||||
|
} AnimationClip;
|
||||||
|
|
||||||
|
typedef struct Animation
|
||||||
|
{
|
||||||
|
Sprite *sprite;
|
||||||
|
Timer *clipTimer;
|
||||||
|
unsigned int currentClip;
|
||||||
|
bool loop;
|
||||||
|
unsigned int clipCount;
|
||||||
|
bool running;
|
||||||
|
AnimationClip clips[];
|
||||||
|
} Animation;
|
||||||
|
|
||||||
|
Animation*
|
||||||
|
animation_create(unsigned int clipCount);
|
||||||
|
|
||||||
|
void
|
||||||
|
animation_load_texture(Animation *, const char *path, SDL_Renderer*);
|
||||||
|
|
||||||
|
void
|
||||||
|
animation_set_frames(Animation*, AnimationClip clips[]);
|
||||||
|
|
||||||
|
void
|
||||||
|
animation_run(Animation*);
|
||||||
|
|
||||||
|
void
|
||||||
|
animation_update(Animation*);
|
||||||
|
|
||||||
|
void
|
||||||
|
animation_render(Animation*, Camera*);
|
||||||
|
|
||||||
|
void
|
||||||
|
animation_stop(Animation*);
|
||||||
|
|
||||||
|
void
|
||||||
|
animation_destroy(Animation*);
|
||||||
|
|
||||||
|
#endif // _ANIMATION_H
|
||||||
|
|
||||||
|
|
|
@ -25,7 +25,7 @@
|
||||||
#include "timer.h"
|
#include "timer.h"
|
||||||
#include "vector2d.h"
|
#include "vector2d.h"
|
||||||
|
|
||||||
typedef struct {
|
typedef struct Camera {
|
||||||
Position pos;
|
Position pos;
|
||||||
Position basePos;
|
Position basePos;
|
||||||
Vector2d velocity;
|
Vector2d velocity;
|
||||||
|
|
|
@ -516,6 +516,8 @@ run_game(void)
|
||||||
|
|
||||||
map_render_top_layer(gMap, gCamera);
|
map_render_top_layer(gMap, gCamera);
|
||||||
|
|
||||||
|
player_render_toplayer(gPlayer, gCamera);
|
||||||
|
|
||||||
if (gPlayer->class == MAGE || gPlayer->class == PALADIN)
|
if (gPlayer->class == MAGE || gPlayer->class == PALADIN)
|
||||||
roommatrix_render_mouse_square(gRoomMatrix, gCamera);
|
roommatrix_render_mouse_square(gRoomMatrix, gCamera);
|
||||||
|
|
||||||
|
|
54
src/player.c
54
src/player.c
|
@ -33,6 +33,7 @@
|
||||||
#include "texturecache.h"
|
#include "texturecache.h"
|
||||||
#include "vector2d.h"
|
#include "vector2d.h"
|
||||||
#include "actiontextbuilder.h"
|
#include "actiontextbuilder.h"
|
||||||
|
#include "animation.h"
|
||||||
|
|
||||||
#define ENGINEER_STATS { 12, 12, 5, 7, 2, 2, 1 }
|
#define ENGINEER_STATS { 12, 12, 5, 7, 2, 2, 1 }
|
||||||
#define MAGE_STATS { 12, 12, 5, 7, 1, 2, 1 }
|
#define MAGE_STATS { 12, 12, 5, 7, 1, 2, 1 }
|
||||||
|
@ -133,6 +134,8 @@ has_collided(Player *player, RoomMatrix *matrix, Vector2d direction)
|
||||||
|
|
||||||
monster_hit(space->monster, hit);
|
monster_hit(space->monster, hit);
|
||||||
|
|
||||||
|
animation_run(player->swordAnimation);
|
||||||
|
|
||||||
if (hit > 0) {
|
if (hit > 0) {
|
||||||
gui_log("You hit %s for %u damage",
|
gui_log("You hit %s for %u damage",
|
||||||
space->monster->lclabel, hit);
|
space->monster->lclabel, hit);
|
||||||
|
@ -246,6 +249,27 @@ handle_next_move(UpdateData *data)
|
||||||
++step;
|
++step;
|
||||||
step = step % 4;
|
step = step % 4;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!vector2d_equals(nextDir, VECTOR2D_NODIR))
|
||||||
|
player->swordAnimation->sprite->pos = player->sprite->pos;
|
||||||
|
|
||||||
|
if (vector2d_equals(nextDir, VECTOR2D_UP)) {
|
||||||
|
player->swordAnimation->sprite->pos.y -= 32;
|
||||||
|
player->swordAnimation->sprite->angle = -90;
|
||||||
|
player->swordAnimation->sprite->flip = SDL_FLIP_NONE;
|
||||||
|
} else if (vector2d_equals(nextDir, VECTOR2D_DOWN)) {
|
||||||
|
player->swordAnimation->sprite->pos.y += 32;
|
||||||
|
player->swordAnimation->sprite->angle = 90;
|
||||||
|
player->swordAnimation->sprite->flip = SDL_FLIP_NONE;
|
||||||
|
} else if (vector2d_equals(nextDir, VECTOR2D_LEFT)) {
|
||||||
|
player->swordAnimation->sprite->pos.x -= 32;
|
||||||
|
player->swordAnimation->sprite->angle = 0;
|
||||||
|
player->swordAnimation->sprite->flip = SDL_FLIP_HORIZONTAL;
|
||||||
|
} else if (vector2d_equals(nextDir, VECTOR2D_RIGHT)) {
|
||||||
|
player->swordAnimation->sprite->pos.x += 32;
|
||||||
|
player->swordAnimation->sprite->angle = 0;
|
||||||
|
player->swordAnimation->sprite->flip = SDL_FLIP_NONE;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
@ -327,6 +351,24 @@ check_skill_trigger(UpdateData *data)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
build_sword_animation(Player *p, SDL_Renderer *renderer)
|
||||||
|
{
|
||||||
|
animation_load_texture(p->swordAnimation, "Extras/SwordSwing.png", renderer);
|
||||||
|
animation_set_frames(p->swordAnimation, (AnimationClip[]) {
|
||||||
|
{ 0, 0, 16, 16, 20 },
|
||||||
|
{ 16, 0, 16, 16, 20 },
|
||||||
|
{ 32, 0, 16, 16, 20 },
|
||||||
|
{ 48, 0, 16, 16, 20 },
|
||||||
|
{ 64, 0, 16, 16, 20 }
|
||||||
|
});
|
||||||
|
|
||||||
|
p->swordAnimation->loop = false;
|
||||||
|
p->swordAnimation->sprite->dim = GAME_DIMENSION;
|
||||||
|
p->swordAnimation->sprite->clip = (SDL_Rect) { 0, 0, 16, 16 };
|
||||||
|
p->swordAnimation->sprite->rotationPoint = (SDL_Point) { 16, 16 };
|
||||||
|
}
|
||||||
|
|
||||||
Player*
|
Player*
|
||||||
player_create(class_t class, SDL_Renderer *renderer)
|
player_create(class_t class, SDL_Renderer *renderer)
|
||||||
{
|
{
|
||||||
|
@ -349,6 +391,9 @@ player_create(class_t class, SDL_Renderer *renderer)
|
||||||
player->state = ALIVE;
|
player->state = ALIVE;
|
||||||
player->projectiles = linkedlist_create();
|
player->projectiles = linkedlist_create();
|
||||||
player->animationTimer = timer_create();
|
player->animationTimer = timer_create();
|
||||||
|
player->swordAnimation = animation_create(5);
|
||||||
|
|
||||||
|
build_sword_animation(player, renderer);
|
||||||
|
|
||||||
for (size_t i = 0; i < PLAYER_SKILL_COUNT; ++i) {
|
for (size_t i = 0; i < PLAYER_SKILL_COUNT; ++i) {
|
||||||
player->skills[i] = NULL;
|
player->skills[i] = NULL;
|
||||||
|
@ -451,6 +496,12 @@ player_render(Player *player, Camera *cam)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
player_render_toplayer(Player *player, Camera *camera)
|
||||||
|
{
|
||||||
|
animation_render(player->swordAnimation, camera);
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
player_reset_steps(Player *p)
|
player_reset_steps(Player *p)
|
||||||
{
|
{
|
||||||
|
@ -503,6 +554,8 @@ void player_update(UpdateData *data)
|
||||||
|
|
||||||
linkedlist_destroy(&player->projectiles);
|
linkedlist_destroy(&player->projectiles);
|
||||||
player->projectiles = remaining;
|
player->projectiles = remaining;
|
||||||
|
|
||||||
|
animation_update(player->swordAnimation);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -511,6 +564,7 @@ player_destroy(Player *player)
|
||||||
if (player->sprite)
|
if (player->sprite)
|
||||||
sprite_destroy(player->sprite);
|
sprite_destroy(player->sprite);
|
||||||
|
|
||||||
|
animation_destroy(player->swordAnimation);
|
||||||
timer_destroy(player->animationTimer);
|
timer_destroy(player->animationTimer);
|
||||||
|
|
||||||
for (size_t i = 0; i < PLAYER_SKILL_COUNT; ++i) {
|
for (size_t i = 0; i < PLAYER_SKILL_COUNT; ++i) {
|
||||||
|
|
|
@ -31,7 +31,8 @@
|
||||||
#define PLAYER_SKILL_COUNT 5
|
#define PLAYER_SKILL_COUNT 5
|
||||||
|
|
||||||
// Foward declare
|
// Foward declare
|
||||||
struct UpdateData;
|
typedef struct UpdateData UpdateData;
|
||||||
|
typedef struct Animation Animation;
|
||||||
|
|
||||||
typedef enum PlayerClass { ENGINEER, MAGE, PALADIN, ROGUE, WARRIOR } class_t;
|
typedef enum PlayerClass { ENGINEER, MAGE, PALADIN, ROGUE, WARRIOR } class_t;
|
||||||
typedef enum PlayerState { ALIVE, DEAD, FALLING } state_t;
|
typedef enum PlayerState { ALIVE, DEAD, FALLING } state_t;
|
||||||
|
@ -64,6 +65,7 @@ typedef struct Player_t {
|
||||||
state_t state;
|
state_t state;
|
||||||
Skill *skills[PLAYER_SKILL_COUNT];
|
Skill *skills[PLAYER_SKILL_COUNT];
|
||||||
Timer *animationTimer;
|
Timer *animationTimer;
|
||||||
|
Animation *swordAnimation;
|
||||||
} Player;
|
} Player;
|
||||||
|
|
||||||
Player*
|
Player*
|
||||||
|
@ -90,6 +92,9 @@ player_update(struct UpdateData *);
|
||||||
void
|
void
|
||||||
player_render(Player*, Camera*);
|
player_render(Player*, Camera*);
|
||||||
|
|
||||||
|
void
|
||||||
|
player_render_toplayer(Player*, Camera*);
|
||||||
|
|
||||||
void
|
void
|
||||||
player_destroy(Player*);
|
player_destroy(Player*);
|
||||||
|
|
||||||
|
|
|
@ -26,7 +26,7 @@
|
||||||
#include "map_room_modifiers.h"
|
#include "map_room_modifiers.h"
|
||||||
#include "input.h"
|
#include "input.h"
|
||||||
|
|
||||||
typedef struct Sprite_t Sprite;
|
typedef struct Sprite Sprite;
|
||||||
typedef struct Map_t Map;
|
typedef struct Map_t Map;
|
||||||
typedef struct Monster_t Monster;
|
typedef struct Monster_t Monster;
|
||||||
typedef struct Player_t Player;
|
typedef struct Player_t Player;
|
||||||
|
|
|
@ -51,7 +51,7 @@ sprite_create(void)
|
||||||
|
|
||||||
void
|
void
|
||||||
sprite_load_texture(Sprite *sprite,
|
sprite_load_texture(Sprite *sprite,
|
||||||
char *path,
|
const char *path,
|
||||||
int index,
|
int index,
|
||||||
SDL_Renderer *renderer)
|
SDL_Renderer *renderer)
|
||||||
{
|
{
|
||||||
|
@ -68,7 +68,7 @@ sprite_load_texture(Sprite *sprite,
|
||||||
sprite->destroyTextures = true;
|
sprite->destroyTextures = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void sprite_load_text_texture(Sprite *sprite, char * path, int index, int size, int outline)
|
void sprite_load_text_texture(Sprite *sprite, const char * path, int index, int size, int outline)
|
||||||
{
|
{
|
||||||
if (index > 1)
|
if (index > 1)
|
||||||
fatal("in sprite_load_texture() index out of bounds");
|
fatal("in sprite_load_texture() index out of bounds");
|
||||||
|
@ -122,7 +122,7 @@ sprite_render(Sprite *s, Camera *cam)
|
||||||
cameraPos.x, cameraPos.y, s->dim.width, s->dim.height
|
cameraPos.x, cameraPos.y, s->dim.width, s->dim.height
|
||||||
};
|
};
|
||||||
|
|
||||||
if ((s->clip.w && s->clip.h) || s->angle != 0 || s->flip != SDL_FLIP_NONE) {
|
if (s->angle != 0 || s->flip != SDL_FLIP_NONE) {
|
||||||
texture_render_clip_ex(s->textures[s->texture_index],
|
texture_render_clip_ex(s->textures[s->texture_index],
|
||||||
&box,
|
&box,
|
||||||
&s->clip,
|
&s->clip,
|
||||||
|
|
|
@ -27,7 +27,7 @@
|
||||||
#include "roommatrix.h"
|
#include "roommatrix.h"
|
||||||
#include "timer.h"
|
#include "timer.h"
|
||||||
|
|
||||||
typedef struct Sprite_t {
|
typedef struct Sprite {
|
||||||
Texture* textures[2];
|
Texture* textures[2];
|
||||||
SDL_Rect clip;
|
SDL_Rect clip;
|
||||||
bool destroyTextures;
|
bool destroyTextures;
|
||||||
|
@ -46,9 +46,9 @@ typedef struct Sprite_t {
|
||||||
|
|
||||||
Sprite* sprite_create(void);
|
Sprite* sprite_create(void);
|
||||||
|
|
||||||
void sprite_load_texture(Sprite *, char *path, int index, SDL_Renderer *);
|
void sprite_load_texture(Sprite *, const char *path, int index, SDL_Renderer *);
|
||||||
|
|
||||||
void sprite_load_text_texture(Sprite *, char *path, int index, int size, int outline);
|
void sprite_load_text_texture(Sprite *, const char *path, int index, int size, int outline);
|
||||||
|
|
||||||
void sprite_set_texture(Sprite *, Texture *, int index);
|
void sprite_set_texture(Sprite *, Texture *, int index);
|
||||||
|
|
||||||
|
|
|
@ -21,7 +21,7 @@
|
||||||
|
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
|
|
||||||
typedef struct {
|
typedef struct Timer {
|
||||||
unsigned int startTime;
|
unsigned int startTime;
|
||||||
} Timer;
|
} Timer;
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue