added colors; repl works

This commit is contained in:
John Alanbrook 2023-09-21 17:50:39 +00:00
parent 47dc6aa1fe
commit 14d743e704
8 changed files with 145 additions and 69 deletions

View file

@ -136,6 +136,8 @@ Ur-types are directly related to your file directory hierarchy. In a pinball gam
This is how resources are loaded in any given ur-type. Relative file paths work. So, in 'ball.js', it can reference 'hit.wav', and will play that file when it does; when bumper.js loads 'hit.wav', it will load the one located in its folder. This is how resources are loaded in any given ur-type. Relative file paths work. So, in 'ball.js', it can reference 'hit.wav', and will play that file when it does; when bumper.js loads 'hit.wav', it will load the one located in its folder.
An ur-type is a list of properties and functions. When the ur-type is created, an entity is spawned in the world, and the entity is pasted with all the properties of the ur-type. After that, hookup happens, for start, update, physupdate, etc, functions.
The left flipper can use the root flipper flip sound by loading "../flip.wav". The left flipper can use the root flipper flip sound by loading "../flip.wav".
Absolute paths can be specified using a leading slash. The absolute path the bumper's hit sound is "/bumper/hit.wav". Absolute paths can be specified using a leading slash. The absolute path the bumper's hit sound is "/bumper/hit.wav".

View file

@ -39,6 +39,18 @@ var descriptors = {};
return target; return target;
}; };
Object.deepfreeze = function(obj)
{
for (var key in obj) {
if (typeof obj[key] === 'object') {
Object.freeze(obj[key]);
Object.deepfreeze(obj[key]);
}
}
Object.freeze(obj);
}
/* Goes through each key and overwrites if it's present, adds if it is not */
Object.dainty_assign = function(target, source) Object.dainty_assign = function(target, source)
{ {
for (var key in source) { for (var key in source) {
@ -60,6 +72,9 @@ Object.dainty_assign = function(target, source)
} }
} }
/* This name is more consistent with Ruby, etc */
Object.merge = Object.dainty_assign;
Object.totalassign = function(to, from) Object.totalassign = function(to, from)
{ {
for (var key in from) for (var key in from)

View file

@ -26,17 +26,28 @@ var component = {
component.toJSON = ur_json; component.toJSON = ur_json;
component.sprite = Object.copy(component, { component.sprite = {
pos:[0,0],
color:[1,1,1],
layer:0,
enabled:true,
toString() { return "sprite"; },
make(go) {
var nsprite = Object.create(component.sprite.maker);
Object.assign(nsprite, make_sprite(go));
Object.assign(nsprite, this);
nsprite.ur = this;
return nsprite;
},
};
component.sprite.maker = Object.copy(component, {
name: "sprite", name: "sprite",
path: "", set path(x) { cmd(12,this.id,x,this.rect); },
layer: 0,
pos: [0,0],
get visible() { return this.enabled; }, get visible() { return this.enabled; },
set visible(x) { this.enabled = x; }, set visible(x) { this.enabled = x; },
asset(str) { this.path = str; this.sync();}, asset(str) { this.path = str; },
angle: 0,
rect: {s0:0, s1: 1, t0: 0, t1: 1}, rect: {s0:0, s1: 1, t0: 0, t1: 1},
get enabled() { return cmd(114,this.id); }, get enabled() { return cmd(114,this.id); },
set enabled(x) { cmd(20,this.id,x); }, set enabled(x) { cmd(20,this.id,x); },
set color(x) { cmd(96,this.id,x); }, set color(x) { cmd(96,this.id,x); },
@ -47,6 +58,7 @@ component.sprite = Object.copy(component, {
get layer() { return undefined; }, get layer() { return undefined; },
boundingbox() { boundingbox() {
return cwh2bb([0,0],[0,0]);
var dim = this.dimensions(); var dim = this.dimensions();
dim = dim.scale(this.gameobject.scale); dim = dim.scale(this.gameobject.scale);
var realpos = this.pos.copy(); var realpos = this.pos.copy();
@ -55,35 +67,13 @@ component.sprite = Object.copy(component, {
return cwh2bb(realpos,dim); return cwh2bb(realpos,dim);
}, },
sync() {
if (this.path)
cmd(12,this.id,this.path,this.rect);
},
kill() { cmd(9,this.id); }, kill() { cmd(9,this.id); },
dimensions() { return cmd(64,this.path); }, dimensions() { return cmd(64,this.path); },
width() { return cmd(64,this.path).x; }, width() { return cmd(64,this.path).x; },
height() { return cmd(64,this.path).y; }, height() { return cmd(64,this.path).y; },
make(go) {
var sprite = Object.create(this);
sprite.id = make_sprite(go);
sprite.sync();
return sprite;
},
POS_MID: [-0.5, -0.5],
}); });
var sprite = component.sprite; var sprite = component.sprite.maker;
component.sprite.ur = {
pos:[0,0],
color:[1,1,1],
layer:0,
enabled:true,
toString() { return "sprite"; },
};
sprite.inputs = {}; sprite.inputs = {};
sprite.inputs.kp9 = function() { this.pos = [0,0]; }; sprite.inputs.kp9 = function() { this.pos = [0,0]; };

View file

@ -43,10 +43,7 @@ var editor = {
do_select(go) { do_select(go) {
var obj = go >= 0 ? Game.object(go) : undefined; var obj = go >= 0 ? Game.object(go) : undefined;
if (!obj || !obj.selectable) return undefined; if (!obj || !obj.selectable) return undefined;
return obj;
if (this.working_layer > -1 && obj.draw_layer !== this.working_layer) return undefined;
if (obj.level !== this.edit_level) { if (obj.level !== this.edit_level) {
var testlevel = obj.level; var testlevel = obj.level;
while (testlevel && testlevel.level !== this.edit_level) { while (testlevel && testlevel.level !== this.edit_level) {
@ -55,6 +52,10 @@ var editor = {
return testlevel; return testlevel;
} }
return obj;
if (this.working_layer > -1 && obj.draw_layer !== this.working_layer) return undefined;
return obj; return obj;
}, },
@ -520,8 +521,14 @@ var editor = {
}); });
this.selectlist.forEach(function(x) { this.selectlist.forEach(function(x) {
var color = x.color ? x.color : [255,255,255]; var color = x.color ? x.color : Color.white;
GUI.text(x.toString(), world2screen(x.pos).add([0, 16]), 1, color); GUI.text(x.ur.toString(), world2screen(x.pos).add([0, 16]), 1, Color.purple);
for (var key in x.$) {
var o = x.$[key];
GUI.text(o.ur.toString(), world2screen(o.pos).add([0,16]),1,Color.purple);
GUI.text(key, world2screen(o.pos), 1, Color.green);
}
GUI.text(x.pos.map(function(x) { return Math.round(x); }), world2screen(x.pos), 1, color); GUI.text(x.pos.map(function(x) { return Math.round(x); }), world2screen(x.pos), 1, color);
Debug.arrow(world2screen(x.pos), world2screen(x.pos.add(x.up().scale(40))), Color.yellow, 1); Debug.arrow(world2screen(x.pos), world2screen(x.pos.add(x.up().scale(40))), Color.yellow, 1);
@ -597,20 +604,8 @@ var editor = {
this.curpanels.forEach(function(x) { this.curpanels.forEach(function(x) {
if (x.on) x.gui(); if (x.on) x.gui();
}); });
if (this.repl) {
Nuke.window("repl");
Nuke.newrow(500);
var log = cmd(84);
var f = log.prev('\n', 0, 10);
Nuke.scrolltext(log.slice(f));
this.replstr = Nuke.textbox(this.replstr);
Nuke.end();
}
}, },
replstr: "",
ed_debug() { ed_debug() {
if (!Debug.phys_drawing) if (!Debug.phys_drawing)
this.selectlist.forEach(function(x) { Debug.draw_obj_phys(x); }); this.selectlist.forEach(function(x) { Debug.draw_obj_phys(x); });
@ -694,8 +689,6 @@ var editor = {
this.edit_level.file = file; this.edit_level.file = file;
this.save_current(); this.save_current();
}, },
repl: false,
} }
editor.inputs = {}; editor.inputs = {};
@ -711,7 +704,7 @@ editor.inputs['C-a'] = function() {
}; };
editor.inputs['C-a'].doc = "Select all objects."; editor.inputs['C-a'].doc = "Select all objects.";
editor.inputs['`'] = function() { editor.repl = !editor.repl; }; editor.inputs['`'] = function() { editor.openpanel(replpanel); }
editor.inputs['`'].doc = "Open or close the repl."; editor.inputs['`'].doc = "Open or close the repl.";
/* Return if selected component. */ /* Return if selected component. */
@ -1433,6 +1426,7 @@ inputpanel.inputs.char = function(c) { this.value += c; this.keycb(); }
inputpanel.inputs.tab = function() { this.value = tab_complete(this.value, this.assets); } inputpanel.inputs.tab = function() { this.value = tab_complete(this.value, this.assets); }
inputpanel.inputs.escape = function() { this.close(); } inputpanel.inputs.escape = function() { this.close(); }
inputpanel.inputs.backspace = function() { this.value = this.value.slice(0,-1); this.keycb(); }; inputpanel.inputs.backspace = function() { this.value = this.value.slice(0,-1); this.keycb(); };
inputpanel.inputs.backspace.rep = true;
inputpanel.inputs.enter = function() { this.submit(); } inputpanel.inputs.enter = function() { this.submit(); }
function proto_count_lvls(name) function proto_count_lvls(name)
@ -1480,6 +1474,31 @@ function proto_children(name) {
load("scripts/textedit.js"); load("scripts/textedit.js");
var replpanel = Object.copy(inputpanel, {
title: "REPL",
closeonsubmit:false,
guibody() {
Nuke.newrow(400);
var log = cmd(84);
var f = log.prev('\n', 0,10);
Nuke.scrolltext(log.slice(f));
Nuke.newrow(30);
this.value = Nuke.textbox(this.value);
},
action() {
var ecode = "";
if (editor.selectlist.length === 1)
for (var key in editor.selectlist[0].$)
ecode += `var ${key} = editor.selectlist[0].$['${key}'];`;
ecode += this.value;
this.value = "";
Log.say(eval(ecode));
},
});
var objectexplorer = Object.copy(inputpanel, { var objectexplorer = Object.copy(inputpanel, {
title: "object explorer", title: "object explorer",
obj: undefined, obj: undefined,

View file

@ -38,10 +38,51 @@ var Color = {
yellow: [251,255,43,255], yellow: [251,255,43,255],
red: [255,36,20,255], red: [255,36,20,255],
teal: [96, 252, 237,255], teal: [96, 252, 237,255],
gray: [181, 181,181,255], gray: [181,181,181,255],
cyan: [0,255,255], cyan: [0,255,255],
purple: [162,93,227],
}; };
Color.Arkanoid = {
orange: [255,143,0,255],
teal: [0,255,255,255],
green: [0,255,0,255],
red: [255,0,0,255],
blue: [0,112,255,255],
purple: [255,0,255,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]
};
Object.deepfreeze(Color);
function bb2wh(bb) { function bb2wh(bb) {
return [bb.r-bb.l, bb.t-bb.b]; return [bb.r-bb.l, bb.t-bb.b];
}; };
@ -378,13 +419,16 @@ var ur_json = function()
function objdiff(from, to) { function objdiff(from, to) {
if (!to) return from; // Everything on from is unique if (!to) return from; // Everything on from is unique
var ret = {}; var ret = {};
ret.ur = to.toString();
for (var key in from) { for (var key in from) {
if (!(key in to)) continue; if (!from[key] || !to[key]) continue;
if (typeof from[key] === 'function') continue;
if (typeof to === 'object' && !(key in to)) continue;
if (typeof from[key] === 'object') { if (typeof from[key] === 'object') {
if ('ur' in from[key]) { if ('ur' in from[key]) {
ret[key] = objdiff(from[key],from[key].ur); var urdiff = objdiff(from[key],from[key].ur);
if (urdiff && !urdiff.empty) ret[key] = urdiff;
continue; continue;
} }
var diff = objdiff(from[key], to[key]); var diff = objdiff(from[key], to[key]);

View file

@ -322,7 +322,7 @@ var gameobject = {
Object.totalassign(obj, ur); Object.totalassign(obj, ur);
obj.ur = ur; obj.ur = ur;
for (var prop in obj) { /* for (var prop in obj) {
if (typeof obj[prop] === 'object' && 'comp' in obj[prop]) { if (typeof obj[prop] === 'object' && 'comp' in obj[prop]) {
var newcomp = component[obj[prop].comp].make(obj.body); var newcomp = component[obj[prop].comp].make(obj.body);
Object.assign(newcomp, obj[prop]); Object.assign(newcomp, obj[prop]);
@ -332,21 +332,28 @@ var gameobject = {
obj.components[prop] = obj[prop]; obj.components[prop] = obj[prop];
} }
}; };
*/
level.add_child(obj);
for (var prop in obj) {
var p = obj[prop];
if (typeof p !== 'object') continue;
/* Spawn subobjects defined */ if ('ur' in p) {
if (obj.$) { Log.warn(`spawning a ${prop} on this obj`);
for (var e in obj.$) { var newobj = obj.spawn(prototypes.get_ur(p.ur));
var newobj = obj.spawn(prototypes.get_ur(obj.$[e].ur)); Object.assign(newobj, p);
Object.assign(newobj, obj.$[e].diff); obj.$[prop] = newobj;
obj.$[e] = newobj; } else if ('make' in p) {
obj[prop] = obj[prop].make(obj.body);
obj.components[prop] = obj[prop];
} }
} };
obj.check_registers(obj); obj.check_registers(obj);
if (typeof obj.start === 'function') obj.start(); if (typeof obj.start === 'function') obj.start();
level.add_child(obj);
return obj; return obj;
}, },
@ -482,8 +489,6 @@ prototypes.from_file = function(file)
Object.assign(nested_access(ur,path), newur); Object.assign(nested_access(ur,path), newur);
nested_access(ur,path).__proto__ = newur.__proto__; nested_access(ur,path).__proto__ = newur.__proto__;
Log.warn(`Made ur from script ${file}: ${JSON.stringify(newur)}`);
return nested_access(ur,path); return nested_access(ur,path);
} }
prototypes.from_file.doc = "Create a new ur-type from a given script file."; prototypes.from_file.doc = "Create a new ur-type from a given script file.";

View file

@ -1387,7 +1387,9 @@ JSValue duk_q_body(JSContext *js, JSValueConst this, int argc, JSValueConst *arg
} }
JSValue duk_make_sprite(JSContext *js, JSValueConst this, int argc, JSValueConst *argv) { JSValue duk_make_sprite(JSContext *js, JSValueConst this, int argc, JSValueConst *argv) {
return JS_NewInt64(js, make_sprite(js2int(argv[0]))); JSValue sprite = JS_NewObject(js);
JS_SetPropertyStr(js,sprite,"id",JS_NewInt64(js, make_sprite(js2int(argv[0]))));
return sprite;
} }
/* Make anim from texture */ /* Make anim from texture */

View file

@ -192,7 +192,6 @@ void input_btn(int btn, int state, uint32_t mod)
void input_key(int key, uint32_t mod) void input_key(int key, uint32_t mod)
{ {
if (mod != 0) return;
JSValue argv[2]; JSValue argv[2];
char out[2] = {0}; char out[2] = {0};
out[0] = (char)key; out[0] = (char)key;