Start and restart play mode

This commit is contained in:
John Alanbrook 2023-10-11 22:22:41 +00:00
parent cff5483325
commit 8f455476f1
9 changed files with 129 additions and 172 deletions

View file

@ -43,6 +43,14 @@ Object.rkeys = function(o)
return keys; return keys;
} }
Object.extend = function(from, src)
{
var n = {};
Object.mixin(n, from);
Object.mixin(n, src);
return n;
}
Object.mixin = function(target, source) Object.mixin = function(target, source)
{ {
if (typeof source !== 'object') return target; if (typeof source !== 'object') return target;
@ -57,6 +65,15 @@ Object.mixin = function(target, source)
return target; return target;
}; };
Object.deepmixin = function(target, source)
{
var o = source;
while (o !== Object.prototype) {
Object.mixin(target, o);
o = o.__proto__;
};
}
Object.deepfreeze = function(obj) Object.deepfreeze = function(obj)
{ {
for (var key in obj) { for (var key in obj) {
@ -67,23 +84,6 @@ Object.deepfreeze = function(obj)
} }
/* Goes through each key and overwrites if it's present */ /* Goes through each key and overwrites if it's present */
/*
Object.dainty_assign = function(target, source)
{
Object.keys(target).forEach(function(key) {
if (!(key in source)) return;
if (typeof target[key] === 'function') return;
if (Array.isArray(target[key]))
target[key] = deep_copy(source[key]);
else if (typeof target[key] === 'object')
Object.dainty_assign(target[key], source[key]);
else
target[key] = source[key];
});
}
*/
Object.dainty_assign = function(target, source) Object.dainty_assign = function(target, source)
{ {
Object.keys(source).forEach(function(k) { Object.keys(source).forEach(function(k) {
@ -230,13 +230,6 @@ Object.defineProperty(Object.prototype, 'nulldef', {
} }
}); });
/*Object.defineProperty(Object.prototype, 'writable', {
value: function(name) {
return Object.getPropertyDescriptor(this, name).writable;
}
});
*/
Object.defineProperty(Object.prototype, 'prop_obj', { Object.defineProperty(Object.prototype, 'prop_obj', {
value: function() { return JSON.parse(JSON.stringify(this)); } value: function() { return JSON.parse(JSON.stringify(this)); }
}); });

View file

@ -324,11 +324,14 @@ var collider2d = Object.copy(component, {
register_hit(fn, obj) { register_hit(fn, obj) {
register_collide(1, fn, obj, this.gameobject.body, this.shape); register_collide(1, fn, obj, this.gameobject.body, this.shape);
}, },
/* set sensor(x) { cmd(18,this.shape,x); },
impl: {
set sensor(x) { cmd(18,this.shape,x); },
get sensor() { return cmd(21,this.shape); }, get sensor() { return cmd(21,this.shape); },
set enabled(x) { cmd(22,this.shape,x); }, // set enabled(x) { cmd(22,this.shape,x); },
get enabled() { return cmd(23,this.shape); } // get enabled() { return cmd(23,this.shape); }
*/ },
}); });
collider2d.inputs = {}; collider2d.inputs = {};
@ -403,14 +406,14 @@ component.polygon2d = Object.copy(collider2d, {
}, },
}); });
component.polygon2d.impl = { component.polygon2d.impl = Object.extend(collider2d.impl, {
sync() { sync() {
cmd_poly2d(0, this.id, this.spoints); cmd_poly2d(0, this.id, this.spoints);
}, },
query() { query() {
return cmd(80, this.shape); return cmd(80, this.shape);
}, },
}; });
var polygon2d = component.polygon2d; var polygon2d = component.polygon2d;
@ -448,7 +451,6 @@ component.edge2d = Object.copy(collider2d, {
degrees:2, degrees:2,
dimensions:2, dimensions:2,
thickness:0, thickness:0,
points: [],
/* open: 0 /* open: 0
clamped: 1 clamped: 1
beziers: 2 beziers: 2
@ -524,7 +526,7 @@ component.edge2d = Object.copy(collider2d, {
assert knots%order != 0 assert knots%order != 0
*/ */
if (this.type === typeid.this.looped) if (this.type === component.edge2d.typeid.this.looped)
return spline_cmd(0, this.degrees, this.dimensions, 0, spoints.wrapped(this.degrees), n); return spline_cmd(0, this.degrees, this.dimensions, 0, spoints.wrapped(this.degrees), n);
return spline_cmd(0, this.degrees, this.dimensions, this.type, spoints, n); return spline_cmd(0, this.degrees, this.dimensions, this.type, spoints, n);
@ -536,16 +538,8 @@ component.edge2d = Object.copy(collider2d, {
return points2bb(this.points.map(x => x.scale(this.gameobject.scale))); return points2bb(this.points.map(x => x.scale(this.gameobject.scale)));
}, },
make(go) { hides: ['gameobject', 'id', 'shape', 'points'],
var edge = Object.create(this); _enghook: make_edge2d,
edge.gameobject = go;
// edge.cpoints = [];
// edge.points = [];
Object.assign(edge, make_edge2d(go.body, edge.points, 0));
Object.mixin(edge,edge.impl);
Object.hide(edge, 'gameobject', 'id', 'shape');
return edge;
},
/* EDITOR */ /* EDITOR */
gizmo() { gizmo() {
@ -570,23 +564,22 @@ component.edge2d = Object.copy(collider2d, {
sync: this.sync.bind(this), sync: this.sync.bind(this),
}; };
return undefined; return undefined;
}, },
}); });
component.edge2d.impl = { component.edge2d.impl = Object.extend(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); },
sync() { sync() {
var sensor = this.sensor; var sensor = this.sensor;
this.points = this.sample(this.samples); var points = this.sample(this.samples);
cmd_edge2d(0,this.id,this.points); cmd_edge2d(0,this.id,points);
this.sensor = sensor; this.sensor = sensor;
}, },
}; });
var bucket = component.edge2d; var bucket = component.edge2d;
bucket.inputs = {}; bucket.inputs = {};
@ -655,6 +648,8 @@ bucket.inputs['C-M-lm'] = function() {
}; };
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.";
bucket.inputs.lm = function(){};
bucket.inputs['C-lm'] = function() { bucket.inputs['C-lm'] = function() {
var idx = 0; var idx = 0;
@ -670,13 +665,15 @@ bucket.inputs['C-lm'] = function() {
}; };
bucket.inputs['C-lm'].doc = "Add a point to the spline at the mouse position."; bucket.inputs['C-lm'].doc = "Add a point to the spline at the mouse position.";
bucket.inputs['S-lm'] = function() { bucket.inputs['C-M-lm'] = function() {
var idx = grab_from_points(screen2world(Mouse.pos), this.cpoints.map(function(x) {return x.add(this.gameobject.pos); }, this), 25); var idx = cmd(59, Mouse.worldpos.sub(this.gameobject.pos), this.cpoints, 250);
Log.warn(idx);
// var idx = grab_from_points(screen2world(Mouse.pos), this.cpoints.map(function(x) {return x.add(this.gameobject.pos); }, this), 25);
if (idx === -1) return; if (idx === -1) return;
this.cpoints.splice(idx, 1); this.cpoints.splice(idx, 1);
}; };
bucket.inputs['S-lm'].doc = "Remove point from the spline."; bucket.inputs['C-M-lm'].doc = "Remove point from the spline.";
bucket.inputs.lb = function() { bucket.inputs.lb = function() {
var np = []; var np = [];
@ -703,17 +700,6 @@ bucket.inputs.rb.doc = "Rotate the points CW.";
bucket.inputs.rb.rep = true; bucket.inputs.rb.rep = true;
component.circle2d = Object.copy(collider2d, { component.circle2d = Object.copy(collider2d, {
impl: {
set radius(x) { cmd_circle2d(0,this.id,x); },
get radius() { return cmd_circle2d(2,this.id); },
set scale(x) { this.radius = x; },
get scale() { return this.radius; },
set offset(x) { cmd_circle2d(1,this.id,x); },
get offset() { return cmd_circle2d(3,this.id); },
},
radius:10, radius:10,
offset:[0,0], offset:[0,0],
toString() { return "circle2d"; }, toString() { return "circle2d"; },
@ -727,6 +713,17 @@ component.circle2d = Object.copy(collider2d, {
_enghook: make_circle2d, _enghook: make_circle2d,
}); });
component.circle2d.impl = Object.extend(collider2d.impl, {
set radius(x) { cmd_circle2d(0,this.id,x); },
get radius() { return cmd_circle2d(2,this.id); },
set scale(x) { this.radius = x; },
get scale() { return this.radius; },
set offset(x) { cmd_circle2d(1,this.id,x); },
get offset() { return cmd_circle2d(3,this.id); },
});
/* ASSETS */ /* ASSETS */
var Texture = { var Texture = {

View file

@ -154,8 +154,8 @@ DebugControls.inputs.f1.doc = "Draw physics debugging aids.";
//DebugControls.inputs.f3 = function() { Debug.draw_bb = !Debug.draw_bb; }; //DebugControls.inputs.f3 = function() { Debug.draw_bb = !Debug.draw_bb; };
//DebugControls.inputs.f3.doc = "Toggle drawing bounding boxes."; //DebugControls.inputs.f3.doc = "Toggle drawing bounding boxes.";
DebugControls.inputs.f4 = function() { DebugControls.inputs.f4 = function() {
Debug.draw_names = !Debug.draw_names; // Debug.draw_names = !Debug.draw_names;
Debug.draw_gizmos = !Debug.draw_gizmos; // Debug.draw_gizmos = !Debug.draw_gizmos;
}; };
DebugControls.inputs.f4.doc = "Toggle drawing gizmos and names of objects."; DebugControls.inputs.f4.doc = "Toggle drawing gizmos and names of objects.";

View file

@ -197,10 +197,10 @@ var editor = {
stash: undefined, stash: undefined,
start_play_ed() { start_play_ed() {
this.stash = this.edit_level.json_obj(); this.stash = this.desktop.instance_obj();
this.edit_level.kill(); Primum.clear();
// load_configs("game.config");
Game.play(); Game.play();
Game.editor_mode(false);
Player.players[0].uncontrol(this); Player.players[0].uncontrol(this);
Player.players[0].control(limited_editor); Player.players[0].control(limited_editor);
Register.unregister_obj(this); Register.unregister_obj(this);
@ -215,6 +215,16 @@ var editor = {
Debug.register_call(editor.ed_debug, editor); Debug.register_call(editor.ed_debug, editor);
Register.update.register(gui_controls.update, gui_controls); Register.update.register(gui_controls.update, gui_controls);
Player.players[0].control(gui_controls); Player.players[0].control(gui_controls);
this.desktop = Primum.spawn(ur.arena);
this.edit_level = this.desktop;
editor.edit_level._ed.selectable = false;
if (this.stash) {
this.desktop.make_objs(this.stash.objects);
Object.dainty_assign(this.desktop, this.stash);
}
this.selectlist = [];
Game.view_camera(editor.camera);
}, },
end_debug() { end_debug() {
@ -356,23 +366,6 @@ var editor = {
} }
}, },
clear_level() {
if (this.edit_level) {
if (this.edit_level.level) {
this.openpanel(gen_notify("Can't close a nested level. Save up to the root before continuing."));
return;
}
this.unselect();
this.edit_level.kill();
}
this.edit_level = Primum.spawn(ur.arena);
this.desktop = this.edit_level;
if (this.stash)
editor.edit_level._ed.selectable = false;
},
load_desktop(d) { load_desktop(d) {
}, },
@ -663,13 +656,13 @@ editor.inputs['C-e'].doc = "Open asset explorer.";
editor.inputs['C-l'] = function() { editor.openpanel(entitylistpanel); }; editor.inputs['C-l'] = function() { editor.openpanel(entitylistpanel); };
editor.inputs['C-l'].doc = "Open list of spawned entities."; editor.inputs['C-l'].doc = "Open list of spawned entities.";
/*editor.inputs['C-i'] = function() { editor.inputs['C-i'] = function() {
if (editor.selectlist.length !== 1) return; if (editor.selectlist.length !== 1) return;
objectexplorer.obj = editor.selectlist[0]; objectexplorer.obj = editor.selectlist[0];
editor.openpanel(objectexplorer); editor.openpanel(objectexplorer);
}; };
editor.inputs['C-i'].doc = "Open the object explorer for a selected object."; editor.inputs['C-i'].doc = "Open the object explorer for a selected object.";
*/
editor.inputs['C-d'] = function() { editor.inputs['C-d'] = function() {
if (editor.selectlist.length === 0) return; if (editor.selectlist.length === 0) return;
var duped = editor.dup_objects(editor.selectlist); var duped = editor.dup_objects(editor.selectlist);
@ -854,13 +847,14 @@ editor.inputs['M-t'] = function() { editor.edit_level.objects.forEach(function(x
editor.inputs['M-t'].doc = "Unlock all objects in current level."; editor.inputs['M-t'].doc = "Unlock all objects in current level.";
editor.inputs['C-n'] = function() { editor.inputs['C-n'] = function() {
if (editor.edit_level._ed.dirty) { /* if (editor.edit_level._ed.dirty) {
Log.info("Level has changed; save before starting a new one."); Log.info("Level has changed; save before starting a new one.");
editor.openpanel(gen_notify("Level is changed. Are you sure you want to close it?", _ => editor.clear_level())); editor.openpanel(gen_notify("Level is changed. Are you sure you want to close it?", _ => editor.clear_level()));
return; return;
} }
editor.clear_level(); editor.clear_level();
*/
}; };
editor.inputs['C-n'].doc = "Open a new level."; editor.inputs['C-n'].doc = "Open a new level.";
@ -1631,23 +1625,23 @@ var objectexplorer = Object.copy(inputpanel, {
obj: undefined, obj: undefined,
previous: [], previous: [],
start() { start() {
this.previous = []; this.previous = [];
Input.setnuke(); Input.setnuke();
}, },
on_close() { Input.setgame(); },
input_enter_pressed() {},
goto_obj(obj) { goto_obj(obj) {
if (obj === this.obj) return; if (obj === this.obj) return;
this.previous.push(this.obj); this.previous.push(this.obj);
this.obj = obj; this.obj = obj;
}, },
prev_obj() {
this.obj = this.previous.pop();
},
guibody() { guibody() {
Nuke.label("Examining " + this.obj); var items = [];
items.push(Mum.text({str:"Examining " + this.obj}));
var n = 0; var n = 0;
var curobj = this.obj; var curobj = this.obj;
@ -1657,23 +1651,14 @@ var objectexplorer = Object.copy(inputpanel, {
} }
n--; n--;
Nuke.newline(n);
curobj = this.obj.__proto__; curobj = this.obj.__proto__;
while (curobj) { while (curobj) {
if (Nuke.button(curobj.toString())) items.push(Mum.text({str:curobj.toString(), action:this.goto_obj(curobj)}));
this.goto_obj(curobj);
curobj = curobj.__proto__; curobj = curobj.__proto__;
} }
Nuke.newline(2); if (!this.previous.empty)
items.push(Mum.text({str:"prev: " + this.previous.last, action: this.prev_obj}));
if (this.previous.empty)
Nuke.label("");
else {
if (Nuke.button("prev: " + this.previous.last))
this.obj = this.previous.pop();
}
Object.getOwnPropertyNames(this.obj).forEach(key => { Object.getOwnPropertyNames(this.obj).forEach(key => {
var descriptor = Object.getOwnPropertyDescriptor(this.obj, key); var descriptor = Object.getOwnPropertyDescriptor(this.obj, key);
@ -1688,70 +1673,52 @@ var objectexplorer = Object.copy(inputpanel, {
var name = (hidden ? "[hidden] " : "") + key; var name = (hidden ? "[hidden] " : "") + key;
var val = this.obj[key]; var val = this.obj[key];
var nuke_str = key + "_nuke";
if (nuke_str in this.obj) {
this.obj[nuke_str]();
if (key in this.obj.__proto__) {
if (Nuke.button("delete " + key)) {
if (("_" + key) in this.obj)
delete this.obj["_"+key];
else
delete this.obj[key];
}
}
} else
switch (typeof val) { switch (typeof val) {
case 'object': case 'object':
if (val) { if (val) {
if (Array.isArray(val)) { if (Array.isArray(val)) {
this.obj[key] = Nuke.pprop(key,val); // this.obj[key] = Nuke.pprop(key,val);
break; break;
} }
Nuke.newline(2); // Nuke.newline(2);
Nuke.label(name); items.push(Mum.text({str:name}));
if (Nuke.button(val.toString())) this.goto_obj(val); items.push(Mum.text({str:val.toString(), action: this.goto_obj.bind(val)}));
} else { } else {
this.obj[key] = Nuke.pprop(key,val); // this.obj[key] = Nuke.pprop(key,val);
} }
break; break;
case 'function': case 'function':
Nuke.newline(2); items.push(Mum.text({str:name}));
Nuke.label(name); items.push(Mum.text({str:"function"}));
Nuke.label("function");
break; break;
default: default:
if (!hidden) {// && Object.getOwnPropertyDescriptor(this.obj, key).writable) { if (!hidden) {// && Object.getOwnPropertyDescriptor(this.obj, key).writable) {
if (key.startsWith('_')) key = key.slice(1); // this.obj[key] = Nuke.pprop(key, this.obj[key]);
this.obj[key] = Nuke.pprop(key, this.obj[key]); /* if (key in this.obj.__proto__) {
if (key in this.obj.__proto__) {
if (Nuke.button("delete " + key)) { if (Nuke.button("delete " + key)) {
if ("_"+key in this.obj) if ("_"+key in this.obj)
delete this.obj["_"+key]; delete this.obj["_"+key];
else else
delete this.obj[key]; delete this.obj[key];
} }
} }*/
} }
else { else {
Nuke.newline(2); items.push(Mum.text({str:name}));
Nuke.label(name); items.push(Mum.text({str:val.toString()}));
Nuke.label(val.toString());
} }
break; break;
} }
}); });
Nuke.newline(); items.push(Mum.text({str:"Properties that can be pulled in ..."}));
Nuke.label("Properties that can be pulled in ..."); // Nuke.newline(3);
Nuke.newline(3);
var pullprops = []; var pullprops = [];
for (var key in this.obj.__proto__) { for (var key in this.obj.__proto__) {
if (key.startsWith('_')) key = key.slice(1);
if (!this.obj.hasOwn(key)) { if (!this.obj.hasOwn(key)) {
if (typeof this.obj[key] === 'object' || typeof this.obj[key] === 'function') continue; if (typeof this.obj[key] === 'object' || typeof this.obj[key] === 'function') continue;
pullprops.push(key); pullprops.push(key);
@ -1761,13 +1728,12 @@ var objectexplorer = Object.copy(inputpanel, {
pullprops = pullprops.sort(); pullprops = pullprops.sort();
pullprops.forEach(function(key) { pullprops.forEach(function(key) {
if (Nuke.button(key)) items.push(Mum.text({str:key}));
this.obj[key] = this.obj[key]; // this.obj[key] = this.obj[key];
}, this); });
Game.objects.forEach(function(x) { x.sync(); }); // Game.objects.forEach(function(x) { x.sync(); });
return items;
Nuke.newline();
}, },
@ -1994,10 +1960,9 @@ limited_editor.inputs['M-p'] = function()
limited_editor.inputs['C-q'] = function() limited_editor.inputs['C-q'] = function()
{ {
Sound.killall(); Sound.killall();
Primum.clear();
editor.enter_editor(); editor.enter_editor();
Primum.clear_all();
editor.load_json(editor.stash);
Game.view_camera(editor.camera);
} }
limited_editor.inputs['M-q'] = function() limited_editor.inputs['M-q'] = function()
@ -2013,10 +1978,10 @@ if (IO.exists("editor.config"))
load_configs("editor.config"); load_configs("editor.config");
/* This is the editor level & camera - NOT the currently edited level, but a level to hold editor things */ /* This is the editor level & camera - NOT the currently edited level, but a level to hold editor things */
editor.clear_level();
editor.camera = Game.camera; editor.camera = Game.camera;
Game.stop(); Game.stop();
Game.editor_mode(true); Game.editor_mode(true);
Debug.draw_phys(true);
editor.enter_editor(); editor.enter_editor();

View file

@ -601,6 +601,11 @@ var Game = {
this.objects[obj.body] = obj; this.objects[obj.body] = obj;
}, },
unregister_obj(obj) {
if (this.objects[obj.body] === obj)
this.objects[obj.body] = undefined;
},
/* Returns an object given an id */ /* Returns an object given an id */
object(id) { object(id) {
return this.objects[id]; return this.objects[id];

View file

@ -131,9 +131,9 @@ var gameobject = {
in_air() { return q_body(7, this.body);}, in_air() { return q_body(7, this.body);},
on_ground() { return !this.in_air(); }, on_ground() { return !this.in_air(); },
spawn_from_instance(inst) { spawn_from_instance(inst) {
var ur = prototypes.get_ur(inst.ur); return this.spawn(inst.ur, inst);
}, },
spawn(ur, data) { spawn(ur, data) {
if (typeof ur === 'string') if (typeof ur === 'string')
ur = prototypes.get_ur(ur); ur = prototypes.get_ur(ur);
@ -380,19 +380,24 @@ var gameobject = {
// Register.endofloop(() => { // Register.endofloop(() => {
cmd(2, this.body); cmd(2, this.body);
delete Game.objects[this.body]; Game.unregister_obj(this);
if (this.level)
if (this.level) {
this.level.remove_obj(this); this.level.remove_obj(this);
this.level = undefined;
}
Player.uncontrol(this); Player.uncontrol(this);
Register.unregister_obj(this); Register.unregister_obj(this);
this.instances.remove(this); // this.instances.remove(this);
this.body = -1; this.body = -1;
for (var key in this.components) { for (var key in this.components) {
Register.unregister_obj(this.components[key]); Register.unregister_obj(this.components[key]);
this.components[key].kill(); this.components[key].kill();
this.components.gameobject = undefined;
} }
delete this.components;
for (var key in this.objects) for (var key in this.objects)
this.objects[key].kill(); this.objects[key].kill();
@ -406,13 +411,12 @@ var gameobject = {
down() { return [0,-1].rotate(Math.deg2rad(this.angle));}, down() { return [0,-1].rotate(Math.deg2rad(this.angle));},
right() { return [1,0].rotate(Math.deg2rad(this.angle));}, right() { return [1,0].rotate(Math.deg2rad(this.angle));},
left() { return [-1,0].rotate(Math.deg2rad(this.angle));}, left() { return [-1,0].rotate(Math.deg2rad(this.angle));},
instances: [],
make(level, data) { make(level, data) {
level ??= Primum; level ??= Primum;
var obj = Object.create(this); var obj = Object.create(this);
obj.level = level; obj.level = level;
this.instances.push(obj); // this.instances.push(obj);
obj.body = make_gameobject(); obj.body = make_gameobject();
obj.components = {}; obj.components = {};
obj.objects = {}; obj.objects = {};
@ -441,33 +445,24 @@ var gameobject = {
} }
}; };
if (this.objects) { if (this.objects)
for (var prop in this.objects) { obj.make_objs(this.objects);
var o = this.objects[prop];
var newobj = obj.spawn(o.ur, o);
if (!newobj) continue;
obj.rename_obj(newobj.toString(), prop);
}
}
Object.dainty_assign(obj, this); Object.dainty_assign(obj, this);
obj.sync(); obj.sync();
gameobject.check_registers(obj); gameobject.check_registers(obj);
if (typeof obj.start === 'function') obj.start(); if (Game.playing() && typeof obj.start === 'function') obj.start();
return obj; return obj;
}, },
make_objs(objs) { make_objs(objs) {
for (var prop in objs) { for (var prop in objs) {
var o = objs[prop]; var newobj = this.spawn_from_instance(objs[prop]);
var newobj = this.spawn(o.ur, o);
if (!newobj) continue; if (!newobj) continue;
this.rename_obj(newobj.toString(), prop); this.rename_obj(newobj.toString(), prop);
Log.warn(`setting object ${prop} to ${JSON.stringify(o)}`);
// Object.assign(newobj,o);
} }
}, },

View file

@ -153,9 +153,9 @@ var Player = {
if (typeof fn === 'function') { if (typeof fn === 'function') {
fn.call(pawn, ... args); fn.call(pawn, ... args);
pawn.inputs.post?.call(pawn); pawn.inputs.post?.call(pawn);
if (!pawn.inputs.fallthru)
return;
} }
if (!pawn.inputs.fallthru) return;
} }
}, },

View file

@ -20,7 +20,7 @@ var Sound = {
sounds: [], /* array of loaded sound files */ sounds: [], /* array of loaded sound files */
play(file) { play(file) {
if (!IO.exists(file)) { if (!IO.exists(file)) {
Log.warn(`Cannot play sound ${file}: does not exist.`); Log.error(`Cannot play sound ${file}: does not exist.`);
return; return;
} }
this.id = cmd(14,file); this.id = cmd(14,file);

View file

@ -607,8 +607,10 @@ struct postphys_cb {
static struct postphys_cb *begins = NULL; static struct postphys_cb *begins = NULL;
void flush_collide_cbs() { void flush_collide_cbs() {
for (int i = 0; i < arrlen(begins); i++) for (int i = 0; i < arrlen(begins); i++) {
script_callee(begins[i].c, 1, &begins[i].send); script_callee(begins[i].c, 1, &begins[i].send);
JS_FreeValue(js, begins[i].send);
}
arrsetlen(begins,0); arrsetlen(begins,0);
} }