diff options
-rw-r--r-- | src/modules/sparkler/burst.c | 38 | ||||
-rw-r--r-- | src/modules/sparkler/burst.h | 9 | ||||
-rw-r--r-- | src/modules/sparkler/burst_params.def | 7 | ||||
-rw-r--r-- | src/modules/sparkler/params_def.def | 21 | ||||
-rw-r--r-- | src/modules/sparkler/params_undef.def | 19 | ||||
-rw-r--r-- | src/modules/sparkler/particle.c | 12 | ||||
-rw-r--r-- | src/modules/sparkler/particle.h | 14 | ||||
-rw-r--r-- | src/modules/sparkler/particles.c | 30 | ||||
-rw-r--r-- | src/modules/sparkler/particles.h | 6 | ||||
-rw-r--r-- | src/modules/sparkler/rocket.c | 56 | ||||
-rw-r--r-- | src/modules/sparkler/simple.c | 15 | ||||
-rw-r--r-- | src/modules/sparkler/spark.c | 3 | ||||
-rw-r--r-- | src/modules/sparkler/sparkler.c | 4 | ||||
-rw-r--r-- | src/modules/sparkler/xplode.c | 49 | ||||
-rw-r--r-- | src/modules/sparkler/xplode.h | 9 | ||||
-rw-r--r-- | src/modules/sparkler/xplode_params.def | 8 |
16 files changed, 219 insertions, 81 deletions
diff --git a/src/modules/sparkler/burst.c b/src/modules/sparkler/burst.c index cf35b31..ae74e26 100644 --- a/src/modules/sparkler/burst.c +++ b/src/modules/sparkler/burst.c @@ -1,6 +1,8 @@ +#include <stdarg.h> #include <stdlib.h> #include "bsp.h" +#include "burst.h" #include "container.h" #include "particle.h" #include "particles.h" @@ -9,21 +11,33 @@ /* a "burst" (shockwave) particle type */ /* this doesn't draw anything, it just pushes neighbors away in an increasing radius */ -#define BURST_FORCE 0.01f -#define BURST_MAX_LIFETIME 8 - typedef struct _burst_ctxt_t { - int longevity; - int lifetime; +#define PARAMS_DECLARE_STRUCT +#include "burst_params.def" + int age; } burst_ctxt_t; -static int burst_init(particles_t *particles, const particles_conf_t *conf, particle_t *p) +static int burst_init(particles_t *particles, const particles_conf_t *conf, particle_t *p, unsigned n_params, va_list params) { burst_ctxt_t *ctxt = p->ctxt; - ctxt->longevity = ctxt->lifetime = BURST_MAX_LIFETIME; +#define PARAMS_ASSIGN_DEFAULTS +#include "burst_params.def" + + for (; n_params; n_params--) { + switch (va_arg(params, burst_param_t)) { +#define PARAMS_IMPLEMENT_SWITCH +#include "burst_params.def" + default: + return 0; + } + } + p->props->virtual = 1; + ctxt->age = ctxt->duration; + p->props->velocity = 0; /* burst should be stationary */ + p->props->mass = 0; /* no mass prevents gravity's effects */ return 1; } @@ -31,14 +45,15 @@ static int burst_init(particles_t *particles, const particles_conf_t *conf, part static inline void thrust_part(particle_t *burst, particle_t *victim, float distance_sq) { - v3f_t direction = v3f_sub(&victim->props->position, &burst->props->position); + burst_ctxt_t *ctxt = burst->ctxt; + v3f_t direction = v3f_sub(&victim->props->position, &burst->props->position); /* TODO: normalize is expensive, see about removing these. */ direction = v3f_normalize(&direction); victim->props->direction = v3f_add(&victim->props->direction, &direction); victim->props->direction = v3f_normalize(&victim->props->direction); - victim->props->velocity += BURST_FORCE; + victim->props->velocity += ctxt->force; } @@ -100,12 +115,13 @@ static particle_status_t burst_sim(particles_t *particles, const particles_conf_ bsp_t *bsp = particles_bsp(particles); /* XXX see note above about bsp_occupant_t */ burst_sphere_t s; - if (!ctxt->longevity || (ctxt->longevity--) <= 0) { + if (!ctxt->duration || (ctxt->duration--) <= 0) { return PARTICLE_DEAD; } /* affect neighbors for the shock-wave */ - s.radius_min = (1.0f - ((float)ctxt->longevity / ctxt->lifetime)) * 0.075f; + /* TODO: ctxt->radius should probably describe the max radius, and the min - .01f... FIXME later. */ + s.radius_min = (1.0f - ((float)ctxt->duration / ctxt->age)) * ctxt->radius; s.radius_max = s.radius_min + .01f; s.center = s.last = p; s.trace_matches = (conf->show_bsp_matches && !conf->show_bsp_matches_affected_only); diff --git a/src/modules/sparkler/burst.h b/src/modules/sparkler/burst.h new file mode 100644 index 0000000..ea5095e --- /dev/null +++ b/src/modules/sparkler/burst.h @@ -0,0 +1,9 @@ +#ifndef _BURST_H +#define _BURST_H + +typedef enum burst_param_t { +#define PARAMS_DECLARE_ENUM +#include "burst_params.def" +} burst_param_t; + +#endif diff --git a/src/modules/sparkler/burst_params.def b/src/modules/sparkler/burst_params.def new file mode 100644 index 0000000..97d66ae --- /dev/null +++ b/src/modules/sparkler/burst_params.def @@ -0,0 +1,7 @@ +#include "params_def.def" + +param(radius, 0.075f, BURST_PARAM_RADIUS_FLOAT, float, double) /* eventual radius of burst */ +param(force, 0.01f, BURST_PARAM_FORCE_FLOAT, float, double) /* how much to accelerate victims */ +param(duration, 7, BURST_PARAM_DURATION_UINT, unsigned, unsigned) /* how many steps to perform the burst */ + +#include "params_undef.def" diff --git a/src/modules/sparkler/params_def.def b/src/modules/sparkler/params_def.def new file mode 100644 index 0000000..cd27423 --- /dev/null +++ b/src/modules/sparkler/params_def.def @@ -0,0 +1,21 @@ +#ifdef PARAMS_DECLARE_ENUM +#define param(_member, _default, _sym, _ctxt_type, _va_type) \ + _sym, +#endif + +#ifdef PARAMS_DECLARE_STRUCT +#define param(_member, _default, _sym, _ctxt_type, _va_type) \ + _ctxt_type _member; +#endif + +#ifdef PARAMS_IMPLEMENT_SWITCH +#define param(_member, _default, _sym, _ctxt_type, _va_type) \ + case _sym: \ + ctxt->_member = va_arg(params, _va_type); \ + break; +#endif + +#ifdef PARAMS_ASSIGN_DEFAULTS +#define param(_member, _default, _sym, _ctxt_type, _va_type) \ + ctxt->_member = _default; +#endif diff --git a/src/modules/sparkler/params_undef.def b/src/modules/sparkler/params_undef.def new file mode 100644 index 0000000..f8f8440 --- /dev/null +++ b/src/modules/sparkler/params_undef.def @@ -0,0 +1,19 @@ +#ifdef param +#undef param +#endif + +#ifdef PARAMS_DECLARE_ENUM +#undef PARAMS_DECLARE_ENUM +#endif + +#ifdef PARAMS_DECLARE_STRUCT +#undef PARAMS_DECLARE_STRUCT +#endif + +#ifdef PARAMS_IMPLEMENT_SWITCH +#undef PARAMS_IMPLEMENT_SWITCH +#endif + +#ifdef PARAMS_ASSIGN_DEFAULTS +#undef PARAMS_ASSIGN_DEFAULTS +#endif diff --git a/src/modules/sparkler/particle.c b/src/modules/sparkler/particle.c index 76d0c70..a3184ea 100644 --- a/src/modules/sparkler/particle.c +++ b/src/modules/sparkler/particle.c @@ -1,8 +1,14 @@ +#include <stdarg.h> + #include "particle.h" /* convert a particle to a new type */ -void particle_convert(particles_t *particles, const particles_conf_t *conf, particle_t *p, particle_props_t *props, particle_ops_t *ops) +void particle_convert(particles_t *particles, const particles_conf_t *conf, particle_t *p, particle_props_t *props, particle_ops_t *ops, unsigned n_params, ...) { + va_list ap; + + va_start(ap, n_params); + particle_cleanup(particles, conf, p); if (props) { *p->props = *props; @@ -10,5 +16,7 @@ void particle_convert(particles_t *particles, const particles_conf_t *conf, part if (ops) { p->ops = ops; } - particle_init(particles, conf, p); + particle_init(particles, conf, p, n_params, ap); + + va_end(ap); } diff --git a/src/modules/sparkler/particle.h b/src/modules/sparkler/particle.h index a7c4138..491dc65 100644 --- a/src/modules/sparkler/particle.h +++ b/src/modules/sparkler/particle.h @@ -1,6 +1,8 @@ #ifndef _PARTICLE_H #define _PARTICLE_H +#include <stdarg.h> + #include "til_fb.h" #include "bsp.h" @@ -26,10 +28,10 @@ typedef struct particles_t particles_t; typedef struct particles_conf_t particles_conf_t; typedef struct particle_ops_t { - unsigned context_size; /* size of the particle context (0 for none) */ - int (*init)(particles_t *, const particles_conf_t *, particle_t *); /* initialize the particle, called after allocating context (optional) */ + unsigned context_size; /* size of the particle context (0 for none) */ + int (*init)(particles_t *, const particles_conf_t *, particle_t *, unsigned, va_list); /* initialize the particle, called after allocating context (optional) */ void (*cleanup)(particles_t *, const particles_conf_t *, particle_t *); /* cleanup function, called before freeing context (optional) */ - particle_status_t (*sim)(particles_t *, const particles_conf_t *, particle_t *, til_fb_fragment_t *); /* simulate the particle for another cycle (required) */ + particle_status_t (*sim)(particles_t *, const particles_conf_t *, particle_t *, til_fb_fragment_t *); /* simulate the particle for another cycle (required) */ void (*draw)(particles_t *, const particles_conf_t *, particle_t *, int, int, til_fb_fragment_t *); /* draw the particle, 3d->2d projection has been done already (optional) */ } particle_ops_t; @@ -49,9 +51,9 @@ struct particle_t { #define INHERIT_PROPS NULL -static inline int particle_init(particles_t *particles, const particles_conf_t *conf, particle_t *p) { +static inline int particle_init(particles_t *particles, const particles_conf_t *conf, particle_t *p, unsigned n_params, va_list params) { if (p->ops->init) { - return p->ops->init(particles, conf, p); + return p->ops->init(particles, conf, p, n_params, params); } return 1; @@ -81,6 +83,6 @@ static inline void particle_draw(particles_t *particles, const particles_conf_t } -void particle_convert(particles_t *particles, const particles_conf_t *conf, particle_t *p, particle_props_t *props, particle_ops_t *ops); +void particle_convert(particles_t *particles, const particles_conf_t *conf, particle_t *p, particle_props_t *props, particle_ops_t *ops, unsigned n_params, ...); #endif diff --git a/src/modules/sparkler/particles.c b/src/modules/sparkler/particles.c index f6adf13..8fc93a2 100644 --- a/src/modules/sparkler/particles.c +++ b/src/modules/sparkler/particles.c @@ -1,4 +1,5 @@ #include <assert.h> +#include <stdarg.h> #include <stdio.h> #include <stdlib.h> #include <sys/types.h> @@ -128,7 +129,7 @@ static void particles_reap_particle(particles_t *particles, _particle_t *particl /* add a particle to the specified list */ -static inline int _particles_add_particle(particles_t *particles, list_head_t *list, particle_props_t *props, particle_ops_t *ops) +static inline int _particles_add_particle(particles_t *particles, list_head_t *list, particle_props_t *props, particle_ops_t *ops, unsigned n_params, va_list ap) { _particle_t *p; @@ -158,7 +159,7 @@ static inline int _particles_add_particle(particles_t *particles, list_head_t *l p->public.ctxt = p->context; } - if (!particle_init(particles, &particles->conf, &p->public)) { + if (!particle_init(particles, &particles->conf, &p->public, n_params, ap)) { /* XXX FIXME this shouldn't be normal, we don't want to allocate * particles that cannot be initialized. the rockets today set a cap * by failing initialization, that's silly. */ @@ -175,36 +176,49 @@ static inline int _particles_add_particle(particles_t *particles, list_head_t *l /* add a new "top-level" particle of the specified props and ops taking from the provided parts list */ -int particles_add_particle(particles_t *particles, particle_props_t *props, particle_ops_t *ops) +int particles_add_particle(particles_t *particles, particle_props_t *props, particle_ops_t *ops, unsigned n_params, ...) { + int ret; + va_list ap; + assert(particles); - return _particles_add_particle(particles, &particles->active, props, ops); + va_start(ap, n_params); + ret = _particles_add_particle(particles, &particles->active, props, ops, n_params, ap); + va_end(ap); + + return ret; } /* spawn a new child particle from a parent, initializing it via inheritance if desired */ -void particles_spawn_particle(particles_t *particles, particle_t *parent, particle_props_t *props, particle_ops_t *ops) +void particles_spawn_particle(particles_t *particles, particle_t *parent, particle_props_t *props, particle_ops_t *ops, unsigned n_params, ...) { + va_list ap; _particle_t *p = container_of(parent, _particle_t, public); assert(particles); assert(parent); - _particles_add_particle(particles, &p->children, props ? props : parent->props, ops ? ops : parent->ops); + va_start(ap, n_params); + _particles_add_particle(particles, &p->children, props ? props : parent->props, ops ? ops : parent->ops, n_params, ap); + va_end(ap); } /* plural version of particle_add(); adds multiple "top-level" particles of uniform props and ops */ -void particles_add_particles(particles_t *particles, particle_props_t *props, particle_ops_t *ops, int num) +void particles_add_particles(particles_t *particles, particle_props_t *props, particle_ops_t *ops, unsigned num, unsigned n_params, ...) { + va_list ap; int i; assert(particles); + va_start(ap, n_params); for (i = 0; i < num; i++) { - _particles_add_particle(particles, &particles->active, props, ops); + _particles_add_particle(particles, &particles->active, props, ops, n_params, ap); } + va_end(ap); } diff --git a/src/modules/sparkler/particles.h b/src/modules/sparkler/particles.h index a419e2c..d3add36 100644 --- a/src/modules/sparkler/particles.h +++ b/src/modules/sparkler/particles.h @@ -23,9 +23,9 @@ void particles_draw(particles_t *particles, til_fb_fragment_t *fragment); particle_status_t particles_sim(particles_t *particles, til_fb_fragment_t *fragment); void particles_age(particles_t *particles); void particles_free(particles_t *particles); -int particles_add_particle(particles_t *particles, particle_props_t *props, particle_ops_t *ops); -void particles_spawn_particle(particles_t *particles, particle_t *parent, particle_props_t *props, particle_ops_t *ops); -void particles_add_particles(particles_t *particles, particle_props_t *props, particle_ops_t *ops, int num); +int particles_add_particle(particles_t *particles, particle_props_t *props, particle_ops_t *ops, unsigned n_params, ...); +void particles_spawn_particle(particles_t *particles, particle_t *parent, particle_props_t *props, particle_ops_t *ops, unsigned n_params, ...); +void particles_add_particles(particles_t *particles, particle_props_t *props, particle_ops_t *ops, unsigned num, unsigned n_params, ...); bsp_t * particles_bsp(particles_t *particles); void particles_draw_line(particles_t *particles, const v3f_t *a, const v3f_t *b, til_fb_fragment_t *fragment); diff --git a/src/modules/sparkler/rocket.c b/src/modules/sparkler/rocket.c index 8afceb4..e0b17a2 100644 --- a/src/modules/sparkler/rocket.c +++ b/src/modules/sparkler/rocket.c @@ -1,10 +1,13 @@ +#include <stdarg.h> #include <stdlib.h> #include "til_fb.h" +#include "burst.h" #include "helpers.h" #include "particle.h" #include "particles.h" +#include "xplode.h" /* a "rocket" particle type */ #define ROCKET_MAX_DECAY_RATE 20 @@ -28,8 +31,16 @@ typedef struct rocket_ctxt_t { float last_velocity; /* cache velocity to sense violent accelerations and explode when they happen */ } rocket_ctxt_t; +static unsigned xplode_colors[] = { + 0xffff00, + 0xff0000, + 0xff00ff, + 0x00ffff, + 0x0000ff, + 0x00ff00, +}; -static int rocket_init(particles_t *particles, const particles_conf_t *conf, particle_t *p) +static int rocket_init(particles_t *particles, const particles_conf_t *conf, particle_t *p, unsigned n_params, va_list params) { rocket_ctxt_t *ctxt = p->ctxt; @@ -41,9 +52,9 @@ static int rocket_init(particles_t *particles, const particles_conf_t *conf, par ctxt->decay_rate = rand_within_range(conf->seedp, ROCKET_MIN_DECAY_RATE, ROCKET_MAX_DECAY_RATE); ctxt->longevity = rand_within_range(conf->seedp, ROCKET_MIN_LIFETIME, ROCKET_MAX_LIFETIME); - ctxt->wander.x = (float)(rand_within_range(conf->seedp, 0, 628) - 314) / 10000.0f; - ctxt->wander.y = (float)(rand_within_range(conf->seedp, 0, 628) - 314) / 10000.0f; - ctxt->wander.z = (float)(rand_within_range(conf->seedp, 0, 628) - 314) / 10000.0f; + ctxt->wander.x = (float)(rand_within_range(conf->seedp, 0, 628) - 314) * .0001; + ctxt->wander.y = (float)(rand_within_range(conf->seedp, 0, 628) - 314) * .0001; + ctxt->wander.z = (float)(rand_within_range(conf->seedp, 0, 628) - 314) * .0001; ctxt->wander = v3f_normalize(&ctxt->wander); ctxt->last_velocity = p->props->velocity; @@ -63,31 +74,34 @@ static particle_status_t rocket_sim(particles_t *particles, const particles_conf if (!ctxt->longevity || (ctxt->longevity -= ctxt->decay_rate) <= 0 || p->props->velocity - ctxt->last_velocity > p->props->velocity * .05) { /* explode if accelerated too hard (burst) */ - int n_xplode; + int n_xplode; + unsigned color = xplode_colors[rand_within_range(conf->seedp, 0, nelems(xplode_colors))]; /* on death we explode */ ctxt->longevity = 0; - /* add a burst shockwave particle at our location - * TODO: need way to supply particle-type-specific parameters at spawn (burst size should derive from n_xplode) - */ - particles_spawn_particle(particles, p, NULL, &burst_ops); - /* add a bunch of new explosion particles */ - /* TODO: also particle-type-specific parameters, colors! rocket bursts should be able to vary the color. */ + /* how many explosion particles? */ n_xplode = rand_within_range(conf->seedp, ROCKETS_XPLODE_MIN_SIZE, ROCKETS_XPLODE_MAX_SIZE); + + /* add a burst shockwave particle at our location, scale force + * and radius according to explosion size. + */ + particles_spawn_particle(particles, p, NULL, &burst_ops, 1, BURST_PARAM_FORCE_FLOAT, (float)n_xplode * 0.00001f); + + /* add the explosion particles */ for (i = 0; i < n_xplode; i++) { particle_props_t props = *p->props; particle_ops_t *ops = &xplode_ops; - props.direction.x = ((float)(rand_within_range(conf->seedp, 0, 314159 * 2) - 314159) / 100000.0); - props.direction.y = ((float)(rand_within_range(conf->seedp, 0, 314159 * 2) - 314159) / 100000.0); - props.direction.z = ((float)(rand_within_range(conf->seedp, 0, 314159 * 2) - 314159) / 100000.0); + props.direction.x = ((float)(rand_within_range(conf->seedp, 0, 31415900 * 2) - 31415900) * .0000001); + props.direction.y = ((float)(rand_within_range(conf->seedp, 0, 31415900 * 2) - 31415900) * .0000001); + props.direction.z = ((float)(rand_within_range(conf->seedp, 0, 31415900 * 2) - 31415900) * .0000001); props.direction = v3f_normalize(&props.direction); //props->velocity = ((float)rand_within_range(100, 200) / 100000.0); - props.velocity = ((float)rand_within_range(conf->seedp, 100, 300) / 100000.0); - particles_spawn_particle(particles, p, &props, ops); + props.velocity = ((float)rand_within_range(conf->seedp, 100, 400) * .00001); + particles_spawn_particle(particles, p, &props, ops, 1, XPLODE_PARAM_COLOR_UINT, color); } return PARTICLE_DEAD; } @@ -106,13 +120,13 @@ static particle_status_t rocket_sim(particles_t *particles, const particles_conf props.direction = v3f_negate(&props.direction); - props.direction.x += (float)(rand_within_range(conf->seedp, 0, 40) - 20) / 100.0; - props.direction.y += (float)(rand_within_range(conf->seedp, 0, 40) - 20) / 100.0; - props.direction.z += (float)(rand_within_range(conf->seedp, 0, 40) - 20) / 100.0; + props.direction.x += (float)(rand_within_range(conf->seedp, 0, 40) - 20) * .01; + props.direction.y += (float)(rand_within_range(conf->seedp, 0, 40) - 20) * .01; + props.direction.z += (float)(rand_within_range(conf->seedp, 0, 40) - 20) * .01; props.direction = v3f_normalize(&props.direction); - props.velocity = (float)rand_within_range(conf->seedp, 10, 50) / 100000.0; - particles_spawn_particle(particles, p, &props, &spark_ops); + props.velocity = (float)rand_within_range(conf->seedp, 10, 50) * .00001; + particles_spawn_particle(particles, p, &props, &spark_ops, 0); } ctxt->last_velocity = p->props->velocity; diff --git a/src/modules/sparkler/simple.c b/src/modules/sparkler/simple.c index 3bc3076..74b3d58 100644 --- a/src/modules/sparkler/simple.c +++ b/src/modules/sparkler/simple.c @@ -1,3 +1,4 @@ +#include <stdarg.h> #include <stdlib.h> #include "til_fb.h" @@ -24,7 +25,7 @@ typedef struct _simple_ctxt_t { } simple_ctxt_t; -static int simple_init(particles_t *particles, const particles_conf_t *conf, particle_t *p) +static int simple_init(particles_t *particles, const particles_conf_t *conf, particle_t *p, unsigned n_params, va_list params) { simple_ctxt_t *ctxt = p->ctxt; @@ -78,17 +79,17 @@ static particle_status_t simple_sim(particles_t *particles, const particles_conf if (i == (SIMPLE_MAX_SPAWN - 2)) { ops = &rocket_ops; - props.velocity = (float)rand_within_range(conf->seedp, 60, 100) / 1000000.0; + props.velocity = (float)rand_within_range(conf->seedp, 60, 100) * .000001; } else { - props.velocity = (float)rand_within_range(conf->seedp, 30, 100) / 10000.0; + props.velocity = (float)rand_within_range(conf->seedp, 30, 400) * .00001; } - props.direction.x += (float)(rand_within_range(conf->seedp, 0, 315 * 2) - 315) / 100.0; - props.direction.y += (float)(rand_within_range(conf->seedp, 0, 315 * 2) - 315) / 100.0; - props.direction.z += (float)(rand_within_range(conf->seedp, 0, 315 * 2) - 315) / 100.0; + props.direction.x += (float)(rand_within_range(conf->seedp, 0, 315 * 2) - 315) * .01; + props.direction.y += (float)(rand_within_range(conf->seedp, 0, 315 * 2) - 315) * .01; + props.direction.z += (float)(rand_within_range(conf->seedp, 0, 315 * 2) - 315) * .01; props.direction = v3f_normalize(&props.direction); - particles_spawn_particle(particles, p, &props, ops); // XXX + particles_spawn_particle(particles, p, &props, ops, 0); // XXX } } diff --git a/src/modules/sparkler/spark.c b/src/modules/sparkler/spark.c index 3e45cc8..6866999 100644 --- a/src/modules/sparkler/spark.c +++ b/src/modules/sparkler/spark.c @@ -1,3 +1,4 @@ +#include <stdarg.h> #include <stdlib.h> #include "til_fb.h" @@ -19,7 +20,7 @@ typedef struct _spark_ctxt_t { } spark_ctxt_t; -static int spark_init(particles_t *particles, const particles_conf_t *conf, particle_t *p) +static int spark_init(particles_t *particles, const particles_conf_t *conf, particle_t *p, unsigned n_params, va_list params) { spark_ctxt_t *ctxt = p->ctxt; diff --git a/src/modules/sparkler/sparkler.c b/src/modules/sparkler/sparkler.c index 1e7e171..76f1c9b 100644 --- a/src/modules/sparkler/sparkler.c +++ b/src/modules/sparkler/sparkler.c @@ -55,7 +55,7 @@ static til_module_context_t * sparkler_create_context(const til_module_t *module return NULL; } - particles_add_particles(ctxt->particles, NULL, &simple_ops, INIT_PARTS); + particles_add_particles(ctxt->particles, NULL, &simple_ops, INIT_PARTS, 0); return &ctxt->til_module_context; } @@ -81,7 +81,7 @@ static void sparkler_prepare_frame(til_module_context_t *context, til_stream_t * til_fb_fragment_clear(fragment); particles_sim(ctxt->particles, fragment); - particles_add_particles(ctxt->particles, NULL, &simple_ops, INIT_PARTS / 4); + particles_add_particles(ctxt->particles, NULL, &simple_ops, INIT_PARTS / 4, 0); particles_age(ctxt->particles); } diff --git a/src/modules/sparkler/xplode.c b/src/modules/sparkler/xplode.c index 1534369..bf50a10 100644 --- a/src/modules/sparkler/xplode.c +++ b/src/modules/sparkler/xplode.c @@ -1,3 +1,4 @@ +#include <stdarg.h> #include <stdlib.h> #include "til_fb.h" @@ -5,31 +6,38 @@ #include "helpers.h" #include "particle.h" #include "particles.h" +#include "xplode.h" -/* a "xplode" particle type, emitted by rockets in large numbers at the end of their lifetime */ -#define XPLODE_MAX_DECAY_RATE 10 -#define XPLODE_MIN_DECAY_RATE 5 -#define XPLODE_MAX_LIFETIME 150 -#define XPLODE_MIN_LIFETIME 5 +/* a "xplode" particle type, emitted by rockets in large numbers at the end of their duration */ extern particle_ops_t spark_ops; particle_ops_t xplode_ops; typedef struct _xplode_ctxt_t { - int decay_rate; - int longevity; - int lifetime; +#define PARAMS_DECLARE_STRUCT +#include "xplode_params.def" + int remaining; } xplode_ctxt_t; -static int xplode_init(particles_t *particles, const particles_conf_t *conf, particle_t *p) +static int xplode_init(particles_t *particles, const particles_conf_t *conf, particle_t *p, unsigned n_params, va_list params) { xplode_ctxt_t *ctxt = p->ctxt; - ctxt->decay_rate = rand_within_range(conf->seedp, XPLODE_MIN_DECAY_RATE, XPLODE_MAX_DECAY_RATE); - ctxt->lifetime = ctxt->longevity = rand_within_range(conf->seedp, XPLODE_MIN_LIFETIME, XPLODE_MAX_LIFETIME); +#define PARAMS_ASSIGN_DEFAULTS +#include "xplode_params.def" - p->props->drag = 10.9; + for (; n_params; n_params--) { + switch (va_arg(params, xplode_param_t)) { +#define PARAMS_IMPLEMENT_SWITCH +#include "xplode_params.def" + default: + return 0; + } + } + + ctxt->remaining = ctxt->duration; + p->props->drag = 10.5; p->props->mass = 0.3; p->props->virtual = 0; @@ -41,17 +49,17 @@ static particle_status_t xplode_sim(particles_t *particles, const particles_conf { xplode_ctxt_t *ctxt = p->ctxt; - if (!ctxt->longevity || (ctxt->longevity -= ctxt->decay_rate) <= 0) { - ctxt->longevity = 0; + if (!ctxt->remaining || (ctxt->remaining -= ctxt->decay_rate) <= 0) { + ctxt->remaining = 0; return PARTICLE_DEAD; } /* litter some small sparks behind the explosion particle */ - if (!(ctxt->lifetime % 30)) { + if (!(ctxt->duration % 30)) { particle_props_t props = *p->props; - props.velocity = (float)rand_within_range(conf->seedp, 10, 50) / 10000.0; - particles_spawn_particle(particles, p, &props, &xplode_ops); + props.velocity = (float)rand_within_range(conf->seedp, 10, 50) * .0001; + particles_spawn_particle(particles, p, &props, &xplode_ops, 1, XPLODE_PARAM_COLOR_UINT, ctxt->color); } return PARTICLE_ALIVE; @@ -63,13 +71,14 @@ static void xplode_draw(particles_t *particles, const particles_conf_t *conf, pa xplode_ctxt_t *ctxt = p->ctxt; uint32_t color; - if (!should_draw_expire_if_oob(particles, p, x, y, f, &ctxt->longevity)) + if (!should_draw_expire_if_oob(particles, p, x, y, f, &ctxt->remaining)) return; - if (ctxt->longevity == ctxt->lifetime) { + if (ctxt->remaining == ctxt->duration) { + /* always start with a white flash */ color = makergb(0xff, 0xff, 0xa0, 1.0); } else { - color = makergb(0xff, 0xff, 0x00, ((float)ctxt->longevity / ctxt->lifetime)); + color = makergb((ctxt->color & 0xff0000) >> 16, (ctxt->color & 0xff00) >> 8, ctxt->color & 0xff, ((float)ctxt->remaining / ctxt->duration)); } til_fb_fragment_put_pixel_unchecked(f, 0, x, y, color); diff --git a/src/modules/sparkler/xplode.h b/src/modules/sparkler/xplode.h new file mode 100644 index 0000000..d0bac58 --- /dev/null +++ b/src/modules/sparkler/xplode.h @@ -0,0 +1,9 @@ +#ifndef _XPLODE_H +#define _XPLODE_H + +typedef enum xplode_param_t { +#define PARAMS_DECLARE_ENUM +#include "xplode_params.def" +} xplode_param_t; + +#endif diff --git a/src/modules/sparkler/xplode_params.def b/src/modules/sparkler/xplode_params.def new file mode 100644 index 0000000..dacb920 --- /dev/null +++ b/src/modules/sparkler/xplode_params.def @@ -0,0 +1,8 @@ +#include "params_def.def" + +param(color, 0xffff00, XPLODE_PARAM_COLOR_UINT, unsigned, unsigned) +param(decay_rate, rand_within_range(conf->seedp, 6, 10), XPLODE_PARAM_DECAY_INT, int, int) +param(duration, rand_within_range(conf->seedp, 50, 150), XPLODE_PARAM_DURATION_INT, int, int) + +#include "params_undef.def" + |