Separate entity from rigidbody
This commit is contained in:
parent
e86e126894
commit
79e4772f93
|
@ -177,7 +177,7 @@ Object.mixin(os.sprite(true), {
|
|||
height() { return this.dimensions().y; },
|
||||
});
|
||||
globalThis.allsprites = {};
|
||||
os.sprite(true).make = function(go)
|
||||
os.sprite().make = function(go)
|
||||
{
|
||||
var sp = os.sprite();
|
||||
sp.go = go;
|
||||
|
|
|
@ -344,7 +344,7 @@ var editor = {
|
|||
root = root ? root + "." : root;
|
||||
Object.entries(obj.objects).forEach(function(x) {
|
||||
var p = root + x[0];
|
||||
render.text(p, x[1].screenpos(), 1, editor.color_depths[depth]);
|
||||
render.text(p, x[1].this2screen(), 1, editor.color_depths[depth]);
|
||||
editor.draw_objects_names(x[1], p, depth+1);
|
||||
});
|
||||
},
|
||||
|
@ -402,7 +402,7 @@ var editor = {
|
|||
if (this.comp_info && this.sel_comp)
|
||||
render.text(input.print_pawn_kbm(this.sel_comp,false), [100,700],1);
|
||||
|
||||
render.cross(editor.edit_level.screenpos(),3,Color.blue);
|
||||
render.cross(editor.edit_level.this2screen(),3,Color.blue);
|
||||
|
||||
var thiso = editor.get_this();
|
||||
var clvl = thiso;
|
||||
|
@ -447,16 +447,16 @@ var editor = {
|
|||
render.text("$$$$$$", [0,ypos],1,editor.color_depths[depth]);
|
||||
|
||||
this.selectlist.forEach(function(x) {
|
||||
render.text(x.urstr(), x.screenpos().add([0, render.font.linegap*2]), 1, Color.editor.ur);
|
||||
render.text(x.pos.map(function(x) { return Math.round(x); }), x.screenpos());
|
||||
render.cross(x.screenpos(), 10, Color.blue);
|
||||
render.text(x.urstr(), x.this2screen().add([0, render.font.linegap*2]), 1, Color.editor.ur);
|
||||
render.text(x.pos.map(function(x) { return Math.round(x); }), x.this2screen());
|
||||
render.cross(x.this2screen(), 10, Color.blue);
|
||||
});
|
||||
|
||||
Object.entries(thiso.objects).forEach(function(x) {
|
||||
var p = x[1].namestr();
|
||||
render.text(p, x[1].screenpos().add([0,render.font.linegap]),1,editor.color_depths[depth]);
|
||||
render.point(x[1].screenpos(),5,Color.blue.alpha(0.3));
|
||||
render.point(x[1].screenpos(), 1, Color.red);
|
||||
render.text(p, x[1].this2screen().add([0,render.font.linegap]),1,editor.color_depths[depth]);
|
||||
render.point(x[1].this2screen(),5,Color.blue.alpha(0.3));
|
||||
render.point(x[1].this2screen(), 1, Color.red);
|
||||
});
|
||||
|
||||
var mg = physics.pos_query(input.mouse.worldpos());
|
||||
|
@ -474,7 +474,7 @@ var editor = {
|
|||
for (var key in this.selectlist[0].components) {
|
||||
var selected = this.sel_comp === this.selectlist[0].components[key];
|
||||
var str = (selected ? ">" : " ") + key + " [" + this.selectlist[0].components[key].toString() + "]";
|
||||
render.text(str, this.selectlist[0].screenpos().add([0,-render.font.linegap*(i++)]));
|
||||
render.text(str, this.selectlist[0].this2screen().add([0,-render.font.linegap*(i++)]));
|
||||
}
|
||||
|
||||
if (this.sel_comp) {
|
||||
|
@ -879,7 +879,7 @@ editor.inputs['C-s'] = function() {
|
|||
}
|
||||
|
||||
var savejs = saveobj.json_obj();
|
||||
var tur = saveobj.get_ur();
|
||||
var tur = saveobj.ur;
|
||||
if (!tur) {
|
||||
console.warn(`Can't save object because it has no ur.`);
|
||||
return;
|
||||
|
|
|
@ -289,7 +289,6 @@ game.engine_start = function(s) {
|
|||
gggstart(function() {
|
||||
global.mixin("scripts/sound.js");
|
||||
world_start();
|
||||
go_init();
|
||||
window.set_icon(os.make_texture("icons/moon.gif"))
|
||||
Object.readonly(window.__proto__, 'vsync');
|
||||
Object.readonly(window.__proto__, 'enable_dragndrop');
|
||||
|
@ -330,9 +329,9 @@ function process()
|
|||
}
|
||||
var st = profile.now();
|
||||
if (!game.camera)
|
||||
prosperon.window_render(world, 1);
|
||||
prosperon.window_render(world.transform, 1);
|
||||
else
|
||||
prosperon.window_render(game.camera, game.camera.zoom);
|
||||
prosperon.window_render(game.camera.transform, game.camera.zoom);
|
||||
|
||||
render.set_camera();
|
||||
|
||||
|
@ -627,7 +626,8 @@ global.mixin("scripts/actor");
|
|||
global.mixin("scripts/entity");
|
||||
|
||||
function world_start() {
|
||||
globalThis.world = os.make_gameobject();
|
||||
globalThis.world = Object.create(entity);
|
||||
world.transform = os.make_transform2d();
|
||||
world.objects = {};
|
||||
world.toString = function() { return "world"; };
|
||||
world.ur = "world";
|
||||
|
|
|
@ -12,7 +12,18 @@ function obj_unique_name(name, obj) {
|
|||
return n;
|
||||
}
|
||||
|
||||
var gameobject = {
|
||||
function unique_name(list, name = "new_object") {
|
||||
var str = name.replaceAll('.', '_');
|
||||
var n = 1;
|
||||
var t = str;
|
||||
while (list.indexOf(t) !== -1) {
|
||||
t = str + n;
|
||||
n++;
|
||||
}
|
||||
return t;
|
||||
};
|
||||
|
||||
var entity = {
|
||||
get_comp_by_name(name) {
|
||||
var comps = [];
|
||||
for (var c of Object.values(this.components))
|
||||
|
@ -22,79 +33,6 @@ var gameobject = {
|
|||
return undefined;
|
||||
},
|
||||
|
||||
check_dirty() {
|
||||
this._ed.urdiff = this.json_obj();
|
||||
this._ed.dirty = !Object.empty(this._ed.urdiff);
|
||||
return; // TODO: IMPLEMENT
|
||||
var lur = this.master.ur;
|
||||
if (!lur) return;
|
||||
var lur = lur.objects[this.toString()];
|
||||
var d = ediff(this._ed.urdiff, lur);
|
||||
if (!d || Object.empty(d))
|
||||
this._ed.inst = true;
|
||||
else
|
||||
this._ed.inst = false;
|
||||
},
|
||||
|
||||
namestr() {
|
||||
var s = this.toString();
|
||||
if (this._ed?.dirty)
|
||||
if (this._ed.inst) s += "#";
|
||||
else s += "*";
|
||||
return s;
|
||||
},
|
||||
|
||||
urstr() {
|
||||
var str = this.ur.name;
|
||||
if (this._ed.dirty) str = "*" + str;
|
||||
return str;
|
||||
},
|
||||
|
||||
full_path() {
|
||||
return this.path_from(world);
|
||||
},
|
||||
/* pin this object to the to object */
|
||||
pin(to) {
|
||||
var p = joint.pin(this,to);
|
||||
},
|
||||
slide(to, a = [0,0], b = [0,0], min = 0, max = 50) {
|
||||
var p = joint.slide(this, to, a, b, min, max);
|
||||
p.max_force = 500;
|
||||
p.break();
|
||||
},
|
||||
pivot(to, piv = this.pos) {
|
||||
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 = [0,0]) {
|
||||
var p = joint.groove(to, this, a, b, anchor);
|
||||
},
|
||||
damped_spring(to, length = Vector.length(this.pos,to.pos), stiffness = 1, damping = 1) {
|
||||
var dc = 2 * Math.sqrt(stiffness * this.mass);
|
||||
var p = joint.damped_spring(this, to, [0, 0], [0, 0], stiffness, damping * dc);
|
||||
},
|
||||
damped_rotary_spring(to, angle = 0, stiffness = 1, damping = 1) {
|
||||
/* calculate actual damping value from the damping ratio */
|
||||
/* 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, to, angle, stiffness, damping * dc);
|
||||
},
|
||||
rotary_limit(to, min, 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, to, phase, Math.turn2rad(ratch));
|
||||
},
|
||||
gear(to, ratio = 1, phase = 0) {
|
||||
var phase = this.angle - to.angle;
|
||||
var p = joint.gear(this, to, phase, ratio);
|
||||
},
|
||||
motor(to, rate) {
|
||||
var p = joint.motor(this, to, rate);
|
||||
},
|
||||
|
||||
path_from(o) {
|
||||
var p = this.toString();
|
||||
var c = this.master;
|
||||
|
@ -106,6 +44,8 @@ var gameobject = {
|
|||
return p;
|
||||
},
|
||||
|
||||
full_path() { return this.path_from(world); },
|
||||
|
||||
clear() {
|
||||
for (var k in this.objects) {
|
||||
this.objects[k].kill();
|
||||
|
@ -113,6 +53,11 @@ var gameobject = {
|
|||
this.objects = {};
|
||||
},
|
||||
|
||||
sync() {
|
||||
this.components.forEach(function(x) { x.sync?.(); });
|
||||
this.objects.forEach(function(x) { x.sync(); });
|
||||
},
|
||||
|
||||
delay(fn, seconds) {
|
||||
var timers = this.timers;
|
||||
var stop = function() {
|
||||
|
@ -145,110 +90,60 @@ var gameobject = {
|
|||
|
||||
cry(file) { return audio.cry(file); },
|
||||
|
||||
set pos(x) { this.set_pos(x); },
|
||||
get pos() { return this.rpos; },
|
||||
set angle(x) { this.set_angle(x); },
|
||||
get angle() { return this.rangle; },
|
||||
set scale(x) { this.set_scale(x); },
|
||||
get scale() { return this.rscale; },
|
||||
get pos() { return this.transform.pos; },
|
||||
set pos(x) { this.transform.pos = x; },
|
||||
get angle() { return this.transform.angle; },
|
||||
set angle(x) { this.transform.angle = x; },
|
||||
get scale() { return this.transform.scale; },
|
||||
set scale(x) { this.transform.scale = x; },
|
||||
|
||||
set_pos(x, relative = world) {
|
||||
var newpos = relative.this2world(x);
|
||||
var move = newpos.sub(this.pos);
|
||||
this.rpos = newpos;
|
||||
this.objects.forEach(x => x.move(move));
|
||||
},
|
||||
|
||||
set_angle(x, relative = world) {
|
||||
var newangle = relative.angle + x;
|
||||
var diff = newangle - this.angle;
|
||||
this.rangle = newangle;
|
||||
this.objects.forEach(obj => {
|
||||
obj.rotate(diff);
|
||||
obj.set_pos(Vector.rotate(obj.get_pos(obj.master), diff), obj.master);
|
||||
});
|
||||
},
|
||||
|
||||
set_scale(x, relative = world) {
|
||||
if (typeof x === 'number') x = [x,x,x];
|
||||
var newscale = relative.scale.map((s,i) => x[i]*s);
|
||||
var pct = this.scale.map((s,i) => newscale[i]/s);
|
||||
this.rscale = newscale;
|
||||
this.objects.forEach(obj => {
|
||||
obj.grow(pct);
|
||||
obj.set_pos(obj.get_pos(obj.master).map((x,i) => x*pct[i]), obj.master);
|
||||
});
|
||||
},
|
||||
|
||||
get_pos(relative = world) {
|
||||
if (relative === world) return this.pos;
|
||||
return relative.world2this(this.pos);
|
||||
//return this.pos.sub(relative.pos);
|
||||
},
|
||||
|
||||
get_angle(relative = world) {
|
||||
if (relative === world) return this.angle;
|
||||
return this.angle - relative.angle;
|
||||
},
|
||||
|
||||
get_scale(relative = world) {
|
||||
if (relative === world) return this.scale;
|
||||
var masterscale = relative.scale;
|
||||
return this.scale.map((x,i) => x/masterscale[i]);
|
||||
},
|
||||
|
||||
/* Moving, rotating, scaling functions, world relative */
|
||||
move(vec) { this.set_pos(this.pos.add(vec)); },
|
||||
rotate(x) { this.set_angle(this.angle + x); },
|
||||
move(vec) { this.pos = this.pos.add(vec); },
|
||||
rotate(x) { this.angle += x; },
|
||||
grow(vec) {
|
||||
if (typeof vec === 'number') vec = [vec,vec,vec];
|
||||
this.set_scale(this.scale.map((x, i) => x * vec[i]));
|
||||
if (typeof vec === 'number') vec = [vec,vec];
|
||||
this.scale = this.scale.map((x,i) => x*vec[i]);
|
||||
},
|
||||
|
||||
screenpos() { return game.camera.world2view(this.pos); },
|
||||
/* Reparent 'this' to be 'parent's child */
|
||||
reparent(parent) {
|
||||
assert(parent, `Tried to reparent ${this.toString()} to nothing.`);
|
||||
console.spam(`parenting ${this.toString()} to ${parent.toString()}`);
|
||||
if (this.master === parent) {
|
||||
console.warn("not reparenting ...");
|
||||
console.warn(`${this.master} is the same as ${parent}`);
|
||||
return;
|
||||
}
|
||||
|
||||
get_ur() { return this.ur; },
|
||||
var name = unique_name(Object.keys(parent), this.name);
|
||||
this.name = name;
|
||||
|
||||
this.master?.remove_obj(this);
|
||||
this.master = parent;
|
||||
parent.objects[this.guid] = this;
|
||||
parent[name] = this;
|
||||
Object.hide(parent, name);
|
||||
},
|
||||
|
||||
remove_obj(obj) {
|
||||
delete this.objects[obj.guid];
|
||||
delete this[obj.name];
|
||||
Object.unhide(this, obj.name);
|
||||
},
|
||||
|
||||
/* spawn an entity
|
||||
text can be:
|
||||
the file path of a script
|
||||
an ur object
|
||||
nothing
|
||||
*/
|
||||
spawn(text, config, callback) {
|
||||
var st = profile.now();
|
||||
var ent = os.make_gameobject();
|
||||
var ent = Object.create(entity);
|
||||
ent.transform = os.make_transform2d();
|
||||
|
||||
ent.guid = prosperon.guid();
|
||||
|
||||
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 (!text)
|
||||
ent.ur = emptyur;
|
||||
else 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();
|
||||
|
@ -294,7 +189,7 @@ var gameobject = {
|
|||
if (sim.playing())
|
||||
if (typeof ent.start === 'function') ent.start();
|
||||
|
||||
Object.hide(ent, 'ur', 'components', 'objects', 'timers', 'guid', 'master', 'categories');
|
||||
Object.hide(ent, 'ur', 'components', 'objects', 'timers', 'guid', 'master');
|
||||
|
||||
ent._ed = {
|
||||
selectable: true,
|
||||
|
@ -324,6 +219,7 @@ var gameobject = {
|
|||
|
||||
if (callback) callback(ent);
|
||||
|
||||
|
||||
ent.ur.fresh ??= json.decode(json.encode(ent));
|
||||
ent.ur.fresh.objects = {};
|
||||
for (var i in ent.objects)
|
||||
|
@ -333,60 +229,17 @@ var gameobject = {
|
|||
return ent;
|
||||
},
|
||||
|
||||
/* Reparent 'this' to be 'parent's child */
|
||||
reparent(parent) {
|
||||
assert(parent, `Tried to reparent ${this.toString()} to nothing.`);
|
||||
console.spam(`parenting ${this.toString()} to ${parent.toString()}`);
|
||||
if (this.master === parent) {
|
||||
console.warn("not reparenting ...");
|
||||
console.warn(`${this.master} is the same as ${parent}`);
|
||||
return;
|
||||
}
|
||||
|
||||
this.master?.remove_obj(this);
|
||||
|
||||
this.master = parent;
|
||||
|
||||
function unique_name(list, name = "new_object") {
|
||||
var str = name.replaceAll('.', '_');
|
||||
var n = 1;
|
||||
var t = str;
|
||||
while (list.indexOf(t) !== -1) {
|
||||
t = str + n;
|
||||
n++;
|
||||
}
|
||||
return t;
|
||||
};
|
||||
|
||||
var name = unique_name(Object.keys(parent.objects), this.ur.name);
|
||||
|
||||
parent.objects[name] = this;
|
||||
parent[name] = this;
|
||||
Object.hide(parent, name);
|
||||
this.toString = function() { return name; };
|
||||
},
|
||||
|
||||
remove_obj(obj) {
|
||||
delete this.objects[obj.toString()];
|
||||
delete this[obj.toString()];
|
||||
Object.unhide(this, obj.toString());
|
||||
},
|
||||
|
||||
components: {},
|
||||
objects: {},
|
||||
master: undefined,
|
||||
disable() { this.components.forEach(function(x) { x.disable(); }); },
|
||||
enable() { this.components.forEach(function(x) { x.enable(); }); },
|
||||
|
||||
this2screen(pos) { return game.camera.world2view(this.this2world(pos)); },
|
||||
screen2this(pos) { return this.world2this(game.camera.view2world(pos)); },
|
||||
|
||||
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?.(); }); },
|
||||
/* Make a unique object the same as its prototype */
|
||||
revert() { Object.merge(this, this.ur.fresh); },
|
||||
|
||||
name: "new_object",
|
||||
toString() { return this.name; },
|
||||
width() {
|
||||
var bb = this.boundingbox();
|
||||
return bb.r - bb.l;
|
||||
|
@ -397,19 +250,11 @@ var gameobject = {
|
|||
return bb.t - bb.b;
|
||||
},
|
||||
|
||||
/* Make a unique object the same as its prototype */
|
||||
revert() { Object.merge(this, this.ur.fresh); },
|
||||
|
||||
toString() { return "new_object"; },
|
||||
|
||||
flipx() { return this.scale.x < 0; },
|
||||
flipy() { return this.scale.y < 0; },
|
||||
|
||||
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(); }); },
|
||||
|
||||
/* Bounding box of the object in world dimensions */
|
||||
boundingbox() {
|
||||
var boxes = [];
|
||||
|
@ -476,22 +321,7 @@ var gameobject = {
|
|||
return t;
|
||||
},
|
||||
|
||||
/* Velocity and angular velocity of the object */
|
||||
phys_obj() {
|
||||
var phys = {};
|
||||
phys.velocity = this.velocity;
|
||||
phys.angularvelocity = this.angularvelocity;
|
||||
return phys;
|
||||
},
|
||||
|
||||
phys_mat() {
|
||||
return {
|
||||
friction: this.friction,
|
||||
elasticity: this.elasticity
|
||||
}
|
||||
},
|
||||
|
||||
dup(diff) {
|
||||
dup(diff) {
|
||||
var n = this.master.spawn(this.ur);
|
||||
Object.totalmerge(n, this.transform());
|
||||
return n;
|
||||
|
@ -532,10 +362,6 @@ var gameobject = {
|
|||
}
|
||||
},
|
||||
|
||||
up() { return [0, 1].rotate(this.angle); },
|
||||
down() { return [0, -1].rotate(this.angle); },
|
||||
right() { return [1, 0].rotate(this.angle); },
|
||||
left() { return [-1, 0].rotate(this.angle); },
|
||||
|
||||
make_objs(objs) {
|
||||
for (var prop in objs) {
|
||||
|
@ -575,19 +401,159 @@ var gameobject = {
|
|||
Object.assign(this[name], data);
|
||||
return this[name];
|
||||
},
|
||||
}
|
||||
};
|
||||
|
||||
function go_init() {
|
||||
var gop = os.make_gameobject().__proto__;
|
||||
Object.mixin(gop, gameobject);
|
||||
gop.sync = function() {
|
||||
this.selfsync();
|
||||
this.components.forEach(function(x) { x.sync?.(); });
|
||||
this.objects.forEach(function(x) { x.sync?.(); });
|
||||
var gameobject = {
|
||||
check_dirty() {
|
||||
this._ed.urdiff = this.json_obj();
|
||||
this._ed.dirty = !Object.empty(this._ed.urdiff);
|
||||
return; // TODO: IMPLEMENT
|
||||
var lur = this.master.ur;
|
||||
if (!lur) return;
|
||||
var lur = lur.objects[this.toString()];
|
||||
var d = ediff(this._ed.urdiff, lur);
|
||||
if (!d || Object.empty(d))
|
||||
this._ed.inst = true;
|
||||
else
|
||||
this._ed.inst = false;
|
||||
},
|
||||
|
||||
namestr() {
|
||||
var s = this.toString();
|
||||
if (this._ed?.dirty)
|
||||
if (this._ed.inst) s += "#";
|
||||
else s += "*";
|
||||
return s;
|
||||
},
|
||||
|
||||
urstr() {
|
||||
var str = this.ur.name;
|
||||
if (this._ed.dirty) str = "*" + str;
|
||||
return str;
|
||||
},
|
||||
|
||||
/* pin this object to the to object */
|
||||
pin(to) {
|
||||
var p = joint.pin(this,to);
|
||||
},
|
||||
slide(to, a = [0,0], b = [0,0], min = 0, max = 50) {
|
||||
var p = joint.slide(this, to, a, b, min, max);
|
||||
p.max_force = 500;
|
||||
p.break();
|
||||
},
|
||||
pivot(to, piv = this.pos) {
|
||||
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 = [0,0]) {
|
||||
var p = joint.groove(to, this, a, b, anchor);
|
||||
},
|
||||
damped_spring(to, length = Vector.length(this.pos,to.pos), stiffness = 1, damping = 1) {
|
||||
var dc = 2 * Math.sqrt(stiffness * this.mass);
|
||||
var p = joint.damped_spring(this, to, [0, 0], [0, 0], stiffness, damping * dc);
|
||||
},
|
||||
damped_rotary_spring(to, angle = 0, stiffness = 1, damping = 1) {
|
||||
/* calculate actual damping value from the damping ratio */
|
||||
/* 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, to, angle, stiffness, damping * dc);
|
||||
},
|
||||
rotary_limit(to, min, 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, to, phase, Math.turn2rad(ratch));
|
||||
},
|
||||
gear(to, ratio = 1, phase = 0) {
|
||||
var phase = this.angle - to.angle;
|
||||
var p = joint.gear(this, to, phase, ratio);
|
||||
},
|
||||
motor(to, rate) {
|
||||
var p = joint.motor(this, to, rate);
|
||||
},
|
||||
|
||||
set_pos(x, relative = world) {
|
||||
var newpos = relative.this2world(x);
|
||||
var move = newpos.sub(this.pos);
|
||||
this.rpos = newpos;
|
||||
this.objects.forEach(x => x.move(move));
|
||||
},
|
||||
|
||||
set_angle(x, relative = world) {
|
||||
var newangle = relative.angle + x;
|
||||
var diff = newangle - this.angle;
|
||||
this.rangle = newangle;
|
||||
this.objects.forEach(obj => {
|
||||
obj.rotate(diff);
|
||||
obj.set_pos(Vector.rotate(obj.get_pos(obj.master), diff), obj.master);
|
||||
});
|
||||
},
|
||||
|
||||
set_scale(x, relative = world) {
|
||||
if (typeof x === 'number') x = [x,x,x];
|
||||
var newscale = relative.scale.map((s,i) => x[i]*s);
|
||||
var pct = this.scale.map((s,i) => newscale[i]/s);
|
||||
this.rscale = newscale;
|
||||
this.objects.forEach(obj => {
|
||||
obj.grow(pct);
|
||||
obj.set_pos(obj.get_pos(obj.master).map((x,i) => x*pct[i]), obj.master);
|
||||
});
|
||||
},
|
||||
|
||||
get_pos(relative = world) {
|
||||
if (relative === world) return this.pos;
|
||||
return relative.world2this(this.pos);
|
||||
//return this.pos.sub(relative.pos);
|
||||
},
|
||||
|
||||
get_angle(relative = world) {
|
||||
if (relative === world) return this.angle;
|
||||
return this.angle - relative.angle;
|
||||
},
|
||||
|
||||
get_scale(relative = world) {
|
||||
if (relative === world) return this.scale;
|
||||
var masterscale = relative.scale;
|
||||
return this.scale.map((x,i) => x/masterscale[i]);
|
||||
},
|
||||
|
||||
in_air() { return this.in_air(); },
|
||||
|
||||
/* Velocity and angular velocity of the object */
|
||||
phys_obj() {
|
||||
var phys = {};
|
||||
phys.velocity = this.velocity;
|
||||
phys.angularvelocity = this.angularvelocity;
|
||||
return phys;
|
||||
},
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
gameobject.spawn.doc = `Spawn an entity of type 'ur' on this entity. Returns the spawned entity.`;
|
||||
entity.spawn.doc = `Spawn an entity of type 'ur' on this entity. Returns the spawned entity.`;
|
||||
|
||||
gameobject.doc = {
|
||||
doc: "All objects in the game created through spawning have these attributes.",
|
||||
|
@ -695,8 +661,18 @@ function apply_ur(u, ent) {
|
|||
}
|
||||
}
|
||||
|
||||
var emptyur = {
|
||||
name: "empty"
|
||||
}
|
||||
|
||||
var getur = function(text, data)
|
||||
{
|
||||
if (!text && !data) {
|
||||
console.info('empty ur');
|
||||
return {
|
||||
name: "empty"
|
||||
};
|
||||
}
|
||||
var urstr = text + "+" + data;
|
||||
if (!ur[urstr]) {
|
||||
ur[urstr] = {
|
||||
|
@ -784,4 +760,4 @@ game.ur.save = function(str)
|
|||
}
|
||||
}
|
||||
|
||||
return { go_init }
|
||||
return { entity }
|
|
@ -84,8 +84,6 @@ void model_free(model *m);
|
|||
|
||||
void model_draw_go(model *m, gameobject *go, gameobject *cam);
|
||||
|
||||
void model_init();
|
||||
|
||||
material *material_make();
|
||||
void material_free(material *mat);
|
||||
|
||||
|
|
|
@ -204,9 +204,3 @@ HMM_Vec3 go_pos3d(gameobject *go)
|
|||
HMM_Vec2 pos2d = go_pos(go);
|
||||
return (HMM_Vec3){pos2d.x, pos2d.y, go->drawlayer};
|
||||
}
|
||||
|
||||
void gameobject_draw_debug(gameobject *go) {
|
||||
if (!go || !go->body) return;
|
||||
|
||||
cpBodyEachShape(go->body, body_draw_shapes_dbg, NULL);
|
||||
}
|
||||
|
|
|
@ -779,7 +779,21 @@ JSC_CCALL(render_setuniproj,
|
|||
)
|
||||
|
||||
JSC_CCALL(render_setunim4,
|
||||
HMM_Mat4 m = transform2d2mat4(js2transform2d(argv[2]));
|
||||
HMM_Mat4 m = MAT1;
|
||||
if (JS_IsArray(js, argv[2])) {
|
||||
JSValue arr = argv[2];
|
||||
int n = js_arrlen(arr);
|
||||
if (n == 1)
|
||||
m = transform2d2mat4(js2transform2d(js_getpropidx(arr,0)));
|
||||
else {
|
||||
for (int i = 0; i < n; i++) {
|
||||
HMM_Mat4 p = transform2d2mat4(js2transform2d(js_getpropidx(arr, i)));
|
||||
m = HMM_MulM4(p,m);
|
||||
}
|
||||
}
|
||||
} else
|
||||
m = transform2d2mat4(js2transform2d(argv[2]));
|
||||
|
||||
sg_apply_uniforms(js2number(argv[0]), js2number(argv[1]), SG_RANGE_REF(m.e));
|
||||
);
|
||||
|
||||
|
@ -920,7 +934,7 @@ static const JSCFunctionListEntry js_input_funcs[] = {
|
|||
|
||||
JSC_CCALL(prosperon_emitters_step, emitters_step(js2number(argv[0])))
|
||||
JSC_CCALL(prosperon_phys2d_step, phys2d_update(js2number(argv[0])))
|
||||
JSC_CCALL(prosperon_window_render, openglRender(&mainwin, js2gameobject(argv[0]), js2number(argv[1])))
|
||||
JSC_CCALL(prosperon_window_render, openglRender(&mainwin, js2transform2d(argv[0]), js2number(argv[1])))
|
||||
JSC_CCALL(prosperon_guid,
|
||||
uint8_t bytes[16];
|
||||
for (int i = 0; i < 16; i++) bytes[i] = rand()%256;
|
||||
|
@ -1089,8 +1103,6 @@ static const JSCFunctionListEntry js_io_funcs[] = {
|
|||
MIST_FUNC_DEF(io, mod,1)
|
||||
};
|
||||
|
||||
JSC_CCALL(debug_draw_gameobject, gameobject_draw_debug(js2gameobject(argv[0]));)
|
||||
|
||||
JSC_GETSET_GLOBAL(disabled_color, color)
|
||||
JSC_GETSET_GLOBAL(sleep_color, color)
|
||||
JSC_GETSET_GLOBAL(dynamic_color, color)
|
||||
|
@ -1098,7 +1110,6 @@ JSC_GETSET_GLOBAL(kinematic_color, color)
|
|||
JSC_GETSET_GLOBAL(static_color, color)
|
||||
|
||||
static const JSCFunctionListEntry js_debug_funcs[] = {
|
||||
MIST_FUNC_DEF(debug, draw_gameobject, 1),
|
||||
CGETSET_ADD(global, disabled_color),
|
||||
CGETSET_ADD(global, sleep_color),
|
||||
CGETSET_ADD(global, dynamic_color),
|
||||
|
@ -1716,7 +1727,16 @@ JSC_SCALL(os_make_texture,
|
|||
JSC_CCALL(os_make_font, return font2js(MakeFont(js2str(argv[0]), js2number(argv[1]))))
|
||||
|
||||
JSC_CCALL(os_make_transform2d,
|
||||
return transform2d2js(make_transform2d());
|
||||
if (JS_IsUndefined(argv[0]))
|
||||
return transform2d2js(make_transform2d());
|
||||
|
||||
int n = js2number(argv[0]);
|
||||
transform2d *t = calloc(sizeof(transform2d), n);
|
||||
JSValue arr = JS_NewArray(js);
|
||||
for (int i = 0; i < n; i++)
|
||||
js_setprop_num(arr, i, transform2d2js(t+i));
|
||||
|
||||
return arr;
|
||||
)
|
||||
|
||||
JSC_SCALL(os_system, return number2js(system(str)); )
|
||||
|
@ -1742,7 +1762,7 @@ static const JSCFunctionListEntry js_os_funcs[] = {
|
|||
MIST_FUNC_DEF(os, make_texture, 1),
|
||||
MIST_FUNC_DEF(os, make_font, 2),
|
||||
MIST_FUNC_DEF(os, make_model, 1),
|
||||
MIST_FUNC_DEF(os, make_transform2d, 0),
|
||||
MIST_FUNC_DEF(os, make_transform2d, 1),
|
||||
};
|
||||
|
||||
#include "steam.h"
|
||||
|
|
|
@ -258,8 +258,6 @@ void render_init() {
|
|||
font_init();
|
||||
debugdraw_init();
|
||||
|
||||
model_init();
|
||||
|
||||
sg_color c = (sg_color){0,0,0,1};
|
||||
pass_action = (sg_pass_action){
|
||||
.colors[0] = {.load_action = SG_LOADACTION_CLEAR, .clear_value = c},
|
||||
|
@ -337,7 +335,7 @@ HMM_Mat4 useproj = {0};
|
|||
#define MODE_EXPAND 4
|
||||
#define MODE_FULL 5
|
||||
|
||||
void openglRender(struct window *window, gameobject *cam, float zoom) {
|
||||
void openglRender(struct window *window, transform2d *cam, float zoom) {
|
||||
sg_swapchain sch = sglue_swapchain();
|
||||
sg_begin_pass(&(sg_pass){
|
||||
.action = pass_action,
|
||||
|
@ -372,7 +370,7 @@ void openglRender(struct window *window, gameobject *cam, float zoom) {
|
|||
}
|
||||
|
||||
// 2D projection
|
||||
campos = go_pos(cam);
|
||||
campos = cam->pos;
|
||||
camzoom = zoom;
|
||||
|
||||
projection = HMM_Orthographic_RH_NO(
|
||||
|
|
|
@ -14,6 +14,7 @@
|
|||
#include "sokol/sokol_gfx.h"
|
||||
#include "HandmadeMath.h"
|
||||
#include "gameobject.h"
|
||||
#include "transform.h"
|
||||
|
||||
#define RGBA_MAX 255
|
||||
|
||||
|
@ -61,7 +62,7 @@ void render_init();
|
|||
extern HMM_Vec2 campos;
|
||||
extern float camzoom;
|
||||
|
||||
void openglRender(struct window *window, gameobject *cam, float zoom);
|
||||
void openglRender(struct window *window, transform2d *cam, float zoom);
|
||||
void opengl_rendermode(enum RenderMode r);
|
||||
|
||||
void openglInit3d(struct window *window);
|
||||
|
|
Loading…
Reference in a new issue