104 lines
2.8 KiB
Plaintext
104 lines
2.8 KiB
Plaintext
/* anim.js – drop this at top of your script or in a module */
|
||
var Anim = (() => {
|
||
def DEFAULT_MIN = 1 / 60; /* 16 ms – one frame */
|
||
|
||
function play(source, loop=true){
|
||
return {
|
||
src : source,
|
||
idx : 0,
|
||
timer : 0,
|
||
loop : loop ?? source.loop ?? true
|
||
};
|
||
}
|
||
|
||
function update(a, dt){
|
||
a.timer += dt;
|
||
def frames = a.src.frames;
|
||
while(true){
|
||
def time = max(frames[a.idx].time || 0, Anim.minDelay);
|
||
if(a.timer < time) break; /* still on current frame */
|
||
|
||
a.timer -= time;
|
||
a.idx += 1;
|
||
|
||
if(a.idx >= length(frames)){
|
||
if(a.loop) a.idx = 0;
|
||
else { a.idx = length(frames) - 1; a.timer = 0; break; }
|
||
}
|
||
}
|
||
}
|
||
|
||
function current(a){ return a.src.frames[a.idx].image; }
|
||
function updateAll(arr, dt){ arrfor(arr, function(a){ update(a, dt); }) }
|
||
function draw(a, pos, opt, pipe){
|
||
draw2d.image(current(a), pos, 0, [0,0], [0,0], opt, pipe);
|
||
}
|
||
|
||
return {play, update, current, updateAll, draw, minDelay:DEFAULT_MIN};
|
||
})();
|
||
|
||
var render = use('render');
|
||
/* ── init window ───────────────────────── */
|
||
render.initialize({width:500, height:500, resolution_x:500, resolution_y:500,
|
||
mode:'letterboxed', refresh:60});
|
||
|
||
var os = use('os');
|
||
var draw2d = use('draw2d');
|
||
var gfx = use('graphics');
|
||
var transform = use('transform');
|
||
|
||
var camera = {
|
||
size: [500,500],
|
||
fov:50,
|
||
near_z: 0,
|
||
far_z: 1000,
|
||
surface: null,
|
||
viewport: {x:0,y:0,width:1,height:1},
|
||
ortho:true,
|
||
anchor:[0,0],
|
||
}
|
||
|
||
/* ── load animations ───────────────────── */
|
||
def crab = gfx.texture('tests/crab'); // gif → Animation
|
||
def warrior = gfx.texture('tests/warrior'); // ase → {Original:Animation}
|
||
|
||
def anims = [
|
||
Anim.play(crab), // crab.frames
|
||
Anim.play(warrior.Run) // warrior.Original.frames
|
||
];
|
||
|
||
/* ── fps probe vars ───────────────────── */
|
||
var fpsTimer=0, fpsCount=0
|
||
|
||
Anim.minDelay = 1 / 100; // 10 ms, feel free to tune later
|
||
|
||
var last = os.now();
|
||
|
||
function loop(){
|
||
def now = os.now();
|
||
def dt = now - last; // real frame time
|
||
last = now;
|
||
|
||
Anim.updateAll(anims, dt);
|
||
|
||
/* draw */
|
||
render.clear([22/255,120/255,194/255,255/255]);
|
||
render.camera(camera);
|
||
Anim.draw(anims[0], [ 50,200]);
|
||
Anim.draw(anims[1], [250,200]);
|
||
render.present();
|
||
|
||
/* fps probe (unchanged) */
|
||
fpsTimer += dt; fpsCount++;
|
||
if(fpsTimer >= 0.5){
|
||
prosperon.window.title =
|
||
`Anim demo FPS ${(fpsCount/fpsTimer).toFixed(1)}`;
|
||
fpsTimer = fpsCount = 0;
|
||
}
|
||
|
||
/* schedule next tick: aim for 60 Hz but won’t matter to anim speed */
|
||
$delay(loop, max(0, (1/60) - (os.now()-now)));
|
||
}
|
||
loop();
|
||
|