prosperon/scripts/engine.js

651 lines
16 KiB
JavaScript
Raw Normal View History

2023-12-11 16:59:59 -06:00
"use math";
2024-06-18 16:14:23 -05:00
Object.defineProperty(String.prototype, "tolast", {
value: function (val) {
2024-04-01 17:58:29 -05:00
var idx = this.lastIndexOf(val);
if (idx === -1) return this.slice();
2024-06-18 16:14:23 -05:00
return this.slice(0, idx);
},
2024-04-01 17:58:29 -05:00
});
2024-06-18 16:14:23 -05:00
Object.defineProperty(String.prototype, "dir", {
value: function () {
if (!this.includes("/")) return "";
return this.tolast("/");
},
2024-04-01 17:58:29 -05:00
});
2024-06-18 16:14:23 -05:00
Object.defineProperty(String.prototype, "folder", {
value: function () {
var dir = this.dir();
if (!dir) return "";
else return dir + "/";
2024-06-18 16:14:23 -05:00
},
});
2024-04-01 17:58:29 -05:00
globalThis.Resources = {};
2024-06-18 16:14:23 -05:00
Resources.replpath = function (str, path) {
2024-04-01 17:58:29 -05:00
if (!str) return str;
2024-06-18 16:14:23 -05:00
if (str[0] === "/") return str.rm(0);
2024-04-01 17:58:29 -05:00
2024-06-18 16:14:23 -05:00
if (str[0] === "@") return os.prefpath() + "/" + str.rm(0);
2024-04-01 17:58:29 -05:00
if (!path) return str;
2024-06-18 16:14:23 -05:00
2024-04-01 17:58:29 -05:00
var stem = path.dir();
while (stem) {
2024-06-18 16:14:23 -05:00
var tr = stem + "/" + str;
2024-04-01 17:58:29 -05:00
if (io.exists(tr)) return tr;
stem = stem.updir();
}
2024-06-18 16:14:23 -05:00
2024-04-01 17:58:29 -05:00
return str;
2024-06-18 16:14:23 -05:00
};
2024-04-01 17:58:29 -05:00
2024-06-18 16:14:23 -05:00
Resources.replstrs = function (path) {
2024-04-01 17:58:29 -05:00
if (!path) return;
var script = io.slurp(path);
var regexp = /"[^"\s]*?\.[^"\s]+?"/g;
var stem = path.dir();
2024-06-18 16:14:23 -05:00
script = script.replace(regexp, function (str) {
2024-04-01 17:58:29 -05:00
var newstr = Resources.replpath(str.trimchr('"'), path);
return `"${newstr}"`;
});
return script;
2024-06-18 16:14:23 -05:00
};
2024-04-01 17:58:29 -05:00
globalThis.json = {};
2024-06-18 16:14:23 -05:00
json.encode = function (value, replacer, space = 1) {
return JSON.stringify(value, replacer, space);
2024-06-18 16:14:23 -05:00
};
2024-06-18 16:14:23 -05:00
json.decode = function (text, reviver) {
if (!text) return undefined;
2024-06-18 16:14:23 -05:00
return JSON.parse(text, reviver);
};
2024-06-18 16:14:23 -05:00
json.readout = function (obj) {
var j = {};
for (var k in obj)
2024-06-18 16:14:23 -05:00
if (typeof obj[k] === "function") j[k] = "function " + obj[k].toString();
else j[k] = obj[k];
return json.encode(j);
2024-06-18 16:14:23 -05:00
};
json.doc = {
doc: "json implementation.",
encode: "Encode a value to json.",
decode: "Decode a json string to a value.",
2024-06-18 16:14:23 -05:00
readout: "Encode an object fully, including function definitions.",
};
Resources.scripts = ["jsoc", "jsc", "jso", "js"];
Resources.images = ["png", "gif", "jpg", "jpeg"];
2024-06-18 16:14:23 -05:00
Resources.sounds = ["wav", "flac", "mp3", "qoa"];
Resources.is_image = function (path) {
var ext = path.ext();
2024-06-18 16:14:23 -05:00
return Resources.images.any((x) => x === ext);
};
2024-06-18 16:14:23 -05:00
function find_ext(file, ext) {
if (io.exists(file)) return file;
for (var e of ext) {
var nf = `${file}.${e}`;
if (io.exists(nf)) return nf;
}
return;
}
2024-06-18 16:14:23 -05:00
Resources.find_image = function (file) {
return find_ext(file, Resources.images);
};
Resources.find_sound = function (file) {
return find_ext(file, Resources.sounds);
};
Resources.find_script = function (file) {
return find_ext(file, Resources.scripts);
};
2024-06-18 16:14:23 -05:00
profile.best_t = function (t) {
var qq = "ns";
if (t > 1000) {
t /= 1000;
2024-06-18 16:14:23 -05:00
qq = "us";
if (t > 1000) {
t /= 1000;
2024-06-18 16:14:23 -05:00
qq = "ms";
}
}
return `${t.toPrecision(4)} ${qq}`;
2024-06-18 16:14:23 -05:00
};
2024-06-18 16:14:23 -05:00
profile.report = function (start, msg = "[undefined report]") {
console.info(`${msg} in ${profile.best_t(profile.now() - start)}`);
};
2024-04-14 14:53:41 -05:00
2024-06-18 16:14:23 -05:00
profile.addreport = function (cache, line, start) {
2024-04-14 14:53:41 -05:00
cache[line] ??= [];
2024-06-18 16:14:23 -05:00
cache[line].push(profile.now() - start);
};
2024-04-14 14:53:41 -05:00
2024-06-18 16:14:23 -05:00
profile.printreport = function (cache, name) {
2024-04-14 14:53:41 -05:00
var report = name + "\n";
2024-05-21 18:50:53 -05:00
for (var i in cache)
2024-06-18 16:14:23 -05:00
report += `${i} ${profile.best_t(cache[i].reduce((a, b) => a + b) / cache[i].length)}\n`;
2024-04-14 14:53:41 -05:00
return report;
2024-06-18 16:14:23 -05:00
};
2024-04-14 14:53:41 -05:00
2024-04-03 17:17:32 -05:00
console.transcript = "";
2024-06-18 16:14:23 -05:00
console.say = function (msg) {
msg += "\n";
2024-04-03 17:17:32 -05:00
console.print(msg);
console.transcript += msg;
};
console.log = console.say;
2024-04-15 07:58:23 -05:00
globalThis.say = console.say;
globalThis.print = console.print;
2024-04-03 17:17:32 -05:00
2024-06-18 16:14:23 -05:00
console.pprint = function (msg, lvl = 0) {
if (typeof msg === "object") msg = JSON.stringify(msg, null, 2);
2024-04-03 17:17:32 -05:00
var file = "nofile";
var line = 0;
2024-06-18 16:14:23 -05:00
console.rec(0, msg, file, line);
var caller = new Error().stack.split("\n")[2];
if (caller) {
2024-04-03 17:17:32 -05:00
var md = caller.match(/\((.*)\:/);
var m = md ? md[1] : "SCRIPT";
if (m) file = m;
md = caller.match(/\:(\d*)\)/);
m = md ? md[1] : 0;
if (m) line = m;
}
2024-06-18 16:14:23 -05:00
2024-04-03 17:17:32 -05:00
console.rec(lvl, msg, file, line);
};
2024-06-18 16:14:23 -05:00
console.spam = function (msg) {
console.pprint(msg, 0);
};
console.debug = function (msg) {
console.pprint(msg, 1);
};
console.info = function (msg) {
console.pprint(msg, 2);
};
console.warn = function (msg) {
console.pprint(msg, 3);
};
console.error = function (msg) {
console.pprint(msg + "\n" + console.stackstr(2), 4);
};
console.panic = function (msg) {
console.pprint(msg + "\n" + console.stackstr(2), 5);
};
console.stackstr = function (skip = 0) {
2024-04-03 17:17:32 -05:00
var err = new Error();
2024-06-18 16:14:23 -05:00
var stack = err.stack.split("\n");
return stack.slice(skip, stack.length).join("\n");
2024-04-03 17:17:32 -05:00
};
2024-06-18 16:14:23 -05:00
console.stack = function (skip = 0) {
console.log(console.stackstr(skip + 1));
};
2024-03-23 09:56:38 -05:00
console.stdout_lvl = 1;
console.trace = console.stack;
console.doc = {
level: "Set level to output logging to console.",
info: "Output info level message.",
warn: "Output warn level message.",
error: "Output error level message, and print stacktrace.",
critical: "Output critical level message, and exit game immediately.",
write: "Write raw text to console.",
say: "Write raw text to console, plus a newline.",
stack: "Output a stacktrace to console.",
console: "Output directly to in game console.",
2024-06-18 16:14:23 -05:00
clear: "Clear console.",
};
2024-02-25 17:31:48 -06:00
globalThis.global = globalThis;
2023-05-24 20:45:50 -05:00
2024-04-14 14:53:41 -05:00
var profcache = {};
2024-06-18 16:14:23 -05:00
function use(file, env = {}, script) {
file = Resources.find_script(file);
var st = profile.now();
2024-06-18 16:14:23 -05:00
2024-04-14 14:53:41 -05:00
profcache[file] ??= [];
2024-06-18 16:14:23 -05:00
if (use.cache[file]) {
var ret = use.cache[file].call(env);
2024-04-14 14:53:41 -05:00
profile.addreport(profcache, file, st);
return;
}
2024-04-01 17:58:29 -05:00
script ??= Resources.replstrs(file);
script = `(function() { var self = this; ${script}; })`;
2024-06-18 16:14:23 -05:00
var fn = os.eval(file, script);
use.cache[file] = fn;
var ret = fn.call(env);
2024-04-14 14:53:41 -05:00
profile.addreport(profcache, file, st);
return ret;
}
use.cache = {};
2024-06-18 16:14:23 -05:00
global.check_registers = function (obj) {
if (typeof obj.update === "function")
obj.timers.push(Register.update.register(obj.update.bind(obj)));
2024-06-18 16:14:23 -05:00
if (typeof obj.physupdate === "function")
obj.timers.push(Register.physupdate.register(obj.physupdate.bind(obj)));
2024-06-18 16:14:23 -05:00
if (typeof obj.draw === "function")
obj.timers.push(Register.draw.register(obj.draw.bind(obj), obj));
2024-06-18 16:14:23 -05:00
if (typeof obj.debug === "function")
obj.timers.push(Register.debug.register(obj.debug.bind(obj)));
2024-06-18 16:14:23 -05:00
if (typeof obj.gui === "function")
obj.timers.push(Register.gui.register(obj.gui.bind(obj)));
2024-06-18 16:14:23 -05:00
if (typeof obj.screengui === "function")
obj.timers.push(Register.screengui.register(obj.screengui.bind(obj)));
for (var k in obj) {
if (!k.startswith("on_")) continue;
var signal = k.fromfirst("on_");
Event.observe(signal, obj, obj[k]);
}
};
Object.assign(global, use("scripts/base"));
2024-06-18 16:14:23 -05:00
global.obscure("global");
global.mixin("scripts/render");
global.mixin("scripts/debug");
2024-03-15 11:21:36 -05:00
var frame_t = profile.secs(profile.now());
2024-03-15 11:21:36 -05:00
2024-04-03 17:17:32 -05:00
var sim = {};
sim.mode = "play";
2024-06-18 16:14:23 -05:00
sim.play = function () {
this.mode = "play";
os.reindex_static();
};
sim.playing = function () {
return this.mode === "play";
};
sim.pause = function () {
this.mode = "pause";
};
sim.paused = function () {
return this.mode === "pause";
};
sim.step = function () {
this.mode = "step";
};
sim.stepping = function () {
return this.mode === "step";
};
2024-03-15 11:21:36 -05:00
var physlag = 0;
2024-03-18 08:16:25 -05:00
var gggstart = game.engine_start;
2024-06-18 16:14:23 -05:00
game.engine_start = function (s) {
game.startengine = 1;
2024-06-18 16:14:23 -05:00
gggstart(
function () {
global.mixin("scripts/sound.js");
world_start();
window.set_icon(os.make_texture("icons/moon.gif"));
Object.readonly(window.__proto__, "vsync");
Object.readonly(window.__proto__, "enable_dragndrop");
Object.readonly(window.__proto__, "enable_clipboard");
Object.readonly(window.__proto__, "high_dpi");
Object.readonly(window.__proto__, "sample_count");
s();
shape.quad = {
pos: os.make_buffer([0, 0, 0, 1, 0, 0, 0, 1, 0, 1, 1, 0], 0),
verts: 4,
uv: os.make_buffer([0, 1, 1, 1, 0, 0, 1, 0], 2),
index: os.make_buffer([0, 1, 2, 2, 1, 3], 1),
count: 6,
};
shape.triangle = {
pos: os.make_buffer([0, 0, 0, 0.5, 1, 0, 1, 0, 0], 0),
uv: os.make_buffer([0, 0, 0.5, 1, 1, 0], 2),
verts: 3,
count: 3,
index: os.make_buffer([0, 2, 1], 1),
};
render.init();
},
process,
window.size.x,
window.size.y,
);
};
2024-03-18 08:16:25 -05:00
game.startengine = 0;
2024-04-23 15:58:08 -05:00
var frames = [];
2024-06-18 16:14:23 -05:00
function process() {
2024-04-23 15:58:08 -05:00
var startframe = profile.now();
var dt = profile.secs(profile.now()) - frame_t;
frame_t = profile.secs(profile.now());
2024-06-18 16:14:23 -05:00
2024-03-15 11:21:36 -05:00
prosperon.appupdate(dt);
2024-03-18 14:27:52 -05:00
input.procdown();
2024-06-18 16:14:23 -05:00
2024-03-15 11:21:36 -05:00
if (sim.mode === "play" || sim.mode === "step") {
2024-06-18 16:14:23 -05:00
prosperon.update(dt * game.timescale);
if (sim.mode === "step") sim.pause();
2024-04-04 17:28:11 -05:00
physlag += dt;
2024-05-29 20:21:19 -05:00
while (physlag > physics.delta) {
physlag -= physics.delta;
2024-04-21 10:05:18 -05:00
var st = profile.now();
2024-06-18 16:14:23 -05:00
prosperon.phys2d_step(physics.delta * game.timescale);
prosperon.physupdate(physics.delta * game.timescale);
2024-04-21 10:05:18 -05:00
profile.addreport(profcache, "physics step", st);
2024-04-04 17:28:11 -05:00
}
2024-03-15 11:21:36 -05:00
}
2024-04-21 10:05:18 -05:00
var st = profile.now();
2024-07-01 17:00:01 -05:00
prosperon.window_render(window.size);
prosperon.draw();
2024-05-30 12:05:51 -05:00
prosperon.debug();
2024-03-18 14:27:52 -05:00
prosperon.gui();
prosperon.screengui();
2024-05-08 11:07:19 -05:00
prosperon.hookend?.();
2024-04-21 10:05:18 -05:00
profile.addreport(profcache, "render frame", st);
2024-06-18 16:14:23 -05:00
frames.push(profile.secs(profile.now() - startframe));
2024-04-23 15:58:08 -05:00
if (frames.length > 20) frames.shift();
}
2024-06-18 16:14:23 -05:00
globalThis.fps = function () {
2024-04-23 15:58:08 -05:00
var sum = 0;
2024-06-18 16:14:23 -05:00
for (var i = 0; i < frames.length; i++) sum += frames[i];
return frames.length / sum;
};
2024-03-18 08:16:25 -05:00
game.timescale = 1;
2024-06-18 16:14:23 -05:00
var eachobj = function (obj, fn) {
2024-04-11 17:17:49 -05:00
var val = fn(obj);
if (val) return val;
2024-04-10 16:21:46 -05:00
for (var o in obj.objects) {
2024-04-11 17:17:49 -05:00
if (obj.objects[o] === obj)
console.error(`Object ${obj.toString()} is referenced by itself.`);
2024-06-18 16:14:23 -05:00
val = eachobj(obj.objects[o], fn);
2024-04-11 17:17:49 -05:00
if (val) return val;
2024-04-10 16:21:46 -05:00
}
2024-06-18 16:14:23 -05:00
};
2024-04-11 17:17:49 -05:00
2024-06-18 16:14:23 -05:00
game.all_objects = function (fn, startobj = world) {
return eachobj(startobj, fn);
};
game.find_object = function (fn, startobj = world) {};
2024-04-03 00:44:08 -05:00
game.tags = {};
2024-06-18 16:14:23 -05:00
game.tag_add = function (tag, obj) {
2024-04-03 00:44:08 -05:00
game.tags[tag] ??= {};
game.tags[tag][obj.guid] = obj;
2024-06-18 16:14:23 -05:00
};
2024-04-03 00:44:08 -05:00
2024-06-18 16:14:23 -05:00
game.tag_rm = function (tag, obj) {
2024-04-03 00:44:08 -05:00
delete game.tags[tag][obj.guid];
2024-06-18 16:14:23 -05:00
};
2024-04-03 00:44:08 -05:00
2024-06-18 16:14:23 -05:00
game.tag_clear_guid = function (guid) {
for (var tag in game.tags) delete game.tags[tag][guid];
};
2024-03-19 17:00:49 -05:00
2024-06-18 16:14:23 -05:00
game.objects_with_tag = function (tag) {
if (!game.tags[tag]) return [];
2024-04-03 00:44:08 -05:00
return Object.values(game.tags[tag]);
2024-06-18 16:14:23 -05:00
};
2024-03-18 08:16:25 -05:00
game.doc = {};
game.doc.object = "Returns the entity belonging to a given id.";
game.doc.pause = "Pause game simulation.";
game.doc.play = "Resume or start game simulation.";
game.doc.camera = "Current camera.";
2024-02-23 16:05:30 -06:00
2024-07-01 13:05:26 -05:00
game.texture = function (path, force = false) {
if (force && game.texture.cache[path]) return game.texture.cache[path];
2024-06-18 16:14:23 -05:00
if (!io.exists(path)) {
console.warn(`Missing texture: ${path}`);
game.texture.cache[path] = game.texture("icons/no_tex.gif");
2024-06-18 16:14:23 -05:00
} else game.texture.cache[path] ??= os.make_texture(path);
return game.texture.cache[path];
2024-06-18 16:14:23 -05:00
};
game.texture.cache = {};
2024-02-23 16:05:30 -06:00
prosperon.semver = {};
2024-06-18 16:14:23 -05:00
prosperon.semver.valid = function (v, range) {
v = v.split(".");
range = range.split(".");
2024-02-23 16:05:30 -06:00
if (v.length !== 3) return undefined;
if (range.length !== 3) return undefined;
2024-06-18 16:14:23 -05:00
if (range[0][0] === "^") {
2024-02-23 16:05:30 -06:00
range[0] = range[0].slice(1);
if (parseInt(v[0]) >= parseInt(range[0])) return true;
2024-06-18 16:14:23 -05:00
2024-02-23 16:05:30 -06:00
return false;
}
2024-06-18 16:14:23 -05:00
if (range[0] === "~") {
2024-02-23 16:05:30 -06:00
range[0] = range[0].slice(1);
for (var i = 0; i < 2; i++)
if (parseInt(v[i]) < parseInt(range[i])) return false;
return true;
}
2024-06-18 16:14:23 -05:00
return prosperon.semver.cmp(v.join("."), range.join(".")) === 0;
};
2024-02-23 16:05:30 -06:00
2024-06-18 16:14:23 -05:00
prosperon.semver.cmp = function (v1, v2) {
var ver1 = v1.split(".");
var ver2 = v2.split(".");
2024-02-23 16:05:30 -06:00
for (var i = 0; i < 3; i++) {
var n1 = parseInt(ver1[i]);
var n2 = parseInt(ver2[i]);
2024-06-18 16:14:23 -05:00
if (n1 > n2) return 1;
else if (n1 < n2) return -1;
2024-02-23 16:05:30 -06:00
}
2024-06-18 16:14:23 -05:00
2024-02-23 16:05:30 -06:00
return 0;
2024-06-18 16:14:23 -05:00
};
2024-02-23 16:05:30 -06:00
2024-06-18 16:14:23 -05:00
prosperon.semver.doc =
"Functions for semantic versioning numbers. Semantic versioning is given as a triple digit number, as MAJOR.MINOR.PATCH.";
prosperon.semver.cmp.doc =
"Compare two semantic version numbers, given like X.X.X.";
2024-02-23 16:05:30 -06:00
prosperon.semver.valid.doc = `Test if semantic version v is valid, given a range.
Range is given by a semantic versioning number, prefixed with nothing, a ~, or a ^.
~ means that MAJOR and MINOR must match exactly, but any PATCH greater or equal is valid.
^ means that MAJOR must match exactly, but any MINOR and PATCH greater or equal is valid.`;
2024-06-18 16:14:23 -05:00
prosperon.iconified = function (icon) {};
prosperon.focus = function (focus) {};
prosperon.resize = function (dimensions) {
2024-05-16 14:50:18 -05:00
window.size.x = dimensions.x;
window.size.y = dimensions.y;
};
2024-06-18 16:14:23 -05:00
prosperon.suspended = function (sus) {};
prosperon.mouseenter = function () {};
prosperon.mouseleave = function () {};
prosperon.touchpress = function (touches) {};
prosperon.touchrelease = function (touches) {};
prosperon.touchmove = function (touches) {};
prosperon.clipboardpaste = function (str) {};
prosperon.quit = function () {
2024-04-16 07:48:34 -05:00
say(profile.printreport(profcache, "USE REPORT"));
say(profile.printreport(entityreport, "ENTITY REPORT"));
2024-06-18 16:14:23 -05:00
2024-04-14 14:53:41 -05:00
console.info("QUITTING");
for (var i in debug.log.time)
2024-06-18 16:14:23 -05:00
say(debug.log.time[i].map((x) => profile.ms(x)));
};
2024-07-03 16:38:29 -05:00
window.size = [640, 480];
window.mode = "keep";
window.toggle_fullscreen = function() { window.fullscreen = !window.fullscreen; }
window.set_icon.doc = "Set the icon of the window using the PNG image at path.";
window.doc = {};
window.doc.dimensions = "Window width and height packaged in an array [width,height]";
window.doc.title = "Name in the title bar of the window.";
window.doc.boundingbox = "Boundingbox of the window, with top and right being its height and width.";
global.mixin("scripts/input");
global.mixin("scripts/std");
global.mixin("scripts/diff");
global.mixin("scripts/color");
global.mixin("scripts/gui");
2024-04-01 08:13:57 -05:00
global.mixin("scripts/tween");
global.mixin("scripts/ai");
var timer = {
update(dt) {
this.remain -= dt;
2023-12-26 15:39:46 -06:00
if (this.remain <= 0) {
this.fn();
this.kill();
}
},
kill() {
2024-01-03 14:26:42 -06:00
this.end();
delete this.fn;
},
2024-06-18 16:14:23 -05:00
2023-11-29 17:31:41 -06:00
delay(fn, secs) {
var t = Object.create(this);
t.time = secs;
t.remain = secs;
2023-12-26 15:39:46 -06:00
t.fn = fn;
2024-01-03 14:26:42 -06:00
t.end = Register.update.register(timer.update.bind(t));
var returnfn = timer.kill.bind(t);
returnfn.remain = secs;
return returnfn;
},
};
global.mixin("scripts/physics");
global.mixin("scripts/geometry");
2023-04-25 14:59:26 -05:00
/*
Factory for creating registries. Register one with 'X.register',
which returns a function that, when invoked, cancels the registry.
*/
var Register = {
registries: [],
2023-06-05 17:19:43 -05:00
2024-03-11 22:23:02 -05:00
add_cb(name) {
var n = {};
2024-01-03 14:26:42 -06:00
var fns = [];
2024-06-18 16:14:23 -05:00
n.register = function (fn, obj) {
if (typeof fn !== "function") return;
if (typeof obj === "object") fn = fn.bind(obj);
2024-01-03 14:26:42 -06:00
fns.push(fn);
2024-06-18 16:14:23 -05:00
return function () {
2024-03-18 08:16:25 -05:00
fns.remove(fn);
};
2024-06-18 16:14:23 -05:00
};
prosperon[name] = function (...args) {
fns.forEach((x) => x(...args));
};
2024-03-18 08:16:25 -05:00
prosperon[name].fns = fns;
2024-06-18 16:14:23 -05:00
n.clear = function () {
fns = [];
};
Register[name] = n;
Register.registries.push(n);
2024-06-18 16:14:23 -05:00
return n;
},
};
2024-03-11 22:23:02 -05:00
Register.add_cb("appupdate");
2024-03-15 11:21:36 -05:00
Register.add_cb("update").doc = "Called once per frame.";
2024-03-11 22:23:02 -05:00
Register.add_cb("physupdate");
Register.add_cb("gui");
Register.add_cb("debug");
Register.add_cb("draw");
Register.add_cb("screengui");
2023-11-22 03:51:43 -06:00
var Event = {
events: {},
observe(name, obj, fn) {
this.events[name] ??= [];
this.events[name].push([obj, fn]);
},
unobserve(name, obj) {
2024-06-18 16:14:23 -05:00
this.events[name] = this.events[name].filter((x) => x[0] !== obj);
2023-11-22 03:51:43 -06:00
},
2023-12-20 17:20:29 -06:00
rm_obj(obj) {
2024-06-18 16:14:23 -05:00
Object.keys(this.events).forEach((name) => Event.unobserve(name, obj));
2023-12-20 17:20:29 -06:00
},
2024-04-12 13:53:00 -05:00
notify(name, ...args) {
2023-11-22 03:51:43 -06:00
if (!this.events[name]) return;
2024-06-18 16:14:23 -05:00
this.events[name].forEach(function (x) {
2024-04-12 13:53:00 -05:00
x[1].call(x[0], ...args);
2023-11-22 03:51:43 -06:00
});
},
};
global.mixin("scripts/spline");
global.mixin("scripts/components");
global.mixin("scripts/actor");
global.mixin("scripts/entity");
2023-05-27 07:01:17 -05:00
function world_start() {
2024-05-02 17:13:09 -05:00
globalThis.world = Object.create(entity);
2024-05-12 18:36:14 -05:00
world.transform = os.make_transform();
world.objects = {};
2024-06-18 16:14:23 -05:00
world.toString = function () {
return "world";
};
world.ur = "world";
2024-06-18 16:14:23 -05:00
world.kill = function () {
this.clear();
};
world.phys = 2;
2024-03-20 16:48:03 -05:00
world.zoom = 1;
2024-04-10 16:21:46 -05:00
world._ed = { selectable: false };
2024-04-14 14:53:41 -05:00
world.ur = {};
world.ur.fresh = {};
2024-03-20 16:48:03 -05:00
game.cam = world;
}
2023-09-08 12:35:06 -05:00
global.mixin("scripts/physics");
global.mixin("scripts/widget");
globalThis.mum = app.spawn("scripts/mum");
2024-03-18 08:16:25 -05:00
window.title = `Prosperon v${prosperon.version}`;
2024-06-18 16:14:23 -05:00
window.size = [500, 500];