Change physics collisions and masks
This commit is contained in:
parent
17ad44e5a5
commit
c05cb3c6d2
|
@ -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() {
|
||||
|
|
|
@ -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);
|
||||
});
|
||||
},
|
||||
};
|
||||
|
|
|
@ -220,14 +220,42 @@ var gameobject = {
|
|||
ent.components = {};
|
||||
ent.objects = {};
|
||||
ent.timers = [];
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
return pos+1;
|
||||
}
|
||||
});
|
||||
|
||||
if (typeof text === 'object' && text) // assume it's an ur
|
||||
if (typeof text === 'object' && text) {// assume it's an ur
|
||||
ent.ur = text;
|
||||
else
|
||||
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];
|
||||
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 }
|
|
@ -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
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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),
|
||||
|
|
Loading…
Reference in a new issue