Tween and delay fixes now entity lifetime; spline symmetry
This commit is contained in:
parent
e712d06244
commit
cccd472f12
2
Makefile
2
Makefile
|
@ -198,7 +198,7 @@ input.md: $(INPUTMD)
|
|||
|
||||
$(BIN)/libquickjs.a:
|
||||
make -C quickjs clean
|
||||
make -C quickjs SYSRT=$(SYSRT) TTARGET=$(TTARGET) ARCH=$(ARCH) DBG=$(DBG) OPT=$(OPT) HOST_CC=$(CC) AR=$(AR) libquickjs.a libquickjs.lto.a CC=$(CC)
|
||||
make -C quickjs SYSRT=$(SYSRT) TTARGET=$(TTARGET) ARCH=$(ARCH) DBG=$(DBG) OPT=$(OPT) HOST_CC=$(CC) CCC=$(CC) AR=$(AR) libquickjs.a libquickjs.lto.a CC=$(CC)
|
||||
@mkdir -p $(BIN)
|
||||
cp -rf quickjs/libquickjs.* $(BIN)
|
||||
|
||||
|
|
|
@ -22,9 +22,6 @@
|
|||
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
# THE SOFTWARE.
|
||||
|
||||
ifeq ($(shell uname -s),Darwin)
|
||||
CONFIG_DARWIN=y
|
||||
endif
|
||||
# Windows cross compilation from Linux
|
||||
#CONFIG_WIN32=y
|
||||
# use link time optimization (smaller and faster executables but slower build)
|
||||
|
@ -34,12 +31,13 @@ CONFIG_LTO=y
|
|||
# force 32 bit build for some utilities
|
||||
#CONFIG_M32=y
|
||||
|
||||
ifdef CONFIG_DARWIN
|
||||
# use clang instead of gcc
|
||||
CONFIG_CLANG=y
|
||||
CONFIG_DEFAULT_AR=y
|
||||
ifeq ($(CCC),clang)
|
||||
CONFIG_CLANG=y
|
||||
CONFIG_DEFAULT_AR=y
|
||||
endif
|
||||
|
||||
|
||||
# installation directory
|
||||
prefix=/usr/local
|
||||
|
||||
|
@ -63,10 +61,9 @@ else
|
|||
CROSS_PREFIX=
|
||||
EXE=
|
||||
endif
|
||||
ifdef CONFIG_CLANG
|
||||
HOST_CC=clang
|
||||
ifeq ($(CCC), clang)
|
||||
CC=$(CROSS_PREFIX)clang
|
||||
CFLAGS=-g -Wall -MMD -MF $(OBJDIR)/$(@F).d
|
||||
CFLAGS += -g -Wall -MMD -MF $(OBJDIR)/$(@F).d
|
||||
CFLAGS += -Wextra
|
||||
CFLAGS += -Wno-sign-compare
|
||||
CFLAGS += -Wno-missing-field-initializers
|
||||
|
@ -91,9 +88,8 @@ endif
|
|||
endif
|
||||
endif
|
||||
else
|
||||
HOST_CC=gcc
|
||||
CC=$(CROSS_PREFIX)gcc
|
||||
CFLAGS=-g -Wall -MMD -MF $(OBJDIR)/$(@F).d
|
||||
CFLAGS += -g -Wall -MMD -MF $(OBJDIR)/$(@F).d
|
||||
CFLAGS += -Wno-array-bounds -Wno-format-truncation
|
||||
CFLAGS += -Wno-unused-function -Wno-unused-const-variable
|
||||
ifdef CONFIG_LTO
|
||||
|
|
|
@ -485,6 +485,19 @@ Object.defineProperty(String.prototype, 'dir', {
|
|||
value: function() { return this.tolast('/'); }
|
||||
});
|
||||
|
||||
Object.defineProperty(String.prototype, 'splice', {
|
||||
value: function(index, str, ) {
|
||||
return this.slice(0,index) + str + this.slice(index);
|
||||
}
|
||||
});
|
||||
|
||||
Object.defineProperty(String.prototype, 'rm', {
|
||||
value: function(index, endidx) {
|
||||
endidx ??= index+1;
|
||||
return this.slice(0,index) + this.slice(endidx);
|
||||
}
|
||||
});
|
||||
|
||||
Object.defineProperty(String.prototype, 'updir', {
|
||||
value: function() {
|
||||
if (this.lastIndexOf('/') === this.length-1)
|
||||
|
|
|
@ -415,7 +415,8 @@ Geometry.doc = {
|
|||
doc: "Functions for creating a list of points for various geometric shapes.",
|
||||
box: "Create a box.",
|
||||
arc: "Create an arc, made of n points.",
|
||||
circle: "Create a circle, made of n points."
|
||||
circle: "Create a circle, made of n points.",
|
||||
ngon: "Create a polygon of n sides.",
|
||||
};
|
||||
|
||||
/* For all colliders, "shape" is a pointer to a phys2d_shape, "id" is a pointer to the shape data */
|
||||
|
@ -532,12 +533,12 @@ polygon2d.inputs['C-lm'].doc = "Add a point to location of mouse.";
|
|||
polygon2d.inputs.lm = function(){};
|
||||
polygon2d.inputs.lm.released = function(){};
|
||||
|
||||
polygon2d.inputs['S-lm'] = function() {
|
||||
polygon2d.inputs['C-M-lm'] = function() {
|
||||
var idx = grab_from_points(Mouse.worldpos, this.points.map(p => this.gameobject.this2world(p)), 25);
|
||||
if (idx === -1) return;
|
||||
this.points.splice(idx, 1);
|
||||
};
|
||||
polygon2d.inputs['S-lm'].doc = "Remove point under mouse.";
|
||||
polygon2d.inputs['C-M-lm'].doc = "Remove point under mouse.";
|
||||
|
||||
polygon2d.inputs['C-b'] = function() {
|
||||
this.points = this.spoints;
|
||||
|
@ -637,7 +638,7 @@ component.edge2d = Object.copy(collider2d, {
|
|||
return Spline.sample(degrees, this.dimensions, this.type, spoints, n);
|
||||
},
|
||||
|
||||
samples: 10,
|
||||
samples: 1,
|
||||
|
||||
boundingbox() {
|
||||
return points2bb(this.points.map(x => x.scale(this.gameobject.scale)));
|
||||
|
@ -678,7 +679,9 @@ component.edge2d = Object.copy(collider2d, {
|
|||
},
|
||||
|
||||
sample_calc() {
|
||||
return (this.spoints().length-1);
|
||||
var n = this.spoints().length-1;
|
||||
if (this.looped) n++;
|
||||
return n;
|
||||
},
|
||||
|
||||
samples_per_cp() {
|
||||
|
@ -781,14 +784,17 @@ bucket.inputs['C-lm'] = function() {
|
|||
};
|
||||
bucket.inputs['C-lm'].doc = "Add a point to the spline at the mouse position.";
|
||||
|
||||
bucket.inputs['S-lm'] = function() {
|
||||
bucket.inputs['C-M-lm'] = function() {
|
||||
var idx = grab_from_points(Mouse.worldpos, this.cpoints.map(p => this.gameobject.this2world(p)), 25);
|
||||
|
||||
if (idx < 0 || idx > this.cpoints.length) return;
|
||||
|
||||
this.cpoints.splice(idx, 1);
|
||||
};
|
||||
bucket.inputs['S-lm'].doc = "Remove point from the spline.";
|
||||
bucket.inputs['C-M-lm'].doc = "Remove point from the spline.";
|
||||
|
||||
bucket.inputs.lm = function(){};
|
||||
bucket.inputs.lm.released = function(){};
|
||||
|
||||
bucket.inputs.lb = function() {
|
||||
var np = [];
|
||||
|
|
|
@ -895,9 +895,7 @@ editor.inputs['C-s'] = function() {
|
|||
var savejs = saveobj.json_obj();
|
||||
Object.merge(saveobj.__proto__, savejs);
|
||||
if (savejs.objects) saveobj.__proto__.objects = savejs.objects;
|
||||
var path = saveobj.ur.toString();
|
||||
path = path.replaceAll('.','/');
|
||||
path = path + "/" + path.name() + ".json";
|
||||
var path = prototypes.ur_stem(saveobj.ur.toString()) + ".json";
|
||||
|
||||
IO.slurpwrite(JSON.stringify(saveobj.__proto__,null,1), path);
|
||||
Log.warn(`Wrote to file ${path}`);
|
||||
|
|
|
@ -42,11 +42,32 @@ var gameobject = {
|
|||
this.objects = {};
|
||||
},
|
||||
|
||||
timers:[],
|
||||
delay(fn, seconds) {
|
||||
var t = timer.oneshot(fn.bind(this), seconds, this, false);
|
||||
var t = timer.delay(fn.bind(this), seconds, false);
|
||||
this.timers.push(t);
|
||||
return function() { t.kill(); };
|
||||
return t;
|
||||
},
|
||||
|
||||
tween(prop, values, def){
|
||||
var t = Tween.make(this, prop, values, def);
|
||||
t.play();
|
||||
|
||||
var k = function() { t.pause(); }
|
||||
this.timers.push(k);
|
||||
return k;
|
||||
},
|
||||
|
||||
cry(file) {
|
||||
Sound.play(file);
|
||||
return;
|
||||
|
||||
if (this.curcry && !Sound.finished(this.curcry)) return;
|
||||
this.curcry = Sound.play(file);
|
||||
var r = this.curcry;
|
||||
Log.warn(r);
|
||||
var fn = function() { Log.warn(r); if (r) Sound.stop(r); };
|
||||
this.timers.push(fn);
|
||||
return fn;
|
||||
},
|
||||
|
||||
set max_velocity(x) { cmd(151, this.body, x); },
|
||||
|
@ -451,10 +472,7 @@ var gameobject = {
|
|||
q_body(8,this.body);
|
||||
Game.unregister_obj(this);
|
||||
|
||||
this.timers.forEach(function(t) {
|
||||
if (!t) return;
|
||||
t.kill();
|
||||
});
|
||||
this.timers.forEach(t => t());
|
||||
|
||||
if (this.level) {
|
||||
this.level.remove_obj(this);
|
||||
|
@ -503,6 +521,7 @@ var gameobject = {
|
|||
obj.body = make_gameobject();
|
||||
obj.components = {};
|
||||
obj.objects = {};
|
||||
obj.timers = [];
|
||||
assign_impl(obj, gameobject.impl);
|
||||
obj._ed = {
|
||||
selectable: true,
|
||||
|
@ -656,6 +675,7 @@ gameobject.doc = {
|
|||
kill: `Remove this object from the world.`,
|
||||
level: "The entity this entity belongs to.",
|
||||
delay: 'Run the given function after the given number of seconds has elapsed.',
|
||||
cry: 'Make a sound. Can only make one at a time.',
|
||||
};
|
||||
|
||||
/* Default objects */
|
||||
|
@ -895,3 +915,56 @@ prototypes.resani = function(ur, path)
|
|||
}
|
||||
return restry;
|
||||
}
|
||||
|
||||
prototypes.ur_dir = function(ur)
|
||||
{
|
||||
var path = ur.replaceAll('.', '/');
|
||||
Log.warn(path);
|
||||
Log.warn(IO.exists(path));
|
||||
Log.warn(`${path} does not exist; sending ${path.dir()}`);
|
||||
}
|
||||
|
||||
prototypes.ur_json = function(ur)
|
||||
{
|
||||
var path = ur.replaceAll('.', '/');
|
||||
if (IO.exists(path))
|
||||
path = path + "/" + path.name() + ".json";
|
||||
else
|
||||
path = path + ".json";
|
||||
|
||||
return path;
|
||||
}
|
||||
|
||||
prototypes.ur_stem = function(ur)
|
||||
{
|
||||
var path = ur.replaceAll('.', '/');
|
||||
if (IO.exists(path))
|
||||
return path + "/" + path.name();
|
||||
else
|
||||
return path;
|
||||
}
|
||||
|
||||
prototypes.ur_file_exts = ['.jso', '.json'];
|
||||
|
||||
prototypes.ur_folder = function(ur)
|
||||
{
|
||||
var path = ur.replaceAll('.', '/');
|
||||
return IO.exists(path);
|
||||
}
|
||||
|
||||
prototypes.ur_pullout_folder = function(ur)
|
||||
{
|
||||
if (!prototypes.ur_folder(ur)) return;
|
||||
|
||||
var stem = prototypes.ur_stem(ur);
|
||||
|
||||
/* prototypes.ur_file_exts.forEach(function(e) {
|
||||
var p = stem + e;
|
||||
if (IO.exists(p))
|
||||
*/
|
||||
}
|
||||
|
||||
prototypes.ur_pushin_folder = function(ur)
|
||||
{
|
||||
|
||||
}
|
||||
|
|
|
@ -391,10 +391,19 @@ Ease.elastic.c5 = 2*Math.PI / 4.5;
|
|||
|
||||
var Tween = {
|
||||
default: {
|
||||
loop: "restart", /* none, restart, yoyo, circle */
|
||||
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,
|
||||
whole: true, /* True if time is for the entire tween, false if each stage */
|
||||
cb: function(){},
|
||||
},
|
||||
|
||||
start(obj, target, tvals, options)
|
||||
|
@ -416,6 +425,13 @@ var Tween = {
|
|||
|
||||
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();
|
||||
|
@ -445,8 +461,9 @@ var Tween = {
|
|||
};
|
||||
defn.stop = function() { if (!playing) return; defn.pause(); defn.restart(); };
|
||||
defn.pause = function() {
|
||||
Register.update.unregister(defn.fn);
|
||||
if (!playing) return;
|
||||
Register.update.unregister(defn.fn);
|
||||
|
||||
playing = false;
|
||||
};
|
||||
|
||||
|
|
|
@ -27,7 +27,16 @@ var Sound = {
|
|||
Log.error(`Cannot play sound ${file}: does not exist.`);
|
||||
return;
|
||||
}
|
||||
this.id = cmd(14,file);
|
||||
var p = cmd(14,file);
|
||||
return p;
|
||||
},
|
||||
|
||||
finished(sound) {
|
||||
return cmd(165, sound);
|
||||
},
|
||||
|
||||
stop(sound) {
|
||||
cmd(164, sound);
|
||||
},
|
||||
|
||||
music(midi, sf) {
|
||||
|
|
|
@ -101,6 +101,15 @@ Log.doc = {
|
|||
clear: "Clear console."
|
||||
};
|
||||
|
||||
/*
|
||||
IO path rules. Starts with, meaning:
|
||||
"@": playerpath
|
||||
"/": game room
|
||||
"#": Force look locally (instead of in db first)
|
||||
- This is combined with others. #/, #@, etc
|
||||
"": Local path relative to script defined in
|
||||
*/
|
||||
|
||||
var IO = {
|
||||
exists(file) { return cmd(65, file);},
|
||||
slurp(file) {
|
||||
|
@ -116,6 +125,16 @@ var IO = {
|
|||
return paths;
|
||||
},
|
||||
ls() { return cmd(66); },
|
||||
/* Only works on text files currently */
|
||||
cp(f1, f2) {
|
||||
cmd(166, f1, f2);
|
||||
},
|
||||
mv(f1, f2) {
|
||||
return cmd(163, f1, f2);
|
||||
},
|
||||
rm(f) {
|
||||
return cmd(f);
|
||||
},
|
||||
glob(pat) {
|
||||
var paths = IO.ls();
|
||||
pat = pat.replaceAll(/([\[\]\(\)\^\$\.\|\+])/g, "\\$1");
|
||||
|
@ -137,6 +156,25 @@ IO.doc = {
|
|||
glob: "Glob files in game directory.",
|
||||
};
|
||||
|
||||
var Parser = {};
|
||||
Parser.replstrs = function(path)
|
||||
{
|
||||
var script = IO.slurp(path);
|
||||
var regexp = /"[^"\s]*?\.[^"\s]+?"/g;
|
||||
var stem = path.dir();
|
||||
|
||||
script = script.replace(regexp,function(str) {
|
||||
if (str[1] === "/")
|
||||
return str.rm(1);
|
||||
|
||||
if (str[1] === "@")
|
||||
return str.rm(1).splice(1, "playerpath/");
|
||||
|
||||
return str.splice(1, stem + "/");
|
||||
});
|
||||
Log.warn(script);
|
||||
}
|
||||
|
||||
var Cmdline = {};
|
||||
|
||||
Cmdline.cmds = [];
|
||||
|
|
|
@ -546,7 +546,7 @@ JSValue duk_cmd(JSContext *js, JSValueConst this, int argc, JSValueConst *argv)
|
|||
|
||||
case 14:
|
||||
str = JS_ToCString(js, argv[1]);
|
||||
play_oneshot(make_sound(str));
|
||||
ret = ptr2js(play_sound(make_sound(str)));
|
||||
break;
|
||||
|
||||
case 15:
|
||||
|
@ -1152,6 +1152,26 @@ JSValue duk_cmd(JSContext *js, JSValueConst this, int argc, JSValueConst *argv)
|
|||
case 161:
|
||||
ret = vec2js(mat_t_dir(t_go2world(js2go(argv[1])), js2vec2(argv[2])));
|
||||
break;
|
||||
case 162:
|
||||
str = JS_ToCString(js, argv[1]);
|
||||
ret = int2js(remove(str));
|
||||
break;
|
||||
case 163:
|
||||
str = JS_ToCString(js,argv[1]);
|
||||
str2 = JS_ToCString(js,argv[2]);
|
||||
ret = int2js(rename(str, str2));
|
||||
break;
|
||||
case 164:
|
||||
sound_stop(js2ptr(argv[1]));
|
||||
break;
|
||||
case 165:
|
||||
ret = bool2js(sound_paused(js2ptr(argv[1])));
|
||||
break;
|
||||
case 166:
|
||||
str = js2str(argv[1]);
|
||||
str2 = js2str(argv[2]);
|
||||
ret = int2js(cp(str, str2));
|
||||
break;
|
||||
}
|
||||
|
||||
if (str)
|
||||
|
|
|
@ -247,6 +247,19 @@ char *slurp_text(const char *filename, size_t *size)
|
|||
return retstr;
|
||||
}
|
||||
|
||||
int cp(char *p1, char *p2)
|
||||
{
|
||||
long len;
|
||||
void *data = slurp_file(p1, &len);
|
||||
|
||||
FILE *f = fopen_mkdir(p2, "w");
|
||||
if (!f) return 1;
|
||||
fwrite(data, len, 1, f);
|
||||
free(data);
|
||||
fclose(f);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void rek_mkdir(char *path) {
|
||||
char *sep = strrchr(path, '/');
|
||||
if(sep != NULL) {
|
||||
|
|
|
@ -14,7 +14,9 @@ FILE *res_open(char *path, const char *tag);
|
|||
FILE *path_open(const char *tag, const char *fmt, ...);
|
||||
char *make_path(const char *file);
|
||||
char **ls(char *path);
|
||||
int cp(char *p1, char *p2);
|
||||
int fexists(char *path);
|
||||
FILE *fopen_mkdir(char *path, char *mode);
|
||||
|
||||
void *slurp_file(const char *filename, size_t *size);
|
||||
char *slurp_text(const char *filename, size_t *size);
|
||||
|
|
|
@ -233,42 +233,43 @@ void play_oneshot(struct wav *wav) {
|
|||
struct sound *play_sound(struct wav *wav) {
|
||||
struct sound *new = calloc(1, sizeof(*new));
|
||||
new->data = wav;
|
||||
|
||||
new->bus = first_free_bus(dsp_filter(new, sound_fillbuf));
|
||||
new->playing = 1;
|
||||
|
||||
new->loop = 0;
|
||||
new->frame = 0;
|
||||
new->endcb = kill_oneshot;
|
||||
return new;
|
||||
}
|
||||
|
||||
int sound_playing(const struct sound *s) {
|
||||
return s->playing;
|
||||
return !sound_paused(s);
|
||||
}
|
||||
|
||||
int sound_paused(const struct sound *s) {
|
||||
return (!s->playing && s->frame < s->data->frames);
|
||||
return s->bus == NULL;
|
||||
}
|
||||
void sound_pause(struct sound *s) {
|
||||
s->playing = 0;
|
||||
if (s->bus == NULL) return;
|
||||
bus_free(s->bus);
|
||||
s->bus = NULL;
|
||||
}
|
||||
|
||||
void sound_resume(struct sound *s) {
|
||||
s->playing = 1;
|
||||
if (s->bus != NULL) return;
|
||||
s->bus = first_free_bus(dsp_filter(s, sound_fillbuf));
|
||||
}
|
||||
|
||||
void sound_stop(struct sound *s) {
|
||||
s->playing = 0;
|
||||
sound_pause(s);
|
||||
s->frame = 0;
|
||||
bus_free(s->bus);
|
||||
}
|
||||
|
||||
int sound_finished(const struct sound *s) {
|
||||
return !s->playing && s->frame == s->data->frames;
|
||||
return s->frame == s->data->frames;
|
||||
}
|
||||
|
||||
int sound_stopped(const struct sound *s) {
|
||||
return !s->playing && s->frame == 0;
|
||||
return s->bus == NULL;
|
||||
}
|
||||
|
||||
struct mp3 make_music(const char *mp3) {
|
||||
|
@ -298,8 +299,7 @@ void sound_fillbuf(struct sound *s, soundbyte *buf, int n) {
|
|||
s->frame++;
|
||||
|
||||
if (s->frame == s->data->frames) {
|
||||
bus_free(s->bus);
|
||||
s->bus = NULL;
|
||||
sound_stop(s);
|
||||
s->endcb(s);
|
||||
return;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue