prepare more attacks (skills/combos)

This commit is contained in:
Lephenixnoir 2021-08-16 13:31:28 +02:00
parent 89ee5234ea
commit 35718b93ac
Signed by: Lephenixnoir
GPG Key ID: 1BBA026E13FC0495
10 changed files with 93 additions and 52 deletions

View File

@ -57,6 +57,7 @@ set(ASSETS
assets-cg/skills/swing_right.png
assets-cg/skills/swing_down.png
assets-cg/skills/swing_left.png
assets-cg/skills/impale_right.png
assets-cg/skills/hit.png
assets-cg/skills/teleport.png
# Enemies: Slime

View File

@ -7,6 +7,9 @@
swing_*.png:
frame_duration: 30, 60, 30, 30, 30, 60, 30
impale_*.png:
frame_duration: 60, 60, 60, 60, 60
hit.png:
frame_duration: 60, 90, 90, 60, 90

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 181 B

View File

@ -17,6 +17,10 @@ DIRECTIONAL_ANIM(anim_player_attack);
DIRECTIONAL_ANIM(anim_player_damage);
DIRECTIONAL_ANIM(anim_swing);
extern anim_frame_t anim_impale_right[];
anim_frame_t *anim_impale[4] = {
anim_impale_right, anim_impale_right, anim_impale_right, anim_impale_right };
/* Animation functions. */
fixed_t (anim_duration)(anim_frame_t const *first_frame)

View File

@ -72,3 +72,4 @@ extern anim_frame_t *anim_player_idle[4];
extern anim_frame_t *anim_player_attack[4];
extern anim_frame_t *anim_player_damage[4];
extern anim_frame_t *anim_swing[4];
extern anim_frame_t *anim_impale[4];

View File

@ -177,6 +177,48 @@ effect_area_t *effect_area_new(uint16_t type)
return ea;
}
effect_area_t *effect_area_new_attack(uint16_t type, entity_t *e, int facing)
{
effect_area_t *area = effect_area_new(type);
if(!area) return NULL;
frect_t hitbox = { 0 };
fixed_t distance = fix(0.75);
fpoint_t dir = fdir(facing);
anim_frame_t *anim = NULL;
if(type == EFFECT_ATTACK_HIT) {
anim = anim_hit;
hitbox = (frect_t){ -fix(4)/16, fix(3)/16, -fix(4)/16, fix(3)/16 };
}
else if(type == EFFECT_ATTACK_SLASH) {
anim = anim_swing[facing];
hitbox = (frect_t){ -fix(10)/16, fix(10)/16, -fix(4)/16, fix(4)/16 };
}
else if(type == EFFECT_ATTACK_IMPALE) {
anim = anim_impale[facing];
hitbox = (frect_t){ -fix(4)/16, fix(4)/16, -fix(5)/16, fix(5)/16 };
}
area->sprite = rect_rotate(hitbox, UP, facing);
area->anchor = rect_center(entity_sprite(e));
area->anchor.x += fmul(distance, dir.x);
area->anchor.y += fmul(distance, dir.y);
area->lifetime = anim_duration(anim);
area->repeat_delay = 0;
area->origin = e;
if(type == EFFECT_ATTACK_HIT
|| type == EFFECT_ATTACK_SLASH
|| type == EFFECT_ATTACK_IMPALE) {
area->data.slash.strength = e->ATK;
area->data.slash.dir = facing;
}
effect_area_set_anim(area, anim);
return area;
}
void effect_area_set_anim(effect_area_t *ea, anim_frame_t *frame)
{
ea->anim.frame = frame;
@ -236,9 +278,9 @@ void effect_area_apply(game_t *game, effect_area_t *ea, entity_t *e)
if(rec && ea->repeat_delay == 0) return;
if(rec && ea->lifetime > rec->lifetime - ea->repeat_delay) return;
if(ea->type == EFFECT_HIT)
was_hit = slash_hit_apply(game, ea, e);
else if(ea->type == EFFECT_SLASH)
if(ea->type == EFFECT_ATTACK_HIT
|| ea->type == EFFECT_ATTACK_SLASH
|| ea->type == EFFECT_ATTACK_IMPALE)
was_hit = slash_hit_apply(game, ea, e);
if(!was_hit) return;

View File

@ -42,6 +42,14 @@ typedef struct {
} entity_movement_t;
typedef struct {
/* Number of hits in the main combo (TODO: delegate to weapon?) */
uint8_t combo_length;
/* Next hit to be dealt */
uint8_t combo_next;
} entity_player_t;
/* Alive agents with hitboxes and movement control */
typedef struct {
/* Map hitbox, centered around (movement.x, movement.y) */
@ -52,6 +60,8 @@ typedef struct {
entity_movement_t movement;
/* Cinematic parameters */
entity_movement_params_t const *movement_params;
/* Player-only parameters */
entity_player_t const *player;
/* Animated image and state */
anim_state_t anim;
/* Current attack's effect area */
@ -107,9 +117,11 @@ int entity_damage(entity_t *e, int base_damage);
enum {
/* Bare-hand fist/close-contact attack */
EFFECT_HIT,
EFFECT_ATTACK_HIT,
/* Normal attack by a slashing weapon */
EFFECT_SLASH,
EFFECT_ATTACK_SLASH,
/* Impaling attack using a slashing weapon */
EFFECT_ATTACK_IMPALE,
/* Monster spawning */
EFFECT_SPAWN,
};
@ -156,6 +168,10 @@ typedef struct effect_area {
* sprite, anchor, lifetime, anim, repeat_delay, and data should be set. */
effect_area_t *effect_area_new(uint16_t type);
/* Create an effect area for a particular attack
All additional parameters are set by this function. */
effect_area_t *effect_area_new_attack(uint16_t type, entity_t *e, int facing);
/* Set area animation */
void effect_area_set_anim(effect_area_t *ea, anim_frame_t *frame);

View File

@ -223,8 +223,13 @@ int main(void)
fkey_button(5, "PERF", debug.show_perf ? fg : C_WHITE);
}
if(keydown(KEY_F6) && !keydown(KEY_VARS) && usb_is_open())
usb_fxlink_screenshot(false);
static bool record = false;
if(keydown(KEY_F6) && !keydown(KEY_VARS) && usb_is_open()) {
record = !record;
}
if(record) {
usb_fxlink_videocapture(false);
}
/* Instead of dupdate(); for accurate performance measurements. Leaving
the DMA running during the simulation affects the results in extreme
@ -392,32 +397,15 @@ int main(void)
enemies[e->identity]->anim_idle[e->movement.facing == RIGHT]);
if(in_range && !e->current_attack) {
/* Attack */
frect_t hitbox = {
-fix(4)/16, fix(3)/16, -fix(4)/16, fix(3)/16,
};
/* Enemy attack */
int facing = frdir((fpoint_t){
player->movement.x - e->movement.x,
player->movement.y - e->movement.y });
hitbox = rect_rotate(hitbox, UP, facing);
fpoint_t dir = fdir(facing);
fpoint_t anchor = rect_center(entity_sprite(e));
anchor.x += fmul(fix(0.75), dir.x);
anchor.y += fmul(fix(0.75), dir.y);
effect_area_t *area = effect_area_new(EFFECT_HIT);
area->sprite = hitbox;
area->anchor = anchor;
area->lifetime = anim_duration(anim_hit);
area->repeat_delay = 0;
area->origin = e;
area->data.slash.strength = e->ATK;
area->data.slash.dir = e->movement.facing;
effect_area_set_anim(area, anim_hit);
effect_area_t *area = effect_area_new_attack(EFFECT_ATTACK_HIT,
e, facing);
game_add_effect_area(&game, area);
// entity_set_anim(player, anim_player_attack);
e->current_attack = area;
e->attack_follows_movement = true;
}
@ -425,25 +413,8 @@ int main(void)
/* Player attack */
if(player->HP > 0 && attack && !player->current_attack) {
frect_t hitbox = {
-fix(10)/16, fix(10)/16, -fix(4)/16, fix(4)/16,
};
hitbox = rect_rotate(hitbox, UP, player->movement.facing);
fpoint_t dir = fdir(player->movement.facing);
fpoint_t anchor = rect_center(entity_sprite(player));
anchor.x += fmul(fix(0.75), dir.x);
anchor.y += fmul(fix(0.75), dir.y);
effect_area_t *area = effect_area_new(EFFECT_SLASH);
area->sprite = hitbox;
area->anchor = anchor;
area->lifetime = anim_duration(anim_swing);
area->repeat_delay = 0;
area->origin = player;
area->data.slash.strength = player->ATK;
area->data.slash.dir = player->movement.facing;
effect_area_set_anim(area, anim_swing[player->movement.facing]);
effect_area_t *area = effect_area_new_attack(EFFECT_ATTACK_SLASH,
player, player->movement.facing);
game_add_effect_area(&game, area);
entity_set_anim(player, anim_player_attack);

View File

@ -224,16 +224,16 @@ void render_game(game_t const *g, bool show_hitboxes)
g->level->waves[g->wave-1].enemy_count, img_hud_wave2.height,
DIMAGE_NONE);
if(enemies_left > 0)
if(g->wave_spawned < game_current_wave(g)->enemy_count)
dprint_opt(DWIDTH / 2, 2, C_WHITE, C_NONE, DTEXT_CENTER, DTEXT_TOP,
"Wave %d: %d/%d enemies left", g->wave, enemies_left,
g->level->waves[g->wave-1].enemy_count);
else if(g->wave_spawned >= game_current_wave(g)->enemy_count)
"Wave %d: %d enemies spawning", g->wave,
game_current_wave(g)->enemy_count - g->wave_spawned);
else if(enemies_left > 0)
dprint_opt(DWIDTH / 2, 2, C_WHITE, C_NONE, DTEXT_CENTER, DTEXT_TOP,
"Wave %d: Victory!", g->wave);
"Wave %d: %d enemies left", g->wave, enemies_left);
else
dprint_opt(DWIDTH / 2, 2, C_WHITE, C_NONE, DTEXT_CENTER, DTEXT_TOP,
"Wave %d: Starting...", g->wave);
"Wave %d: Victory!", g->wave);
entity_t const *player = g->player;
dprint(2, 2, C_WHITE, "HP: %d", player->HP);
@ -249,6 +249,9 @@ void render_game(game_t const *g, bool show_hitboxes)
cooldown_total = player->movement_params->dash_cooldown;
cooldown_remaining = -player->movement.dash;
}
else if(i > 0) {
cooldown_remaining=fix(1);
}
int x=15+68*i, y=DHEIGHT-28, bg=(cooldown_remaining!=0);
dsubimage(x, y, &img_skillicons, 23*bg, 0, 23, 23, DIMAGE_NONE);