From 6e4b7e63f2d77ccc0e2ea08a75d7c7d7dd8d1dda Mon Sep 17 00:00:00 2001 From: John Alanbrook Date: Thu, 4 Jan 2024 14:14:37 +0000 Subject: [PATCH] particles and warp zones --- docs/warp.md | 9 ++++++++ source/engine/2dphysics.c | 13 +++++++++-- source/engine/2dphysics.h | 2 +- source/engine/gameobject.c | 10 +++++---- source/engine/gameobject.h | 2 ++ source/engine/jsffi.c | 2 +- source/engine/particle.c | 18 ++++++---------- source/engine/particle.h | 22 ++++++++++++++++--- source/engine/warp.c | 44 ++++++++++++++++++++++++++++++++++++++ source/engine/warp.h | 27 +++++++++++++++++++++++ 10 files changed, 126 insertions(+), 23 deletions(-) create mode 100644 docs/warp.md create mode 100644 source/engine/warp.c create mode 100644 source/engine/warp.h diff --git a/docs/warp.md b/docs/warp.md new file mode 100644 index 0000000..9284e00 --- /dev/null +++ b/docs/warp.md @@ -0,0 +1,9 @@ +# Warp effects + +Warp effects deal with particles as well as physics based rigidbodies. + +- Motor: Apply torque. +- Vortex: A whirlpool like force. +- Gravity: A simple gravity force. +- Wind: Wind like force, with simulated turbulence. +- Bomb: Short force radially outwards \ No newline at end of file diff --git a/source/engine/2dphysics.c b/source/engine/2dphysics.c index cc888eb..d9d5c6e 100644 --- a/source/engine/2dphysics.c +++ b/source/engine/2dphysics.c @@ -189,16 +189,25 @@ struct rgba shape_color(cpShape *shape) { return static_color; } +static warp_gravity *space_gravity; + void phys2d_init() { space = cpSpaceNew(); cpSpaceSetSleepTimeThreshold(space, 1); cpSpaceSetCollisionSlop(space, 0.01); cpSpaceSetCollisionBias(space, cpfpow(1.0-0.5, 165.f)); + space_gravity = warp_gravity_make(); + YughWarn("Made gravity with %d spherical", space_gravity->spherical); } -void phys2d_set_gravity(cpVect v) { - cpSpaceSetGravity(space, v); +void phys2d_set_gravity(HMM_Vec2 v) +{ + float str = HMM_LenV2(v); + HMM_Vec2 dir = HMM_NormV2(v); + space_gravity->strength = str; + space_gravity->t.scale = (HMM_Vec3){v.x,v.y, 0}; + space_gravity->planar_force = (HMM_Vec3){v.x,v.y,0}; } void phys2d_update(float deltaT) { cpSpaceStep(space, deltaT); } diff --git a/source/engine/2dphysics.h b/source/engine/2dphysics.h index dc657c0..211164a 100644 --- a/source/engine/2dphysics.h +++ b/source/engine/2dphysics.h @@ -99,7 +99,7 @@ struct shape_cb { void fire_hits(); void phys2d_rm_go_handlers(gameobject *go); -void phys2d_set_gravity(cpVect v); +void phys2d_set_gravity(HMM_Vec2 v); void shape_enabled(struct phys2d_shape *shape, int enabled); int shape_is_enabled(struct phys2d_shape *shape); diff --git a/source/engine/gameobject.c b/source/engine/gameobject.c index fec00d1..b14abaf 100644 --- a/source/engine/gameobject.c +++ b/source/engine/gameobject.c @@ -124,17 +124,19 @@ void gameobject_apply(gameobject *go) { static void velocityFn(cpBody *body, cpVect gravity, cpFloat damping, cpFloat dt) { gameobject *go = body2go(body); + cpVect pos = cpBodyGetPosition(body); + HMM_Vec2 g = warp_force((HMM_Vec3){pos.x, pos.y, 0}, gravmask).xy; if (!go) { - cpBodyUpdateVelocity(body,gravity,damping,dt); + cpBodyUpdateVelocity(body,g.cp,damping,dt); return; } cpFloat d = isfinite(go->damping) ? go->damping : damping; - cpVect g = gravity; + if (isfinite(go->gravity.x) && isfinite(go->gravity.y)) - g = go->gravity.cp; + g = go->gravity; - cpBodyUpdateVelocity(body,g,d,dt*go->timescale); + cpBodyUpdateVelocity(body,g.cp,d,dt*go->timescale); if (isfinite(go->maxvelocity)) cpBodySetVelocity(body, cpvclamp(cpBodyGetVelocity(body), go->maxvelocity)); diff --git a/source/engine/gameobject.h b/source/engine/gameobject.h index 0d5ede8..7fb9e9d 100644 --- a/source/engine/gameobject.h +++ b/source/engine/gameobject.h @@ -5,6 +5,7 @@ #include "HandmadeMath.h" #include "transform.h" #include "script.h" +#include "warp.h" #define dag_rm(p,c) do{\ for (int i = arrlen(p->children)-1; i--; i >=0) {\ @@ -40,6 +41,7 @@ struct gameobject { float damping; unsigned int layer; cpShapeFilter filter; +// warpmask warpmask; struct phys_cbs cbs; struct shape_cb *shape_cbs; JSValue ref; diff --git a/source/engine/jsffi.c b/source/engine/jsffi.c index a910515..c0defdd 100644 --- a/source/engine/jsffi.c +++ b/source/engine/jsffi.c @@ -548,7 +548,7 @@ JSValue duk_cmd(JSContext *js, JSValueConst this, int argc, JSValueConst *argv) break; case 8: - phys2d_set_gravity(js2vec2(argv[1]).cp); + phys2d_set_gravity(js2vec2(argv[1])); break; case 9: diff --git a/source/engine/particle.c b/source/engine/particle.c index 2f42380..36d0d3e 100644 --- a/source/engine/particle.c +++ b/source/engine/particle.c @@ -22,7 +22,6 @@ static int draw_count; struct scheduler sched; void *mem; - struct par_vert { HMM_Vec2 pos; float angle; @@ -88,25 +87,19 @@ void particle_init() } emitter *make_emitter() { - emitter *e = NULL; - e = malloc(sizeof(*e)); + emitter *e = calloc(sizeof(*e),1); + e->max = 20; - e->particles = NULL; arrsetcap(e->particles, e->max); for (int i = 0; i < arrlen(e->particles); i++) e->particles[i].life = 0; e->life = 10; - e->explosiveness = 0; e->tte = lerp(e->explosiveness, e->life/e->max, 0); - e->color.times = NULL; - e->color.data = NULL; - e->color.type = LINEAR; +// e->warp_mask = gravmask; sampler_add(&e->color, 0, (HMM_Vec4){1,1,1,1}); e->scale = 1; e->speed = 20; - e->gravity = 1; - e->on = 0; e->texture = texture_pullfromfile("glass_chunk2.gif"); arrpush(emitters,e); return e; @@ -193,9 +186,10 @@ void parallel_step(emitter *e, struct scheduler *shed, struct sched_task_partiti { for (int i = t.end-1; i >=0; i--) { if (e->particles[i].life <= 0) continue; - if (e->gravity) + + if (e->warp_mask & gravmask) e->particles[i].v = HMM_AddV4(e->particles[i].v, g_accel); - e->particles[i].v = HMM_AddV4(e->particles[i].v, HMM_MulV4F((HMM_Vec4){frand(2)-1, frand(2)-1, 0,0}, 1000*dt)); + e->particles[i].pos = HMM_AddV4(e->particles[i].pos, HMM_MulV4F(e->particles[i].v, dt)); e->particles[i].angle += e->particles[i].av*dt; e->particles[i].life -= dt; diff --git a/source/engine/particle.h b/source/engine/particle.h index a6f78e8..d4d7055 100644 --- a/source/engine/particle.h +++ b/source/engine/particle.h @@ -2,6 +2,7 @@ #define PARTICLE_H #include "HandmadeMath.h" +#include "warp.h" #include "transform.h" #include "texture.h" #include "anim.h" @@ -22,13 +23,28 @@ typedef struct emitter { float explosiveness; /* 0 for a stream, 1 for all at once. Range of values allowed. */ int max; /* number of particles */ double life; /* how long a particle lasts */ - double tte; /* time to emit */ + /* PARTICLE GEN */ + float speed; /* initial speed of particle */ + float variation; /* variation on speed */ + float divergence; /* angular degree of variation from emitter normal, up to 1 */ sampler color; /* color over particle lifetime */ float scale; - float speed; - int gravity; /* true if affected by gravity */ + float scale_var; + float grow_for; /* seconds to grow from small until scale */ + float fade_for; /* seconds to shrink to small prior to its death */ + /* PARTICLE TYPE */ texture *texture; + /* ROTATION AND COLLISION */ + int collision_mask; /* mask for collision */ + float bounce; /* bounce back after collision */ + /* PARTICLE SPAWN */ + int die_after_collision; + float persist; /* how long to linger after death */ + float persist_var; + /* TRAILS */ + warpmask warp_mask; int on; + double tte; /* time to emit */ } emitter; void particle_init(); diff --git a/source/engine/warp.c b/source/engine/warp.c new file mode 100644 index 0000000..25b0b76 --- /dev/null +++ b/source/engine/warp.c @@ -0,0 +1,44 @@ +#include "warp.h" +#include "stb_ds.h" +#include "log.h" + +static warp_gravity **warps = NULL; + +warp_gravity *warp_gravity_make() +{ + warp_gravity *n = calloc(sizeof(*n),0); + n->t.pos = (HMM_Vec3){0,0,0}; + n->strength = 9.8; + n->t.scale = (HMM_Vec3){0,-1,0}; + n->planar_force = HMM_MulV3F(n->t.scale, n->strength); + n->mask = gravmask; + n->spherical = 0; + arrput(warps, n); + return n; +} + +HMM_Vec3 warp_gravity_force(warp_gravity *g, HMM_Vec3 pos) +{ + + HMM_Vec3 f = (HMM_Vec3){0,0,0}; + if (g->strength == 0) return f; + if (g->spherical) { + HMM_Vec3 dir = HMM_SubV3(g->t.pos, pos); + float len = HMM_LenV3(dir); + if (len == 0) return f; + HMM_Vec3 norm = HMM_NormV3(HMM_SubV3(g->t.pos, pos)); + return HMM_MulV3F(norm,g->strength); + } else { + return g->planar_force; + } +} + +HMM_Vec3 warp_force(HMM_Vec3 pos, warpmask mask) +{ + HMM_Vec3 f = (HMM_Vec3){0,0,0}; + for (int i = 0; i < arrlen(warps); i++) { +// if (!(mask & warps[i]->mask)) continue; + f = HMM_AddV3(f, warp_gravity_force(warps[i], pos)); + } + return f; +} diff --git a/source/engine/warp.h b/source/engine/warp.h new file mode 100644 index 0000000..165ad84 --- /dev/null +++ b/source/engine/warp.h @@ -0,0 +1,27 @@ +#ifndef WARP_H +#define WARP_H + +#include "stdint.h" +#include "transform.h" + +typedef uint32_t warpmask; + +#define gravmask 1U + +typedef struct { + transform3d t; + float strength; + float decay; + int spherical; + HMM_Vec3 planar_force; + warpmask mask; +} warp_gravity; + +/* returns the total force for an object at pos */ +HMM_Vec3 warp_force(HMM_Vec3 pos, warpmask mask); + +warp_gravity *warp_gravity_make(); + + + +#endif