add 'grow' function to components and entities

This commit is contained in:
John Alanbrook 2024-03-05 22:23:38 -06:00
parent 4ba14ddd91
commit aa4b3e6954
6 changed files with 116 additions and 89 deletions

View file

@ -160,6 +160,10 @@ component.sprite.impl = {
set angle(x) { cmd(218,this.id,x); }, set angle(x) { cmd(218,this.id,x); },
get scale() { return cmd(215, this.id); }, get scale() { return cmd(215, this.id); },
set scale(x) { cmd(216, this.id, x); }, set scale(x) { cmd(216, this.id, x); },
grow(x) {
this.scale = this.scale.scale(x);
this.pos = this.pos.scale(x);
},
get drawmode() { return cmd(220,this.id); }, get drawmode() { return cmd(220,this.id); },
set drawmode(x) { cmd(219,this.id,x); }, set drawmode(x) { cmd(219,this.id,x); },
emissive(x) { cmd(170, this.id, x); }, emissive(x) { cmd(170, this.id, x); },
@ -417,9 +421,15 @@ component.polygon2d = Object.copy(collider2d, {
}, },
}); });
function pointscaler(x) {
if (typeof x === 'number') return;
this.points = this.points.map(p => p.mult(x));
}
component.polygon2d.impl = Object.mix(collider2d.impl, { component.polygon2d.impl = Object.mix(collider2d.impl, {
sync() { cmd_poly2d(0, this.id, this.spoints());}, sync() { cmd_poly2d(0, this.id, this.spoints());},
query() { return cmd(80, this.shape); }, query() { return cmd(80, this.shape); },
grow: pointscaler,
}); });
var polygon2d = component.polygon2d; var polygon2d = component.polygon2d;
@ -463,15 +473,15 @@ component.edge2d = Object.copy(collider2d, {
flipx: false, flipx: false,
flipy: false, flipy: false,
cpoints:[], points:[],
toString() { return "edge2d"; }, toString() { return "edge2d"; },
hollow: false, hollow: false,
hollowt: 0, hollowt: 0,
spoints() { spoints() {
if (!this.cpoints) return []; if (!this.points) return [];
var spoints = this.cpoints.slice(); var spoints = this.points.slice();
if (this.flipx) { if (this.flipx) {
if (Spline.is_bezier(this.type)) if (Spline.is_bezier(this.type))
@ -507,12 +517,12 @@ component.edge2d = Object.copy(collider2d, {
}, },
setpoints(points) { setpoints(points) {
this.cpoints = points; this.points = points;
// this.sync(); // this.sync();
}, },
post() { post() {
this.cpoints = []; this.points = [];
}, },
sample() { sample() {
@ -546,25 +556,25 @@ component.edge2d = Object.copy(collider2d, {
gizmo() { gizmo() {
if (this.type === Spline.type.catmull || this.type === -1) { if (this.type === Spline.type.catmull || this.type === -1) {
this.spoints().forEach(x => render.point(this.gameobject.this2screen(x), 3, Color.teal)); this.spoints().forEach(x => render.point(this.gameobject.this2screen(x), 3, Color.teal));
this.cpoints.forEach((x,i) => Debug.numbered_point(this.gameobject.this2screen(x), i)); this.points.forEach((x,i) => Debug.numbered_point(this.gameobject.this2screen(x), i));
} else { } else {
for (var i = 0; i < this.cpoints.length; i += 3) for (var i = 0; i < this.points.length; i += 3)
Debug.numbered_point(this.gameobject.this2screen(this.cpoints[i]), i, Color.teal); Debug.numbered_point(this.gameobject.this2screen(this.points[i]), i, Color.teal);
for (var i = 1; i < this.cpoints.length; i+=3) { for (var i = 1; i < this.points.length; i+=3) {
Debug.numbered_point(this.gameobject.this2screen(this.cpoints[i]), i, Color.green); Debug.numbered_point(this.gameobject.this2screen(this.points[i]), i, Color.green);
Debug.numbered_point(this.gameobject.this2screen(this.cpoints[i+1]), i+1, Color.green); Debug.numbered_point(this.gameobject.this2screen(this.points[i+1]), i+1, Color.green);
render.line([this.gameobject.this2screen(this.cpoints[i-1]), this.gameobject.this2screen(this.cpoints[i])], Color.yellow); render.line([this.gameobject.this2screen(this.points[i-1]), this.gameobject.this2screen(this.points[i])], Color.yellow);
render.line([this.gameobject.this2screen(this.cpoints[i+1]), this.gameobject.this2screen(this.cpoints[i+2])], Color.yellow); render.line([this.gameobject.this2screen(this.points[i+1]), this.gameobject.this2screen(this.points[i+2])], Color.yellow);
} }
} }
}, },
finish_center(change) { this.cpoints = this.cpoints.map(function(x) { return x.sub(change); }); }, finish_center(change) { this.points = this.points.map(function(x) { return x.sub(change); }); },
pick(pos) { pick(pos) {
var i = Gizmos.pick_gameobject_points(pos, this.gameobject, this.cpoints); var i = Gizmos.pick_gameobject_points(pos, this.gameobject, this.points);
var p = this.cpoints[i]; var p = this.points[i];
if (!p) return undefined; if (!p) return undefined;
if (Spline.is_catmull(this.type) || this.type === -1) if (Spline.is_catmull(this.type) || this.type === -1)
@ -577,38 +587,38 @@ component.edge2d = Object.copy(collider2d, {
pos: p, pos: p,
sync: me.sync.bind(me) sync: me.sync.bind(me)
}; };
if (Spline.bezier_is_handle(this.cpoints,i)) if (Spline.bezier_is_handle(this.points,i))
o.move = function(d) { o.move = function(d) {
d = that.dir_world2this(d); d = that.dir_world2this(d);
p.x += d.x; p.x += d.x;
p.y += d.y; p.y += d.y;
Spline.bezier_cp_mirror(me.cpoints,i); Spline.bezier_cp_mirror(me.points,i);
}; };
else else
o.move = function(d) { o.move = function(d) {
d = that.dir_world2this(d); d = that.dir_world2this(d);
p.x += d.x; p.x += d.x;
p.y += d.y; p.y += d.y;
var pp = Spline.bezier_point_handles(me.cpoints,i); var pp = Spline.bezier_point_handles(me.points,i);
pp.forEach(ph => me.cpoints[ph] = me.cpoints[ph].add(d)); pp.forEach(ph => me.points[ph] = me.points[ph].add(d));
} }
return o; return o;
} }
}, },
rm_node(idx) { rm_node(idx) {
if (idx < 0 || idx >= this.cpoints.length) return; if (idx < 0 || idx >= this.points.length) return;
if (Spline.is_catmull(this.type)) if (Spline.is_catmull(this.type))
this.cpoints.splice(idx,1); this.points.splice(idx,1);
if (Spline.is_bezier(this.type)) { if (Spline.is_bezier(this.type)) {
Debug.assert(Spline.bezier_is_node(this.cpoints, idx), 'Attempted to delete a bezier handle.'); Debug.assert(Spline.bezier_is_node(this.points, idx), 'Attempted to delete a bezier handle.');
if (idx === 0) if (idx === 0)
this.cpoints.splice(idx,2); this.points.splice(idx,2);
else if (idx === this.cpoints.length-1) else if (idx === this.points.length-1)
this.cpoints.splice(this.cpoints.length-2,2); this.points.splice(this.points.length-2,2);
else else
this.cpoints.splice(idx-1,3); this.points.splice(idx-1,3);
} }
}, },
@ -616,46 +626,47 @@ component.edge2d = Object.copy(collider2d, {
pos = this.gameobject.world2this(pos); pos = this.gameobject.world2this(pos);
var idx = 0; var idx = 0;
if (Spline.is_catmull(this.type) || this.type === -1) { if (Spline.is_catmull(this.type) || this.type === -1) {
if (this.cpoints.length >= 2) if (this.points.length >= 2)
idx = cmd(59, pos, this.cpoints, 400); idx = cmd(59, pos, this.points, 400);
if (idx === this.cpoints.length) if (idx === this.points.length)
this.cpoints.push(pos); this.points.push(pos);
else else
this.cpoints.splice(idx, 0, pos); this.points.splice(idx, 0, pos);
} }
if (Spline.is_bezier(this.type)) { if (Spline.is_bezier(this.type)) {
idx = cmd(59, pos, Spline.bezier_nodes(this.cpoints),400); idx = cmd(59, pos, Spline.bezier_nodes(this.points),400);
if (idx < 0) return; if (idx < 0) return;
if (idx === 0) { if (idx === 0) {
this.cpoints.unshift(pos.slice(), pos.add([-100,0]), Vector.reflect_point(this.cpoints[1], this.cpoints[0])); this.points.unshift(pos.slice(), pos.add([-100,0]), Vector.reflect_point(this.points[1], this.points[0]));
return; return;
} }
if (idx === Spline.bezier_node_count(this.cpoints)) { if (idx === Spline.bezier_node_count(this.points)) {
this.cpoints.push(Vector.reflect_point(this.cpoints.at(-2), this.cpoints.at(-1)), pos.add([-100,0]), pos.slice()); this.points.push(Vector.reflect_point(this.points.at(-2), this.points.at(-1)), pos.add([-100,0]), pos.slice());
return; return;
} }
idx = 2 + (idx-1)*3; idx = 2 + (idx-1)*3;
var adds = [pos.add([100,0]), pos.slice(), pos.add([-100,0])]; var adds = [pos.add([100,0]), pos.slice(), pos.add([-100,0])];
this.cpoints.splice(idx, 0, ...adds); this.points.splice(idx, 0, ...adds);
} }
}, },
pick_all() { pick_all() {
var picks = []; var picks = [];
this.cpoints.forEach(x =>picks.push(make_point_obj(this,x))); this.points.forEach(x =>picks.push(make_point_obj(this,x)));
return picks; return picks;
}, },
}); });
component.edge2d.impl = Object.mix({ component.edge2d.impl = Object.mix(collider2d.impl, {
set thickness(x) { set thickness(x) {
cmd_edge2d(1,this.id,x); cmd_edge2d(1,this.id,x);
}, },
get thickness() { return cmd(112,this.id); }, get thickness() { return cmd(112,this.id); },
grow: pointscaler,
sync() { sync() {
var sensor = this.sensor; var sensor = this.sensor;
var points = this.sample(); var points = this.sample();
@ -663,7 +674,7 @@ component.edge2d.impl = Object.mix({
cmd_edge2d(0,this.id,points); cmd_edge2d(0,this.id,points);
this.sensor = sensor; this.sensor = sensor;
}, },
}, component.edge2d.impl); });
var bucket = component.edge2d; var bucket = component.edge2d;
bucket.spoints.doc = "Returns the controls points after modifiers are applied, such as it being hollow or mirrored on its axises."; bucket.spoints.doc = "Returns the controls points after modifiers are applied, such as it being hollow or mirrored on its axises.";
@ -685,7 +696,7 @@ bucket.inputs['M-v'].doc = "Decrease spline thickness.";
bucket.inputs['M-v'].rep = true; bucket.inputs['M-v'].rep = true;
bucket.inputs['C-y'] = function() { bucket.inputs['C-y'] = function() {
this.cpoints = this.spoints(); this.points = this.spoints();
this.flipx = false; this.flipx = false;
this.flipy = false; this.flipy = false;
this.hollow = false; this.hollow = false;
@ -709,7 +720,7 @@ bucket.inputs.minus = function() { this.angle *= 1.1; };
bucket.inputs.minus.doc = "Decrease the number of samples on this spline."; bucket.inputs.minus.doc = "Decrease the number of samples on this spline.";
bucket.inputs.minus.rep = true; bucket.inputs.minus.rep = true;
bucket.inputs['C-r'] = function() { this.cpoints = this.cpoints.reverse(); }; bucket.inputs['C-r'] = function() { this.points = this.points.reverse(); };
bucket.inputs['C-r'].doc = "Reverse the order of the spline's points."; bucket.inputs['C-r'].doc = "Reverse the order of the spline's points.";
bucket.inputs['C-l'] = function() { this.looped = !this.looped}; bucket.inputs['C-l'] = function() { this.looped = !this.looped};
@ -718,7 +729,7 @@ bucket.inputs['C-l'].doc = "Toggle spline being looped.";
bucket.inputs['C-c'] = function() { bucket.inputs['C-c'] = function() {
switch(this.type) { switch(this.type) {
case Spline.type.bezier: case Spline.type.bezier:
this.cpoints = Spline.bezier2catmull(this.cpoints); this.points = Spline.bezier2catmull(this.points);
break; break;
} }
this.type = Spline.type.catmull; this.type = Spline.type.catmull;
@ -729,7 +740,7 @@ bucket.inputs['C-c'].doc = "Set type of spline to catmull-rom.";
bucket.inputs['C-b'] = function() { bucket.inputs['C-b'] = function() {
switch(this.type) { switch(this.type) {
case Spline.type.catmull: case Spline.type.catmull:
this.cpoints = Spline.catmull2bezier(Spline.catmull_caps(this.cpoints)); this.points = Spline.catmull2bezier(Spline.catmull_caps(this.points));
break; break;
} }
this.type = Spline.type.bezier; this.type = Spline.type.bezier;
@ -740,13 +751,13 @@ bucket.inputs['C-o'].doc = "Set spline to linear.";
bucket.inputs['C-M-lm'] = function() { bucket.inputs['C-M-lm'] = function() {
if (Spline.is_catmull(this.type)) { if (Spline.is_catmull(this.type)) {
var idx = Math.grab_from_points(Mouse.worldpos, this.cpoints.map(p => this.gameobject.this2world(p)), 25); var idx = Math.grab_from_points(Mouse.worldpos, this.points.map(p => this.gameobject.this2world(p)), 25);
if (idx === -1) return; if (idx === -1) return;
} else { } else {
} }
this.cpoints = this.cpoints.newfirst(idx); this.points = this.points.newfirst(idx);
}; };
bucket.inputs['C-M-lm'].doc = "Select the given point as the '0' of this spline."; bucket.inputs['C-M-lm'].doc = "Select the given point as the '0' of this spline.";
@ -756,9 +767,9 @@ bucket.inputs['C-lm'].doc = "Add a point to the spline at the mouse position.";
bucket.inputs['C-M-lm'] = function() { bucket.inputs['C-M-lm'] = function() {
var idx = -1; var idx = -1;
if (Spline.is_catmull(this.type)) if (Spline.is_catmull(this.type))
idx = Math.grab_from_points(Mouse.worldpos, this.cpoints.map(p => this.gameobject.this2world(p)), 25); idx = Math.grab_from_points(Mouse.worldpos, this.points.map(p => this.gameobject.this2world(p)), 25);
else { else {
var nodes = Spline.bezier_nodes(this.cpoints); var nodes = Spline.bezier_nodes(this.points);
idx = Math.grab_from_points(Mouse.worldpos, nodes.map(p => this.gameobject.this2world(p)), 25); idx = Math.grab_from_points(Mouse.worldpos, nodes.map(p => this.gameobject.this2world(p)), 25);
idx *= 3; idx *= 3;
} }
@ -773,11 +784,11 @@ bucket.inputs.lm.released = function(){};
bucket.inputs.lb = function() { bucket.inputs.lb = function() {
var np = []; var np = [];
this.cpoints.forEach(function(c) { this.points.forEach(function(c) {
np.push(Vector.rotate(c, Math.deg2rad(-1))); np.push(Vector.rotate(c, Math.deg2rad(-1)));
}); });
this.cpoints = np; this.points = np;
}; };
bucket.inputs.lb.doc = "Rotate the points CCW."; bucket.inputs.lb.doc = "Rotate the points CCW.";
bucket.inputs.lb.rep = true; bucket.inputs.lb.rep = true;
@ -785,11 +796,11 @@ bucket.inputs.lb.rep = true;
bucket.inputs.rb = function() { bucket.inputs.rb = function() {
var np = []; var np = [];
this.cpoints.forEach(function(c) { this.points.forEach(function(c) {
np.push(Vector.rotate(c, Math.deg2rad(1))); np.push(Vector.rotate(c, Math.deg2rad(1)));
}); });
this.cpoints = np; this.points = np;
}; };
bucket.inputs.rb.doc = "Rotate the points CW."; bucket.inputs.rb.doc = "Rotate the points CW.";
bucket.inputs.rb.rep = true; bucket.inputs.rb.rep = true;
@ -820,6 +831,11 @@ component.circle2d.impl = Object.mix({
get pos() { return cmd_circle2d(3,this.id); }, get pos() { return cmd_circle2d(3,this.id); },
set pos(x) { cmd_circle2d(1,this.id,x); }, set pos(x) { cmd_circle2d(1,this.id,x); },
grow(x) {
if (typeof x === 'number') this.scale *= x;
else if (typeof x === 'object') this.scale *= x[0];
},
}, collider2d.impl); }, collider2d.impl);
return {component}; return {component};

View file

@ -164,18 +164,16 @@ performance.test.call_fn_n.doc = "Calls fn1 n times, and then fn2.";
performance.cpu.doc = `Output the time it takes to do a given function n number of times. Provide 'q' as "ns", "us", or "ms" to output the time taken in the requested resolution.`; performance.cpu.doc = `Output the time it takes to do a given function n number of times. Provide 'q' as "ns", "us", or "ms" to output the time taken in the requested resolution.`;
/* These controls are available during editing, and during play of debug builds */ /* These controls are available during editing, and during play of debug builds */
var DebugControls = {}; Debug.inputs = {};
DebugControls.toString = function() { return "Debug"; }; Debug.inputs.f1 = function () { Debug.draw_phys(!Debug.phys_drawing); };
DebugControls.inputs = {}; Debug.inputs.f1.doc = "Draw physics debugging aids.";
DebugControls.inputs.f1 = function () { Debug.draw_phys(!Debug.phys_drawing); }; //Debug.inputs.f3 = function() { Debug.draw_bb = !Debug.draw_bb; };
DebugControls.inputs.f1.doc = "Draw physics debugging aids."; //Debug.inputs.f3.doc = "Toggle drawing bounding boxes.";
//DebugControls.inputs.f3 = function() { Debug.draw_bb = !Debug.draw_bb; }; Debug.inputs.f4 = function() {
//DebugControls.inputs.f3.doc = "Toggle drawing bounding boxes."; Debug.draw_names = !Debug.draw_names;
DebugControls.inputs.f4 = function() { Debug.draw_gizmos = !Debug.draw_gizmos;
// Debug.draw_names = !Debug.draw_names;
// Debug.draw_gizmos = !Debug.draw_gizmos;
}; };
DebugControls.inputs.f4.doc = "Toggle drawing gizmos and names of objects."; Debug.inputs.f4.doc = "Toggle drawing gizmos and names of objects.";
Debug.Options.gif = { Debug.Options.gif = {
w: 640, /* Max width */ w: 640, /* Max width */
@ -215,26 +213,26 @@ Debug.Options.gif = {
}, },
}; };
DebugControls.inputs.f8 = function() { Debug.inputs.f8 = function() {
var now = new Date(); var now = new Date();
Debug.Options.gif.file = now.toISOString() + ".gif"; Debug.Options.gif.file = now.toISOString() + ".gif";
Debug.Options.gif.start(); Debug.Options.gif.start();
}; };
DebugControls.inputs.f9 = function() { Debug.inputs.f9 = function() {
Debug.Options.gif.stop(); Debug.Options.gif.stop();
} }
DebugControls.inputs.f10 = function() { Time.timescale = 0.1; }; Debug.inputs.f10 = function() { Time.timescale = 0.1; };
DebugControls.inputs.f10.doc = "Toggle timescale to 1/10."; Debug.inputs.f10.doc = "Toggle timescale to 1/10.";
DebugControls.inputs.f10.released = function () { Time.timescale = 1.0; }; Debug.inputs.f10.released = function () { Time.timescale = 1.0; };
DebugControls.inputs.f12 = function() { GUI.defaults.debug = !GUI.defaults.debug; console.warn("GUI toggle debug");}; Debug.inputs.f12 = function() { GUI.defaults.debug = !GUI.defaults.debug; console.warn("GUI toggle debug");};
DebugControls.inputs.f12.doc = "Toggle drawing GUI debugging aids."; Debug.inputs.f12.doc = "Toggle drawing GUI debugging aids.";
DebugControls.inputs['M-1'] = render.normal; Debug.inputs['M-1'] = render.normal;
DebugControls.inputs['M-2'] = render.wireframe; Debug.inputs['M-2'] = render.wireframe;
DebugControls.inputs['C-M-f'] = function() {}; Debug.inputs['C-M-f'] = function() {};
DebugControls.inputs['C-M-f'].doc = "Enter camera fly mode."; Debug.inputs['C-M-f'].doc = "Enter camera fly mode.";
var Time = { var Time = {
set timescale(x) { cmd(3, x); }, set timescale(x) { cmd(3, x); },
@ -276,9 +274,6 @@ Time.doc.time = "Seconds elapsed since the game started.";
Time.doc.pause = "Pause the game by setting the timescale to 0; remembers the current timescale on play."; Time.doc.pause = "Pause the game by setting the timescale to 0; remembers the current timescale on play.";
Time.doc.play = "Resume the game after using Time.pause."; Time.doc.play = "Resume the game after using Time.pause.";
player[0].control(DebugControls);
Register.gui.register(Debug.draw, Debug);
Debug.api = {}; Debug.api = {};
Debug.api.doc_entry = function(obj, key) Debug.api.doc_entry = function(obj, key)
{ {

View file

@ -7,6 +7,9 @@ global.mixin("config.js");
Window.aspect(Window.mode.full); Window.aspect(Window.mode.full);
Game.loadurs(); Game.loadurs();
player[0].control(Debug);
Register.gui.register(Debug.draw, Debug);
var editor = { var editor = {
toString() { return "editor"; }, toString() { return "editor"; },
grid_size: 100, grid_size: 100,
@ -209,7 +212,7 @@ var editor = {
player[0].control(limited_editor); player[0].control(limited_editor);
editor.cbs.forEach(cb=>cb()); editor.cbs.forEach(cb=>cb());
editor.cbs = []; editor.cbs = [];
global.mixin("game.js"); actor.spawn("game.js");
}, },
cbs: [], cbs: [],
@ -622,6 +625,23 @@ editor.new_from_img = function(path)
} }
editor.inputs = {}; editor.inputs = {};
editor.inputs['C-b'] = function() {
if (this.selectlist.length !== 1) {
console.warn(`Can only bake a single object at a time.`);
return;
}
var obj = this.selectlist[0];
obj.components.forEach(function(c) {
if (typeof c.grow !== 'function') return;
c.grow(obj.scale);
c.sync?.();
});
obj.scale = [1,1,1];
}
editor.inputs.drop = function(str) { editor.inputs.drop = function(str) {
str = str.slice(os.cwd().length+1); str = str.slice(os.cwd().length+1);
if (!Resources.is_image(str)) { if (!Resources.is_image(str)) {

View file

@ -147,6 +147,7 @@ global.Game = {
set height(h) { cmd(126, h); }, set height(h) { cmd(126, h); },
get width() { return cmd(48); }, get width() { return cmd(48); },
get height() { return cmd(49); }, get height() { return cmd(49); },
dimensions() { return [this.width,this.height]; },
}; };
Game.gc = function() { cmd(259); } Game.gc = function() { cmd(259); }

View file

@ -42,11 +42,6 @@ var gameobject_impl = {
get scale() { get scale() {
Debug.assert(this.master, `No master set on ${this.toString()}`); Debug.assert(this.master, `No master set on ${this.toString()}`);
var pscale = [1,1,1]; var pscale = [1,1,1];
/* if (typeof this.master.scale === 'object')
pscale = this.master.scale;
else
pscale = [1,1,1];
*/
return this.gscale().map((x,i) => x/(this.master.gscale()[i]*pscale[i])); return this.gscale().map((x,i) => x/(this.master.gscale()[i]*pscale[i]));
}, },
@ -55,11 +50,11 @@ var gameobject_impl = {
x = [x,x]; x = [x,x];
var pct = this.scale.map((s,i) => x[i]/s); var pct = this.scale.map((s,i) => x[i]/s);
this.spread(pct); this.grow(pct);
/* TRANSLATE ALL SUB OBJECTS */ /* TRANSLATE ALL SUB OBJECTS */
this.objects.forEach(obj => { this.objects.forEach(obj => {
obj.spread(pct); obj.grow(pct);
obj.pos = obj.pos.map((x,i)=>x*pct[i]); obj.pos = obj.pos.map((x,i)=>x*pct[i]);
}); });
}, },
@ -448,7 +443,7 @@ var gameobject = {
/* Moving, rotating, scaling functions, world relative */ /* Moving, rotating, scaling functions, world relative */
move(vec) { this.set_worldpos(this.worldpos().add(vec)); }, move(vec) { this.set_worldpos(this.worldpos().add(vec)); },
rotate(x) { this.sworldangle(this.worldangle()+x); }, rotate(x) { this.sworldangle(this.worldangle()+x); },
spread(vec) { this.sgscale(this.gscale().map((x,i)=>x*vec[i])); }, grow(vec) { this.sgscale(this.gscale().map((x,i)=>x*vec[i])); },
/* Make a unique object the same as its prototype */ /* Make a unique object the same as its prototype */
revert() { revert() {
@ -480,8 +475,8 @@ var gameobject = {
disable() { this.components.forEach(function(x) { x.disable(); });}, disable() { this.components.forEach(function(x) { x.disable(); });},
enable() { this.components.forEach(function(x) { x.enable(); });}, enable() { this.components.forEach(function(x) { x.enable(); });},
sync() { sync() {
this.components.forEach(function(x) { x.sync(); }); this.components.forEach(function(x) { x.sync?.(); });
this.objects.forEach(function(x) { x.sync(); }); this.objects.forEach(function(x) { x.sync?.(); });
}, },
/* Bounding box of the object in world dimensions */ /* Bounding box of the object in world dimensions */

View file

@ -345,7 +345,7 @@ Cmdline.register_order("init", function() {
}, "Turn the directory into a Prosperon game."); }, "Turn the directory into a Prosperon game.");
Cmdline.register_order("debug", function() { Cmdline.register_order("debug", function() {
Cmdline.orders.play(); Cmdline.orders.play([]);
}, "Play the game with debugging enabled."); }, "Play the game with debugging enabled.");
Cmdline.register_order("play", function(argv) { Cmdline.register_order("play", function(argv) {