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.
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".
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;
};
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)
{
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)
{
for (var key in from)

View file

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

View file

@ -43,9 +43,6 @@ var editor = {
do_select(go) {
var obj = go >= 0 ? Game.object(go) : 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) {
var testlevel = obj.level;
@ -57,6 +54,10 @@ var editor = {
}
return obj;
if (this.working_layer > -1 && obj.draw_layer !== this.working_layer) return undefined;
return obj;
},
curpanel: undefined,
@ -520,8 +521,14 @@ var editor = {
});
this.selectlist.forEach(function(x) {
var color = x.color ? x.color : [255,255,255];
GUI.text(x.toString(), world2screen(x.pos).add([0, 16]), 1, color);
var color = x.color ? x.color : Color.white;
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);
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) {
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() {
if (!Debug.phys_drawing)
this.selectlist.forEach(function(x) { Debug.draw_obj_phys(x); });
@ -694,8 +689,6 @@ var editor = {
this.edit_level.file = file;
this.save_current();
},
repl: false,
}
editor.inputs = {};
@ -711,7 +704,7 @@ editor.inputs['C-a'] = function() {
};
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.";
/* 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.escape = function() { this.close(); }
inputpanel.inputs.backspace = function() { this.value = this.value.slice(0,-1); this.keycb(); };
inputpanel.inputs.backspace.rep = true;
inputpanel.inputs.enter = function() { this.submit(); }
function proto_count_lvls(name)
@ -1480,6 +1474,31 @@ function proto_children(name) {
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, {
title: "object explorer",
obj: undefined,

View file

@ -38,10 +38,51 @@ var Color = {
yellow: [251,255,43,255],
red: [255,36,20,255],
teal: [96, 252, 237,255],
gray: [181, 181,181,255],
gray: [181,181,181,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) {
return [bb.r-bb.l, bb.t-bb.b];
};
@ -378,13 +419,16 @@ var ur_json = function()
function objdiff(from, to) {
if (!to) return from; // Everything on from is unique
var ret = {};
ret.ur = to.toString();
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 ('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;
}
var diff = objdiff(from[key], to[key]);

View file

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

View file

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