Change physics collisions and masks

This commit is contained in:
John Alanbrook 2024-04-12 13:53:00 -05:00
parent 17ad44e5a5
commit c05cb3c6d2
9 changed files with 103 additions and 97 deletions

View file

@ -1530,7 +1530,7 @@ var replpanel = Object.copy(inputpanel, {
this.caret = 0;
var ret = function() {return eval(ecode);}.call(repl_obj);
if (typeof ret === 'object') ret = json.encode(ret,null,1);
if (ret) say(ret);
if (typeof ret !== 'undefined') say(ret);
},
resetscroll() {

View file

@ -524,10 +524,10 @@ var Event = {
Object.keys(this.events).forEach(name => Event.unobserve(name,obj));
},
notify(name) {
notify(name, ...args) {
if (!this.events[name]) return;
this.events[name].forEach(function(x) {
x[1].call(x[0]);
x[1].call(x[0], ...args);
});
},
};

View file

@ -221,13 +221,41 @@ var gameobject = {
ent.objects = {};
ent.timers = [];
if (typeof text === 'object' && text) // assume it's an ur
ent.ur = text;
else
ent.ur = getur(text, config);
Object.mixin(ent, {
set category(n) {
if (n === 0) {
this.categories = n;
return;
}
var cat = (1 << (n-1));
this.categories = cat;
},
get category() {
if (this.categories === 0) return 0;
var pos = 0;
var num = this.categories;
while (num > 0) {
if (num & 1) {
break;
}
pos++;
num >>>= 1;
}
text = ent.ur.text;
config = [ent.ur.data, config];
return pos+1;
}
});
if (typeof text === 'object' && text) {// assume it's an ur
ent.ur = text;
text = ent.ur.text;
config = [ent.ur.data, config].filter(x => x).flat();
}
else {
ent.ur = getur(text, config);
text = ent.ur.text;
config = [ent.ur.data, config];
}
if (typeof text === 'string')
use(text, ent);
@ -264,7 +292,7 @@ var gameobject = {
if (sim.playing())
if (typeof ent.start === 'function') ent.start();
Object.hide(ent, 'ur', 'components', 'objects', 'timers', 'guid', 'master');
Object.hide(ent, 'ur', 'components', 'objects', 'timers', 'guid', 'master', 'categories');
ent._ed = {
selectable: true,
@ -406,7 +434,7 @@ var gameobject = {
},
/* The unique components of this object. Its diff. */
json_obj() {
json_obj(depth=0) {
var fresh = this.ur.fresh;
var thiso = json.decode(json.encode(this)); // TODO: SLOW. Used to ignore properties in toJSON of components.
var d = ediff(thiso, fresh);
@ -698,7 +726,8 @@ game.loadurs = function() {
for (var file of io.glob("**.ur")) {
var newur = ur_from_file(file);
if (!newur) continue;
var urjson = json.decode(io.slurp(file));
var uur = Resources.replstrs(file);
var urjson = json.decode(uur);
Object.assign(newur, urjson);
}
@ -725,4 +754,31 @@ game.loadurs = function() {
}
};
game.ur = {};
game.ur.load = function(str) {}
game.ur.add_data = function(str, data)
{
var nur = ur[str];
if (!nur) {
console.warn(`Cannot add data to the ur ${str}.`);
return;
}
if (!Array.isArray(ur.data)) {
var arr = [];
if (ur.data) arr.push(ur.data);
ur.data = arr;
}
ur.data.push(data);
}
game.ur.save = function(str)
{
var nur = ur[str];
if (!nur) {
console.warn(`Cannot save ur ${str}.`);
return;
}
}
return { go_init }

View file

@ -47,33 +47,11 @@ physics.doc.pos_query = "Returns any object colliding with the given point.";
physics.doc.box_query = "Calls a given function on every shape object in the given bbox.";
physics.doc.box_point_query = "Returns the subset of points from a given list that are inside a given box.";
physics.collision = {
types: {},
num: 32,
set_collide(a, b, x) {
this.types[a][b] = x;
this.types[b][a] = x;
this.sync();
},
sync() {
for (var i = 0; i < this.num; i++)
physics.set_cat_mask(i,this.types[i]);
},
};
for (var i = 0; i < physics.collision.num; i++) {
physics.collision.types[i] = [];
for (var j = 0; j < physics.collision.num; j++)
physics.collision.types[i][j] = false;
};
physics.collision.sync();
physics.gravity = physics.make_gravity();
physics.gravity.mask = [true];
physics.gravity.mask = ~1;
physics.gravity.strength = 500;
physics.damp = physics.make_damp();
physics.damp.mask = [true];
physics.damp.mask = ~1;
return {
physics

View file

@ -35,10 +35,6 @@ static int cb_idx = 0;
static const unsigned char col_alpha = 40;
static const float sensor_seg = 10;
unsigned int category_masks[32];
void set_cat_mask(int cat, unsigned int mask) { category_masks[cat] = mask; }
cpTransform m3_to_cpt(HMM_Mat3 m)
{
cpTransform t;
@ -52,7 +48,7 @@ cpTransform m3_to_cpt(HMM_Mat3 m)
}
cpShape *phys2d_query_pos(cpVect pos) {
return cpSpacePointQueryNearest(space, pos, 0.f, allfilter, NULL);
return cpSpacePointQueryNearest(space, pos, 0.f, CP_SHAPE_FILTER_ALL, NULL);
}
@ -67,23 +63,11 @@ void bbhit(cpShape *shape, int *data)
qhit++;
}
cpShapeFilter nofilter = {
.group = CP_NO_GROUP,
.mask = ~CP_ALL_CATEGORIES,
.categories = ~CP_ALL_CATEGORIES
};
cpShapeFilter allfilter = {
.group = CP_NO_GROUP,
.mask = CP_ALL_CATEGORIES,
.categories = CP_ALL_CATEGORIES,
};
int query_point(HMM_Vec2 pos)
{
qhit = 0;
// cpSpacePointQuery(space, pos.cp, 0, filter, qpoint, &qhit);
cpSpaceBBQuery(space, cpBBNewForCircle(pos.cp, 2), allfilter, bbhit, &qhit);
cpSpaceBBQuery(space, cpBBNewForCircle(pos.cp, 2), CP_SHAPE_FILTER_ALL, bbhit, &qhit);
return qhit;
}
@ -599,8 +583,13 @@ void register_hit(cpArbiter *arb, gameobject *go, const char *name)
cpShape *s1, *s2;
cpArbiterGetShapes(arb, &s1, &s2);
if (JS_IsUndefined(shape2go(s1)->ref)) return;
if (JS_IsUndefined(shape2go(s2)->ref)) return;
gameobject *g1, *g2;
g1 = shape2go(s1);
g2 = shape2go(g2);
if (!g1) return;
if (!g2) return;
if (JS_IsUndefined(g1->ref)) return;
if (JS_IsUndefined(g2->ref)) return;
struct phys2d_shape *pshape1 = cpShapeGetUserData(s1);
if (JS_IsUndefined(pshape1->ref)) return;
@ -614,7 +603,7 @@ void register_hit(cpArbiter *arb, gameobject *go, const char *name)
}
}
void script_phys_cb_begin(cpArbiter *arb, cpSpace *space, gameobject *go) { register_hit(arb, go, "collide"); }
int script_phys_cb_begin(cpArbiter *arb, cpSpace *space, gameobject *go) { register_hit(arb, go, "collide"); return 1; }
void script_phys_cb_separate(cpArbiter *arb, cpSpace *space, gameobject *go) { register_hit(arb, go, "separate"); }
void phys2d_setup_handlers(gameobject *go) {

View file

@ -17,9 +17,6 @@ extern struct rgba kinematic_color;
extern struct rgba static_color;
extern struct rgba sleep_color;
extern cpShapeFilter allfilter;
extern cpShapeFilter nofilter;
typedef struct constraint {
cpConstraint *c;
JSValue break_cb; /* function called when it is forcibly broken */
@ -129,7 +126,5 @@ void phys2d_setup_handlers(gameobject *go);
int query_point(HMM_Vec2 pos);
void phys2d_reindex_body(cpBody *body);
extern unsigned int category_masks[32];
void set_cat_mask(int cat, unsigned int mask);
#endif

View file

@ -55,8 +55,6 @@ transform2d go2t(gameobject *go)
return t;
}
unsigned int editor_cat = 1<<31;
void go_shape_apply(cpBody *body, cpShape *shape, gameobject *go) {
cpShapeSetFriction(shape, go->friction);
cpShapeSetElasticity(shape, go->elasticity);
@ -64,8 +62,8 @@ void go_shape_apply(cpBody *body, cpShape *shape, gameobject *go) {
cpShapeFilter filter;
filter.group = (cpCollisionType)go;
filter.categories = 1<<go->layer | editor_cat;
filter.mask = category_masks[go->layer] | editor_cat;
filter.categories = go->categories;
filter.mask = go->mask;
// filter.mask = CP_ALL_CATEGORIES;
cpShapeSetFilter(shape, filter);
@ -106,7 +104,7 @@ 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}, go->warp_filter).xy;
HMM_Vec2 g = warp_force((HMM_Vec3){pos.x, pos.y, 0}, go->warp_mask).xy;
if (!go) {
cpBodyUpdateVelocity(body,g.cp,damping,dt);
return;
@ -140,6 +138,9 @@ gameobject *MakeGameobject() {
.damping = INFINITY,
.timescale = 1.0,
.ref = JS_UNDEFINED,
.mask = ~0,
.categories = 1,
.warp_mask = ~0
};
go.body = cpSpaceAddBody(space, cpBodyNew(go.mass, 1.f));
@ -163,7 +164,7 @@ void rm_body_shapes(cpBody *body, cpShape *shape, void *data) {
free(s->data);
}
cpShapeSetFilter(shape, nofilter);
cpShapeSetFilter(shape, CP_SHAPE_FILTER_NONE);
cpSpaceRemoveShape(space, shape);
cpShapeFree(shape);

View file

@ -39,8 +39,9 @@ struct gameobject {
float maxvelocity;
float maxangularvelocity;
unsigned int layer;
cpShapeFilter filter;
unsigned int warp_filter;
cpBitmask categories;
cpBitmask mask;
unsigned int warp_mask;
JSValue ref;
HMM_Mat4 world;
float drawlayer;

View file

@ -336,18 +336,11 @@ JSValue vec32js(HMM_Vec3 v)
}
cpBitmask js2bitmask(JSValue v) {
cpBitmask mask = 0;
int len = js_arrlen(v);
for (int i = 0; i < len; i++) {
int val = js2boolean(js_getpropidx( v, i));
if (!val) continue;
mask |= 1 << i;
}
return mask;
cpBitmask a;
JS_ToUint32(js, &a, v);
return a;
}
JSValue bitmask2js(cpBitmask mask) { return JS_NewUint32(js, mask); }
HMM_Vec2 *js2cpvec2arr(JSValue v) {
HMM_Vec2 *arr = NULL;
@ -370,14 +363,6 @@ HMM_Vec2 *jsfloat2vec(JSValue v)
return arr;
}
JSValue bitmask2js(cpBitmask mask) {
JSValue arr = JS_NewArray(js);
for (int i = 0; i < 11; i++)
js_setprop_num(arr,i,boolean2js(mask & 1 << i));
return arr;
}
JSValue vecarr2js(HMM_Vec2 *points, int n) {
JSValue array = JS_NewArray(js);
for (int i = 0; i < n; i++)
@ -918,8 +903,6 @@ JSC_CCALL(physics_sgscale,
cpSpaceReindexShapesForBody(space, js2gameobject(argv[0])->body);
)
JSC_CCALL(physics_set_cat_mask, set_cat_mask(js2number(argv[0]), js2bitmask(argv[1])))
JSC_CCALL(physics_closest_point,
void *v1 = js2cpvec2arr(argv[1]);
JSValue ret = number2js(point2segindex(js2vec2(argv[0]), v1, js2number(argv[2])));
@ -945,7 +928,7 @@ JSC_CCALL(physics_box_query,
bbox.r = pos.x+wh.x/2;
bbox.t = pos.y+wh.y/2;
bbox.b = pos.y-wh.y/2;
cpSpaceBBQuery(space, bbox, allfilter, bb_query_fn, &argv[3]);
cpSpaceBBQuery(space, bbox, CP_SHAPE_FILTER_ALL, bb_query_fn, &argv[3]);
return ret;
)
@ -972,7 +955,7 @@ static void ray_query_fn(cpShape *shape, float t, cpVect n, float a, JSValue *cb
}
JSC_CCALL(physics_ray_query,
cpSpaceSegmentQuery(space, js2vec2(argv[0]).cp, js2vec2(argv[1]).cp, js2number(argv[2]), allfilter, ray_query_fn, &argv[3]);
cpSpaceSegmentQuery(space, js2vec2(argv[0]).cp, js2vec2(argv[1]).cp, js2number(argv[2]), CP_SHAPE_FILTER_ALL, ray_query_fn, &argv[3]);
);
static void point_query_fn(cpShape *shape, float dist, cpVect point, JSValue *cb)
@ -987,7 +970,7 @@ static void point_query_fn(cpShape *shape, float dist, cpVect point, JSValue *cb
}
JSC_CCALL(physics_point_query,
cpSpacePointQuery(space, js2vec2(argv[0]).cp, js2number(argv[1]), allfilter, point_query_fn, &argv[2]);
cpSpacePointQuery(space, js2vec2(argv[0]).cp, js2number(argv[1]), CP_SHAPE_FILTER_ALL, point_query_fn, &argv[2]);
);
JSValue pointinfo2js(cpPointQueryInfo info)
@ -1001,14 +984,13 @@ JSValue pointinfo2js(cpPointQueryInfo info)
JSC_CCALL(physics_point_query_nearest,
cpPointQueryInfo info;
cpShape *sh = cpSpacePointQueryNearest(space, js2vec2(argv[0]).cp, js2number(argv[1]), allfilter, &info);
cpShape *sh = cpSpacePointQueryNearest(space, js2vec2(argv[0]).cp, js2number(argv[1]), CP_SHAPE_FILTER_ALL, &info);
if (!sh) return JS_UNDEFINED;
return pointinfo2js(info);
)
static const JSCFunctionListEntry js_physics_funcs[] = {
MIST_FUNC_DEF(physics, sgscale, 2),
MIST_FUNC_DEF(physics, set_cat_mask, 2),
MIST_FUNC_DEF(physics, point_query, 3),
MIST_FUNC_DEF(physics, point_query_nearest, 2),
MIST_FUNC_DEF(physics, ray_query, 4),
@ -1153,8 +1135,10 @@ JSC_GETSET(gameobject, damping, number)
JSC_GETSET(gameobject, timescale, number)
JSC_GETSET(gameobject, maxvelocity, number)
JSC_GETSET(gameobject, maxangularvelocity, number)
JSC_GETSET(gameobject, warp_filter, bitmask)
JSC_GETSET(gameobject, warp_mask, bitmask)
JSC_GETSET(gameobject, drawlayer, number)
JSC_GETSET(gameobject, categories, bitmask)
JSC_GETSET(gameobject, mask, bitmask)
JSC_CCALL(gameobject_selfsync, gameobject_apply(js2gameobject(this)))
JSC_CCALL(gameobject_world2this, return vec22js(world2go(js2gameobject(this), js2vec2(argv[0]))))
JSC_CCALL(gameobject_this2world, return vec22js(go2world(js2gameobject(this), js2vec2(argv[0]))))
@ -1170,8 +1154,10 @@ static const JSCFunctionListEntry js_gameobject_funcs[] = {
CGETSET_ADD(gameobject,maxvelocity),
CGETSET_ADD(gameobject,maxangularvelocity),
CGETSET_ADD(gameobject,layer),
CGETSET_ADD(gameobject,warp_filter),
CGETSET_ADD(gameobject,warp_mask),
CGETSET_ADD(gameobject,drawlayer),
CGETSET_ADD(gameobject, categories),
CGETSET_ADD(gameobject, mask),
CGETSET_ADD_HID(gameobject, rpos),
CGETSET_ADD_HID(gameobject, rangle),
CGETSET_ADD_HID(gameobject, rscale),