From d3db5ca61ef0337c6aa0c73cbaa950a91c8a51d4 Mon Sep 17 00:00:00 2001 From: John Alanbrook Date: Wed, 20 Mar 2024 16:07:23 -0500 Subject: [PATCH] unseparated body from gameobject; now 'entity' --- scripts/components.js | 4 +- scripts/debug.js | 2 +- scripts/engine.js | 25 ++----- scripts/entity.js | 143 ++++++++++++------------------------- source/engine/2dphysics.c | 1 + source/engine/gameobject.c | 7 +- source/engine/gameobject.h | 4 +- source/engine/jsffi.c | 43 +++++------ source/engine/yugine.c | 2 +- 9 files changed, 81 insertions(+), 150 deletions(-) diff --git a/scripts/components.js b/scripts/components.js index 40884ff..5021cd3 100644 --- a/scripts/components.js +++ b/scripts/components.js @@ -22,7 +22,7 @@ var component = { make(go) { var nc = Object.create(this); nc.gameobject = go; - Object.mixin(nc, this._enghook(go.body)); + Object.mixin(nc, this._enghook(go)); assign_impl(nc,this.impl); Object.hide(nc, 'gameobject', 'id'); nc.post(); @@ -152,7 +152,7 @@ Object.mixin(os.sprite(true), { os.sprite(true).make = function(go) { var sp = os.sprite(); - sp.go = go.body; + sp.go = go; sp.gameobject = go; return sp; } diff --git a/scripts/debug.js b/scripts/debug.js index e323e6b..ca5433c 100644 --- a/scripts/debug.js +++ b/scripts/debug.js @@ -14,7 +14,7 @@ debug.draw_bb = false; debug.draw_gizmos = false; debug.draw_names = false; debug.draw = function() { - if (this.draw_phys) game.all_objects(function(x) { debug.draw_gameobject(x.body); }); + if (this.draw_phys) game.all_objects(function(x) { debug.draw_gameobject(x); }); if (this.draw_bb) game.all_objects(function(x) { debug.boundingbox(x.boundingbox(), Color.debug.boundingbox.alpha(0.05)); }); diff --git a/scripts/engine.js b/scripts/engine.js index 167aa2e..8ad4b74 100644 --- a/scripts/engine.js +++ b/scripts/engine.js @@ -58,8 +58,6 @@ console.doc = { clear: "Clear console." }; -console.stdout_lvl = 1; - globalThis.global = globalThis; function use(file) @@ -102,10 +100,10 @@ global.check_registers = function(obj) obj.timers.push(Register.physupdate.register(obj.physupdate.bind(obj))); if (typeof obj.collide === 'function') - physics.collide_begin(obj.collide.bind(obj), obj.body); + physics.collide_begin(obj.collide.bind(obj), obj); if (typeof obj.separate === 'function') - physics.collide_separate(obj.separate.bind(obj), obj.body); + physics.collide_separate(obj.separate.bind(obj), obj); if (typeof obj.draw === 'function') obj.timers.push(Register.draw.register(obj.draw.bind(obj), obj)); @@ -428,26 +426,13 @@ global.mixin("scripts/actor.js"); global.mixin("scripts/entity.js"); function world_start() { - gameobject.body = os.make_gameobject(); - gameobject.body.setref(gameobject); - - console.info("START WORLD"); - globalThis.world = Object.create(gameobject); - gameobject.level = world; + globalThis.world = os.make_gameobject(); + world.setref(world); world.objects = {}; - world.check_dirty = function() {}; - world.namestr = function(){}; - world._ed = { - selectable:false, - dirty:false, - }; world.toString = function() { return "world"; }; - world.master = gameobject; world.ur = "world"; world.kill = function() { this.clear(); }; world.phys = 2; - - Object.hide(gameobject, 'timescale'); var cam = world.spawn("scripts/camera2d.jso"); game.view_camera(cam); } @@ -457,7 +442,7 @@ global.mixin("scripts/physics.js"); game.view_camera = function(cam) { game.camera = cam; - render.cam_body(game.camera.body); + render.cam_body(game.camera); } window.title = `Prosperon v${prosperon.version}`; diff --git a/scripts/entity.js b/scripts/entity.js index 4471e96..a387d8c 100644 --- a/scripts/entity.js +++ b/scripts/entity.js @@ -13,12 +13,12 @@ function obj_unique_name(name, obj) { var gameobject_impl = { get pos() { assert(this.master, `Entity ${this.toString()} has no master.`); - return this.master.body.world2this(this.worldpos()); + return this.master.world2this(this.worldpos()); }, set pos(x) { assert(this.master, `Entity ${this.toString()} has no master.`); - this.set_worldpos(this.master.body.this2world(x)); + this.set_worldpos(this.master.this2world(x)); }, get angle() { @@ -56,47 +56,6 @@ var gameobject_impl = { obj.pos = obj.pos.map((x, i) => x * pct[i]); }); }, - - get draw_layer() { return this.body.drawlayer; }, - set draw_layer(x) { this.body.drawlayer = x; }, - set layer(x) { this.body.layer = x; }, - get layer() { return this.body.layer; }, - set warp_layer(x) { this.body.warp_filter = x; }, - get warp_layer() { return this.body.warp_filter; }, - - set mass(x) { this.body.mass = x; }, - get mass() { - if (!(this.phys === physics.dynamic)) - return undefined; - - return this.body.mass; - }, - get elasticity() { return this.body.e; }, - set elasticity(x) { this.body.e = x; }, - get friction() { return this.body.f; }, - set friction(x) { this.body.f = x; }, - set timescale(x) { this.body.timescale = x; }, - get timescale() { return this.body.timescale; }, - set phys(x) { this.body.phys = x; }, - get phys() { return this.body.phys; }, - get velocity() { return this.body.velocity; }, - set velocity(x) { this.body.velocity = x; }, - get damping() { return this.body.damping; }, - set damping(x) { this.body.damping = x }, - get angularvelocity() { return Math.rad2turn(this.body.angularvelocity); }, - set angularvelocity(x) { this.body.angularvelocity = Math.turn2rad(x); }, - get max_velocity() { return this.body.maxvelocity; }, - set max_velocity(x) { this.body.maxvelocity = x; }, - get max_angularvelocity() { return this.body.maxangularvelocity; }, - set max_angularvelocity(x) { this.body.maxangularvelocity = x; }, - get_moi() { return this.body.moi; }, - set_moi(x) { - if (x <= 0) { - console.error("Cannot set moment of inertia to 0 or less."); - return; - } - this.body.moi = x; - }, }; var gameobject = { @@ -108,6 +67,7 @@ var gameobject = { if (comps.length) return comps; return undefined; }, + check_dirty() { this._ed.urdiff = this.json_obj(); this._ed.dirty = !Object.empty(this._ed.urdiff); @@ -121,6 +81,7 @@ var gameobject = { else this._ed.inst = false; }, + _ed: { selectable: false, dirty: false @@ -144,32 +105,32 @@ var gameobject = { }, /* pin this object to the to object */ pin(to) { - var p = joint.pin(this.body,to.body); + var p = joint.pin(this,to); }, slide(to, a, b, min, max) { a ??= [0, 0]; b ??= [0, 0]; min ??= 0; max ??= 50; - var p = joint.slide(this.body, to.body, a, b, min, max); + var p = joint.slide(this, to, a, b, min, max); p.max_force = 500; p.break(); }, pivot(to, piv) { piv ??= this.worldpos(); - var p = joint.pivot(this.body, to.body, piv); + var p = joint.pivot(this, to, piv); }, /* groove is on to, from local points a and b, anchored to this at local anchor */ groove(to, a, b, anchor) { anchor ??= [0, 0]; - var p = joint.groove(to.body, this.body, a, b, anchor); + var p = joint.groove(to, this, a, b, anchor); }, damped_spring(to, length, stiffness, damping) { length ??= Vector.length(this.worldpos(), to.worldpos()); stiffness ??= 1; damping ??= 1; var dc = 2 * Math.sqrt(stiffness * this.mass); - var p = joint.damped_spring(this.body, to.body, [0, 0], [0, 0], stiffness, damping * dc); + var p = joint.damped_spring(this, to, [0, 0], [0, 0], stiffness, damping * dc); }, damped_rotary_spring(to, angle, stiffness, damping) { angle ??= 0; @@ -179,23 +140,23 @@ var gameobject = { /* damping = 1 is critical */ var dc = 2 * Math.sqrt(stiffness * this.get_moi()); /* critical damping number */ /* zeta = actual/critical */ - var p = joint.damped_rotary(this.body, to.body, angle, stiffness, damping * dc); + var p = joint.damped_rotary(this, to, angle, stiffness, damping * dc); }, rotary_limit(to, min, max) { - var p = joint.rotary(this.body, to.body, Math.turn2rad(min), Math.turn2rad(max)); + var p = joint.rotary(this, to, Math.turn2rad(min), Math.turn2rad(max)); }, ratchet(to, ratch) { var phase = this.angle - to.angle; - var p = joint.ratchet(this.body, to.body, phase, Math.turn2rad(ratch)); + var p = joint.ratchet(this, to, phase, Math.turn2rad(ratch)); }, gear(to, ratio) { phase ??= 1; ratio ??= 1; var phase = this.angle - to.angle; - var p = joint.gear(this.body, to.body, phase, ratio); + var p = joint.gear(this, to, phase, ratio); }, motor(to, rate) { - var p = joint.motor(this.body, to.body, rate); + var p = joint.motor(this, to, rate); }, path_from(o) { @@ -254,15 +215,12 @@ var gameobject = { return killfn; }, - set torque(x) { if (!(x >= 0 && x <= Infinity)) return; - this.body.torque = x; }, - - gscale() { return this.body.scale; }, + gscale() { return this.scale; }, sgscale(x) { if (typeof x === 'number') x = [x, x]; - physics.sgscale(this.body, x) + physics.sgscale(this, x) }, phys_material() { @@ -272,21 +230,18 @@ var gameobject = { return mat; }, - worldpos() { return this.body.pos; }, + worldpos() { return this.pos; }, set_worldpos(x) { var poses = this.objects.map(x => x.pos); - this.body.pos = x; + this.pos = x; this.objects.forEach((o, i) => o.set_worldpos(this.this2world(poses[i]))); }, screenpos() { return window.world2screen(this.worldpos()); }, - worldangle() { return Math.rad2turn(this.body.angle); }, - sworldangle(x) { this.body.angle = Math.turn2rad(x); }, + worldangle() { return Math.rad2turn(this.angle); }, + sworldangle(x) { this.angle = Math.turn2rad(x); }, - get_ur() { - // if (this.ur === 'empty') return undefined; - return Object.access(ur, this.ur); - }, + get_ur() { return Object.access(ur, this.ur); }, /* spawn an entity text can be: @@ -295,8 +250,8 @@ var gameobject = { nothing */ spawn(text) { - var ent = Object.create(gameobject); - + var ent = os.make_gameobject(); + if (typeof text === 'object') text = text.name; @@ -318,8 +273,6 @@ var gameobject = { console.info(`Creating entity of type ${ent.ur}`); - Object.mixin(ent, gameobject_impl); - ent.body = os.make_gameobject(); ent.warp_layer = [true]; ent.phys = 2; ent.components = {}; @@ -335,9 +288,9 @@ var gameobject = { urdiff: {}, }; - ent.body.setref(ent); // set the internal obj reference to this obj + ent.setref(ent); - Object.hide(ent, 'ur', 'body', 'components', 'objects', '_ed', 'timers', 'master'); + Object.hide(ent, 'ur', 'components', 'objects', '_ed', 'timers', 'master'); if (ent.ur === 'empty') { if (!ur.empty.proto) ur.empty.proto = json.decode(json.encode(ent)); return ent; @@ -361,10 +314,9 @@ var gameobject = { check_registers(ent); ent.components.forEach(function(x) { if (typeof x.collide === 'function') - physics.collide_shape(x.collide.bind(x), ent.body, x.shape); + physics.collide_shape(x.collide.bind(x), ent, x.shape); }); - if (typeof ent.load === 'function') ent.load(); if (sim.playing()) if (typeof ent.start === 'function') ent.start(); @@ -374,6 +326,7 @@ var gameobject = { mur.proto = json.decode(json.encode(ent)); ent.sync(); + console.info(`entity is type ${ent.phys}`); if (!Object.empty(ent.objects)) { var o = ent.objects; @@ -386,8 +339,8 @@ var gameobject = { Object.assign(n, o[i]); } } - - this.body.phys = this.body.phys; // simple way to sync + + console.info(`Made object with mass ${ent.mass} and moi ${ent.moi}`); return ent; }, @@ -436,17 +389,14 @@ var gameobject = { objects: {}, master: undefined, - pulse(vec) { this.body.impulse(vec); }, - shove(vec) { this.body.force(vec); }, - shove_at(vec, at) { this.body.force_local(vec,at); }, this2screen(pos) { return window.world2screen(this.this2world(pos)); }, screen2this(pos) { return this.world2this(window.screen2world(pos)); }, - alive() { return this.body >= 0; }, - in_air() { return this.body.in_air(); }, + in_air() { return this.in_air(); }, hide() { this.components.forEach(x => x.hide?.()); this.objects.forEach(x => x.hide?.()); }, + show() { this.components.forEach(function(x) { x.show?.(); }); this.objects.forEach(function(x) { x.show?.(); }); }, @@ -484,21 +434,11 @@ var gameobject = { flipx() { return this.scale.x < 0; }, flipy() { return this.scale.y < 0; }, - mirror(plane) { - this.scale = Vector.reflect(this.scale, plane); - }, - - save: true, - selectable: true, - ed_locked: false, + mirror(plane) { this.scale = Vector.reflect(this.scale, plane); }, disable() { this.components.forEach(function(x) { x.disable(); }); }, enable() { this.components.forEach(function(x) { x.enable(); }); }, - sync() { - this.components.forEach(function(x) { x.sync?.(); }); - this.objects.forEach(function(x) { x.sync?.(); }); - }, - + /* Bounding box of the object in world dimensions */ boundingbox() { var boxes = []; @@ -603,7 +543,7 @@ var gameobject = { this.timers = []; Event.rm_obj(this); Player.do_uncontrol(this); - physics.collide_rm(this.body); + physics.collide_rm(this); if (this.master) { this.master.remove_obj(this); @@ -679,7 +619,16 @@ var gameobject = { this.objects[o].obj_descend(fn); }, } -Object.mixin(gameobject, gameobject_impl); + +var gop = os.make_gameobject().__proto__; +Object.mixin(gop, gameobject); +var gsync = gop.sync; +gop.sync = function() { + gsync.call(this); + this.components.forEach(function(x) { x.sync?.(); }); + this.objects.forEach(function(x) { x.sync(); }); +} + gameobject.spawn.doc = `Spawn an entity of type 'ur' on this entity. Returns the spawned entity.`; @@ -835,7 +784,3 @@ game.loadurs = function() { name: "empty" }; }; - -return { - gameobject -} diff --git a/source/engine/2dphysics.c b/source/engine/2dphysics.c index 9e5b179..0e73c32 100644 --- a/source/engine/2dphysics.c +++ b/source/engine/2dphysics.c @@ -309,6 +309,7 @@ void phys2d_shape_apply(struct phys2d_shape *s) float newmoi = s->moi(s->data); moment-=moi; moment += newmoi; + if (moment < 0) moment = 0; cpBodySetMoment(s->go->body, moment); } diff --git a/source/engine/gameobject.c b/source/engine/gameobject.c index 0a30573..ba09f94 100644 --- a/source/engine/gameobject.c +++ b/source/engine/gameobject.c @@ -75,8 +75,8 @@ transform2d go2t(gameobject *go) unsigned int editor_cat = 1<<31; void go_shape_apply(cpBody *body, cpShape *shape, gameobject *go) { - cpShapeSetFriction(shape, go->f); - cpShapeSetElasticity(shape, go->e); + cpShapeSetFriction(shape, go->friction); + cpShapeSetElasticity(shape, go->elasticity); cpShapeSetCollisionType(shape, (cpCollisionType)go); cpShapeFilter filter; @@ -105,6 +105,7 @@ void go_shape_moi(cpBody *body, cpShape *shape, gameobject *go) { } void gameobject_apply(gameobject *go) { + YughInfo("Applying gameobject %p", go); cpBodySetType(go->body, go->phys); cpBodyEachShape(go->body, go_shape_apply, go); @@ -115,8 +116,6 @@ void gameobject_apply(gameobject *go) { if (cpBodyGetMoment(go->body) <= 0.f) cpBodySetMoment(go->body, 1.f); - - return; } } diff --git a/source/engine/gameobject.h b/source/engine/gameobject.h index 4e8ec37..497fe21 100644 --- a/source/engine/gameobject.h +++ b/source/engine/gameobject.h @@ -32,8 +32,8 @@ struct gameobject { HMM_Vec3 scale; /* local */ int next; float mass; - float f; /* friction */ - float e; /* elasticity */ + float friction; + float elasticity; float damping; float timescale; float maxvelocity; diff --git a/source/engine/jsffi.c b/source/engine/jsffi.c index 7db5b4e..0358269 100644 --- a/source/engine/jsffi.c +++ b/source/engine/jsffi.c @@ -1312,36 +1312,36 @@ static const JSCFunctionListEntry js_window_funcs[] = { JSC_GETSET_BODY(pos, Position, cvec2) JSC_GETSET_BODY(angle, Angle, number) -JSC_GETSET(gameobject, scale, vec3) JSC_GETSET_BODY(velocity, Velocity, cvec2) JSC_GETSET_BODY(angularvelocity, AngularVelocity, number) JSC_GETSET_BODY(moi, Moment, number) -//JSC_GETSET_BODY(phys, Type, number) -JSC_GETSET(gameobject, phys, number) JSC_GETSET_BODY(torque, Torque, number) JSC_CCALL(gameobject_impulse, cpBodyApplyImpulseAtWorldPoint(js2gameobject(this)->body, js2vec2(argv[0]).cp, cpBodyGetPosition(js2gameobject(this)->body))) JSC_CCALL(gameobject_force, cpBodyApplyForceAtWorldPoint(js2gameobject(this)->body, js2vec2(argv[0]).cp, cpBodyGetPosition(js2gameobject(this)->body))) JSC_CCALL(gameobject_force_local, cpBodyApplyForceAtLocalPoint(js2gameobject(this)->body, js2vec2(argv[0]).cp, js2vec2(argv[1]).cp)) +JSC_GETSET_APPLY(gameobject, friction, number) +JSC_GETSET_APPLY(gameobject, elasticity, number) +JSC_GETSET_APPLY(gameobject, mass, number) +JSC_GETSET_APPLY(gameobject, phys, number) +JSC_GETSET_APPLY(gameobject, layer, number) +JSC_GETSET(gameobject, scale, vec3) +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, drawlayer, number) +JSC_CCALL(gameobject_setref, js2gameobject(this)->ref = argv[0]); +JSC_CCALL(gameobject_sync, gameobject_apply(js2gameobject(this))) JSC_CCALL(gameobject_in_air, return boolean2js(phys2d_in_air(js2gameobject(this)->body))) JSC_CCALL(gameobject_world2this, return vec22js(world2go(js2gameobject(this), js2vec2(argv[0])))) JSC_CCALL(gameobject_this2world, return vec22js(go2world(js2gameobject(this), js2vec2(argv[0])))) JSC_CCALL(gameobject_dir_world2this, return vec22js(mat_t_dir(t_world2go(js2gameobject(this)), js2vec2(argv[0])))) JSC_CCALL(gameobject_dir_this2world, return vec22js(mat_t_dir(t_go2world(js2gameobject(this)), js2vec2(argv[0])))) -JSC_GETSET_APPLY(gameobject, f, number) -JSC_GETSET_APPLY(gameobject, e, number) -JSC_GETSET_APPLY(gameobject, mass, number) -JSC_GETSET(gameobject, damping, number) -JSC_GETSET(gameobject, timescale, number) -JSC_GETSET(gameobject, maxvelocity, number) -JSC_GETSET(gameobject, maxangularvelocity, number) -JSC_GETSET_APPLY(gameobject, layer, number) -JSC_GETSET(gameobject, warp_filter, bitmask) -JSC_GETSET(gameobject, drawlayer, number) -JSC_CCALL(gameobject_setref, js2gameobject(this)->ref = argv[0]); static const JSCFunctionListEntry js_gameobject_funcs[] = { - CGETSET_ADD(gameobject, f), - CGETSET_ADD(gameobject, e), + CGETSET_ADD(gameobject, friction), + CGETSET_ADD(gameobject, elasticity), CGETSET_ADD(gameobject,mass), CGETSET_ADD(gameobject,damping), CGETSET_ADD(gameobject, scale), @@ -1368,6 +1368,7 @@ static const JSCFunctionListEntry js_gameobject_funcs[] = { MIST_FUNC_DEF(gameobject, dir_world2this, 1), MIST_FUNC_DEF(gameobject, dir_this2world, 1), MIST_FUNC_DEF(gameobject,setref,1), + MIST_FUNC_DEF(gameobject, sync, 0), }; JSC_CCALL(joint_pin, return constraint2js(constraint_make(cpPinJointNew(js2gameobject(argv[0])->body, js2gameobject(argv[1])->body, cpvzero,cpvzero)))) @@ -1584,13 +1585,9 @@ void ffi_load() { globalThis = JS_GetGlobalObject(js); QJSCLASSPREP(ptr); + QJSCLASSPREP_FUNCS(gameobject); QJSCLASSPREP_FUNCS(dsp_node); - - sound_proto = JS_NewObject(js); - JS_SetPropertyFunctionList(js, sound_proto, js_sound_funcs, countof(js_sound_funcs)); - JS_SetPrototype(js, sound_proto, dsp_node_proto); - QJSCLASSPREP_FUNCS(emitter); QJSCLASSPREP_FUNCS(warp_gravity); QJSCLASSPREP_FUNCS(warp_damp); @@ -1629,6 +1626,10 @@ void ffi_load() { JS_SetPropertyStr(js, globalThis, "window", window2js(&mainwin)); JS_SetPropertyStr(js, globalThis, "texture", JS_DupValue(js,texture_proto)); + sound_proto = JS_NewObject(js); + JS_SetPropertyFunctionList(js, sound_proto, js_sound_funcs, countof(js_sound_funcs)); + JS_SetPrototype(js, sound_proto, dsp_node_proto); + JS_FreeValue(js,globalThis); } diff --git a/source/engine/yugine.c b/source/engine/yugine.c index ffe5db0..e6430c0 100644 --- a/source/engine/yugine.c +++ b/source/engine/yugine.c @@ -201,6 +201,7 @@ int main(int argc, char **argv) { signal(SIGABRT, seghandle); signal(SIGFPE, seghandle); #endif + phys2d_init(); resources_init(); stm_setup(); /* time */ @@ -237,7 +238,6 @@ void engine_start(JSValue start, JSValue procfn) c_process_fn = procfn; sound_init(); - phys2d_init(); start_desc.width = mainwin.size.x; start_desc.height = mainwin.size.y;