lasers: prototype a better interface for position rules

This commit is contained in:
Andrei Alexeyev 2024-04-08 09:27:30 +02:00
parent e3a4e9065e
commit daa1b38987
No known key found for this signature in database
GPG key ID: 72D26128040B9690
14 changed files with 376 additions and 137 deletions

View file

@ -46,11 +46,7 @@ void lasers_shutdown(void) {
laserintern_shutdown();
}
Laser *create_laser(
cmplx pos, float time, float deathtime, const Color *color,
LaserPosRule prule,
cmplx a0, cmplx a1, cmplx a2, cmplx a3
) {
Laser *create_laser(cmplx pos, float time, float deathtime, const Color *color, LaserRule rule) {
Laser *l = objpool_acquire(&stage_object_pools.lasers);
alist_push(&global.lasers, l);
@ -59,11 +55,7 @@ Laser *create_laser(
l->deathtime = deathtime;
l->pos = pos;
l->color = *color;
l->args[0] = a0;
l->args[1] = a1;
l->args[2] = a2;
l->args[3] = a3;
l->prule = prule;
l->rule = rule;
l->width = 10;
l->width_exponent = 1.0;
l->speed = 1;
@ -73,7 +65,7 @@ Laser *create_laser(
l->ent.draw_func = laserdraw_ent_drawfunc;
ent_register(&l->ent, ENT_TYPE_ID(Laser));
l->prule(l, EVENT_BIRTH);
laser_pos_at(l, EVENT_BIRTH);
return l;
}
@ -90,7 +82,7 @@ Laser *create_laserline_ab(cmplx a, cmplx b, float width, float charge, float du
// This value works well for the default exponent (1.0), but may need to be adjusted for other
// values. 0 exponent can get away with 1 sample, because the width is then constant.
float timespan = 4;
Laser *l = create_laser(0, timespan, dur, clr, las_linear, 0, 0, 0, 0);
Laser *l = create_laser(0, timespan, dur, clr, laser_rule_linear(0));
laserline_set_ab(l, a, b);
INVOKE_TASK(laser_charge,
.laser = ENT_BOX(l),
@ -101,8 +93,9 @@ Laser *create_laserline_ab(cmplx a, cmplx b, float width, float charge, float du
}
void laserline_set_ab(Laser *l, cmplx a, cmplx b) {
auto rd = NOT_NULL(laser_get_ruledata_linear(l));
rd->velocity = (b - a) / l->timespan;
l->pos = a;
l->args[0] = (b - a) / l->timespan;
}
void laserline_set_posdir(Laser *l, cmplx pos, cmplx dir) {
@ -231,7 +224,7 @@ static int quantize_laser(Laser *l) {
// Begin constructing at t0
// WARNING: these must be double precision to prevent cross-platform replay desync
cmplx a, b;
a = l->prule(l, t0);
a = laser_pos_at(l, t0);
// Width value of the last included sample
// Initialized to the width at t0
@ -241,7 +234,7 @@ static int quantize_laser(Laser *l) {
t += sp.time_step;
// Vector from A to B of the last included segment, and its squared length.
cmplxf v0 = a - l->prule(l, t0 - sp.time_step);
cmplxf v0 = a - laser_pos_at(l, t0 - sp.time_step);
float v0_abs2 = cabs2f(v0);
float viewmargin = l->width * 0.5f;
@ -256,7 +249,7 @@ static int quantize_laser(Laser *l) {
bottom_right.as_cmplx = a;
for(uint i = 1; i < sp.num_samples; ++i, t += sp.time_step) {
b = l->prule(l, t);
b = laser_pos_at(l, t);
if(i < sp.num_samples - 1 && (t - t0) < thres_temporal) {
cmplxf v1 = b - a;
@ -672,89 +665,6 @@ bool laser_intersects_circle(Laser *l, Circle circle) {
return laser_intersects_ellipse(l, ellipse);
}
cmplx las_linear(Laser *l, float t) {
if(t == EVENT_BIRTH) {
return 0;
}
return l->pos + l->args[0]*t;
}
cmplx las_accel(Laser *l, float t) {
if(t == EVENT_BIRTH) {
return 0;
}
return l->pos + l->args[0]*t + 0.5*l->args[1]*t*t;
}
cmplx las_sine(Laser *l, float t) { // [0] = velocity; [1] = sine amplitude; [2] = sine frequency; [3] = sine phase
// this is actually shaped like a sine wave
if(t == EVENT_BIRTH) {
return 0;
}
cmplx line_vel = l->args[0];
cmplx line_dir = line_vel / cabs(line_vel);
cmplx line_normal = im(line_dir) - I*re(line_dir);
cmplx sine_amp = l->args[1];
real sine_freq = re(l->args[2]);
real sine_phase = re(l->args[3]);
cmplx sine_ofs = line_normal * sine_amp * sin(sine_freq * t + sine_phase);
return l->pos + t * line_vel + sine_ofs;
}
cmplx las_sine_expanding(Laser *l, float t) { // [0] = velocity; [1] = sine amplitude; [2] = sine frequency; [3] = sine phase
if(t == EVENT_BIRTH) {
return 0;
}
cmplx velocity = l->args[0];
real amplitude = re(l->args[1]);
real frequency = re(l->args[2]);
real phase = re(l->args[3]);
real angle = carg(velocity);
real speed = cabs(velocity);
real s = (frequency * t + phase);
return l->pos + cdir(angle + amplitude * sin(s)) * t * speed;
}
cmplx las_turning(Laser *l, float t) { // [0] = vel0; [1] = vel1; [2] r: turn begin time, i: turn end time
if(t == EVENT_BIRTH) {
return 0;
}
cmplx v0 = l->args[0];
cmplx v1 = l->args[1];
float begin = re(l->args[2]);
float end = im(l->args[2]);
float a = clamp((t - begin) / (end - begin), 0, 1);
a = 1.0 - (0.5 + 0.5 * cos(a * M_PI));
a = 1.0 - pow(1.0 - a, 2);
cmplx v = v1 * a + v0 * (1 - a);
return l->pos + v * t;
}
cmplx las_circle(Laser *l, float t) {
if(t == EVENT_BIRTH) {
return 0;
}
real turn_speed = re(l->args[0]);
real time_ofs = im(l->args[0]);
real radius = re(l->args[1]);
return l->pos + radius * cdir(turn_speed * (t + time_ofs));
}
void laser_charge(Laser *l, int t, float charge, float width) {
float new_width;

View file

@ -16,15 +16,30 @@
#include "resource/shader_program.h"
#include "entity.h"
typedef LIST_ANCHOR(Laser) LaserList;
typedef cmplx LaserRuleFunc(Laser *p, real t, void *ruledata);
typedef cmplx (*LaserPosRule)(Laser* l, float time);
typedef struct LaserRule {
LaserRuleFunc *func;
alignas(cmplx) char data[sizeof(cmplx) * 5];
} LaserRule;
typedef cmplx (*LegacyLaserPosRule)(Laser *l, float time);
typedef LegacyLaserPosRule LaserPosRule
attr_deprecated("For compatibility with legacy rules");
typedef LIST_ANCHOR(Laser) LaserList;
DEFINE_ENTITY_TYPE(Laser, {
cmplx pos;
cmplx args[4];
LaserPosRule prule;
union {
LaserRule rule;
struct {
char _padding[offsetof(LaserRule, data)];
cmplx args[(sizeof(LaserRule) - offsetof(LaserRule, data)) / sizeof(cmplx)]
attr_deprecated("For compatibility with legacy rules");
};
};
struct {
int segments_ofs;
@ -50,10 +65,14 @@ DEFINE_ENTITY_TYPE(Laser, {
uchar collision_active : 1;
});
#define create_lasercurve1c(p, time, deathtime, clr, rule, a0) create_laser(p, time, deathtime, clr, rule, a0, 0, 0, 0)
#define create_lasercurve2c(p, time, deathtime, clr, rule, a0, a1) create_laser(p, time, deathtime, clr, rule, a0, a1, 0, 0)
#define create_lasercurve3c(p, time, deathtime, clr, rule, a0, a1, a2) create_laser(p, time, deathtime, clr, rule, a0, a1, a2, 0)
#define create_lasercurve4c(p, time, deathtime, clr, rule, a0, a1, a2, a3) create_laser(p, time, deathtime, clr, rule, a0, a1, a2, a3)
#define create_lasercurve1c(p, time, deathtime, clr, rule, a0) \
create_laser(p, time, deathtime, clr, laser_rule_compat(rule, a0, 0, 0, 0))
#define create_lasercurve2c(p, time, deathtime, clr, rule, a0, a1) \
create_laser(p, time, deathtime, clr, laser_rule_compat(rule, a0, a1, 0, 0))
#define create_lasercurve3c(p, time, deathtime, clr, rule, a0, a1, a2) \
create_laser(p, time, deathtime, clr, laser_rule_compat(rule, a0, a1, a2, 0))
#define create_lasercurve4c(p, time, deathtime, clr, rule, a0, a1, a2, a3) \
create_laser(p, time, deathtime, clr, laser_rule_compat(rule, a0, a1, a2, a3))
void lasers_init(void);
void lasers_shutdown(void);
@ -66,19 +85,12 @@ Laser *create_laserline_ab(cmplx a, cmplx b, float width, float charge, float du
void laserline_set_ab(Laser *l, cmplx a, cmplx b);
void laserline_set_posdir(Laser *l, cmplx pos, cmplx dir);
Laser *create_laser(cmplx pos, float time, float deathtime, const Color *color, LaserPosRule prule, cmplx a0, cmplx a1, cmplx a2, cmplx a3);
Laser *create_laser(cmplx pos, float time, float deathtime, const Color *color, LaserRule rule);
bool laser_is_active(Laser *l);
bool laser_is_clearable(Laser *l);
bool clear_laser(Laser *l, uint flags);
cmplx las_linear(Laser *l, float t);
cmplx las_accel(Laser *l, float t);
cmplx las_sine(Laser *l, float t);
cmplx las_sine_expanding(Laser *l, float t);
cmplx las_turning(Laser *l, float t);
cmplx las_circle(Laser *l, float t);
void laser_make_static(Laser *l);
void laser_charge(Laser *l, int t, float charge, float width);
@ -110,8 +122,14 @@ typedef struct LaserTraceSample {
typedef void *(*LaserTraceFunc)(Laser *l, const LaserTraceSample *sample, void *userdata);
void *laser_trace(Laser *l, real step, LaserTraceFunc trace, void *userdata);
INLINE cmplx laser_pos_at(Laser *l, real t) {
return l->rule.func(l, t, &l->rule.data);
}
DECLARE_EXTERN_TASK(laser_charge, {
BoxedLaser laser;
float charge_delay;
float target_width;
});
#include "rules.h"

View file

@ -1,6 +1,7 @@
lasers_src = files(
'laser.c',
'draw.c',
'internal.c',
'laser.c',
'rules.c',
)

211
src/lasers/rules.c Normal file
View file

@ -0,0 +1,211 @@
/*
* This software is licensed under the terms of the MIT License.
* See COPYING for further information.
* ---
* Copyright (c) 2011-2019, Lukas Weber <laochailan@web.de>.
* Copyright (c) 2012-2019, Andrei Alexeyev <akari@taisei-project.org>.
*/
#include "taisei.h"
#include "rules.h"
#include "global.h"
static cmplx laser_rule_linear_impl(Laser *l, real t, void *ruledata) {
LaserRuleLinearData *rd = ruledata;
return l->pos + t * rd->velocity;
}
LaserRule laser_rule_linear(cmplx velocity) {
LaserRuleLinearData rd = {
.velocity = velocity,
};
return MAKE_LASER_RULE(laser_rule_linear_impl, rd);
}
IMPL_LASER_RULE_DATAGETTER(laser_get_ruledata_linear,
laser_rule_linear_impl, LaserRuleLinearData)
static cmplx laser_rule_accelerated_impl(Laser *l, real t, void *ruledata) {
LaserRuleAcceleratedData *rd = ruledata;
return l->pos + t * (rd->velocity + t * rd->half_accel);
}
LaserRule laser_rule_accelerated(cmplx velocity, cmplx accel) {
LaserRuleAcceleratedData rd = {
.velocity = velocity,
.half_accel = accel * 0.5,
};
return MAKE_LASER_RULE(laser_rule_accelerated_impl, rd);
}
IMPL_LASER_RULE_DATAGETTER(laser_get_ruledata_accelerated,
laser_rule_accelerated_impl, LaserRuleAcceleratedData)
static cmplx laser_rule_sine_impl(Laser *l, real t, void *ruledata) {
LaserRuleSineData *rd = ruledata;
cmplx line_vel = rd->velocity;
cmplx line_dir = line_vel / cabs(line_vel);
cmplx line_normal = im(line_dir) - I*re(line_dir);
cmplx sine_ofs = line_normal * rd->amplitude * sin(rd->frequency * t + rd->phase);
return l->pos + t * line_vel + sine_ofs;
}
LaserRule laser_rule_sine(cmplx velocity, cmplx amplitude, real frequency, real phase) {
LaserRuleSineData rd = {
.velocity = velocity,
.amplitude = amplitude,
.frequency = frequency,
.phase = phase,
};
return MAKE_LASER_RULE(laser_rule_sine_impl, rd);
}
IMPL_LASER_RULE_DATAGETTER(laser_get_ruledata_sine,
laser_rule_sine_impl, LaserRuleSineData)
static cmplx laser_rule_sine_expanding_impl(Laser *l, real t, void *ruledata) {
LaserRuleSineExpandingData *rd = ruledata;
real angle = carg(rd->velocity);
real speed = cabs(rd->velocity);
real s = (rd->frequency * t + rd->phase);
return l->pos + cdir(angle + rd->amplitude * sin(s)) * t * speed;
}
LaserRule laser_rule_sine_expanding(cmplx velocity, real amplitude, real frequency, real phase) {
LaserRuleSineExpandingData rd = {
.velocity = velocity,
.amplitude = amplitude,
.frequency = frequency,
.phase = phase,
};
return MAKE_LASER_RULE(laser_rule_sine_expanding_impl, rd);
}
IMPL_LASER_RULE_DATAGETTER(laser_get_ruledata_sine_expanding,
laser_rule_sine_expanding_impl, LaserRuleSineExpandingData)
static cmplx laser_rule_arc_impl(Laser *l, real t, void *ruledata) {
LaserRuleArcData *rd = ruledata;
return l->pos + rd->radius * cdir(rd->turn_speed * (t + rd->time_ofs));
}
LaserRule laser_rule_arc(cmplx radius, real turnspeed, real timeofs) {
LaserRuleArcData rd = {
.radius = radius,
.turn_speed = turnspeed,
.time_ofs = timeofs,
};
return MAKE_LASER_RULE(laser_rule_arc_impl, rd);
}
IMPL_LASER_RULE_DATAGETTER(laser_get_ruledata_arc,
laser_rule_arc_impl, LaserRuleArcData)
/*
* Legacy rules for compatibility (TODO remove)
*/
static cmplx laser_rule_compat_impl(Laser *l, real t, void *ruledata) {
LaserRuleCompatData *rd = ruledata;
return rd->oldrule(l, t);
}
LaserRule laser_rule_compat(LegacyLaserPosRule oldrule, cmplx a0, cmplx a1, cmplx a2, cmplx a3) {
LaserRuleCompatData rd = {
.oldrule = oldrule,
.args = { a0, a1, a2, a3 },
};
return MAKE_LASER_RULE(laser_rule_compat_impl, rd);
}
IMPL_LASER_RULE_DATAGETTER(laser_get_ruledata_compat,
laser_rule_compat_impl, LaserRuleCompatData)
DIAGNOSTIC(ignored "-Wdeprecated-declarations")
cmplx las_linear(Laser *l, float t) {
if(t == EVENT_BIRTH) {
return 0;
}
return l->pos + l->args[0]*t;
}
cmplx las_accel(Laser *l, float t) {
if(t == EVENT_BIRTH) {
return 0;
}
return l->pos + l->args[0]*t + 0.5*l->args[1]*t*t;
}
cmplx las_sine(Laser *l, float t) { // [0] = velocity; [1] = sine amplitude; [2] = sine frequency; [3] = sine phase
// this is actually shaped like a sine wave
if(t == EVENT_BIRTH) {
return 0;
}
cmplx line_vel = l->args[0];
cmplx line_dir = line_vel / cabs(line_vel);
cmplx line_normal = im(line_dir) - I*re(line_dir);
cmplx sine_amp = l->args[1];
real sine_freq = re(l->args[2]);
real sine_phase = re(l->args[3]);
cmplx sine_ofs = line_normal * sine_amp * sin(sine_freq * t + sine_phase);
return l->pos + t * line_vel + sine_ofs;
}
cmplx las_sine_expanding(Laser *l, float t) { // [0] = velocity; [1] = sine amplitude; [2] = sine frequency; [3] = sine phase
if(t == EVENT_BIRTH) {
return 0;
}
cmplx velocity = l->args[0];
real amplitude = re(l->args[1]);
real frequency = re(l->args[2]);
real phase = re(l->args[3]);
real angle = carg(velocity);
real speed = cabs(velocity);
real s = (frequency * t + phase);
return l->pos + cdir(angle + amplitude * sin(s)) * t * speed;
}
cmplx las_turning(Laser *l, float t) { // [0] = vel0; [1] = vel1; [2] r: turn begin time, i: turn end time
if(t == EVENT_BIRTH) {
return 0;
}
cmplx v0 = l->args[0];
cmplx v1 = l->args[1];
float begin = re(l->args[2]);
float end = im(l->args[2]);
float a = clamp((t - begin) / (end - begin), 0, 1);
a = 1.0 - (0.5 + 0.5 * cos(a * M_PI));
a = 1.0 - pow(1.0 - a, 2);
cmplx v = v1 * a + v0 * (1 - a);
return l->pos + v * t;
}
cmplx las_circle(Laser *l, float t) {
if(t == EVENT_BIRTH) {
return 0;
}
real turn_speed = re(l->args[0]);
real time_ofs = im(l->args[0]);
real radius = re(l->args[1]);
return l->pos + radius * cdir(turn_speed * (t + time_ofs));
}

99
src/lasers/rules.h Normal file
View file

@ -0,0 +1,99 @@
/*
* This software is licensed under the terms of the MIT License.
* See COPYING for further information.
* ---
* Copyright (c) 2011-2019, Lukas Weber <laochailan@web.de>.
* Copyright (c) 2012-2019, Andrei Alexeyev <akari@taisei-project.org>.
*/
#pragma once
#include "taisei.h"
#include "laser.h"
cmplx las_linear(Laser *l, float t) attr_deprecated("Use laser_rule_linear");
cmplx las_accel(Laser *l, float t) attr_deprecated("Use laser_rule_accelerated");
cmplx las_sine(Laser *l, float t) attr_deprecated("Use laser_rule_sine");
cmplx las_sine_expanding(Laser *l, float t) attr_deprecated("Use laser_rule_sine_expanding");
cmplx las_turning(Laser *l, float t) attr_deprecated("No replacement");
cmplx las_circle(Laser *l, float t) attr_deprecated("Use laser_rule_arc");
extern LaserRuleFunc laser_rule_compat_adapter;
typedef struct LaserRuleLinearData {
cmplx velocity;
} LaserRuleLinearData;
LaserRule laser_rule_linear(cmplx velocity);
LaserRuleLinearData *laser_get_ruledata_linear(Laser *l);
typedef struct LaserRuleAcceleratedData {
cmplx velocity;
cmplx half_accel;
} LaserRuleAcceleratedData;
LaserRule laser_rule_accelerated(cmplx velocity, cmplx accel);
LaserRuleAcceleratedData *laser_get_ruledata_accelerated(Laser *l);
typedef struct LaserRuleSineData {
cmplx velocity;
cmplx amplitude;
real frequency;
real phase;
} LaserRuleSineData;
LaserRule laser_rule_sine(cmplx velocity, cmplx amplitude, real frequency, real phase);
LaserRuleSineData *laser_get_ruledata_sine(Laser *l);
typedef struct LaserRuleSineExpandingData {
cmplx velocity;
real amplitude;
real frequency;
real phase;
} LaserRuleSineExpandingData;
LaserRule laser_rule_sine_expanding(cmplx velocity, real amplitude, real frequency, real phase);
LaserRuleSineExpandingData *laser_get_ruledata_sine_expanding(Laser *l);
typedef struct LaserRuleArcData {
cmplx radius;
real turn_speed;
real time_ofs;
} LaserRuleArcData;
LaserRule laser_rule_arc(cmplx radius, real turnspeed, real timeofs);
LaserRuleArcData *laser_get_ruledata_arc(Laser *l);
typedef struct LaserRuleCompatData {
cmplx args[4];
LegacyLaserPosRule oldrule;
} LaserRuleCompatData;
LaserRule laser_rule_compat(LegacyLaserPosRule oldrule, cmplx a0, cmplx a1, cmplx a2, cmplx a3)
attr_deprecated("Use the new rule format (see laser/rules.h)");
LaserRuleCompatData *laser_get_ruledata_compat(Laser *l);
#define MAKE_LASER_RULE(func, data) ({ \
union { \
LaserRule r; \
struct { \
LaserRuleFunc *f; \
typeof(data) _data; \
} src; \
} cvt = { \
.src.f = func, \
.src._data = data, \
}; \
static_assert(sizeof(cvt) == sizeof(LaserRule)); \
cvt.r; \
})
#define GET_LASER_RULEDATA(_laser, _func, _data_type) ( \
(_laser)->rule.func == _func \
? CASTPTR_ASSUME_ALIGNED(&(_laser)->rule.data, _data_type) \
: NULL)
#define IMPL_LASER_RULE_DATAGETTER(_getter_func, _rule_func, _data_type) \
_data_type *_getter_func(Laser *l) { \
return GET_LASER_RULEDATA(l, _rule_func, _data_type); \
}

View file

@ -15,9 +15,9 @@
#include "global.h"
TASK(singularity_laser, { cmplx pos; cmplx vel; real amp; real freq; }) {
Laser *l = TASK_BIND(create_laser(ARGS.pos,
Laser *l = TASK_BIND(create_lasercurve3c(ARGS.pos,
200, 10000, RGBA(0.0, 0.2, 1.0, 0.0), las_sine_expanding,
ARGS.vel, ARGS.amp, ARGS.freq, 0
ARGS.vel, ARGS.amp, ARGS.freq
));
laser_make_static(l);

View file

@ -64,7 +64,7 @@ TASK(laser_bullet, { BoxedProjectile p; BoxedLaser l; CoEvent *event; int event_
Projectile *p = TASK_BIND(ARGS.p);
for(int t = 0; (l = ENT_UNBOX(ARGS.l)); ++t, YIELD) {
p->pos = l->prule(l, t);
p->pos = laser_pos_at(l, t);
if(t == 0) {
p->prevpos = p->pos;

View file

@ -603,7 +603,7 @@ TASK(laser_pattern_fairy, { cmplx pos; cmplx dir; }) {
int count = 5;
real length = difficulty_value(20,30,40,50);
for(int i = 0; i < count; i++) {
create_laser(e->pos, length, 200, RGBA(0.7, 1.0, 0.2, 0), las_linear, 3*ARGS.dir*cdir(M_TAU/count * i), 0, 0, 0);
create_lasercurve1c(e->pos, length, 200, RGBA(0.7, 1.0, 0.2, 0), las_linear, 3*ARGS.dir*cdir(M_TAU/count * i));
}
play_sfx("laser1");

View file

@ -678,9 +678,9 @@ TASK(lasertrap_warning, { cmplx pos; int time; real radius; }) {
static Laser *laser_arc(cmplx center, real lifetime, real radius, real arcangle, real arcshift) {
real a = arcangle/lifetime;
Laser *l = create_laser(
Laser *l = create_lasercurve2c(
center, lifetime, lifetime, RGBA(0.5, 0.1, 1.0, 0), las_circle,
a + I*arcshift/a, radius, 0, 0
a + I*arcshift/a, radius
);
laser_make_static(l);
@ -708,11 +708,11 @@ TASK(lasertrap_arc_bullet, { BoxedLaser l; int timeout; }) {
));
Laser *l = NOT_NULL(ENT_UNBOX(ARGS.l));
p->pos = l->prule(l, 0);
p->pos = laser_pos_at(l, 0);
for(;(l = ENT_UNBOX(ARGS.l)); YIELD) {
p->prevpos = p->pos;
p->pos = l->prule(l, 0);
p->pos = laser_pos_at(l, 0);
iku_lightning_particle(p->pos);
}

View file

@ -22,8 +22,8 @@ TASK(broglie_particle, { BoxedLaser laser; real laser_offset; Color color; bool
real speed = ARGS.fast ? 2.0 : 1.5;
cmplx pos = l->prule(l, ARGS.laser_offset);
cmplx dir = cnormalize(pos - l->prule(l, ARGS.laser_offset-0.1));
cmplx pos = laser_pos_at(l, ARGS.laser_offset);
cmplx dir = cnormalize(pos - laser_pos_at(l, ARGS.laser_offset-0.1));
dir *= cdir(angle_ampl * sin(scatter_time * ARGS.angle_freq) * cos(2 * scatter_time * ARGS.angle_freq));
PROJECTILE(

View file

@ -21,7 +21,7 @@ static real lhc_target_height(int turn) {
TASK(lhc_laser, { BoxedEllyBaryons baryons; int baryon_idx; real direction; Color color;}) {
EllyBaryons *baryons = NOT_NULL(ENT_UNBOX(ARGS.baryons));
Laser *l = TASK_BIND(create_laser(baryons->poss[ARGS.baryon_idx], 200, 300, &ARGS.color, las_linear, ARGS.direction * VIEWPORT_W * 0.005, 0, 0, 0));
Laser *l = TASK_BIND(create_lasercurve1c(baryons->poss[ARGS.baryon_idx], 200, 300, &ARGS.color, las_linear, ARGS.direction * VIEWPORT_W * 0.005));
l->unclearable = true;
INVOKE_SUBTASK(laser_charge, ENT_BOX(l), 200, 30);

View file

@ -26,7 +26,7 @@ static cmplx maxwell_laser(Laser *l, float t) {
}
TASK(maxwell_laser, { cmplx pos; cmplx dir; real phase; real phase_speed; }) {
Laser *l = TASK_BIND(create_laser(ARGS.pos, 200, 10000, RGBA(0, 0.2, 1, 0.0), maxwell_laser, ARGS.dir*VIEWPORT_H*0.005, 0, 0, 0));
Laser *l = TASK_BIND(create_lasercurve1c(ARGS.pos, 200, 10000, RGBA(0, 0.2, 1, 0.0), maxwell_laser, ARGS.dir*VIEWPORT_H*0.005));
INVOKE_SUBTASK(laser_charge, ENT_BOX(l), .charge_delay = 200, .target_width = 15);

View file

@ -36,7 +36,7 @@ static real safe_radius(real phase) {
}
TASK(ricci_laser, { BoxedEllyBaryons baryons; int baryon_idx; cmplx offset; Color color; real turn_speed; real timespan; int time_offset; }) {
Laser *l = TASK_BIND(create_laser(0, ARGS.timespan, 60, &ARGS.color, las_circle, ARGS.turn_speed + I * ARGS.time_offset, 0, 0, 0));
Laser *l = TASK_BIND(create_lasercurve1c(0, ARGS.timespan, 60, &ARGS.color, las_circle, ARGS.turn_speed + I * ARGS.time_offset));
real radius = SAFE_RADIUS_MAX * difficulty_value(0.4, 0.47, 0.53, 0.6);

View file

@ -377,20 +377,20 @@ TASK(toe_laser_respawn, { cmplx pos; cmplx vel; int type; }) {
}
DEFINE_TASK(toe_laser) {
Laser *l = TASK_BIND(create_laser(ARGS.pos, LASER_LENGTH, ARGS.deathtime, RGBA(1, 1, 1, 0),
toe_laser_pos,
ARGS.vel,
ARGS.type,
0,
0
));
Laser *l = TASK_BIND(
create_lasercurve2c(ARGS.pos, LASER_LENGTH, ARGS.deathtime, RGBA(1, 1, 1, 0),
toe_laser_pos,
ARGS.vel,
ARGS.type
)
);
toe_laser_particle(l, ARGS.pos);
cmplx drift = 0.2 * I;
for(int t = 0;; t++) {
if(t == l->deathtime - 1) {
cmplx newpos = l->prule(l, l->deathtime);
cmplx newpos = laser_pos_at(l, l->deathtime);
INVOKE_TASK(toe_laser_respawn, newpos, ARGS.vel, ARGS.type);
}