nodes,gameobjects cleanup

This commit is contained in:
John Alanbrook 2023-11-29 18:40:13 +00:00
parent 7e7514f5d7
commit b9db31c84e
16 changed files with 501 additions and 889 deletions

View file

@ -1,5 +1,9 @@
# Yugine Scripting Guide
Primum programs are organized into two different types of source files: scripts and entities. Scripts end with .js, entities end with .jso.
## Scripts
Script hooks exist to allow to modification of the game.
|config.js|called before any game play, including play from editor|
@ -9,7 +13,13 @@ Script hooks exist to allow to modification of the game.
|debug.js|called when play in editor is selected, after level load|
|dbgret.js|called when play in editor returns to editor|
All objects in the Yugine can have an associated script. This script can perform setup, teardown, and handles responses for the object.
In addition, any script can be run by running "load".
## Entities
Entities are defined in a jso file. The "this" parameter in the jso file is a reference to the actor, allowing you to define properties on it.
Computation takes place in turns. Each entity has functions called, if they exist. If a machine has multiple threads, multiple entities may be taking turns at a time.
|function|description|
|---|---|

View file

@ -23,6 +23,17 @@ Promise = undefined;
Set = undefined;
WeakSet = undefined;
var json = {};
json.encode = function(value, space, replacer, whitelist)
{
return JSON.stringify(value, space, replacer);
}
json.decode = function(text, reviver)
{
return JSON.parse(text,reviver);
}
Object.methods = function(o)
{
var m = [];
@ -31,6 +42,7 @@ Object.methods = function(o)
});
return m;
}
Object.methods.doc = "Retun an array of all functions an object has access to.";
Object.dig = function(obj, path, def)
{
@ -43,6 +55,17 @@ Object.dig = function(obj, path, def)
return def;
}
Object.samenewkeys = function(a,b)
{
b ??= a.__proto__;
var ret = {};
ret.same = [];
ret.unique = [];
Object.keys(a).forEach(key => (key in b) ? ret.same.push(key) : ret.unique.push(key));
return ret;
}
Object.samenewkeys.doc = "Return an object listing which keys are the same and unique on a compared to b.";
Object.rkeys = function(o)
{
var keys = [];

202
scripts/color.js Normal file
View file

@ -0,0 +1,202 @@
var Color = {
white: [255,255,255],
black: [0,0,0],
blue: [84,110,255],
green: [120,255,10],
yellow: [251,255,43],
red: [255,36,20],
teal: [96, 252, 237],
gray: [181,181,181],
cyan: [0,255,255],
purple: [162,93,227],
};
Color.editor = {};
Color.editor.ur = Color.green;
Color.tohtml = function(v)
{
var html = v.map(function(n) { return Number.hex(n*255); });
return "#" + html.join('');
}
Color.toesc = function(v)
{
return Esc.color(v);
}
var Esc = {};
Esc.reset = "\x1b[0";
Esc.color = function(v) {
var c = v.map(function(n) { return Math.floor(n*255); });
var truecolor = "\x1b[38;2;" + c.join(';') + ';';
return truecolor;
}
Color.Arkanoid = {
orange: [255,143,0],
teal: [0,255,255],
green: [0,255,0],
red: [255,0,0],
blue: [0,112,255],
purple: [255,0,255],
yellow: [255,255,0],
silver: [157,157,157],
gold: [188,174,0],
};
Color.Arkanoid.Powerups = {
red: [174,0,0], /* laser */
blue: [0,0,174], /* enlarge */
green: [0,174,0], /* catch */
orange: [224,143,0], /* slow */
purple: [210,0,210], /* break */
cyan: [0,174,255], /* disruption */
gray: [143,143,143] /* 1up */
};
Color.Gameboy = {
darkest: [229,107,26],
dark: [229,189,26],
light: [189,229,26],
lightest: [107,229,26],
};
Color.Apple = {
green: [94,189,62],
yellow: [255,185,0],
orange: [247,130,0],
red: [226,56,56],
purple: [151,57,153],
blue: [0,156,223]
};
Color.Debug = {
boundingbox: Color.white,
names: [84,110,255],
};
Color.Editor = {
grid: [99,255,128],
select: [255,255,55],
newgroup: [120,255,10],
};
/* Detects the format of all colors and munges them into a floating point format */
Color.normalize = function(c) {
var add_a = function(a) {
var n = this.slice();
n.a = a;
return n;
};
for (var p of Object.keys(c)) {
var fmt = "nrm";
if (typeof c[p] !== 'object') continue;
if (!Array.isArray(c[p])) {
Color.normalize(c[p]);
continue;
}
for (var color of c[p]) {
if (color > 1) {
fmt = "8b";
break;
}
}
switch(fmt) {
case "8b":
c[p] = c[p].map(function(x) { return x/255; });
}
c[p].alpha = add_a;
}
};
Color.normalize(Color);
Object.deepfreeze(Color);
var ColorMap = {};
ColorMap.makemap = function(map)
{
var newmap = Object.create(ColorMap);
Object.assign(newmap, map);
return newmap;
}
ColorMap.Jet = ColorMap.makemap({
0: [0,0,131],
0.125: [0,60,170],
0.375: [5,255,255],
0.625: [255,255,0],
0.875: [250,0,0],
1: [128,0,0]
});
ColorMap.BlueRed = ColorMap.makemap({
0: [0,0,255],
1: [255,0,0]
});
ColorMap.Inferno = ColorMap.makemap({
0:[0,0,4],
0.13: [31,12,72],
0.25: [85,15,109],
0.38: [136,34,106],
0.5: [186,54,85],
0.63: [227,89,51],
0.75: [249,140,10],
0.88: [249,201,50],
1: [252,255,164]
});
ColorMap.Bathymetry = ColorMap.makemap({
0: [40,26,44],
0.13: [59.49,90],
0.25: [64,76,139],
0.38: [63,110,151],
0.5: [72,142,158],
0.63: [85,174,163],
0.75: [120,206,163],
0.88: [187,230,172],
1: [253,254,204]
});
ColorMap.Viridis = ColorMap.makemap({
0: [68,1,84],
0.13: [71,44,122],
0.25: [59,81,139],
0.38: [44,113,142],
0.5: [33,144,141],
0.63: [39,173,129],
0.75: [92,200,99],
0.88: [170,220,50],
1: [253,231,37]
});
Color.normalize(ColorMap);
ColorMap.sample = function(t, map)
{
map ??= this;
if (t < 0) return map[0];
if (t > 1) return map[1];
var lastkey = 0;
for (var key of Object.keys(map).sort()) {
if (t < key) {
var b = map[key];
var a = map[lastkey];
var tt = (key - lastkey) * t;
return a.lerp(b, tt);
}
lastkey = key;
}
return map[1];
}
ColorMap.doc = {
sample: "Sample a given colormap at the given percentage (0 to 1).",
};
Object.freeze(ColorMap);

View file

@ -85,18 +85,18 @@ var Debug = {
draw() {
if (this.draw_bb)
Game.objects.forEach(function(x) { Debug.boundingbox(x.boundingbox(), Color.Debug.boundingbox.alpha(0.05)); });
Game.all_objects(function(x) { Debug.boundingbox(x.boundingbox(), Color.Debug.boundingbox.alpha(0.05)); });
if (Game.paused()) GUI.text("PAUSED", [0,0],1);
if (this.draw_gizmos)
Game.objects.forEach(function(x) {
Game.all_objects(function(x) {
if (!x.icon) return;
GUI.image(x.icon, world2screen(x.pos));
});
if (this.draw_names)
Game.objects.forEach(function(x) {
Game.all_objects(function(x) {
GUI.text(x, world2screen(x.pos).add([0,32]), 1, Color.Debug.names);
});

View file

@ -4,23 +4,12 @@
*/
prototypes.generate_ur('.');
var editor_config = {
var editor = {
toString() { return "editor"; },
grid_size: 100,
ruler_mark_px: 100,
grid_color: Color.green.alpha(0.3),
};
var configs = {
toString() { return "configs"; },
editor: editor_config,
physics: physics,
local: local_conf,
collision: Collision,
};
var editor = {
toString() { return "editor"; },
dbg_ur: "arena.level1",
machine: undefined,
device_test: undefined,
@ -34,7 +23,7 @@ var editor = {
working_layer: 0,
get cursor() {
if (this.selectlist.length === 0 ) return Mouse.worldpos;
return find_com(this.selectlist);
return physics.com(this.selectlist.map(x => x.pos));
},
edit_mode: "basic",
@ -52,9 +41,9 @@ var editor = {
},
/* Tries to select id */
do_select(go) {
var obj = (go >= 0 ? Game.object(go) : undefined);
if (!obj || !obj._ed.selectable) return undefined;
do_select(obj) {
if (!obj) return;
// if (!obj || !obj._ed.selectable) return undefined;
if (obj.level !== this.edit_level) {
var testlevel = obj.level;
@ -102,7 +91,7 @@ var editor = {
step_amt() { return Keys.shift() ? 10 : 1; },
on_grid(pos) {
return pos.every(function(x) { return x % editor_config.grid_size === 0; });
return pos.every(function(x) { return x % editor.grid_size === 0; });
},
snapper(dir, grid) {
@ -115,7 +104,7 @@ var editor = {
key_move(dir) {
if (!editor.grabselect) return;
if (Keys.ctrl())
this.selectlist.forEach(this.snapper(dir.scale(1.01), editor_config.grid_size));
this.selectlist.forEach(this.snapper(dir.scale(1.01), editor.grid_size));
else
this.selectlist.forEach(this.mover(dir.scale(this.step_amt())));
},
@ -234,8 +223,6 @@ var editor = {
Register.draw.register(editor.draw, editor);
Debug.register_call(editor.ed_debug, editor);
Register.update.register(gui_controls.update, gui_controls);
// Player.players[0].control(gui_controls);
this.desktop = Primum.spawn(ur.arena);
Primum.rename_obj(this.desktop.toString(), "desktop");
this.edit_level = this.desktop;
@ -313,17 +300,6 @@ var editor = {
this.edit_level.check_dirty();
},
diff_lvl(d) {
this.unselect();
for (var key in d) {
if (d[key] === "DELETE")
Game.objects[key].kill();
}
diffassign(Game.objects, d);
Game.objects.forEach(function(x) { x.sync(); });
this.curlvl = this.edit_level.save();
},
redo() {
if (this.backshots.empty) {
Log.info("Nothing to redo.");
@ -336,17 +312,6 @@ var editor = {
this.edit_level.load(dd);
this.edit_level.check_dirty();
this.curlvl = dd;
return;
var dd = this.backshots.pop();
this.snapshots.push(dd);
if (this.was_undoing) {
dd = this.backshots.pop();
this.snapshots.push(dd);
this.was_undoing = false;
}
this.diff_lvl(dd);
},
undo() {
@ -359,17 +324,6 @@ var editor = {
var dd = this.snapshots.pop();
Object.dainty_assign(this.edit_level, dd);
this.edit_level._ed.check_dirty();
return;
this.backshots.push(dd);
if (!this.was_undoing) {
dd = this.snapshots.pop();
this.backshots.push(dd);
this.was_undoing = true;
}
this.diff_lvl(dd);
},
restore_buffer() {
@ -511,7 +465,7 @@ var editor = {
GUI.text(p, world2screen(x[1].worldpos().add([0,16])),1,editor.color_depths[depth]);
});
var mg = Game.obj_at(Mouse.worldpos);
var mg = physics.pos_query(Mouse.worldpos);
if (mg) {
var p = mg.path_from(thiso);
@ -536,15 +490,15 @@ var editor = {
GUI.image("icons/icons8-lock-16.png", world2screen(obj.worldpos()));
});
Debug.draw_grid(1, editor_config.grid_size, Color.Editor.grid.alpha(0.3));
var startgrid = screen2world([-20,0]).map(function(x) { return Math.snap(x, editor_config.grid_size); });
Debug.draw_grid(1, editor.grid_size, Color.Editor.grid.alpha(0.3));
var startgrid = screen2world([-20,0]).map(function(x) { return Math.snap(x, editor.grid_size); });
var endgrid = screen2world([Window.width, Window.height]);
var w_step = Math.round(editor_config.ruler_mark_px/Window.width * (endgrid.x-startgrid.x)/editor_config.grid_size)*editor_config.grid_size;
if (w_step === 0) w_step = editor_config.grid_size;
var w_step = Math.round(editor.ruler_mark_px/Window.width * (endgrid.x-startgrid.x)/editor.grid_size)*editor.grid_size;
if (w_step === 0) w_step = editor.grid_size;
var h_step = Math.round(editor_config.ruler_mark_px/Window.height * (endgrid.y-startgrid.y)/editor_config.grid_size)*editor_config.grid_size;
if (h_step === 0) h_step = editor_config.grid_size;
var h_step = Math.round(editor.ruler_mark_px/Window.height * (endgrid.y-startgrid.y)/editor.grid_size)*editor.grid_size;
if (h_step === 0) h_step = editor.grid_size;
while(startgrid[0] <= endgrid[0]) {
GUI.text(startgrid[0], [world2screen([startgrid[0], 0])[0],0]);
@ -620,25 +574,6 @@ var editor = {
this.unselect();
},
groupsaveas(group, file) {
if (!file) return;
file = file+".lvl";
if (IO.exists(file)) {
this.openpanel(gen_notify("Level already exists with that name. Overwrite?", dosave.bind(this,file)));
return;
} else
dosave(file);
function dosave(file) {
var com = find_com(group);
Level.saveas(group, file);
editor.addlevel(file, com);
group.forEach(function(x) { x.kill(); });
}
},
/* Checking to save an entity as a subtype. */
/* sub is the name of the (sub)type; obj is the object to save it as */
saveas_check(sub, obj) {
@ -924,7 +859,8 @@ editor.inputs['C-s'] = function() {
Object.values(saveobj.objects).forEach(function(x) { x._ed.check_dirty(); });
Game.objects.forEach(function(x) {
Game.all_objects(function(x) {
if (typeof x !== 'object') return;
if (!('_ed' in x)) return;
if (x._ed.dirty) return;
@ -1141,7 +1077,7 @@ editor.inputs['C-mm'] = editor.inputs.mm;
editor.inputs['C-M-lm'] = function()
{
var go = Game.obj_at(Mouse.worldpos);
var go = physics.pos_query(Mouse.worldpos);
if (!go) return;
editor.edit_level = go.level;
}
@ -1312,20 +1248,20 @@ editor.inputs['M-g'] = function()
editor.inputs['M-g'].doc = "Move all.";
editor.inputs['C-lb'] = function() {
editor_config.grid_size -= Keys.shift() ? 10 : 1;
if (editor_config.grid_size <= 0) editor_config.grid_size = 1;
editor.grid_size -= Keys.shift() ? 10 : 1;
if (editor.grid_size <= 0) editor.grid_size = 1;
};
editor.inputs['C-lb'].doc = "Decrease grid size. Hold shift to decrease it more.";
editor.inputs['C-lb'].rep = true;
editor.inputs['C-rb'] = function() { editor_config.grid_size += Keys.shift() ? 10 : 1; };
editor.inputs['C-rb'] = function() { editor.grid_size += Keys.shift() ? 10 : 1; };
editor.inputs['C-rb'].doc = "Increase grid size. Hold shift to increase it more.";
editor.inputs['C-rb'].rep = true;
editor.inputs['C-c'] = function() {
this.killring = [];
this.killcom = [];
this.killcom = find_com(this.selectlist);
this.killcom = physics.com(this.selectlist.map(x=>x.pos));
this.selectlist.forEach(function(x) {
this.killring.push(x.make_ur());
@ -1590,7 +1526,7 @@ replpanel.inputs = Object.create(inputpanel.inputs);
replpanel.inputs.block = true;
replpanel.inputs.lm = function()
{
var mg = Game.obj_at(Mouse.worldpos);
var mg = physics.pos_query(Mouse.worldpos);
if (!mg) return;
var p = mg.path_from(editor.get_this());
this.value = p;
@ -1833,7 +1769,7 @@ var objectexplorer = Object.copy(inputpanel, {
// this.obj[key] = this.obj[key];
});
// Game.objects.forEach(function(x) { x.sync(); });
// Game.all_objects(function(x) { x.sync(); });
return items;
},

View file

@ -28,208 +28,7 @@ function run_env(file, env)
load("scripts/diff.js");
Log.level = 1;
var Color = {
white: [255,255,255],
black: [0,0,0],
blue: [84,110,255],
green: [120,255,10],
yellow: [251,255,43],
red: [255,36,20],
teal: [96, 252, 237],
gray: [181,181,181],
cyan: [0,255,255],
purple: [162,93,227],
};
Color.editor = {};
Color.editor.ur = Color.green;
Color.tohtml = function(v)
{
var html = v.map(function(n) { return Number.hex(n*255); });
return "#" + html.join('');
}
Color.toesc = function(v)
{
return Esc.color(v);
}
var Esc = {};
Esc.reset = "\x1b[0";
Esc.color = function(v) {
var c = v.map(function(n) { return Math.floor(n*255); });
var truecolor = "\x1b[38;2;" + c.join(';') + ';';
return truecolor;
}
Color.Arkanoid = {
orange: [255,143,0],
teal: [0,255,255],
green: [0,255,0],
red: [255,0,0],
blue: [0,112,255],
purple: [255,0,255],
yellow: [255,255,0],
silver: [157,157,157],
gold: [188,174,0],
};
Color.Arkanoid.Powerups = {
red: [174,0,0], /* laser */
blue: [0,0,174], /* enlarge */
green: [0,174,0], /* catch */
orange: [224,143,0], /* slow */
purple: [210,0,210], /* break */
cyan: [0,174,255], /* disruption */
gray: [143,143,143] /* 1up */
};
Color.Gameboy = {
darkest: [229,107,26],
dark: [229,189,26],
light: [189,229,26],
lightest: [107,229,26],
};
Color.Apple = {
green: [94,189,62],
yellow: [255,185,0],
orange: [247,130,0],
red: [226,56,56],
purple: [151,57,153],
blue: [0,156,223]
};
Color.Debug = {
boundingbox: Color.white,
names: [84,110,255],
};
Color.Editor = {
grid: [99,255,128],
select: [255,255,55],
newgroup: [120,255,10],
};
/* Detects the format of all colors and munges them into a floating point format */
Color.normalize = function(c) {
var add_a = function(a) {
var n = this.slice();
n.a = a;
return n;
};
for (var p of Object.keys(c)) {
var fmt = "nrm";
if (typeof c[p] !== 'object') continue;
if (!Array.isArray(c[p])) {
Color.normalize(c[p]);
continue;
}
for (var color of c[p]) {
if (color > 1) {
fmt = "8b";
break;
}
}
switch(fmt) {
case "8b":
c[p] = c[p].map(function(x) { return x/255; });
}
c[p].alpha = add_a;
}
};
Color.normalize(Color);
Object.deepfreeze(Color);
var ColorMap = {};
ColorMap.makemap = function(map)
{
var newmap = Object.create(ColorMap);
Object.assign(newmap, map);
return newmap;
}
ColorMap.Jet = ColorMap.makemap({
0: [0,0,131],
0.125: [0,60,170],
0.375: [5,255,255],
0.625: [255,255,0],
0.875: [250,0,0],
1: [128,0,0]
});
ColorMap.BlueRed = ColorMap.makemap({
0: [0,0,255],
1: [255,0,0]
});
ColorMap.Inferno = ColorMap.makemap({
0:[0,0,4],
0.13: [31,12,72],
0.25: [85,15,109],
0.38: [136,34,106],
0.5: [186,54,85],
0.63: [227,89,51],
0.75: [249,140,10],
0.88: [249,201,50],
1: [252,255,164]
});
ColorMap.Bathymetry = ColorMap.makemap({
0: [40,26,44],
0.13: [59.49,90],
0.25: [64,76,139],
0.38: [63,110,151],
0.5: [72,142,158],
0.63: [85,174,163],
0.75: [120,206,163],
0.88: [187,230,172],
1: [253,254,204]
});
ColorMap.Viridis = ColorMap.makemap({
0: [68,1,84],
0.13: [71,44,122],
0.25: [59,81,139],
0.38: [44,113,142],
0.5: [33,144,141],
0.63: [39,173,129],
0.75: [92,200,99],
0.88: [170,220,50],
1: [253,231,37]
});
Color.normalize(ColorMap);
ColorMap.sample = function(t, map)
{
map ??= this;
if (t < 0) return map[0];
if (t > 1) return map[1];
var lastkey = 0;
for (var key of Object.keys(map).sort()) {
if (t < key) {
var b = map[key];
var a = map[lastkey];
var tt = (key - lastkey) * t;
return a.lerp(b, tt);
}
lastkey = key;
}
return map[1];
}
ColorMap.doc = {
sample: "Sample a given colormap at the given percentage (0 to 1).",
};
Object.freeze(ColorMap);
load("scripts/color.js");
function bb2wh(bb) {
return [bb.r-bb.l, bb.t-bb.b];
@ -269,7 +68,6 @@ var Device = {
gamegear: [160,144,3.2],
};
load("scripts/gui.js");
var ctimer = {
@ -348,6 +146,7 @@ var timer = {
var t = timer.make(fn,secs,desc);
t.loop = false;
t.restart();
return t;
t.fn = function() { fn(); t.kill(); };
return function() { t.kill(); };
},
@ -378,78 +177,7 @@ timer.doc = {
remain: "The time remianing before the function is executed.",
};
var animation = {
time: 0,
loop: false,
playtime: 0,
playing: false,
keyframes: [],
create() {
var anim = Object.create(animation);
Register.update.register(anim.update, anim);
return anim;
},
start() {
this.playing = true;
this.time = this.keyframes.last[1];
this.playtime = 0;
},
interval(a, b, t) {
return (t - a) / (b - a);
},
near_val(t) {
for (var i = 0; i < this.keyframes.length-1; i++) {
if (t > this.keyframes[i+1][1]) continue;
return this.interval(this.keyframes[i][1], this.keyframes[i+1][1], t) >= 0.5 ? this.keyframes[i+1][0] : this.keyframes[i][0];
}
return this.keyframes.last[0];
},
lerp_val(t) {
for (var i = 0; i < this.keyframes.length-1; i++) {
if (t > this.keyframes[i+1][1]) continue;
var intv = this.interval(this.keyframes[i][1], this.keyframes[i+1][1], t);
return ((1 - intv) * this.keyframes[i][0]) + (intv * this.keyframes[i+1][0]);
}
return this.keyframes.last[0];
},
cubic_val(t) {
},
mirror() {
if (this.keyframes.length <= 1) return;
for (var i = this.keyframes.length-1; i >= 1; i--) {
this.keyframes.push(this.keyframes[i-1]);
this.keyframes.last[1] = this.keyframes[i][1] + (this.keyframes[i][1] - this.keyframes[i-1][1]);
}
},
update(dt) {
if (!this.playing) return;
this.playtime += dt;
if (this.playtime >= this.time) {
if (this.loop)
this.playtime = 0;
else {
this.playing = false;
return;
}
}
this.fn(this.lerp_val(this.playtime));
},
};
load("scripts/animation.js");
var Render = {
normal() {
@ -717,24 +445,6 @@ Spline.type = {
load("scripts/components.js");
function find_com(objects)
{
if (!objects || objects.length === 0)
return [0,0];
var com = [0,0];
com[0] = objects.reduce(function(acc, val) {
return acc + val.pos[0];
}, 0);
com[0] /= objects.length;
com[1] = objects.reduce(function(acc, val) {
return acc + val.pos[1];
}, 0);
com[1] /= objects.length;
return com;
};
var Game = {
init() {
if (!Game.edit) {
@ -747,29 +457,13 @@ var Game = {
editor.enter_editor();
}
},
objects: [],
native: Device.pc,
edit: true,
register_obj(obj) {
this.objects[obj.body] = obj;
},
unregister_obj(obj) {
if (this.objects[obj.body] === obj)
this.objects[obj.body] = undefined;
},
obj_at(worldpos) {
var idx = physics.pos_query(worldpos);
if (idx === -1) return undefined;
return Game.objects[idx];
},
/* Returns an object given an id */
object(id) {
return this.objects[id];
all_objects(fn) {
/* Wind down from Primum */
},
/* Returns a list of objects by name */
@ -787,35 +481,6 @@ var Game = {
},
groupify(objects, spec) {
var newgroup = {
locked: true,
breakable: true,
objs: objects,
// get pos() { return find_com(objects); },
// set pos(x) { this.objs.forEach(function(obj) { obj.pos = x; }) },
};
Object.assign(newgroup, spec);
objects.forEach(function(x) {
x.defn('group', newgroup);
});
var bb = bb_from_objects(newgroup.objs);
newgroup.startbb = bb2cwh(bb);
newgroup.bboffset = newgroup.startbb.c.sub(newgroup.objs[0].pos);
newgroup.boundingbox = function() {
newgroup.startbb.c = newgroup.objs[0].pos.add(newgroup.bboffset);
return cwh2bb(newgroup.startbb.c, newgroup.startbb.wh);
};
if (newgroup.file)
newgroup.color = Color.Editor.newgroup;
return newgroup;
},
quit()
{
sys_cmd(0);
@ -890,81 +555,21 @@ Register.update.register(Game.exec, Game);
load("scripts/entity.js");
function world_start() {
globalThis.preprimum = Object.create(gameobject);
var preprimum = globalThis.preprimum;
preprimum.objects = {};
preprimum.worldpos = function() { return [0,0]; };
preprimum.worldangle = function() { return 0; };
preprimum.scale = [1,1,1];
preprimum.gscale = function() { return [1,1,1]; };
preprimum.pos = [0,0];
preprimum.angle = 0;
preprimum.remove_obj = function() {};
preprimum.toString = function() { return "preprimum"; };
globalThis.World = preprimum.make(preprimum);
globalThis.Primum = World;
var Primum = globalThis.Primum;
Primum.level = undefined;
globalThis.Primum = Object.create(gameobject);
Primum.objects = {};
Primum._ed = {
selectable:false,
check_dirty() {},
dirty:false,
namestr(){},
};
Primum.toString = function() { return "Primum"; };
Primum._ed.selectable = false;
Primum._ed.check_dirty = function() { };
Primum._ed.dirty = false;
Primum.revert = function(){};
Primum.ur = undefined;
globalThis.World.reparent = function(parent) { Log.warn("Cannot reparent the Primum."); }
Game.view_camera(Primum.spawn(ur.camera2d));
}
/* Load configs */
function load_configs(file) {
Log.info(`Loading config file ${file}.`);
var configs = JSON.parse(IO.slurp(file));
for (var key in configs) {
if (typeof globalThis[key] !== "object") continue;
Object.assign(globalThis[key], configs[key]);
}
Collision.sync();
Game.objects.forEach(function(x) { x.sync(); });
if (!local_conf.mouse) {
Log.info("disabling mouse features");
Mouse.disabled = function() {};
Mouse.hidden = function() {};
};
};
var local_conf = {
mouse: true,
};
if (IO.exists("game.config"))
load_configs("game.config");
/* Save configs */
function save_configs() {
Log.info("saving configs");
var configs = {};
configs.editor_config = editor_config;
configs.Nuke = Nuke;
configs.local_conf = local_conf;
IO.slurpwrite(JSON.stringify(configs, null, 1), "editor.config");
save_game_configs();
};
function save_game_configs() {
var configs = {};
configs.physics = physics;
configs.Collision = Collision;
Log.info(configs);
IO.slurpwrite(JSON.stringify(configs,null,1), "game.config");
Collision.sync();
Game.objects.forEach(function(x) { x.sync(); });
};
load("scripts/physics.js");
Game.view_camera = function(cam)

View file

@ -11,19 +11,34 @@ function grab_from_points(pos, points, slop) {
};
var actor = {};
actor.spawn = function(ur, config){};
actor.die = function(actor){};
actor.kill = function(actor){};
actor.delay = function(fn, seconds) {};
actor.spawn = function(script, config){
if (typeof script !== 'string') return;
var padawan = Object.create(actor);
compile_env(script, padawan, "script");
if (typeof config === 'object')
Object.merge(padawan, config);
return padawan;
};
actor.die = function(actor){
};
actor.kill = function(actor){
this.timers.forEach(t => t());
this.timers = undefined;
};
actor.delay = function(fn, seconds) {
var t = timer.delay(fn.bind(this), seconds, true);
this.timers.push(t);
return function() { t.kill(); };
};
actor.clock = function(fn){};
var Empyrean = Object.create(actor);
var gameobject = {
impl: {
full_path() {
return this.path_from(Primum);
},
full_path() {
return this.path_from(Primum);
},
path_from(o) {
var p = this.toString();
@ -46,8 +61,9 @@ var gameobject = {
delay(fn, seconds) {
var t = timer.delay(fn.bind(this), seconds, false);
this.timers.push(t);
return t;
var killfn = function() { t.kill(); };
this.timers.push(killfn);
return killfn;
},
tween(prop, values, def){
@ -98,7 +114,10 @@ var gameobject = {
},
set pos(x) {
this.set_worldpos(this.level.this2world(x));
if (!this.level)
this.set_worldpos(x);
else
this.set_worldpos(this.level.this2world(x));
},
get pos() {
@ -133,7 +152,7 @@ var gameobject = {
get phys() { return q_body(0,this.body); },
get velocity() { return q_body(3, this.body); },
set velocity(x) { set_body(9, this.body, x); },
// get damping() { return cmd(157,this.body); },
get damping() { return cmd(157,this.body); },
set_damping(x) { cmd(156, this.body, x); },
get angularvelocity() { return Math.rad2deg(q_body(4, this.body)); },
set angularvelocity(x) { set_body(8, this.body, Math.deg2rad(x)); },
@ -155,7 +174,6 @@ var gameobject = {
var thatpos = this.pos;
this.objects.forEach(function(x) {
x.rotate(diff);
// x.angle = x.angle + diff;
var opos = x.pos;
var r = Vector.length(opos);
var p = Math.rad2deg(Math.atan2(opos.y, opos.x));
@ -163,8 +181,11 @@ var gameobject = {
p = Math.deg2rad(p);
x.pos = [r*Math.cos(p), r*Math.sin(p)];
});
set_body(0,this.body, Math.deg2rad(x - this.level.worldangle()));
if (this.level)
set_body(0,this.body, Math.deg2rad(x - this.level.worldangle()));
else
set_body(0,this.body,x);
},
rotate(x) {
@ -222,9 +243,6 @@ var gameobject = {
delete this.objects[obj.toString()];
delete this[obj.toString()];
},
},
components: {},
objects: {},
@ -242,7 +260,6 @@ var gameobject = {
pulse(vec) { set_body(4, this.body, vec);},
shove(vec) { set_body(12,this.body,vec);},
shove_at(vec, at) { set_body(14,this.body,vec,at); },
// torque(val) { cmd(153, this.body, val); },
world2this(pos) { return cmd(70, this.body, pos); },
this2world(pos) { return cmd(71, this.body,pos); },
dir_world2this(dir) { return cmd(160, this.body, dir); },
@ -281,6 +298,10 @@ var gameobject = {
/* Make a unique object the same as its prototype */
revert() {
// var keys = Object.samenewkeys(this, this.__proto__);
// keys.unique.forEach(x => delete this[x]);
// keys.same.forEach(x => this[x] = this.__proto__[x]);
var jobj = this.json_obj();
var lobj = this.level.__proto__.objects[this.toString()];
delete jobj.objects;
@ -328,39 +349,22 @@ var gameobject = {
register_collide(1, x.collide, x, obj.body, x.shape);
});
},
pos: [0,0],
angle:0,
velocity:[0,0],
angularvelocity:0,
phys:Physics.static,
flipx() { return this.scale.x < 0; },
flipy() { return this.scale.y < 0; },
timescale: 1,
scale:[1,1],
mirror(plane) {
this.scale = Vector.reflect(this.scale, plane);
},
elasticity:0.5,
friction:1,
gravity: true,
max_velocity: Infinity,
max_angularvelocity: Infinity,
mass:1,
layer:0,
draw_layer:0,
worldpos() { return [0,0]; },
save:true,
selectable:true,
ed_locked:false,
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(); });
},
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() {
@ -416,10 +420,6 @@ var gameobject = {
return d;
},
full_obj() {
},
transform_obj() {
var t = this.json_obj();
Object.assign(t, this.transform());
@ -467,57 +467,43 @@ var gameobject = {
Object.totalmerge(n, this.make_ur());
return n;
},
kill() {
if (this.body === -1) {
// Log.warn(`Object is already dead!`);
return;
}
// Register.endofloop(() => {
// cmd(2, this.body);
q_body(8,this.body);
Game.unregister_obj(this);
kill() {
this.timers.forEach(t => t());
if (this.level) {
this.level.remove_obj(this);
this.level = undefined;
}
this.timers.forEach(t => t());
Player.do_uncontrol(this);
Register.unregister_obj(this);
if (this.level) {
this.level.remove_obj(this);
this.level = undefined;
}
if (this.__proto__.instances)
this.__proto__.instances.remove(this);
Player.do_uncontrol(this);
Register.unregister_obj(this);
for (var key in this.components) {
Register.unregister_obj(this.components[key]);
Log.info(`Destroying component ${key}`);
this.components[key].kill();
this.components.gameobject = undefined;
}
if (this.__proto__.instances)
this.__proto__.instances.remove(this);
this.body = -1;
delete this.components;
for (var key in this.components) {
Register.unregister_obj(this.components[key]);
Log.info(`Destroying component ${key}`);
this.components[key].kill();
this.components.gameobject = undefined;
}
delete this.components;
this.clear();
this.clear();
if (typeof this.stop === 'function')
this.stop();
},
if (typeof this.stop === 'function')
this.stop();
// });
},
up() { 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));},
left() { return [-1,0].rotate(Math.deg2rad(this.angle));},
up() { 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));},
left() { return [-1,0].rotate(Math.deg2rad(this.angle));},
make(level, data) {
level ??= Primum;
// level ??= Primum;
var obj = Object.create(this);
obj.make = undefined;
obj.level = level;
@ -525,10 +511,10 @@ var gameobject = {
this.instances.push(obj);
obj.body = make_gameobject();
obj.components = {};
obj.objects = {};
obj.timers = [];
assign_impl(obj, gameobject.impl);
obj._ed = {
selectable: true,
check_dirty() {
@ -547,7 +533,6 @@ var gameobject = {
dirty: false,
inst: false,
model: Object.create(this),
urdiff: {},
namestr() {
var s = obj.toString();
@ -558,10 +543,9 @@ var gameobject = {
return s;
},
};
obj.ur = this.toString();
Game.register_obj(obj);
cmd(113, obj.body, obj); // set the internal obj reference to this obj
for (var prop in this) {
@ -579,7 +563,7 @@ var gameobject = {
obj.level = undefined;
obj.reparent(level);
Object.hide(obj, 'ur','body', 'components', 'objects', '_ed', 'level', 'timers', 'timescale');
Object.hide(obj, 'ur','body', 'components', 'objects', '_ed', 'level', 'timers');
Object.dainty_assign(obj, this);
obj.sync();
@ -596,6 +580,7 @@ var gameobject = {
make_objs(objs) {
for (var prop in objs) {
Log.warn(prop);
var newobj = this.spawn_from_instance(objs[prop]);
if (!newobj) continue;
this.rename_obj(newobj.toString(), prop);
@ -624,7 +609,8 @@ var gameobject = {
},
add_component(comp) {
if (typeof comp['comp'] !== 'string') return;
if (typeof comp.make !== 'function') return;
return {comp:comp.toString()};
},
register_hit(fn, obj) {
@ -642,7 +628,11 @@ var gameobject = {
},
}
gameobject.impl.spawn.doc = `Spawn an entity of type 'ur' on this entity. Returns the spawned entity.`;
gameobject.body = make_gameobject();
cmd(113,gameobject.body, gameobject);
Object.hide(gameobject, 'timescale');
gameobject.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.",

View file

@ -283,192 +283,3 @@ Mum.debug_colors = {
};
Object.values(Mum.debug_colors).forEach(function(v) { v.a = 100; });
/* Take numbers from 0 to 1 and remap them to easing functions */
var Ease = {
linear(t) { return t; },
in(t) { return t*t; },
out(t) {
var d = 1-t;
return 1 - d*d
},
inout(t) {
var d = -2*t + 2;
return t < 0.5 ? 2 * t * t : 1 - (d * d) / 2;
},
};
function make_easing_fns(num) {
var obj = {};
obj.in = function(t) {
return Math.pow(t,num);
};
obj.out = function(t) {
return 1 - Math.pow(1 - t, num);
};
var mult = Math.pow(2, num-1);
obj.inout = function(t) {
return t < 0.5 ? mult * Math.pow(t, num) : 1 - Math.pow(-2 * t + 2, num) / 2;
};
return obj;
};
Ease.quad = make_easing_fns(2);
Ease.cubic = make_easing_fns(3);
Ease.quart = make_easing_fns(4);
Ease.quint = make_easing_fns(5);
Ease.expo = {
in(t) {
return t === 0 ? 0 : Math.pow(2, 10 * t - 10);
},
out(t) {
return t === 1 ? 1 : 1 - Math.pow(2, -10 * t);
},
inout(t) {
return t === 0 ? 0 : t === 1 ? 1 : t < 0.5 ? Math.pow(2, 20 * t - 10) / 2 : (2 - Math.pow(2, -20 * t + 10)) / 2;
}
};
Ease.bounce = {
in(t) {
return 1 - this.out(t - 1);
},
out(t) {
var n1 = 7.5625;
var d1 = 2.75;
if (t < 1 / d1) { return n1 * t * t; }
else if (t < 2 / d1) { return n1 * (t -= 1.5 / d1) * t + 0.75; }
else if (t < 2.5 / d1) { return n1 * (t -= 2.25 / d1) * t + 0.9375; }
else
return n1 * (t -= 2.625 / d1) * t + 0.984375;
},
inout(t) {
return t < 0.5 ? (1 - this.out(1 - 2 * t)) / 2 : (1 + this.out(2 * t - 1)) / 2;
}
};
Ease.sine = {
in(t) { return 1 - Math.cos((t * Math.PI)/2); },
out(t) { return Math.sin((t*Math.PI)/2); },
inout(t) { return -(Math.cos(Math.PI*t) - 1) / 2; }
};
Ease.elastic = {
in(t) {
return t === 0 ? 0 : t === 1 ? 1 : -Math.pow(2, 10*t-10) * Math.sin((t * 10 - 10.75) * this.c4);
},
out(t) {
return t === 0 ? 0 : t === 1 ? 1 : Math.pow(2, -10*t) * Math.sin((t * 10 - 0.75) * this.c4) + 1;
},
inout(t) {
t === 0 ? 0 : t === 1 ? 1 : t < 0.5 ?
-(Math.pow(2, 20 * t - 10) * Math.sin((20 * t - 11.125) * this.c5)) / 2
: (Math.pow(2, -20 * t + 10) * Math.sin((20 * t - 11.125) * this.c5)) / 2 + 1;
},
};
Ease.elastic.c4 = 2*Math.PI/3;
Ease.elastic.c5 = 2*Math.PI / 4.5;
var Tween = {
default: {
loop: "restart",
/*
loop types
none: when done, return to first value
hold: hold last value of tween
restart: restart at beginning, looping
yoyo: go up and then back down
circle: go up and back down, looped
*/
time: 1, /* seconds to do */
ease: Ease.linear,
whole: true, /* True if time is for the entire tween, false if each stage */
cb: function(){},
},
start(obj, target, tvals, options)
{
var defn = Object.create(this.default);
Object.assign(defn, options);
if (defn.loop === 'circle')
tvals.push(tvals[0]);
else if (defn.loop === 'yoyo') {
for (var i = tvals.length-2; i >= 0; i--)
tvals.push(tvals[i]);
}
defn.accum = 0;
var slices = tvals.length - 1;
var slicelen = 1 / slices;
defn.fn = function(dt) {
defn.accum += dt;
if (defn.accum >= defn.time && defn.loop === 'hold') {
obj[target] = tvals[tvals.length-1];
defn.pause();
defn.cb.call(obj);
return;
}
defn.pct = (defn.accum % defn.time) / defn.time;
if (defn.loop === 'none' && defn.accum >= defn.time)
defn.stop();
var t = defn.whole ? defn.ease(defn.pct) : defn.pct;
var nval = t / slicelen;
var i = Math.trunc(nval);
nval -= i;
if (!defn.whole)
nval = defn.ease(nval);
obj[target] = tvals[i].lerp(tvals[i+1], nval);
};
var playing = false;
defn.play = function() {
if (playing) return;
Register.update.register(defn.fn, defn);
playing = true;
};
defn.restart = function() {
defn.accum = 0;
obj[target] = tvals[0];
};
defn.stop = function() { if (!playing) return; defn.pause(); defn.restart(); };
defn.pause = function() {
Register.update.unregister(defn.fn);
if (!playing) return;
playing = false;
};
return defn;
},
};
Tween.make = Tween.start;

View file

@ -27,7 +27,6 @@ var physics = {
/* Returns a list of body ids that a box collides with */
box_query(box) {
var pts = cmd(52,box.pos,box.wh);
return cmd(52, box.pos, box.wh);
},
@ -41,6 +40,18 @@ var physics = {
shape_query(shape) {
return cmd(80,shape);
},
com(pos) {
if (!Array.isArray(pos)) return;
var com = [];
for (var i = 0; i < pos[0].length; i++) {
com[i] = pos.reduce(function(acc,val) {
return acc + val[i];
});
com[i] /= pos.length;
}
return com;
},
};
physics.doc = {};

View file

@ -233,6 +233,7 @@ int pos2gameobject(HMM_Vec2 pos) {
if (dist <= 25) return i;
}
return -1;
}
@ -373,11 +374,11 @@ int MakeGameobject() {
.cgravity = (HMM_Vec2){0,0},
.damping = NAN,
.timescale = 1.0,
.ref = JS_NULL,
.ref = JS_UNDEFINED,
};
go.cbs.begin.obj = JS_NULL;
go.cbs.separate.obj = JS_NULL;
go.cbs.begin.obj = JS_UNDEFINED;
go.cbs.separate.obj = JS_UNDEFINED;
go.body = cpSpaceAddBody(space, cpBodyNew(go.mass, 1.f));
cpBodySetVelocityUpdateFunc(go.body, velocityFn);
@ -432,6 +433,13 @@ void gameobject_delete(int id) {
gameobject_clean(id);
}
void gameobject_free(int id)
{
YughWarn("FREED A GAMEOBJECT!!!");
if (id >= 0)
gameobject_delete(id);
}
void gameobjects_cleanup() {
for (int i = 0; i < arrlen(go_toclean); i++)
gameobject_clean(go_toclean[i]);

View file

@ -69,6 +69,7 @@ extern struct gameobject *gameobjects;
int MakeGameobject();
void gameobject_apply(struct gameobject *go);
void gameobject_delete(int id);
void gameobject_free(int id);
void gameobjects_cleanup();
void gameobject_set_sensor(int id, int sensor);

View file

@ -73,7 +73,7 @@ JSValue input2js(int state)
case 3: return jstr("pressrep");
case 4: return jstr("down");
}
return JS_NULL;
return JS_UNDEFINED;
}
void input_mouse(int btn, int state, uint32_t mod)

View file

@ -36,7 +36,6 @@ static JSValue globalThis;
static JSClassID js_ptr_id;
static JSClassDef js_ptr_class = { "POINTER" };
#define QJSCLASS(TYPE)\
static JSClassID js_ ## TYPE ## _id;\
static void js_##TYPE##_finalizer(JSRuntime *rt, JSValue val){\
@ -44,22 +43,25 @@ TYPE *n = JS_GetOpaque(val, js_##TYPE##_id);\
TYPE##_free(n);}\
static JSClassDef js_##TYPE##_class = {\
#TYPE,\
.finalizer = js_##TYPE##_finalizer\
.finalizer = js_##TYPE##_finalizer,\
};\
static TYPE *js2##TYPE (JSValue val) { return JS_GetOpaque(val,js_##TYPE##_id); }\
static JSValue js_##TYPE##2js(TYPE *n) { \
static JSValue TYPE##2js(TYPE *n) { \
JSValue j = JS_NewObjectClass(js,js_##TYPE##_id);\
JS_SetOpaque(j,n);\
return j; }\
QJSCLASS(dsp_node)
// gamobject2js, js2gameobject deals with gameobject*
// go2js,js2go deals with gameobject ids
QJSCLASS(gameobject)
#define QJSCLASSPREP(TYPE) \
JS_NewClassID(&js_##TYPE##_id);\
JS_NewClass(JS_GetRuntime(js), js_##TYPE##_id, &js_##TYPE##_class);\
//QJSCLASS(sprite)
#define BYTE_TO_BINARY_PATTERN "%c%c%c%c%c%c%c%c"
#define BYTE_TO_BINARY(byte) \
(byte & 0x80 ? '1' : '0'), \
@ -81,6 +83,21 @@ void js_setprop_num(JSValue obj, uint32_t i, JSValue v)
JS_SetPropertyUint32(js, obj, i, v);
}
JSValue go2ref(int id)
{
if (id == -1) return JS_UNDEFINED;
return JS_DupValue(js,id2go(id)->ref);
}
JSValue gos2ref(int *go)
{
JSValue array = JS_NewArray(js);
for (int i = 0; i < arrlen(go); i++)
js_setprop_num(array,i,go2ref(go[i]));
return array;
}
JSValue js_getpropstr(JSValue v, const char *str)
{
JSValue p = JS_GetPropertyStr(js,v,str);
@ -155,9 +172,11 @@ JSValue num2js(double g) {
}
struct gameobject *js2go(JSValue v) {
return id2go(js2int(v));
return id2go(js2gameobject(v));
}
static int jsgo2id(JSValue v) { return go2id(js2go(v)); }
struct sprite *js2sprite(JSValue v) { return id2sprite(js2int(v)); }
void *js2ptr(JSValue v) {
@ -343,7 +362,7 @@ JSValue duk_gui_img(JSContext *js, JSValueConst this, int argc, JSValueConst *ar
const char *img = JS_ToCString(js, argv[0]);
gui_draw_img(img, js2vec2(argv[1]), js2vec2(argv[2]), js2number(argv[3]), js2bool(argv[4]), js2vec2(argv[5]), 1.0, js2color(argv[6]));
JS_FreeCString(js, img);
return JS_NULL;
return JS_UNDEFINED;
}
struct rect js2rect(JSValue v) {
@ -375,7 +394,6 @@ JSValue bb2js(struct boundingbox bb)
return obj;
}
JSValue duk_spline_cmd(JSContext *js, JSValueConst this, int argc, JSValueConst *argv) {
// static_assert(sizeof(tsReal) * 2 == sizeof(HMM_Vec2));
@ -501,7 +519,7 @@ JSValue duk_cmd(JSContext *js, JSValueConst this, int argc, JSValueConst *argv)
const char *str2 = NULL;
const void *d1 = NULL;
const void *d2 = NULL;
JSValue ret = JS_NULL;
JSValue ret = JS_UNDEFINED;
switch (cmd) {
case 0:
@ -700,7 +718,7 @@ JSValue duk_cmd(JSContext *js, JSValueConst this, int argc, JSValueConst *argv)
break;
case 44:
ret = JS_NewInt64(js, pos2gameobject(js2vec2(argv[1])));
ret = go2ref(pos2gameobject(js2vec2(argv[1])));
break;
case 45:
@ -732,7 +750,7 @@ JSValue duk_cmd(JSContext *js, JSValueConst this, int argc, JSValueConst *argv)
break;
case 52:
ret = ints2js(phys2d_query_box(js2vec2(argv[1]), js2vec2(argv[2])));
ret = gos2ref(phys2d_query_box(js2vec2(argv[1]), js2vec2(argv[2])));
break;
case 53:
@ -803,7 +821,7 @@ JSValue duk_cmd(JSContext *js, JSValueConst this, int argc, JSValueConst *argv)
break;
case 69:
gameobject_set_sensor(js2int(argv[1]), JS_ToBool(js, argv[2]));
gameobject_set_sensor(js2go(argv[1]), JS_ToBool(js, argv[2]));
break;
case 70:
@ -846,7 +864,7 @@ JSValue duk_cmd(JSContext *js, JSValueConst this, int argc, JSValueConst *argv)
break;
case 80:
ret = ints2js(phys2d_query_shape(js2ptr(argv[1])));
ret = gos2ref(phys2d_query_shape(js2ptr(argv[1])));
break;
case 81:
@ -854,7 +872,7 @@ JSValue duk_cmd(JSContext *js, JSValueConst this, int argc, JSValueConst *argv)
break;
case 82:
gameobject_draw_debug(js2int(argv[1]));
gameobject_draw_debug(js2go(argv[1]));
break;
case 83:
@ -870,7 +888,7 @@ JSValue duk_cmd(JSContext *js, JSValueConst this, int argc, JSValueConst *argv)
break;
case 86:
ret = ints2js(phys2d_query_box_points(js2vec2(argv[1]), js2vec2(argv[2]), js2cpvec2arr(argv[3]), js2int(argv[4])));
ret = gos2ref(phys2d_query_box_points(js2vec2(argv[1]), js2vec2(argv[2]), js2cpvec2arr(argv[3]), js2int(argv[4])));
break;
case 87:
@ -985,7 +1003,7 @@ JSValue duk_cmd(JSContext *js, JSValueConst this, int argc, JSValueConst *argv)
break;
case 113:
js2go(argv[1])->ref = JS_DupValue(js,argv[2]);
js2go(argv[1])->ref = argv[2];//JS_DupValue(js,argv[2]);
break;
case 114:
@ -1222,115 +1240,110 @@ JSValue duk_cmd(JSContext *js, JSValueConst this, int argc, JSValueConst *argv)
str = js2str(argv[1]);
ds_openvideo(str);
break;
case 175:
ret = num2js(((dsp_node*)js2ptr(argv[1]))->gain);
ret = num2js((js2dsp_node(argv[1]))->gain);
break;
case 176:
((dsp_node*)js2ptr(argv[1]))->gain = js2number(argv[2]);
js2dsp_node(argv[1])->gain = js2number(argv[2]);
break;
case 177:
plugin_node(js2ptr(argv[1]), js2ptr(argv[2]));
break;
case 178:
ret = num2js(((dsp_node*)js2ptr(argv[1]))->pan);
ret = num2js(js2dsp_node(argv[1])->pan);
break;
case 179:
((dsp_node*)js2ptr(argv[1]))->pan=js2number(argv[2]);
js2dsp_node(argv[1])->pan=js2number(argv[2]);
break;
case 180:
ret = ptr2js(masterbus);
ret = dsp_node2js(masterbus);
break;
case 181:
ret = ptr2js(make_node(NULL,NULL,NULL));
ret = dsp_node2js(make_node(NULL,NULL,NULL));
break;
case 182:
str = js2str(argv[1]);
ret = ptr2js(dsp_source(str));
((sound*)((dsp_node*)js2ptr(ret))->data)->hook = JS_DupValue(js,argv[2]);
((sound*)js2dsp_node(ret)->data)->hook = JS_DupValue(js,argv[2]);
break;
case 183:
((dsp_node*)js2ptr(argv[1]))->off = js2bool(argv[2]);
js2dsp_node(argv[1])->off = js2bool(argv[2]);
break;
case 184:
((dsp_node*)js2ptr(argv[1]))->pass = js2bool(argv[2]);
js2dsp_node(argv[1])->pass = js2bool(argv[2]);
break;
case 185:
ret = ptr2js(dsp_delay(js2number(argv[1]), js2number(argv[2])));
ret = dsp_node2js(dsp_delay(js2number(argv[1]), js2number(argv[2])));
break;
case 186:
ret = ptr2js(dsp_lpf(js2number(argv[1])));
ret = dsp_node2js(dsp_lpf(js2number(argv[1])));
break;
case 187:
ret = ptr2js(dsp_hpf(js2number(argv[1])));
ret = dsp_node2js(dsp_hpf(js2number(argv[1])));
break;
case 188:
str = js2str(argv[1]);
ret = ptr2js(dsp_mod(str));
ret = dsp_node2js(dsp_mod(str));
break;
case 189:
ret = ptr2js(dsp_bitcrush(js2number(argv[1]), js2number(argv[2])));
ret = dsp_node2js(dsp_bitcrush(js2number(argv[1]), js2number(argv[2])));
break;
case 190:
ret = ptr2js(dsp_compressor());
ret = dsp_node2js(dsp_compressor());
break;
case 191:
ret = ptr2js(dsp_limiter(js2number(argv[1])));
ret = dsp_node2js(dsp_limiter(js2number(argv[1])));
break;
case 192:
ret = ptr2js(dsp_noise_gate(js2number(argv[1])));
ret = dsp_node2js(dsp_noise_gate(js2number(argv[1])));
break;
case 193:
node_free(js2ptr(argv[1]));
// node_free(js2ptr(argv[1]));
break;
case 194:
ret = bool2js(((sound*)((dsp_node*)js2ptr(argv[1]))->data)->loop);
ret = bool2js(((sound*)js2dsp_node(argv[1])->data)->loop);
break;
case 195:
((sound*)((dsp_node*)js2ptr(argv[1]))->data)->loop = js2bool(argv[2]);
((sound*)js2dsp_node(argv[1])->data)->loop = js2bool(argv[2]);
break;
case 196:
ret = num2js(((sound*)((dsp_node*)js2ptr(argv[1]))->data)->frame);
ret = num2js(((sound*)js2dsp_node(argv[1])->data)->frame);
break;
case 197:
ret = num2js(((sound*)((dsp_node*)js2ptr(argv[1]))->data)->data->frames);
ret = num2js(((sound*)js2dsp_node(argv[1])->data)->data->frames);
break;
case 198:
ret = num2js(SAMPLERATE);
break;
case 199:
((sound*)((dsp_node*)js2ptr(argv[1]))->data)->frame = js2number(argv[2]);
((sound*)js2dsp_node(argv[1])->data)->frame = js2number(argv[2]);
break;
case 200:
ret = ptr2js(dsp_pitchshift(js2number(argv[1])));
ret = dsp_node2js(dsp_pitchshift(js2number(argv[1])));
break;
case 201:
ret = num2js(((sound*)((dsp_node*)js2ptr(argv[1]))->data)->timescale);
ret = num2js(((sound*)js2dsp_node(argv[1])->data)->timescale);
break;
case 202:
YughWarn("%g", js2number(argv[2]));
((sound*)((dsp_node*)js2ptr(argv[1]))->data)->timescale = js2number(argv[2]);
((sound*)js2dsp_node(argv[1])->data)->timescale = js2number(argv[2]);
break;
case 203:
ret = ptr2js(dsp_whitenoise());
ret = dsp_node2js(dsp_whitenoise());
break;
case 204:
ret = ptr2js(dsp_pinknoise());
ret = dsp_node2js(dsp_pinknoise());
break;
case 205:
ret = ptr2js(dsp_rednoise());
ret = dsp_node2js(dsp_rednoise());
break;
case 206:
str = js2str(argv[1]);
str2 = js2str(argv[2]);
ret = ptr2js(dsp_midi(str, make_soundfont(str2)));
ret = dsp_node2js(dsp_midi(str, make_soundfont(str2)));
break;
case 207:
ret = ptr2js(dsp_fwd_delay(js2number(argv[1]), js2number(argv[2])));
break;
case 208:
ret = JS_NewObjectClass(js, js_dsp_node_id);
JS_SetOpaque(ret, dsp_mixer_node());
ret = dsp_node2js(dsp_fwd_delay(js2number(argv[1]), js2number(argv[2])));
break;
}
@ -1347,7 +1360,7 @@ JSValue duk_cmd(JSContext *js, JSValueConst this, int argc, JSValueConst *argv)
return ret;
}
return JS_NULL;
return JS_UNDEFINED;
}
JSValue duk_register(JSContext *js, JSValueConst this, int argc, JSValueConst *argv) {
@ -1402,7 +1415,7 @@ JSValue duk_register(JSContext *js, JSValueConst this, int argc, JSValueConst *a
break;
}
return JS_NULL;
return JS_UNDEFINED;
}
void gameobject_add_shape_collider(int go, struct callee c, struct phys2d_shape *shape) {
@ -1414,7 +1427,7 @@ void gameobject_add_shape_collider(int go, struct callee c, struct phys2d_shape
JSValue duk_register_collide(JSContext *js, JSValueConst this, int argc, JSValueConst *argv) {
int cmd = js2int(argv[0]);
int go = js2int(argv[3]);
int go = jsgo2id(argv[3]);
struct callee c;
c.fn = argv[1];
c.obj = argv[2];
@ -1437,7 +1450,7 @@ JSValue duk_register_collide(JSContext *js, JSValueConst this, int argc, JSValue
break;
}
return JS_NULL;
return JS_UNDEFINED;
}
JSValue duk_sys_cmd(JSContext *js, JSValueConst this, int argc, JSValueConst *argv) {
@ -1486,11 +1499,11 @@ JSValue duk_sys_cmd(JSContext *js, JSValueConst this, int argc, JSValueConst *ar
break;
}
return JS_NULL;
return JS_UNDEFINED;
}
JSValue duk_make_gameobject(JSContext *js, JSValueConst this, int argc, JSValueConst *argv) {
return JS_NewInt64(js, MakeGameobject());
return gameobject2js(MakeGameobject());
}
JSValue duk_yughlog(JSContext *js, JSValueConst this, int argc, JSValueConst *argv) {
@ -1504,15 +1517,14 @@ JSValue duk_yughlog(JSContext *js, JSValueConst this, int argc, JSValueConst *ar
JS_FreeCString(js, s);
JS_FreeCString(js, f);
return JS_NULL;
return JS_UNDEFINED;
}
JSValue duk_set_body(JSContext *js, JSValueConst this, int argc, JSValueConst *argv) {
int cmd = js2int(argv[0]);
int id = js2int(argv[1]);
struct gameobject *go = get_gameobject_from_id(id);
if (!go) return JS_NULL;
struct gameobject *go = js2go(argv[1]);
if (!go) return JS_UNDEFINED;
/* TODO: Possible that reindexing shapes only needs done for static shapes? */
switch (cmd) {
@ -1536,7 +1548,7 @@ JSValue duk_set_body(JSContext *js, JSValueConst this, int argc, JSValueConst *a
case 4:
cpBodyApplyImpulseAtWorldPoint(go->body, js2vec2(argv[2]).cp, cpBodyGetPosition(go->body));
return JS_NULL;
return JS_UNDEFINED;
case 5:
// go->flipx = JS_ToBool(js, argv[2]);
@ -1554,11 +1566,11 @@ JSValue duk_set_body(JSContext *js, JSValueConst this, int argc, JSValueConst *a
case 8:
cpBodySetAngularVelocity(go->body, js2number(argv[2]));
return JS_NULL;
return JS_UNDEFINED;
case 9:
cpBodySetVelocity(go->body, js2vec2(argv[2]).cp);
return JS_NULL;
return JS_UNDEFINED;
case 10:
go->e = fmax(js2number(argv[2]), 0);
@ -1570,27 +1582,26 @@ JSValue duk_set_body(JSContext *js, JSValueConst this, int argc, JSValueConst *a
case 12:
cpBodyApplyForceAtWorldPoint(go->body, js2vec2(argv[2]).cp, cpBodyGetPosition(go->body));
return JS_NULL;
return JS_UNDEFINED;
case 13:
cpBodySetMoment(go->body, js2number(argv[2]));
return JS_NULL;
return JS_UNDEFINED;
case 14:
cpBodyApplyForceAtLocalPoint(go->body, js2vec2(argv[2]).cp, js2vec2(argv[3]).cp);
return JS_NULL;
return JS_UNDEFINED;
}
cpSpaceReindexShapesForBody(space, go->body);
return JS_NULL;
return JS_UNDEFINED;
}
JSValue duk_q_body(JSContext *js, JSValueConst this, int argc, JSValueConst *argv) {
int q = js2int(argv[0]);
int goid = js2int(argv[1]);
struct gameobject *go = get_gameobject_from_id(goid);
struct gameobject *go = js2go(argv[1]);
if (!go) return JS_NULL;
if (!go) return JS_UNDEFINED;
switch (q) {
case 0:
@ -1618,16 +1629,16 @@ JSValue duk_q_body(JSContext *js, JSValueConst this, int argc, JSValueConst *arg
return JS_NewBool(js, phys2d_in_air(go->body));
case 8:
gameobject_delete(goid);
// gameobject_delete(goid);
break;
}
return JS_NULL;
return JS_UNDEFINED;
}
JSValue duk_make_sprite(JSContext *js, JSValueConst this, int argc, JSValueConst *argv) {
JSValue sprite = JS_NewObject(js);
js_setprop_str(sprite,"id",JS_NewInt64(js, make_sprite(js2int(argv[0]))));
js_setprop_str(sprite,"id",JS_NewInt64(js, make_sprite(jsgo2id(argv[0]))));
return sprite;
}
@ -1645,7 +1656,7 @@ JSValue duk_make_anim2d(JSContext *js, JSValueConst this, int argc, JSValueConst
}
JSValue duk_make_box2d(JSContext *js, JSValueConst this, int argc, JSValueConst *argv) {
int go = js2int(argv[0]);
int go = jsgo2id(argv[0]);
HMM_Vec2 size = js2vec2(argv[1]);
struct phys2d_box *box = Make2DBox(go);
@ -1666,7 +1677,7 @@ JSValue duk_cmd_box2d(JSContext *js, JSValueConst this, int argc, JSValueConst *
struct phys2d_box *box = js2ptr(argv[1]);
HMM_Vec2 arg;
if (!box) return JS_NULL;
if (!box) return JS_UNDEFINED;
switch (cmd) {
case 0:
@ -1685,11 +1696,11 @@ JSValue duk_cmd_box2d(JSContext *js, JSValueConst this, int argc, JSValueConst *
}
phys2d_applybox(box);
return JS_NULL;
return JS_UNDEFINED;
}
JSValue duk_make_circle2d(JSContext *js, JSValueConst this, int argc, JSValueConst *argv) {
int go = js2int(argv[0]);
int go = jsgo2id(argv[0]);
struct phys2d_circle *circle = Make2DCircle(go);
@ -1701,7 +1712,7 @@ JSValue duk_make_circle2d(JSContext *js, JSValueConst this, int argc, JSValueCon
JSValue duk_make_model(JSContext *js, JSValueConst this, int argc, JSValueConst *argv)
{
int go = js2int(argv[0]);
int go = jsgo2id(argv[0]);
struct drawmodel *dm = make_drawmodel(go);
JSValue ret = JS_NewObject(js);
js_setprop_str(ret, "id", ptr2js(dm));
@ -1712,7 +1723,7 @@ JSValue duk_cmd_circle2d(JSContext *js, JSValueConst this, int argc, JSValueCons
int cmd = js2int(argv[0]);
struct phys2d_circle *circle = js2ptr(argv[1]);
if (!circle) return JS_NULL;
if (!circle) return JS_UNDEFINED;
switch (cmd) {
case 0:
@ -1731,11 +1742,11 @@ JSValue duk_cmd_circle2d(JSContext *js, JSValueConst this, int argc, JSValueCons
}
phys2d_applycircle(circle);
return JS_NULL;
return JS_UNDEFINED;
}
JSValue duk_make_poly2d(JSContext *js, JSValueConst this, int argc, JSValueConst *argv) {
int go = js2int(argv[0]);
int go = jsgo2id(argv[0]);
struct phys2d_poly *poly = Make2DPoly(go);
phys2d_poly_setverts(poly, NULL);
JSValue polyval = JS_NewObject(js);
@ -1748,7 +1759,7 @@ JSValue duk_cmd_poly2d(JSContext *js, JSValueConst this, int argc, JSValueConst
int cmd = js2int(argv[0]);
struct phys2d_poly *poly = js2ptr(argv[1]);
if (!poly) return JS_NULL;
if (!poly) return JS_UNDEFINED;
switch (cmd) {
case 0:
@ -1756,11 +1767,11 @@ JSValue duk_cmd_poly2d(JSContext *js, JSValueConst this, int argc, JSValueConst
break;
}
return JS_NULL;
return JS_UNDEFINED;
}
JSValue duk_make_edge2d(JSContext *js, JSValueConst this, int argc, JSValueConst *argv) {
int go = js2int(argv[0]);
int go = jsgo2id(argv[0]);
struct phys2d_edge *edge = Make2DEdge(go);
int n = js_arrlen(argv[1]);
@ -1784,7 +1795,7 @@ JSValue duk_cmd_edge2d(JSContext *js, JSValueConst this, int argc, JSValueConst
if (!edge) {
YughError("Attempted to do a cmd on edge %p. Not found.", edge);
return JS_NULL;
return JS_UNDEFINED;
}
switch (cmd) {
@ -1798,7 +1809,7 @@ JSValue duk_cmd_edge2d(JSContext *js, JSValueConst this, int argc, JSValueConst
break;
}
return JS_NULL;
return JS_UNDEFINED;
}
JSValue duk_inflate_cpv(JSContext *js, JSValueConst this, int argc, JSValueConst *argv) {
@ -1835,7 +1846,7 @@ JSValue duk_anim(JSContext *js, JSValueConst this, int argc, JSValueConst *argv)
JS_FreeValue(js,vv);
}
return JS_NULL;
return JS_UNDEFINED;
}
JSValue duk_make_timer(JSContext *js, JSValueConst this, int argc, JSValueConst *argv) {
@ -1843,7 +1854,7 @@ JSValue duk_make_timer(JSContext *js, JSValueConst this, int argc, JSValueConst
// struct callee *c = make_callee(argv[0], argv[3]);
// int id = timer_make(secs, call_callee, c, 1, js2bool(argv[2]));
// return JS_NewInt64(js, id);
return JS_NULL;
return JS_UNDEFINED;
}
JSValue duk_cmd_points(JSContext *js, JSValueConst this, int argc, JSValueConst *argv)
@ -1862,7 +1873,7 @@ JSValue duk_cmd_points(JSContext *js, JSValueConst this, int argc, JSValueConst
break;
}
return JS_NULL;
return JS_UNDEFINED;
}
//#include "dlfcn.h"
@ -1885,7 +1896,7 @@ JSValue duk_cmd_points(JSContext *js, JSValueConst this, int argc, JSValueConst
ffi_call(&cif, fn, &rc, values);
}
return JS_NULL;
return JS_UNDEFINED;
}
*/
#define DUK_FUNC(NAME, ARGS) JS_SetPropertyStr(js, globalThis, #NAME, JS_NewCFunction(js, duk_##NAME, #NAME, ARGS));
@ -1936,4 +1947,6 @@ void ffi_load() {
JS_NewClass(JS_GetRuntime(js), js_ptr_id, &js_ptr_class);
QJSCLASSPREP(dsp_node);
QJSCLASSPREP(gameobject);
}

View file

@ -193,7 +193,7 @@ JSValue script_runfile(const char *file)
{
size_t len;
const char *script = slurp_text(file, &len);
if (!script) return JS_NULL;
if (!script) return JS_UNDEFINED;
JSValue obj = JS_Eval(js, script, len, file, JS_EVAL_FLAGS);
js_print_exception(obj);
@ -266,13 +266,13 @@ void out_memusage(const char *file)
JSValue js_callee_exec(struct callee *c, int argc, JSValue *argv)
{
if (JS_IsUndefined(c->fn)) return JS_NULL;
if (JS_IsUndefined(c->obj)) return JS_NULL;
if (JS_IsUndefined(c->fn)) return JS_UNDEFINED;
if (JS_IsUndefined(c->obj)) return JS_UNDEFINED;
JSValue ret = JS_Call(js, c->fn, c->obj, argc, argv);
js_print_exception(ret);
JS_FreeValue(js, ret);
return JS_NULL;
return JS_UNDEFINED;
}
void call_callee(struct callee *c) {

View file

@ -151,6 +151,7 @@ dsp_node *make_node(void *data, void (*proc)(void *data, soundbyte *out, int sam
void node_free(dsp_node *node)
{
YughWarn("FREEING A NODE");
unplug_node(node);
if (node->data)
if (node->data_free) node->data_free(node->data);

View file

@ -53,6 +53,7 @@ struct slice9_vert {
};
int make_sprite(int go) {
YughWarn("Attaching sprite to gameobject %d", go);
struct sprite sprite = {
.color = color_white,
.emissive = {0,0,0,0},