summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/modules/sparkler/burst.c38
-rw-r--r--src/modules/sparkler/burst.h9
-rw-r--r--src/modules/sparkler/burst_params.def7
-rw-r--r--src/modules/sparkler/params_def.def21
-rw-r--r--src/modules/sparkler/params_undef.def19
-rw-r--r--src/modules/sparkler/particle.c12
-rw-r--r--src/modules/sparkler/particle.h14
-rw-r--r--src/modules/sparkler/particles.c30
-rw-r--r--src/modules/sparkler/particles.h6
-rw-r--r--src/modules/sparkler/rocket.c56
-rw-r--r--src/modules/sparkler/simple.c15
-rw-r--r--src/modules/sparkler/spark.c3
-rw-r--r--src/modules/sparkler/sparkler.c4
-rw-r--r--src/modules/sparkler/xplode.c49
-rw-r--r--src/modules/sparkler/xplode.h9
-rw-r--r--src/modules/sparkler/xplode_params.def8
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"
+
© All Rights Reserved