diff --git a/Makefile b/Makefile index bf4e1e5..b02d5f5 100755 --- a/Makefile +++ b/Makefile @@ -53,13 +53,18 @@ endif CPPFLAGS += -ffast-math ifeq ($(DBG),1) - CPPFLAGS += -g -fsanitize=address + CPPFLAGS += -g INFO += _dbg else CPPFLAGS += -DNDEBUG LDFLAGS += -s endif +ifeq ($(LEAK),1) + CPPFLAGS += -fsanitize=address + INFO += _leak +endif + ifeq ($(OPT),small) CPPFLAGS += -Oz -flto -fno-ident -fno-asynchronous-unwind-tables LDFLAGS += -flto diff --git a/scripts/base.js b/scripts/base.js index 076fca9..a3e51f2 100644 --- a/scripts/base.js +++ b/scripts/base.js @@ -1249,14 +1249,16 @@ Math.snap = function(val, grid) { } Math.angledist = function (a1, a2) { + a1 = Math.turn2deg(a1); + a2 = Math.turn2deg(a2); var dist = a2 - a1; var wrap = dist >= 0 ? dist+360 : dist-360; wrap %= 360; if (Math.abs(dist) < Math.abs(wrap)) - return dist; + return Math.deg2turn(dist); - return wrap; + return Math.deg2turn(wrap); }; Math.angledist.doc = "Find the shortest angle between two angles."; Math.TAU = Math.PI*2; @@ -1266,6 +1268,8 @@ Math.deg2rad = function(x) { return x; }; Math.rad2deg = function(x) { return x; }; Math.turn2rad = function(x) { return x*Math.TAU; }; Math.rad2turn = function(x) { return x/Math.TAU; }; +Math.turn2deg = function(x) { return x*360; }; +Math.deg2turn = function(x) { return x/360; }; Math.randomint = function(max) { return Math.clamp(Math.floor(Math.random() * max), 0, max-1); }; /* BOUNDINGBOXES */ diff --git a/scripts/components.js b/scripts/components.js index d81e62b..92c923c 100644 --- a/scripts/components.js +++ b/scripts/components.js @@ -103,6 +103,10 @@ component.sprite.impl = { get color() {return cmd(148,this.id);}, get pos() { return cmd(111, this.id); }, set pos(x) { cmd(37,this.id,x); }, + get angle() { return cmd(217,this.id); }, + set angle(x) { cmd(218,this.id,x); }, + get scale() { return cmd(215, this.id); }, + set scale(x) { cmd(216, this.id, x); }, set layer(x) { cmd(60, this.id, x); }, get layer() { return undefined; }, emissive(x) { cmd(170, this.id, x); }, diff --git a/scripts/editor.js b/scripts/editor.js index b0d0795..90defdf 100644 --- a/scripts/editor.js +++ b/scripts/editor.js @@ -450,6 +450,7 @@ var editor = { GUI.text(sname, x.screenpos().add([0, 32]), 1, Color.editor.ur); GUI.text(x.worldpos().map(function(x) { return Math.round(x); }), x.screenpos(), 1, Color.white); + Shape.cross(x.screenpos(), 10, Color.blue); }); Object.entries(thiso.objects).forEach(function(x) { @@ -1963,26 +1964,6 @@ var entitylistpanel = Object.copy(inputpanel, { start() { this.level = editor.edit_level; }, - -/* guibody() { - Nuke.newline(4); - Nuke.label("Object"); - Nuke.label("Visible"); - Nuke.label("Selectable"); - Nuke.label("Selected?"); - this.level.objects.forEach(function(x) { - if (Nuke.button(x.toString())) { - editor.selectlist = []; - editor.selectlist.push(x); - } - - x.visible = Nuke.checkbox(x.visible); - x._ed.selectable = Nuke.checkbox(x._ed.selectable); - - if (editor.selectlist.includes(x)) Nuke.label("T"); else Nuke.label("F"); - }); - }, -*/ }); var limited_editor = {}; diff --git a/scripts/engine.js b/scripts/engine.js index ad09678..e65eb89 100644 --- a/scripts/engine.js +++ b/scripts/engine.js @@ -74,8 +74,10 @@ load("scripts/gui.js"); var timer = { update(dt) { this.remain -= dt; - if (this.remain <= 0) - this.fire(); + if (this.remain <= 0) { + this.fn(); + this.kill(); + } }, kill() { @@ -86,7 +88,7 @@ var timer = { var t = Object.create(this); t.time = secs; t.remain = secs; - t.fire = function() { fn(); t.kill(); }; + t.fn = fn; Register.update.register(t.update, t); return function() { t.kill(); }; }, @@ -522,7 +524,7 @@ function world_start() { dirty:false, }; Primum.toString = function() { return "Primum"; }; - Primum.ur = undefined; + Primum.ur = "Primum"; Primum.kill = function() { this.clear(); }; gameobject.level = Primum; } diff --git a/scripts/entity.js b/scripts/entity.js index e542b83..835250f 100644 --- a/scripts/entity.js +++ b/scripts/entity.js @@ -93,7 +93,13 @@ var gameobject_impl = { get scale() { Debug.assert(this.level, `No level set on ${this.toString()}`); - return this.gscale().map((x,i) => x/this.level.gscale()[i]); + var pscale; + if (typeof this.__proto__.scale === 'object') + pscale = this.__proto__.scale; + else + pscale = [1,1,1]; + + return this.gscale().map((x,i) => x/(this.level.gscale()[i]*pscale[i])); }, set scale(x) { @@ -109,7 +115,7 @@ var gameobject_impl = { obj.pos = obj.pos.map((x,i)=>x*pct[i]); }); }, - + get draw_layer() { return cmd(171, this.body); }, set draw_layer(x) { cmd(172, this.body, x); }, set layer(x) { cmd(75,this.body,x); }, @@ -207,7 +213,7 @@ var gameobject = { }, delay(fn, seconds) { - var t = timer.delay(fn.bind(this), seconds, false); + var t = timer.delay(fn.bind(this), seconds); this.timers.push(t); return t; }, @@ -275,8 +281,11 @@ var gameobject = { /* Reparent 'this' to be 'parent's child */ reparent(parent) { Debug.assert(parent, `Tried to reparent ${this.toString()} to nothing.`); - if (this.level === parent) + if (this.level === parent) { + console.warn("not reparenting ..."); + console.warn(`${this.level} is the same as ${parent}`); return; + } this.level?.remove_obj(this); @@ -453,6 +462,7 @@ var gameobject = { delete d.pos; delete d.angle; + delete d.scale; delete d.velocity; delete d.angularvelocity; return d; @@ -547,6 +557,7 @@ var gameobject = { }; obj.ur = this.toString(); + obj.level = undefined; obj.reparent(level); diff --git a/source/engine/2dphysics.c b/source/engine/2dphysics.c index 39d9186..9ff92ac 100644 --- a/source/engine/2dphysics.c +++ b/source/engine/2dphysics.c @@ -37,7 +37,6 @@ void set_cat_mask(int cat, unsigned int mask) { category_masks[cat] = mask; } cpTransform m3_to_cpt(HMM_Mat3 m) { - cpTransform t; t.a = m.Columns[0].x; t.b = m.Columns[0].y; @@ -306,7 +305,8 @@ void phys2d_applypoly(struct phys2d_poly *poly) { assert(sizeof(poly->points[0]) == sizeof(cpVect)); struct gameobject *go = poly->shape.go; // cpTransform T = m3_to_cpt(transform2d2mat(poly->t)); - cpPolyShapeSetVerts(poly->shape.shape, arrlen(poly->points), (cpVect*)poly->points, cpTransformIdentity); + cpTransform T = m3_to_cpt(transform2d2mat(poly->shape.go->t)); + cpPolyShapeSetVerts(poly->shape.shape, arrlen(poly->points), (cpVect*)poly->points, T); cpPolyShapeSetRadius(poly->shape.shape, poly->radius); cpSpaceReindexShapesForBody(space, cpShapeGetBody(poly->shape.shape)); } @@ -320,7 +320,7 @@ void phys2d_dbgdrawpoly(struct phys2d_poly *poly) { HMM_Vec2 points[n+1]; HMM_Mat3 rt = t_go2world(shape2go(poly->shape.shape)); for (int i = 0; i < n; i++) - points[i] = mat_t_pos(rt, (HMM_Vec2)cpPolyShapeGetVert(poly->shape.shape, i)); + points[i] = (HMM_Vec2)cpPolyShapeGetVert(poly->shape.shape, i); points[n] = points[0]; diff --git a/source/engine/gameobject.c b/source/engine/gameobject.c index 25856eb..35ff77d 100644 --- a/source/engine/gameobject.c +++ b/source/engine/gameobject.c @@ -129,17 +129,17 @@ static void velocityFn(cpBody *body, cpVect gravity, cpFloat damping, cpFloat dt return; } - cpFloat d = isnan(go->damping) ? damping : d; + cpFloat d = isfinite(go->damping) ? go->damping : damping; cpVect g = gravity; if (isfinite(go->gravity.x) && isfinite(go->gravity.y)) g = go->gravity.cp; cpBodyUpdateVelocity(body,g,d,dt*go->timescale); - if (!isinf(go->maxvelocity)) + if (isfinite(go->maxvelocity)) cpBodySetVelocity(body, cpvclamp(cpBodyGetVelocity(body), go->maxvelocity)); - if (!isinf(go->maxangularvelocity)) { + if (isfinite(go->maxangularvelocity)) { float av = cpBodyGetAngularVelocity(body); if (fabs(av) > go->maxangularvelocity) cpBodySetAngularVelocity(body, copysignf(go->maxangularvelocity, av)); diff --git a/source/engine/jsffi.c b/source/engine/jsffi.c index e6818d9..e7c260a 100644 --- a/source/engine/jsffi.c +++ b/source/engine/jsffi.c @@ -1354,6 +1354,18 @@ JSValue duk_cmd(JSContext *js, JSValueConst this, int argc, JSValueConst *argv) case 214: ret = int2js(go_count()); break; + case 215: + ret = vec2js(js2sprite(argv[1])->t.scale); + break; + case 216: + js2sprite(argv[1])->t.scale = js2vec2(argv[2]); + break; + case 217: + ret = num2js(js2sprite(argv[1])->t.angle); + break; + case 218: + js2sprite(argv[1])->t.angle = js2number(argv[2]); + break; } if (str)