From 9004133f4ae3a80689733bf4af84159df4b8e9c5 Mon Sep 17 00:00:00 2001 From: Andrei Alexeyev <0x416b617269@gmail.com> Date: Sun, 8 Oct 2017 23:48:12 +0300 Subject: [PATCH] boss shadow tweaks --- src/aniplayer.c | 6 ++++++ src/aniplayer.h | 2 +- src/boss.c | 26 ++++++++++++++------------ src/boss.h | 1 + src/stagedraw.c | 18 ++++++++++++++++-- 5 files changed, 38 insertions(+), 15 deletions(-) diff --git a/src/aniplayer.c b/src/aniplayer.c index b7c0b638..4c24aca1 100644 --- a/src/aniplayer.c +++ b/src/aniplayer.c @@ -30,6 +30,12 @@ void aniplayer_reset(AniPlayer *plr) { // resets to a neutral state with empty q } } +void aniplayer_copy(AniPlayer *dst, AniPlayer *src) { + memcpy(dst, src, sizeof(AniPlayer)); + dst->queue = NULL; + dst->queuesize = 0; +} + AniSequence *aniplayer_queue(AniPlayer *plr, int row, int loops, int delay) { AniSequence *s = create_element_at_end((void **)&plr->queue,sizeof(AniSequence)); plr->queuesize++; diff --git a/src/aniplayer.h b/src/aniplayer.h index 1e77dc0c..58b3fa76 100644 --- a/src/aniplayer.h +++ b/src/aniplayer.h @@ -43,8 +43,8 @@ typedef struct { void aniplayer_create(AniPlayer *plr, Animation *ani); void aniplayer_free(AniPlayer *plr); - void aniplayer_reset(AniPlayer *plr); // resets to a neutral state with empty queue. +void aniplayer_copy(AniPlayer *dst, AniPlayer *src); AniSequence *aniplayer_queue(AniPlayer *plr, int row, int loops, int delay); // 0 loops: played one time AniSequence *aniplayer_queue_pro(AniPlayer *plr, int row, int start, int duration, int delay, int speed); // self-documenting pro version diff --git a/src/boss.c b/src/boss.c index 880493c9..e21f097d 100644 --- a/src/boss.c +++ b/src/boss.c @@ -667,28 +667,21 @@ Attack* boss_add_attack_from_info(Boss *boss, AttackInfo *info, char move) { } void BossShadow(Projectile *p, int t) { - Boss *boss = (Boss *)REF(p->args[2]); - if(boss == NULL) - return; + AniPlayer *aplr = (AniPlayer*)REF(p->args[2]); + assert(aplr != NULL); glPushMatrix(); float s = 1.0+t/p->args[0]*0.5; - - if(boss->pos + p->pos) - glTranslatef(creal(boss->pos + p->pos), cimag(boss->pos + p->pos), 0); - - //if(p->angle != M_PI*0.5) - // glRotatef(p->angle*180/M_PI+90, 0, 0, 1); - glScalef(s+0.2, s+0.2, 1); + glTranslatef(creal(p->pos), cimag(p->pos), 0); + glScalef(s, s, 1); float r,g,b,a; parse_color(p->clr,&r,&g,&b,&a); a = 1.5-s; - glColor4f(r,g,b,a); glBlendFunc(GL_SRC_ALPHA, GL_ONE); - aniplayer_play(&boss->ani,0,0); + aniplayer_play(aplr,0,0); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glPopMatrix(); @@ -696,6 +689,15 @@ void BossShadow(Projectile *p, int t) { glColor3f(1,1,1); } +int boss_shadow_rule(Projectile *p, int t) { + if(t == EVENT_DEATH) { + AniPlayer *aplr = REF(p->args[2]); + free(aplr); + free_ref(p->args[2]); + } + + return enemy_flare(p, t); +} void boss_preload(void) { preload_resources(RES_SFX, RESF_OPTIONAL, diff --git a/src/boss.h b/src/boss.h index 32dc063f..f4c67f13 100644 --- a/src/boss.h +++ b/src/boss.h @@ -138,6 +138,7 @@ void boss_kill_projectiles(void); void boss_preload(void); void BossShadow(Projectile *p, int t); // shadow particle effect behind the boss +int boss_shadow_rule(Projectile *p, int t); #define BOSS_DEFAULT_SPAWN_POS (VIEWPORT_W * 0.5 - I * VIEWPORT_H * 0.5) #define BOSS_DEFAULT_GO_POS (VIEWPORT_W * 0.5 + 200.0*I) diff --git a/src/stagedraw.c b/src/stagedraw.c index 99f05bf2..3d6e85b2 100644 --- a/src/stagedraw.c +++ b/src/stagedraw.c @@ -223,8 +223,22 @@ static void stage_draw_objects(void) { glTranslatef(creal(global.boss->pos), cimag(global.boss->pos), 0); if(!(global.frames % 5)) { - complex offset = (frand()-0.5)*100 + (frand()-0.5)*20.0*I; - create_particle3c("boss_shadow", 0, rgba(0.4,0.6,1,1), BossShadow, enemy_flare, 20, 0.3*(-100.0*I-offset)/(50.0+frand()*10), add_ref(global.boss)); + complex offset = (frand()-0.5)*50 + (frand()-0.5)*20.0*I; + create_particle3c("boss_shadow", 0, rgba(0.2,0.35,0.5,0.5), EnemyFlareShrink, enemy_flare, 50, (-100.0*I-offset)/(50.0+frand()*10), add_ref(global.boss)); + } + + Attack *cur = global.boss->current; + + // XXX: maybe we need an ATTACK_IS_SPELL() macro or something + if(!(global.frames % 2) && cur && cur->type != AT_Move && cur->type != AT_Normal && !cur->endtime) { + // copy animation state to render the same frame even after the boss has changed its own + AniPlayer *aplr = malloc(sizeof(AniPlayer)); + aniplayer_copy(aplr, &global.boss->ani); + + // this is in sync with the boss position oscillation + complex pos = global.boss->pos + I * 6 * sin(global.frames/25.0); + + create_particle3c("boss_shadow", pos, rgb(0.4,0.6,1), BossShadow, boss_shadow_rule, 24, 0, add_ref(aplr)); } glBlendFunc(GL_SRC_ALPHA, GL_ONE);