diff options
author | Vito Caputo <vcaputo@gnugeneration.com> | 2017-01-18 17:14:52 -0800 |
---|---|---|
committer | Vito Caputo <vcaputo@gnugeneration.com> | 2017-01-18 17:31:44 -0800 |
commit | 524db0cf19648e3c7c78d3e73103b7a0bdcd6bfc (patch) | |
tree | 6fd682629904a210927797c92d956c208666b03a /src/modules/sparkler/rocket.c | |
parent | ee2073d4e411555aba878277131b56f7eb562c84 (diff) |
*: move source into src/ subdir
Restoring some organizational sanity since adopting autotools.
Diffstat (limited to 'src/modules/sparkler/rocket.c')
-rw-r--r-- | src/modules/sparkler/rocket.c | 144 |
1 files changed, 144 insertions, 0 deletions
diff --git a/src/modules/sparkler/rocket.c b/src/modules/sparkler/rocket.c new file mode 100644 index 0000000..6b9dc5e --- /dev/null +++ b/src/modules/sparkler/rocket.c @@ -0,0 +1,144 @@ +#include <stdlib.h> + +#include "draw.h" +#include "particle.h" +#include "particles.h" + +/* a "rocket" particle type */ +#define ROCKET_MAX_DECAY_RATE 20 +#define ROCKET_MIN_DECAY_RATE 2 +#define ROCKET_MAX_LIFETIME 500 +#define ROCKET_MIN_LIFETIME 300 +#define ROCKETS_MAX 20 +#define ROCKETS_XPLODE_MIN_SIZE 2000 +#define ROCKETS_XPLODE_MAX_SIZE 8000 + +extern particle_ops_t burst_ops; +extern particle_ops_t spark_ops; +extern particle_ops_t xplode_ops; + +static unsigned rockets_cnt; + +typedef struct rocket_ctxt_t { + int decay_rate; + int longevity; + v3f_t wander; + float last_velocity; /* cache velocity to sense violent accelerations and explode when they happen */ +} rocket_ctxt_t; + + +static int rocket_init(particles_t *particles, particle_t *p) +{ + rocket_ctxt_t *ctxt = p->ctxt; + + if (rockets_cnt >= ROCKETS_MAX) { + return 0; + } + rockets_cnt++; + + ctxt->decay_rate = rand_within_range(ROCKET_MIN_DECAY_RATE, ROCKET_MAX_DECAY_RATE); + ctxt->longevity = rand_within_range(ROCKET_MIN_LIFETIME, ROCKET_MAX_LIFETIME); + + ctxt->wander.x = (float)(rand_within_range(0, 628) - 314) / 10000.0f; + ctxt->wander.y = (float)(rand_within_range(0, 628) - 314) / 10000.0f; + ctxt->wander.z = (float)(rand_within_range(0, 628) - 314) / 10000.0f; + ctxt->wander = v3f_normalize(&ctxt->wander); + + ctxt->last_velocity = p->props->velocity; + p->props->drag = 0.4; + p->props->mass = 0.8; + + return 1; +} + + +static particle_status_t rocket_sim(particles_t *particles, particle_t *p) +{ + rocket_ctxt_t *ctxt = p->ctxt; + int i, n_sparks; + + 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; + /* 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. */ + n_xplode = rand_within_range(ROCKETS_XPLODE_MIN_SIZE, ROCKETS_XPLODE_MAX_SIZE); + 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(0, 314159 * 2) - 314159) / 100000.0); + props.direction.y = ((float)(rand_within_range(0, 314159 * 2) - 314159) / 100000.0); + props.direction.z = ((float)(rand_within_range(0, 314159 * 2) - 314159) / 100000.0); + props.direction = v3f_normalize(&props.direction); + + //props->velocity = ((float)rand_within_range(100, 200) / 100000.0); + props.velocity = ((float)rand_within_range(100, 300) / 100000.0); + particles_spawn_particle(particles, p, &props, ops); + } + return PARTICLE_DEAD; + } + +#if 1 + /* FIXME: this isn't behaving as intended */ + p->props->direction = v3f_add(&p->props->direction, &ctxt->wander); + p->props->direction = v3f_normalize(&p->props->direction); +#endif + p->props->velocity += .00003; + + /* spray some sparks behind the rocket */ + n_sparks = rand_within_range(10, 40); + for (i = 0; i < n_sparks; i++) { + particle_props_t props = *p->props; + + props.direction = v3f_negate(&props.direction); + + props.direction.x += (float)(rand_within_range(0, 40) - 20) / 100.0; + props.direction.y += (float)(rand_within_range(0, 40) - 20) / 100.0; + props.direction.z += (float)(rand_within_range(0, 40) - 20) / 100.0; + props.direction = v3f_normalize(&props.direction); + + props.velocity = (float)rand_within_range(10, 50) / 100000.0; + particles_spawn_particle(particles, p, &props, &spark_ops); + } + + ctxt->last_velocity = p->props->velocity; + + return PARTICLE_ALIVE; +} + + +static void rocket_draw(particles_t *particles, particle_t *p, int x, int y, fb_fragment_t *f) +{ + rocket_ctxt_t *ctxt = p->ctxt; + + if (!draw_pixel(f, x, y, 0xff0000)) { + /* kill off parts that wander off screen */ + ctxt->longevity = 0; + } +} + + +static void rocket_cleanup(particles_t *particles, particle_t *p) +{ + rockets_cnt--; +} + + +particle_ops_t rocket_ops = { + .context_size = sizeof(rocket_ctxt_t), + .sim = rocket_sim, + .init = rocket_init, + .draw = rocket_draw, + .cleanup = rocket_cleanup, + }; |