From cd6004dde03bef88b48ec4b7eb2321de506fa47e Mon Sep 17 00:00:00 2001 From: Andrei Alexeyev Date: Sun, 1 Mar 2020 18:38:54 +0200 Subject: [PATCH] some WIP charge effects --- src/common_tasks.c | 100 +++++++++++++++++++++++++++++++++++++ src/common_tasks.h | 12 +++++ src/stages/corotest.c | 28 +++++++++++ src/stages/stage1_events.c | 64 +++++++++++++++++------- 4 files changed, 186 insertions(+), 18 deletions(-) diff --git a/src/common_tasks.c b/src/common_tasks.c index 79c3d32c..c612b0bb 100644 --- a/src/common_tasks.c +++ b/src/common_tasks.c @@ -10,6 +10,7 @@ #include "common_tasks.h" #include "random.h" +#include "util/glm.h" DEFINE_EXTERN_TASK(common_drop_items) { cmplx p = *ARGS.pos; @@ -54,6 +55,105 @@ DEFINE_EXTERN_TASK(common_start_bgm) { stage_start_bgm(ARGS.bgm); } +static Projectile *spawn_charge_particle(cmplx target, real dist, const Color *clr) { + cmplx pos = target + rng_dir() * dist; + + return PARTICLE( + .sprite = "graze", + .color = clr, + .pos = pos, + .draw_rule = pdraw_timeout_scalefade(2, 0.1*(1+I), 0, 1), + .move = move_towards(target, rng_range(0.12, 0.16)), + .timeout = 30, + // .scale = 0.5+1.5*I, + .flags = PFLAG_NOREFLECT, + .layer = LAYER_PARTICLE_HIGH, + ); +} + +static void randomize_hue(Color *clr, float r) { + float h, s, l, a = clr->a; + color_get_hsl(clr, &h, &s, &l); + h += rng_sreal() * r; + *clr = *HSLA(h, s, l, a); +} + +DEFINE_EXTERN_TASK(common_charge) { + real dist = 256; + int delay = 3; + int maxtime = ARGS.time; + real rayfactor = 1.0 / (real)maxtime; + float hue_rand = 0.02; + + Color local_color; + + cmplx anchor_null = 0; + cmplx pos_offset = ARGS.pos; + const cmplx *pos_anchor = ARGS.anchor; + if(!pos_anchor) { + pos_anchor = &anchor_null; + } + + const Color *p_color = ARGS.color_ref; + if(!p_color) { + assert(ARGS.color != NULL); + local_color = *ARGS.color; + p_color = &local_color; + } + + if(ARGS.bind_to_entity.ent) { + TASK_BIND(ARGS.bind_to_entity); + } + + for(int i = 0; i < maxtime;) { + cmplx pos = *pos_anchor + pos_offset; + int stage = (5 * i) / maxtime; + real sdist = dist * glm_ease_quad_out((stage + 1) / 6.0); + + for(int j = 0; j < stage + 1; ++j) { + Color color = *p_color; + randomize_hue(&color, hue_rand); + color_lerp(&color, RGBA(1, 1, 1, 0), rng_real() * 0.2); + spawn_charge_particle(pos, sdist * (1 + 0.1 * rng_sreal()), &color); + color_mul_scalar(&color, 0.2); + } + + Color color = *p_color; + randomize_hue(&color, hue_rand); + color_lerp(&color, RGBA(1, 1, 1, 0), rng_real() * 0.2); + color_mul_scalar(&color, 0.5); + + PARTICLE( + .sprite = "blast_huge_rays", + .color = &color, + .pos = pos, + .draw_rule = pdraw_timeout_scalefade(0, 1, 1, 0), + .timeout = 30, + .flags = PFLAG_NOREFLECT, + .scale = glm_ease_bounce_out(rayfactor * (i + 1)), + .angle = rng_angle(), + .layer = LAYER_PARTICLE_HIGH, + ); + + i += WAIT(delay); + } + + local_color = *p_color; + randomize_hue(&local_color, hue_rand); + color_mul_scalar(&local_color, 2.0); + + PARTICLE( + .sprite = "blast_huge_halo", + .color = &local_color, + .pos = *pos_anchor + pos_offset, + .draw_rule = pdraw_timeout_scalefade(0, 2, 1, 0), + .timeout = 30, + .flags = PFLAG_NOREFLECT, + .angle = rng_angle(), + .layer = LAYER_PARTICLE_HIGH, + ); +} + cmplx common_wander(cmplx origin, double dist, Rect bounds) { int attempts = 32; double angle; diff --git a/src/common_tasks.h b/src/common_tasks.h index ab12b238..9174fa93 100644 --- a/src/common_tasks.h +++ b/src/common_tasks.h @@ -42,6 +42,18 @@ DECLARE_EXTERN_TASK( { const char *bgm; } ); +DECLARE_EXTERN_TASK( + common_charge, + { + cmplx pos; + const Color *color; + int time; + BoxedEntity bind_to_entity; + const cmplx *anchor; + const Color *color_ref; + } +); + void common_move_loop(cmplx *restrict pos, MoveParams *restrict mp); INLINE Rect viewport_bounds(double margin) { diff --git a/src/stages/corotest.c b/src/stages/corotest.c index 8f5455b8..6f036c77 100644 --- a/src/stages/corotest.c +++ b/src/stages/corotest.c @@ -156,15 +156,26 @@ TASK(punching_bag, NO_ARGS) { .power = 3, .points = 5, }); + + for(;;) { + INVOKE_TASK(common_charge, + .pos = e->pos, + .color = RGBA(1, 0, 0, 0), + .time = 60 + ); + WAIT(80); + } } TASK(stage_main, NO_ARGS) { YIELD; + /* WAIT(30); log_debug("test 1! %i", global.timer); WAIT(60); log_debug("test 2! %i", global.timer); + */ INVOKE_TASK(punching_bag); return; @@ -177,9 +188,26 @@ TASK(stage_main, NO_ARGS) { } static void cotest_begin(void) { + corotest_procs.shader_rules = stage1_procs.shader_rules; + stage1_procs.begin(); INVOKE_TASK(stage_main); } +static void cotest_update(void) { + stage1_procs.update(); +} + +static void cotest_end(void) { + stage1_procs.end(); +} + +static void cotest_draw(void) { + stage1_procs.draw(); +} + StageProcs corotest_procs = { .begin = cotest_begin, + .end = cotest_end, + .update = cotest_update, + .draw = cotest_draw, }; diff --git a/src/stages/stage1_events.c b/src/stages/stage1_events.c index 8b2d61ba..170c15c1 100644 --- a/src/stages/stage1_events.c +++ b/src/stages/stage1_events.c @@ -1362,11 +1362,20 @@ TASK_WITH_INTERFACE(icy_storm, BossAttack) { int size_oscillation = 3; int size_max = size_base + size_oscillation; int burst_interval = difficulty_value(120, 80, 80, 80); + int charge_time = 60; + burst_interval -= charge_time; int flakes_limit = flakes_per_burst * snowflake_bullet_limit(size_max); DECLARE_ENT_ARRAY(Projectile, snowflake_projs, flakes_limit); for(int burst = 0;; ++burst) { + aniplayer_queue(&boss->ani, "(9)", 0); + play_sound("charge_generic"); + INVOKE_TASK(common_charge, boss->pos, RGBA(0, 0.5, 1.0, 0.0), charge_time); + WAIT(charge_time); + play_sound("shot_special1"); + aniplayer_queue(&boss->ani, "main", 0); + double angle_ofs = carg(global.plr.pos - boss->pos); int size = size_base + size_oscillation * sin(burst * 2.21); @@ -1394,6 +1403,26 @@ TASK_WITH_INTERFACE(icy_storm, BossAttack) { } } +TASK(move_frozen, { BoxedProjectileArray *parray; }) { + DECLARE_ENT_ARRAY(Projectile, projs, ARGS.parray->size); + ENT_ARRAY_FOREACH(ARGS.parray, Projectile *p, { + ENT_ARRAY_ADD(&projs, p); + }); + + ENT_ARRAY_FOREACH(&projs, Projectile *p, { + p->color = *RGB(0.9, 0.9, 0.9); + p->move.retention = 1 + 0.002 * global.diff * rng_f64(); + p->move.velocity = 2 * rng_dir(); + spawn_stain(p->pos, p->angle, 30); + spawn_projectile_highlight_effect(p); + play_sound_ex("shot2", 0, false); + + if(rng_chance(0.4)) { + YIELD; + } + }); +} + DEFINE_EXTERN_TASK(stage1_spell_perfect_freeze) { Boss *boss = INIT_BOSS_ATTACK(); BEGIN_BOSS_ATTACK(); @@ -1401,12 +1430,15 @@ DEFINE_EXTERN_TASK(stage1_spell_perfect_freeze) { for(int run = 1;;run++) { boss->move = move_towards(VIEWPORT_W/2.0 + 100.0*I, 0.04); + INVOKE_TASK(common_charge, 0, RGBA(1.0, 0.5, 0.0, 0), 40, .anchor = &boss->pos); + WAIT(40); + play_sound("shot_special1"); + int n = global.diff; int nfrog = n*60; DECLARE_ENT_ARRAY(Projectile, projs, nfrog); - WAIT(20); for(int i = 0; i < nfrog/n; i++) { play_loop("shot1_loop"); @@ -1442,26 +1474,22 @@ DEFINE_EXTERN_TASK(stage1_spell_perfect_freeze) { }); WAIT(60); + double dir = rng_sign(); boss->move = (MoveParams){ .velocity = dir*2.7+I, .retention = 0.99, .acceleration = -dir*0.017 }; - aniplayer_queue(&boss->ani,"(9)",0); + int charge_time = difficulty_value(85, 80, 75, 70); + aniplayer_queue(&boss->ani, "(9)", 0); + + play_sound("charge_generic"); + INVOKE_TASK(common_charge, +60, RGBA(0.3, 0.4, 0.9, 0), charge_time, .anchor = &boss->pos); + INVOKE_TASK(common_charge, -60, RGBA(0.3, 0.4, 0.9, 0), charge_time, .anchor = &boss->pos); + WAIT(charge_time); + play_sound("shot_special1"); + + INVOKE_SUBTASK_DELAYED(120, move_frozen, &projs); + int d = max(0, global.diff - D_Normal); - WAIT(60-5*global.diff); - - ENT_ARRAY_FOREACH(&projs, Projectile *p, { - p->color = *RGB(0.9, 0.9, 0.9); - p->move.retention = 1 + 0.002 * global.diff * rng_f64(); - p->move.velocity = 2 * rng_dir(); - spawn_stain(p->pos, p->angle, 30); - spawn_projectile_highlight_effect(p); - play_sound_ex("shot2", 0, false); - - if(rng_chance(0.4)) { - YIELD; - } - }); - for(int i = 0; i < 30+10*d; i++) { play_loop("shot1_loop"); float r1, r2; @@ -1489,7 +1517,7 @@ DEFINE_EXTERN_TASK(stage1_spell_perfect_freeze) { } aniplayer_queue(&boss->ani,"main",0); - WAIT(40-5*global.diff); + WAIT(20-5*global.diff); } }