some WIP charge effects

This commit is contained in:
Andrei Alexeyev 2020-03-01 18:38:54 +02:00
parent 488aa71acb
commit cd6004dde0
No known key found for this signature in database
GPG key ID: 363707CD4C7FE8A4
4 changed files with 186 additions and 18 deletions

View file

@ -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;

View file

@ -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) {

View file

@ -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,
};

View file

@ -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);
}
}