actor delay
This commit is contained in:
parent
b9db31c84e
commit
03fb016fbc
|
@ -3,3 +3,6 @@
|
|||
Entities are defined by creating a .jso script in your game directory. Variants of the original entity can be created by defining a .json file, typically done via the provided editor. The original entity is known as its ur-type. If you create a player.jso file in your game directory, a player can be spawned by saying Primum.spawn(ur.player).
|
||||
|
||||
An entity which differs from its ur will have an asterisk * next to its name.
|
||||
|
||||
## Ur types
|
||||
|
||||
|
|
|
@ -2,6 +2,10 @@
|
|||
|
||||
Primum programs are organized into two different types of source files: scripts and entities. Scripts end with .js, entities end with .jso.
|
||||
|
||||
Actors can be created with jso files. Make one by calling 'actor.spawn(file)'.
|
||||
|
||||
Entities are specialized actors, that are in the world of the computer game. While calling delay on actor causes a delay relative to real-life time, delay on an entity causes a delay relative to the game world time.
|
||||
|
||||
## Scripts
|
||||
|
||||
Script hooks exist to allow to modification of the game.
|
||||
|
|
|
@ -941,6 +941,19 @@ Object.defineProperty(Array.prototype, 'lerp', {
|
|||
|
||||
Math.lerp = function(s,f,t) { return (f-s)*t + s; };
|
||||
|
||||
Math.grab_from_points = function(pos, points, slop) {
|
||||
var shortest = slop;
|
||||
var idx = -1;
|
||||
points.forEach(function(x,i) {
|
||||
if (Vector.length(pos.sub(x)) < shortest) {
|
||||
shortest = Vector.length(pos.sub(x));
|
||||
idx = i;
|
||||
}
|
||||
});
|
||||
return idx;
|
||||
};
|
||||
|
||||
|
||||
Number.prec = function(num)
|
||||
{
|
||||
return parseFloat(num.toFixed(3));
|
||||
|
|
|
@ -533,7 +533,7 @@ polygon2d.inputs.lm = function(){};
|
|||
polygon2d.inputs.lm.released = function(){};
|
||||
|
||||
polygon2d.inputs['C-M-lm'] = function() {
|
||||
var idx = grab_from_points(Mouse.worldpos, this.points.map(p => this.gameobject.this2world(p)), 25);
|
||||
var idx = Math.grab_from_points(Mouse.worldpos, this.points.map(p => this.gameobject.this2world(p)), 25);
|
||||
if (idx === -1) return;
|
||||
this.points.splice(idx, 1);
|
||||
};
|
||||
|
@ -761,7 +761,7 @@ bucket.inputs['C-b'] = function() { this.type = Spline.type.bezier; this.looped
|
|||
bucket.inputs['C-b'].doc = "Set spline to bezier.";
|
||||
|
||||
bucket.inputs['C-M-lm'] = function() {
|
||||
var idx = grab_from_points(Mouse.worldpos, this.cpoints.map(p => this.gameobject.this2world(p)), 25);
|
||||
var idx = Math.grab_from_points(Mouse.worldpos, this.cpoints.map(p => this.gameobject.this2world(p)), 25);
|
||||
if (idx === -1) return;
|
||||
|
||||
this.cpoints = this.cpoints.newfirst(idx);
|
||||
|
@ -784,7 +784,7 @@ bucket.inputs['C-lm'] = function() {
|
|||
bucket.inputs['C-lm'].doc = "Add a point to the spline at the mouse position.";
|
||||
|
||||
bucket.inputs['C-M-lm'] = function() {
|
||||
var idx = grab_from_points(Mouse.worldpos, this.cpoints.map(p => this.gameobject.this2world(p)), 25);
|
||||
var idx = Math.grab_from_points(Mouse.worldpos, this.cpoints.map(p => this.gameobject.this2world(p)), 25);
|
||||
|
||||
if (idx < 0 || idx > this.cpoints.length) return;
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
var Gizmos = {
|
||||
pick_gameobject_points(worldpos, gameobject, points) {
|
||||
var idx = grab_from_points(worldpos, points.map(gameobject.this2world,gameobject), 25);
|
||||
var idx = Math.grab_from_points(worldpos, points.map(gameobject.this2world,gameobject), 25);
|
||||
if (idx === -1) return undefined;
|
||||
return points[idx];
|
||||
},
|
||||
|
@ -122,7 +122,7 @@ Debug.Options.Color = {
|
|||
|
||||
var Gizmos = {
|
||||
pick_gameobject_points(worldpos, gameobject, points) {
|
||||
var idx = grab_from_points(worldpos, points.map(gameobject.this2world,gameobject), 25);
|
||||
var idx = Math.grab_from_points(worldpos, points.map(gameobject.this2world,gameobject), 25);
|
||||
if (idx === -1) return null;
|
||||
return points[idx];
|
||||
},
|
||||
|
@ -266,12 +266,7 @@ Time.doc.play = "Resume the game after using Time.pause.";
|
|||
Player.players[0].control(DebugControls);
|
||||
Register.gui.register(Debug.draw, Debug);
|
||||
|
||||
var console = {};
|
||||
console.log = Log.say;
|
||||
console.info = Log.info;
|
||||
console.warn = Log.warn;
|
||||
console.error = Log.error;
|
||||
console.stack = Log.stack;
|
||||
var console = Object.create(Log);
|
||||
console.clear = function()
|
||||
{
|
||||
cmd(146);
|
||||
|
|
|
@ -70,112 +70,26 @@ var Device = {
|
|||
|
||||
load("scripts/gui.js");
|
||||
|
||||
var ctimer = {
|
||||
make(fn, secs,obj,loop,app) {
|
||||
obj ??= globalThis;
|
||||
app ??= false;
|
||||
if (secs === 0) {
|
||||
fn.call(obj);
|
||||
return;
|
||||
}
|
||||
|
||||
var t = Object.create(this);
|
||||
t.id = make_timer(fn, secs, app, obj);
|
||||
t.loop = loop;
|
||||
t.pause();
|
||||
|
||||
return t;
|
||||
},
|
||||
|
||||
oneshot(fn, secs,obj, app) {
|
||||
app ??= false;
|
||||
var t = this.make(fn, secs, obj, 0, app);
|
||||
t.start();
|
||||
return t;
|
||||
},
|
||||
get remain() { return cmd(32, this.id); },
|
||||
get on() { return cmd(33, this.id); },
|
||||
get loop() { return cmd(34, this.id); },
|
||||
set loop(x) { cmd(35, this.id, x); },
|
||||
|
||||
start() { cmd(26, this.id); },
|
||||
stop() { cmd(25, this.id); },
|
||||
pause() { cmd(24, this.id); },
|
||||
kill() { if (this.dead) return; cmd(27, this.id); this.dead = true; },
|
||||
set time(x) { cmd(28, this.id, x); },
|
||||
get time() { return cmd(29, this.id); },
|
||||
get pct() { return this.remain / this.time; },
|
||||
};
|
||||
|
||||
var timer = {
|
||||
time: 1,
|
||||
remain: 1,
|
||||
loop: false,
|
||||
on: false,
|
||||
apptime: false, /* If true, based on app's time instead of game world time */
|
||||
start() {
|
||||
this.on = true;
|
||||
},
|
||||
|
||||
restart() {
|
||||
this.remain = this.time;
|
||||
this.start();
|
||||
},
|
||||
|
||||
update(dt) {
|
||||
if (!this.on) return;
|
||||
|
||||
this.remain -= dt;
|
||||
if (this.remain <= 0)
|
||||
this.fire();
|
||||
},
|
||||
|
||||
fire() {
|
||||
this.fn();
|
||||
if (this.loop)
|
||||
this.restart();
|
||||
},
|
||||
|
||||
pct() { return 1 - (this.remain / this.time); },
|
||||
|
||||
kill() {
|
||||
Register.unregister_obj(this);
|
||||
},
|
||||
|
||||
delay(fn, secs, desc) {
|
||||
var t = timer.make(fn,secs,desc);
|
||||
t.loop = false;
|
||||
t.restart();
|
||||
return t;
|
||||
t.fn = function() { fn(); t.kill(); };
|
||||
return function() { t.kill(); };
|
||||
},
|
||||
oneshot(fn, secs, obj, desc) {
|
||||
this.delay(fn,secs,desc);
|
||||
},
|
||||
make(fn, secs, desc) {
|
||||
delay(fn, secs) {
|
||||
var t = Object.create(this);
|
||||
Object.assign(t, desc);
|
||||
t.time = secs;
|
||||
t.remain = secs;
|
||||
t.fn = fn;
|
||||
t.fire = function() { fn(); t.kill(); };
|
||||
Register.update.register(t.update, t);
|
||||
return t;
|
||||
return function() { t.kill(); };
|
||||
},
|
||||
};
|
||||
timer.toJSON = function() { return undefined; };
|
||||
timer.doc = {
|
||||
doc: "Quickly make timers to fire off events once or multiple times.",
|
||||
oneshot: "Executes a given function after the given number of seconds.",
|
||||
make: "Returns a timer that can be handled and reused.",
|
||||
start: "Starts the timer.",
|
||||
stop: "Stops the timer.",
|
||||
loop: "Set to true for the timer to repeat when done.",
|
||||
kill: "Destroys the timer.",
|
||||
pct: "Get the percentange the timer is complete.",
|
||||
time: "Set or get the amount of time this timer waits to execute. Does not reset the time, so if it is set to below the elapsed time it will execute immediately.",
|
||||
remain: "The time remianing before the function is executed.",
|
||||
};
|
||||
|
||||
load("scripts/animation.js");
|
||||
|
||||
|
@ -208,20 +122,6 @@ function screen2world(screenpos) {
|
|||
function world2screen(worldpos) { return Game.camera.world2view(worldpos); }
|
||||
|
||||
var Register = {
|
||||
inloop: false,
|
||||
loopcbs: [],
|
||||
finloop() {
|
||||
this.loopcbs.forEach(x => x());
|
||||
this.loopcbs = [];
|
||||
},
|
||||
|
||||
wraploop(loop) {
|
||||
this.inloop = true;
|
||||
loop();
|
||||
this.inloop = false;
|
||||
this.finloop();
|
||||
},
|
||||
|
||||
kbm_input(mode, btn, state, ...args) {
|
||||
if (state === 'released') {
|
||||
btn = btn.split('-').last;
|
||||
|
@ -321,6 +221,7 @@ var Register = {
|
|||
};
|
||||
|
||||
Register.add_cb(0, "update").doc = "Called once per frame.";
|
||||
Register.add_cb(11, "appupdate");
|
||||
Register.add_cb(1, "physupdate");
|
||||
Register.add_cb(2, "gui");
|
||||
Register.add_cb(6, "debug");
|
||||
|
@ -567,7 +468,6 @@ Primum._ed = {
|
|||
};
|
||||
Primum.toString = function() { return "Primum"; };
|
||||
Primum.ur = undefined;
|
||||
Game.view_camera(Primum.spawn(ur.camera2d));
|
||||
}
|
||||
|
||||
load("scripts/physics.js");
|
||||
|
|
|
@ -1,15 +1,3 @@
|
|||
function grab_from_points(pos, points, slop) {
|
||||
var shortest = slop;
|
||||
var idx = -1;
|
||||
points.forEach(function(x,i) {
|
||||
if (Vector.length(pos.sub(x)) < shortest) {
|
||||
shortest = Vector.length(pos.sub(x));
|
||||
idx = i;
|
||||
}
|
||||
});
|
||||
return idx;
|
||||
};
|
||||
|
||||
var actor = {};
|
||||
actor.spawn = function(script, config){
|
||||
if (typeof script !== 'string') return;
|
||||
|
@ -19,21 +7,54 @@ actor.spawn = function(script, config){
|
|||
if (typeof config === 'object')
|
||||
Object.merge(padawan, config);
|
||||
|
||||
padawan.padawans = [];
|
||||
padawan.timers = [];
|
||||
padawan.master = this;
|
||||
Object.hide(padawan, "master","timers");
|
||||
this.padawans.push(padawan);
|
||||
return padawan;
|
||||
};
|
||||
actor.die = function(actor){
|
||||
|
||||
};
|
||||
actor.kill = function(actor){
|
||||
this.timers.forEach(t => t());
|
||||
this.timers = undefined;
|
||||
actor.timers = [];
|
||||
actor.kill = function(){
|
||||
this.timers.forEach(t => t.kill());
|
||||
this.master.remove(this);
|
||||
this.padawans.forEach(p => p.kill());
|
||||
this.__dead__ = true;
|
||||
};
|
||||
actor.toJSON = function() {
|
||||
if (this.__dead__) return undefined;
|
||||
return this;
|
||||
}
|
||||
actor.delay = function(fn, seconds) {
|
||||
var t = timer.delay(fn.bind(this), seconds, true);
|
||||
var t = Object.create(timer);
|
||||
t.remain = seconds;
|
||||
t.kill = () => {
|
||||
timer.kill.call(t);
|
||||
this.timers.remove(t);
|
||||
}
|
||||
t.fire = () => {
|
||||
if (this.__dead__) return;
|
||||
fn();
|
||||
t.kill();
|
||||
};
|
||||
Register.appupdate.register(t.update, t);
|
||||
this.timers.push(t);
|
||||
return function() { t.kill(); };
|
||||
};
|
||||
actor.clock = function(fn){};
|
||||
actor.master = undefined;
|
||||
|
||||
actor.padawans = [];
|
||||
|
||||
actor.remaster = function(to){
|
||||
this.master.padawans.remove(this);
|
||||
this.master = to;
|
||||
to.padawans.push(this);
|
||||
};
|
||||
|
||||
|
||||
var gameobject = {
|
||||
full_path() {
|
||||
|
@ -148,7 +169,7 @@ var gameobject = {
|
|||
set timescale(x) { cmd(168,this.body,x); },
|
||||
get timescale() { return cmd(169,this.body); },
|
||||
|
||||
set phys(x) { set_body(1, this.body, x); },
|
||||
set phys(x) { console.warn(`Setting phys to ${x}`); set_body(1, this.body, x); },
|
||||
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); },
|
||||
|
@ -490,6 +511,7 @@ var gameobject = {
|
|||
}
|
||||
|
||||
delete this.components;
|
||||
// q_body(8,this.body);
|
||||
|
||||
this.clear();
|
||||
|
||||
|
@ -748,26 +770,12 @@ prototypes.from_file = function(file)
|
|||
prototypes.list.push(urpath);
|
||||
newur.toString = function() { return urpath; };
|
||||
ur[urpath] = newur;
|
||||
// var urs = urpath.split('.');
|
||||
// var u = ur;
|
||||
// for (var i = 0; i < urs.length; i++)
|
||||
// u = u[urs[i]] = u[urs[i]] || newur;
|
||||
//Object.dig(ur, urpath, newur);
|
||||
|
||||
return newur;
|
||||
}
|
||||
prototypes.from_file.doc = "Create a new ur-type from a given script file.";
|
||||
prototypes.list = [];
|
||||
|
||||
prototypes.from_obj = function(name, obj)
|
||||
{
|
||||
var newur = Object.copy(gameobject, obj);
|
||||
prototypes.ur[name] = newur;
|
||||
prototypes.list.push(name);
|
||||
newur.toString = function() { return name; };
|
||||
return prototypes.ur[name];
|
||||
}
|
||||
|
||||
prototypes.list_ur = function()
|
||||
{
|
||||
var list = [];
|
||||
|
@ -844,44 +852,6 @@ prototypes.generate_ur = function(path)
|
|||
|
||||
var ur = prototypes.ur;
|
||||
|
||||
prototypes.from_obj("camera2d", {
|
||||
phys: Physics.kinematic,
|
||||
speed: 300,
|
||||
|
||||
get zoom() {
|
||||
var z = Game.native.y / Window.dimensions.y;
|
||||
return cmd(135) / z;
|
||||
},
|
||||
set zoom(x) {
|
||||
x = Math.clamp(x,0.1,10);
|
||||
var z = Game.native.y / Window.dimensions.y;
|
||||
z *= x;
|
||||
cmd(62, z);
|
||||
},
|
||||
|
||||
realzoom() {
|
||||
return cmd(135);
|
||||
},
|
||||
|
||||
speedmult: 1.0,
|
||||
|
||||
selectable: false,
|
||||
|
||||
dir_view2world(dir) {
|
||||
return dir.scale(this.realzoom());
|
||||
},
|
||||
|
||||
view2world(pos) {
|
||||
return cmd(137,pos);
|
||||
},
|
||||
|
||||
world2view(pos) {
|
||||
return cmd(136,pos);
|
||||
},
|
||||
});
|
||||
|
||||
prototypes.from_obj("arena", {});
|
||||
|
||||
prototypes.resavi = function(ur, path)
|
||||
{
|
||||
if (!ur) return path;
|
||||
|
|
|
@ -677,9 +677,9 @@ JSValue duk_cmd(JSContext *js, JSValueConst this, int argc, JSValueConst *argv)
|
|||
break;
|
||||
|
||||
case 36:
|
||||
id2go(js2int(argv[1]))->scale.XY = js2vec2(argv[2]);
|
||||
gameobject_apply(id2go(js2int(argv[1])));
|
||||
cpSpaceReindexShapesForBody(space, id2go(js2int(argv[1]))->body);
|
||||
js2go(argv[1])->scale.XY = js2vec2(argv[2]);
|
||||
gameobject_apply(js2go(argv[1]));
|
||||
cpSpaceReindexShapesForBody(space, js2go(argv[1])->body);
|
||||
break;
|
||||
|
||||
case 37:
|
||||
|
@ -700,21 +700,21 @@ JSValue duk_cmd(JSContext *js, JSValueConst this, int argc, JSValueConst *argv)
|
|||
break;
|
||||
|
||||
case 40:
|
||||
id2go(js2int(argv[1]))->filter.categories = js2bitmask(argv[2]);
|
||||
gameobject_apply(id2go(js2int(argv[1])));
|
||||
js2go(argv[1])->filter.categories = js2bitmask(argv[2]);
|
||||
gameobject_apply(js2go(argv[1]));
|
||||
break;
|
||||
|
||||
case 41:
|
||||
id2go(js2int(argv[1]))->filter.mask = js2bitmask(argv[2]);
|
||||
gameobject_apply(id2go(js2int(argv[1])));
|
||||
js2go(argv[1])->filter.mask = js2bitmask(argv[2]);
|
||||
gameobject_apply(js2go(argv[1]));
|
||||
break;
|
||||
|
||||
case 42:
|
||||
ret = bitmask2js(id2go(js2int(argv[1]))->filter.categories);
|
||||
ret = bitmask2js(js2go(argv[1])->filter.categories);
|
||||
break;
|
||||
|
||||
case 43:
|
||||
ret = bitmask2js(id2go(js2int(argv[1]))->filter.mask);
|
||||
ret = bitmask2js(js2go(argv[1])->filter.mask);
|
||||
break;
|
||||
|
||||
case 44:
|
||||
|
@ -1247,7 +1247,7 @@ JSValue duk_cmd(JSContext *js, JSValueConst this, int argc, JSValueConst *argv)
|
|||
js2dsp_node(argv[1])->gain = js2number(argv[2]);
|
||||
break;
|
||||
case 177:
|
||||
plugin_node(js2ptr(argv[1]), js2ptr(argv[2]));
|
||||
plugin_node(js2dsp_node(argv[1]), js2dsp_node(argv[2]));
|
||||
break;
|
||||
case 178:
|
||||
ret = num2js(js2dsp_node(argv[1])->pan);
|
||||
|
@ -1263,7 +1263,7 @@ JSValue duk_cmd(JSContext *js, JSValueConst this, int argc, JSValueConst *argv)
|
|||
break;
|
||||
case 182:
|
||||
str = js2str(argv[1]);
|
||||
ret = ptr2js(dsp_source(str));
|
||||
ret = dsp_node2js(dsp_source(str));
|
||||
((sound*)js2dsp_node(ret)->data)->hook = JS_DupValue(js,argv[2]);
|
||||
break;
|
||||
case 183:
|
||||
|
@ -1629,7 +1629,7 @@ 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(go2id(go));
|
||||
break;
|
||||
}
|
||||
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
struct timer {
|
||||
int timerid;
|
||||
int on;
|
||||
|
||||
double interval; // Time of timer
|
||||
int repeat;
|
||||
double remain_time; // How much time until the timer executes
|
||||
|
|
|
@ -162,6 +162,7 @@ int frame_fps() {
|
|||
static void process_frame()
|
||||
{
|
||||
double elapsed = stm_sec(stm_laptime(&frame_t));
|
||||
script_evalf("Register.appupdate.broadcast(%g);", elapsed);
|
||||
call_stack();
|
||||
// ds_advance(bjork, elapsed);
|
||||
input_poll(0);
|
||||
|
|
Loading…
Reference in a new issue