litecanvas 0.81.2 → 0.82.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/dist.dev.js CHANGED
@@ -44,7 +44,6 @@
44
44
  canvas: null,
45
45
  global: true,
46
46
  loop: null,
47
- pauseOnBlur: true,
48
47
  tapEvents: true,
49
48
  keyboardEvents: true,
50
49
  animate: true
@@ -982,6 +981,7 @@
982
981
  */
983
982
  quit() {
984
983
  cancelAnimationFrame(_rafid);
984
+ _rafid = 0;
985
985
  instance.emit("quit");
986
986
  for (const removeListener of _browserEventListeners) {
987
987
  removeListener();
@@ -1196,17 +1196,6 @@
1196
1196
  }
1197
1197
  );
1198
1198
  }
1199
- if (settings.pauseOnBlur) {
1200
- on(root, "blur", () => {
1201
- _rafid = cancelAnimationFrame(_rafid);
1202
- });
1203
- on(root, "focus", () => {
1204
- if (!_rafid) {
1205
- _accumulated = 0;
1206
- _rafid = raf(drawFrame);
1207
- }
1208
- });
1209
- }
1210
1199
  _initialized = true;
1211
1200
  instance.emit("init", instance);
1212
1201
  _lastFrameTime = performance.now();
@@ -1216,17 +1205,18 @@
1216
1205
  let updated = 0, frameTime = (now - _lastFrameTime) / 1e3;
1217
1206
  _lastFrameTime = now;
1218
1207
  if (settings.animate) {
1219
- _rafid = raf(drawFrame);
1220
1208
  if (frameTime > 0.3) {
1221
- return console.warn("skipping too long frame");
1222
- }
1223
- _accumulated += frameTime;
1224
- while (_accumulated >= _deltaTime) {
1225
- instance.emit("update", _deltaTime * _timeScale);
1226
- instance.def("T", instance.T + _deltaTime * _timeScale);
1227
- updated++;
1228
- _accumulated -= _deltaTime;
1209
+ console.warn("skipping too long frame");
1210
+ } else {
1211
+ _accumulated += frameTime;
1212
+ while (_accumulated >= _deltaTime) {
1213
+ updated++;
1214
+ instance.emit("update", _deltaTime * _timeScale, updated);
1215
+ instance.def("T", instance.T + _deltaTime * _timeScale);
1216
+ _accumulated -= _deltaTime;
1217
+ }
1229
1218
  }
1219
+ if (_rafid) _rafid = raf(drawFrame);
1230
1220
  } else {
1231
1221
  updated = 1;
1232
1222
  }
@@ -1236,11 +1226,14 @@
1236
1226
  }
1237
1227
  }
1238
1228
  function setupCanvas() {
1239
- if ("string" === typeof settings.canvas) {
1229
+ if (settings.canvas) {
1230
+ DEV: assert(
1231
+ "string" === typeof settings.canvas,
1232
+ `Litecanvas' option "canvas" should be a string (a selector)`
1233
+ );
1240
1234
  _canvas = document.querySelector(settings.canvas);
1241
- } else {
1242
- _canvas = settings.canvas || document.createElement("canvas");
1243
1235
  }
1236
+ _canvas = _canvas || document.createElement("canvas");
1244
1237
  DEV: assert(
1245
1238
  _canvas && _canvas.tagName === "CANVAS",
1246
1239
  "Invalid canvas element"
package/dist/dist.js CHANGED
@@ -39,7 +39,6 @@
39
39
  canvas: null,
40
40
  global: true,
41
41
  loop: null,
42
- pauseOnBlur: true,
43
42
  tapEvents: true,
44
43
  keyboardEvents: true,
45
44
  animate: true
@@ -709,6 +708,7 @@
709
708
  */
710
709
  quit() {
711
710
  cancelAnimationFrame(_rafid);
711
+ _rafid = 0;
712
712
  instance.emit("quit");
713
713
  for (const removeListener of _browserEventListeners) {
714
714
  removeListener();
@@ -915,17 +915,6 @@
915
915
  }
916
916
  );
917
917
  }
918
- if (settings.pauseOnBlur) {
919
- on(root, "blur", () => {
920
- _rafid = cancelAnimationFrame(_rafid);
921
- });
922
- on(root, "focus", () => {
923
- if (!_rafid) {
924
- _accumulated = 0;
925
- _rafid = raf(drawFrame);
926
- }
927
- });
928
- }
929
918
  _initialized = true;
930
919
  instance.emit("init", instance);
931
920
  _lastFrameTime = performance.now();
@@ -935,17 +924,17 @@
935
924
  let updated = 0, frameTime = (now - _lastFrameTime) / 1e3;
936
925
  _lastFrameTime = now;
937
926
  if (settings.animate) {
938
- _rafid = raf(drawFrame);
939
927
  if (frameTime > 0.3) {
940
- return void 0;
941
- }
942
- _accumulated += frameTime;
943
- while (_accumulated >= _deltaTime) {
944
- instance.emit("update", _deltaTime * _timeScale);
945
- instance.def("T", instance.T + _deltaTime * _timeScale);
946
- updated++;
947
- _accumulated -= _deltaTime;
928
+ } else {
929
+ _accumulated += frameTime;
930
+ while (_accumulated >= _deltaTime) {
931
+ updated++;
932
+ instance.emit("update", _deltaTime * _timeScale, updated);
933
+ instance.def("T", instance.T + _deltaTime * _timeScale);
934
+ _accumulated -= _deltaTime;
935
+ }
948
936
  }
937
+ if (_rafid) _rafid = raf(drawFrame);
949
938
  } else {
950
939
  updated = 1;
951
940
  }
@@ -955,11 +944,10 @@
955
944
  }
956
945
  }
957
946
  function setupCanvas() {
958
- if ("string" === typeof settings.canvas) {
947
+ if (settings.canvas) {
959
948
  _canvas = document.querySelector(settings.canvas);
960
- } else {
961
- _canvas = settings.canvas || document.createElement("canvas");
962
949
  }
950
+ _canvas = _canvas || document.createElement("canvas");
963
951
  instance.def("CANVAS", _canvas);
964
952
  _ctx = _canvas.getContext("2d");
965
953
  on(_canvas, "click", () => root.focus());
package/dist/dist.min.js CHANGED
@@ -1 +1 @@
1
- (()=>{var e=new AudioContext,t=(t=1,a=.05,l=220,n=0,i=0,r=.1,o=0,s=1,f=0,c=0,d=0,u=0,p=0,h=0,g=0,m=0,b=0,v=1,w=0,x=0,y=0)=>{let k=Math,E=2*k.PI,T=f*=500*E/44100/44100,A=l*=(1-a+2*a*k.random(a=[]))*E/44100,C=0,z=0,I=0,P=1,S=0,X=0,Y=0,M=y<0?-1:1,N=E*M*y*2/44100,H=k.cos(N),W=k.sin,B=W(N)/4,D=1+B,F=-2*H/D,L=(1-B)/D,O=(1+M*H)/2/D,V=-(M+H)/D,q=0,R=0,G=0,$=0;for(n=44100*n+9,w*=44100,i*=44100,r*=44100,b*=44100,c*=500*E/85766121e6,g*=E/44100,d*=E/44100,u*=44100,p=44100*p|0,t*=.3*(globalThis.zzfxV||1),M=n+w+i+r+b|0;I<M;a[I++]=Y*t)++X%(100*m|0)||(Y=o?1<o?2<o?3<o?W(C*C):k.max(k.min(k.tan(C),1),-1):1-(2*C/E%2+2)%2:1-4*k.abs(k.round(C/E)-C/E):W(C),Y=(p?1-x+x*W(E*I/p):1)*(Y<0?-1:1)*k.abs(Y)**s*(I<n?I/n:I<n+w?1-(I-n)/w*(1-v):I<n+w+i?v:I<M-b?(M-I-b)/r*v:0),Y=b?Y/2+(b>I?0:(I<M-b?1:(M-I)/b)*a[I-b|0]/2/t):Y,y&&(Y=$=O*q+V*(q=R)+O*(R=Y)-L*G-F*(G=$))),C+=(N=(l+=f+=c)*k.cos(g*z++))+N*h*W(I**5),P&&++P>u&&(l+=d,A+=d,P=0),!p||++S%p||(l=A,f=T,P=P||1);(t=e.createBuffer(1,M,44100)).getChannelData(0).set(a),(l=e.createBufferSource()).buffer=t,l.connect(e.destination),l.start()},a=["#111","#6a7799","#aec2c2","#FFF1E8","#e83b3b","#fabc20","#155fd9","#3cbcfc","#327345","#63c64d","#6c2c1f","#ac7c00"];globalThis.litecanvas=function(e={}){let l=globalThis,n=Math,i=2*n.PI,r=requestAnimationFrame,o=[],s=(e,t,a)=>{e.addEventListener(t,a,!1),o.push(()=>e.removeEventListener(t,a,!1))};e=Object.assign({width:null,height:null,autoscale:!0,pixelart:!1,antialias:!1,canvas:null,global:!0,loop:null,pauseOnBlur:!0,tapEvents:!0,keyboardEvents:!0,animate:!0},e);let f=!1,c=[],d,u=1,p,h=.5,g=1,m,b=1/60,v=0,w,x="sans-serif",y=20,k=Date.now(),E=a,T=[.5,0,1750,,,.3,1,,,,600,.1],A={init:null,update:null,draw:null,resized:null,tap:null,untap:null,tapping:null,tapped:null},C={CANVAS:null,W:0,H:0,T:0,CX:0,CY:0,MX:-1,MY:-1,TWO_PI:i,HALF_PI:n.PI/2,lerp:(e,t,a)=>a*(t-e)+e,deg2rad:e=>n.PI/180*e,rad2deg:e=>180/n.PI*e,round:(e,t=0)=>{if(!t)return n.round(e);let a=10**t;return n.round(e*a)/a},clamp:(e,t,a)=>e<t?t:e>a?a:e,wrap:(e,t,a)=>e-(a-t)*n.floor((e-t)/(a-t)),map(e,t,a,l,n,i){let r=(e-t)/(a-t)*(n-l)+l;return i?C.clamp(r,l,n):r},norm:(e,t,a)=>C.map(e,t,a,0,1),wave:(e,t,a,l=Math.sin)=>e+(l(a)+1)/2*(t-e),rand:(e=0,t=1)=>(k=(1664525*k+0x3c6ef35f)%0x100000000)/0x100000000*(t-e)+e,randi:(e=0,t=1)=>n.floor(C.rand(e,t+1)),rseed(e){k=~~e},cls(e){null==e?p.clearRect(0,0,p.canvas.width,p.canvas.height):C.rectfill(0,0,p.canvas.width,p.canvas.height,e)},rect(e,t,a,l,n,i){p.beginPath(),p[i?"roundRect":"rect"](~~e-h,~~t-h,~~a+2*h,~~l+2*h,i),C.stroke(n)},rectfill(e,t,a,l,n,i){p.beginPath(),p[i?"roundRect":"rect"](~~e,~~t,~~a,~~l,i),C.fill(n)},circ(e,t,a,l){p.beginPath(),p.arc(~~e,~~t,~~a,0,i),C.stroke(l)},circfill(e,t,a,l){p.beginPath(),p.arc(~~e,~~t,~~a,0,i),C.fill(l)},line(e,t,a,l,n){p.beginPath();let i=.5*(0!==h&&~~e==~~a),r=.5*(0!==h&&~~t==~~l);p.moveTo(~~e+i,~~t+r),p.lineTo(~~a+i,~~l+r),C.stroke(n)},linewidth(e){p.lineWidth=~~e,h=.5*(0!=~~e%2)},linedash(e,t=0){p.setLineDash(e),p.lineDashOffset=t},text(e,t,a,l=3,n="normal"){p.font=`${n} ${y}px ${x}`,p.fillStyle=E[~~l%E.length],p.fillText(a,~~e,~~t)},textfont(e){x=e},textsize(e){y=e},textalign(e,t){e&&(p.textAlign=e),t&&(p.textBaseline=t)},image(e,t,a){p.drawImage(a,~~e,~~t)},paint(e,t,a,l={}){let n=l.canvas||new OffscreenCanvas(1,1),i=l.scale||1,r=p;if(n.width=e*i,n.height=t*i,(p=n.getContext("2d")).scale(i,i),a.push){let e=0,t=0;for(let l of(p.imageSmoothingEnabled=!1,a)){for(let a of l)" "!==a&&"."!==a&&C.rectfill(e,t,1,1,parseInt(a,16)),e++;t++,e=0}}else a(p);return p=r,n.transferToImageBitmap()},ctx:e=>(e&&(p=e),p),push:()=>p.save(),pop:()=>p.restore(),translate:(e,t)=>p.translate(~~e,~~t),scale:(e,t)=>p.scale(e,t||e),rotate:e=>p.rotate(e),alpha(e){p.globalAlpha=C.clamp(e,0,1)},path:e=>new Path2D(e),fill(e,t){p.fillStyle=E[~~e%E.length],t?p.fill(t):p.fill()},stroke(e,t){p.strokeStyle=E[~~e%E.length],t?p.stroke(t):p.stroke()},clip(e){p.clip(e)},sfx:(e,a=0,n=1)=>!(l.zzfxV<=0)&&(!navigator.userActivation||!!navigator.userActivation.hasBeenActive)&&(e=e||T,(0!==a||1!==n)&&((e=e.slice())[0]=n*(e[0]||1),e[10]=~~e[10]+a),t.apply(0,e),e),volume(e){l.zzfxV=e},use(e,t={}){f?X(e,t):c.push([e,t])},listen:(e,t)=>(A[e]=A[e]||new Set,A[e].add(t),()=>A[e].delete(t)),emit(e,t,a,l,n){f&&(S("before:"+e,t,a,l,n),S(e,t,a,l,n),S("after:"+e,t,a,l,n))},pal(e=a){E=e},def(t,a){C[t]=a,e.global&&(l[t]=a)},timescale(e){g=e},framerate(e){b=1/~~e},stat:t=>[e,f,w,u,A,E,T,g,l.zzfxV||1,k,y,x][t],quit(){for(let e of(cancelAnimationFrame(w),C.emit("quit"),o))e();if(A={},e.global){for(let e in C)delete l[e];delete l.ENGINE}}};for(let e of"PI,sin,cos,atan2,hypot,tan,abs,ceil,floor,trunc,min,max,pow,sqrt,sign,exp".split(","))C[e]=n[e];function z(){let t=e.loop?e.loop:l;for(let e in A)t[e]&&C.listen(e,t[e]);for(let[e,t]of c)X(e,t);if(e.autoscale&&s(l,"resize",P),e.tapEvents){let e=(e,t)=>[(e-d.offsetLeft)/u,(t-d.offsetTop)/u],t=new Map,a=(e,a,l)=>{let n={x:a,y:l,startX:a,startY:l,ts:performance.now()};return t.set(e,n),n},n=(e,l,n)=>{let i=t.get(e)||a(e);i.x=l,i.y=n},i=e=>e&&performance.now()-e.ts<=300,r=e=>e.preventDefault(),o=!1;s(d,"mousedown",t=>{if(0===t.button){r(t);let[l,n]=e(t.pageX,t.pageY);C.emit("tap",l,n,0),a(0,l,n),o=!0}}),s(d,"mouseup",a=>{if(0===a.button){r(a);let l=t.get(0),[n,s]=e(a.pageX,a.pageY);i(l)&&C.emit("tapped",l.startX,l.startY,0),C.emit("untap",n,s,0),t.delete(0),o=!1}}),s(d,"mousemove",t=>{r(t);let[a,l]=e(t.pageX,t.pageY);C.def("MX",a),C.def("MY",l),o&&(C.emit("tapping",a,l,0),n(0,a,l))}),s(d,"touchstart",t=>{for(let l of(r(t),t.changedTouches)){let[t,n]=e(l.pageX,l.pageY);C.emit("tap",t,n,l.identifier+1),a(l.identifier+1,t,n)}}),s(d,"touchmove",t=>{for(let a of(r(t),t.changedTouches)){let[t,l]=e(a.pageX,a.pageY);C.emit("tapping",t,l,a.identifier+1),n(a.identifier+1,t,l)}});let f=e=>{r(e);let a=[];if(e.targetTouches.length>0)for(let t of e.targetTouches)a.push(t.identifier+1);for(let[e,l]of t)a.includes(e)||(i(l)&&C.emit("tapped",l.startX,l.startY,e),C.emit("untap",l.x,l.y,e),t.delete(e))};s(d,"touchend",f),s(d,"touchcancel",f),s(l,"blur",()=>{for(let[e,a]of(o=!1,t))C.emit("untap",a.x,a.y,e),t.delete(e)})}if(e.keyboardEvents){let e=e=>e.toLowerCase(),t=new Set,a=new Set,n=(t,a)=>a?t.has("space"===e(a)?" ":e(a)):t.size>0;s(l,"keydown",l=>{t.has(e(l.key))||(t.add(e(l.key)),a.add(e(l.key)))}),s(l,"keyup",a=>{t.delete(e(a.key))}),s(l,"blur",()=>t.clear()),C.listen("after:draw",()=>a.clear()),C.def("iskeydown",e=>n(t,e)),C.def("iskeypressed",e=>n(a,e))}e.pauseOnBlur&&(s(l,"blur",()=>{w=cancelAnimationFrame(w)}),s(l,"focus",()=>{w||(v=0,w=r(I))})),f=!0,C.emit("init",C),m=performance.now(),w=r(I)}function I(t){let a=0,l=(t-m)/1e3;if(m=t,e.animate){if(w=r(I),l>.3)return;for(v+=l;v>=b;)C.emit("update",b*g),C.def("T",C.T+b*g),a++,v-=b}else a=1;a&&(C.textalign("start","top"),C.emit("draw"))}function P(){let t=e.width||l.innerWidth,a=e.height||e.width||l.innerHeight;C.def("W",d.width=t),C.def("H",d.height=a),C.def("CX",C.W/2),C.def("CY",C.H/2),e.autoscale&&(d.style.display||(d.style.display="block",d.style.margin="auto"),u=n.min(l.innerWidth/C.W,l.innerHeight/C.H),u=(e.pixelart?~~u:u)||1,d.style.width=C.W*u+"px",d.style.height=C.H*u+"px"),(!e.antialias||e.pixelart)&&(p.imageSmoothingEnabled=!1,d.style.imageRendering="pixelated"),C.emit("resized",u),C.cls(0),e.animate||r(I)}function S(e,t,a,l,n){if(A[e])for(let i of A[e])i(t,a,l,n)}function X(e,t){let a=e(C,t);for(let e in a)C.def(e,a[e])}if(e.global){if(l.ENGINE)throw Error("two global litecanvas detected");Object.assign(l,C),l.ENGINE=C}return d="string"==typeof e.canvas?document.querySelector(e.canvas):e.canvas||document.createElement("canvas"),C.def("CANVAS",d),p=d.getContext("2d"),s(d,"click",()=>l.focus()),d.style="",P(),d.parentNode||document.body.appendChild(d),"loading"===document.readyState?s(l,"DOMContentLoaded",()=>r(z)):r(z),C}})();
1
+ (()=>{var e=new AudioContext,t=(t=1,a=.05,l=220,n=0,i=0,o=.1,r=0,s=1,f=0,c=0,d=0,p=0,u=0,h=0,g=0,m=0,b=0,w=1,x=0,v=0,y=0)=>{let k=Math,E=2*k.PI,T=f*=500*E/44100/44100,C=l*=(1-a+2*a*k.random(a=[]))*E/44100,z=0,A=0,I=0,P=1,S=0,X=0,Y=0,M=y<0?-1:1,N=E*M*y*2/44100,H=k.cos(N),W=k.sin,D=W(N)/4,L=1+D,F=-2*H/L,V=(1-D)/L,q=(1+M*H)/2/L,B=-(M+H)/L,O=0,R=0,G=0,$=0;for(n=44100*n+9,x*=44100,i*=44100,o*=44100,b*=44100,c*=500*E/85766121e6,g*=E/44100,d*=E/44100,p*=44100,u=44100*u|0,t*=.3*(globalThis.zzfxV||1),M=n+x+i+o+b|0;I<M;a[I++]=Y*t)++X%(100*m|0)||(Y=r?1<r?2<r?3<r?W(z*z):k.max(k.min(k.tan(z),1),-1):1-(2*z/E%2+2)%2:1-4*k.abs(k.round(z/E)-z/E):W(z),Y=(u?1-v+v*W(E*I/u):1)*(Y<0?-1:1)*k.abs(Y)**s*(I<n?I/n:I<n+x?1-(I-n)/x*(1-w):I<n+x+i?w:I<M-b?(M-I-b)/o*w:0),Y=b?Y/2+(b>I?0:(I<M-b?1:(M-I)/b)*a[I-b|0]/2/t):Y,y&&(Y=$=q*O+B*(O=R)+q*(R=Y)-V*G-F*(G=$))),z+=(N=(l+=f+=c)*k.cos(g*A++))+N*h*W(I**5),P&&++P>p&&(l+=d,C+=d,P=0),!u||++S%u||(l=C,f=T,P=P||1);(t=e.createBuffer(1,M,44100)).getChannelData(0).set(a),(l=e.createBufferSource()).buffer=t,l.connect(e.destination),l.start()},a=["#111","#6a7799","#aec2c2","#FFF1E8","#e83b3b","#fabc20","#155fd9","#3cbcfc","#327345","#63c64d","#6c2c1f","#ac7c00"];globalThis.litecanvas=function(e={}){let l=globalThis,n=Math,i=2*n.PI,o=requestAnimationFrame,r=[],s=(e,t,a)=>{e.addEventListener(t,a,!1),r.push(()=>e.removeEventListener(t,a,!1))};e=Object.assign({width:null,height:null,autoscale:!0,pixelart:!1,antialias:!1,canvas:null,global:!0,loop:null,tapEvents:!0,keyboardEvents:!0,animate:!0},e);let f=!1,c=[],d,p=1,u,h=.5,g=1,m,b=1/60,w=0,x,v="sans-serif",y=20,k=Date.now(),E=a,T=[.5,0,1750,,,.3,1,,,,600,.1],C={init:null,update:null,draw:null,resized:null,tap:null,untap:null,tapping:null,tapped:null},z={CANVAS:null,W:0,H:0,T:0,CX:0,CY:0,MX:-1,MY:-1,TWO_PI:i,HALF_PI:n.PI/2,lerp:(e,t,a)=>a*(t-e)+e,deg2rad:e=>n.PI/180*e,rad2deg:e=>180/n.PI*e,round:(e,t=0)=>{if(!t)return n.round(e);let a=10**t;return n.round(e*a)/a},clamp:(e,t,a)=>e<t?t:e>a?a:e,wrap:(e,t,a)=>e-(a-t)*n.floor((e-t)/(a-t)),map(e,t,a,l,n,i){let o=(e-t)/(a-t)*(n-l)+l;return i?z.clamp(o,l,n):o},norm:(e,t,a)=>z.map(e,t,a,0,1),wave:(e,t,a,l=Math.sin)=>e+(l(a)+1)/2*(t-e),rand:(e=0,t=1)=>(k=(1664525*k+0x3c6ef35f)%0x100000000)/0x100000000*(t-e)+e,randi:(e=0,t=1)=>n.floor(z.rand(e,t+1)),rseed(e){k=~~e},cls(e){null==e?u.clearRect(0,0,u.canvas.width,u.canvas.height):z.rectfill(0,0,u.canvas.width,u.canvas.height,e)},rect(e,t,a,l,n,i){u.beginPath(),u[i?"roundRect":"rect"](~~e-h,~~t-h,~~a+2*h,~~l+2*h,i),z.stroke(n)},rectfill(e,t,a,l,n,i){u.beginPath(),u[i?"roundRect":"rect"](~~e,~~t,~~a,~~l,i),z.fill(n)},circ(e,t,a,l){u.beginPath(),u.arc(~~e,~~t,~~a,0,i),z.stroke(l)},circfill(e,t,a,l){u.beginPath(),u.arc(~~e,~~t,~~a,0,i),z.fill(l)},line(e,t,a,l,n){u.beginPath();let i=.5*(0!==h&&~~e==~~a),o=.5*(0!==h&&~~t==~~l);u.moveTo(~~e+i,~~t+o),u.lineTo(~~a+i,~~l+o),z.stroke(n)},linewidth(e){u.lineWidth=~~e,h=.5*(0!=~~e%2)},linedash(e,t=0){u.setLineDash(e),u.lineDashOffset=t},text(e,t,a,l=3,n="normal"){u.font=`${n} ${y}px ${v}`,u.fillStyle=E[~~l%E.length],u.fillText(a,~~e,~~t)},textfont(e){v=e},textsize(e){y=e},textalign(e,t){e&&(u.textAlign=e),t&&(u.textBaseline=t)},image(e,t,a){u.drawImage(a,~~e,~~t)},paint(e,t,a,l={}){let n=l.canvas||new OffscreenCanvas(1,1),i=l.scale||1,o=u;if(n.width=e*i,n.height=t*i,(u=n.getContext("2d")).scale(i,i),a.push){let e=0,t=0;for(let l of(u.imageSmoothingEnabled=!1,a)){for(let a of l)" "!==a&&"."!==a&&z.rectfill(e,t,1,1,parseInt(a,16)),e++;t++,e=0}}else a(u);return u=o,n.transferToImageBitmap()},ctx:e=>(e&&(u=e),u),push:()=>u.save(),pop:()=>u.restore(),translate:(e,t)=>u.translate(~~e,~~t),scale:(e,t)=>u.scale(e,t||e),rotate:e=>u.rotate(e),alpha(e){u.globalAlpha=z.clamp(e,0,1)},path:e=>new Path2D(e),fill(e,t){u.fillStyle=E[~~e%E.length],t?u.fill(t):u.fill()},stroke(e,t){u.strokeStyle=E[~~e%E.length],t?u.stroke(t):u.stroke()},clip(e){u.clip(e)},sfx:(e,a=0,n=1)=>!(l.zzfxV<=0)&&(!navigator.userActivation||!!navigator.userActivation.hasBeenActive)&&(e=e||T,(0!==a||1!==n)&&((e=e.slice())[0]=n*(e[0]||1),e[10]=~~e[10]+a),t.apply(0,e),e),volume(e){l.zzfxV=e},use(e,t={}){f?X(e,t):c.push([e,t])},listen:(e,t)=>(C[e]=C[e]||new Set,C[e].add(t),()=>C[e].delete(t)),emit(e,t,a,l,n){f&&(S("before:"+e,t,a,l,n),S(e,t,a,l,n),S("after:"+e,t,a,l,n))},pal(e=a){E=e},def(t,a){z[t]=a,e.global&&(l[t]=a)},timescale(e){g=e},framerate(e){b=1/~~e},stat:t=>[e,f,x,p,C,E,T,g,l.zzfxV||1,k,y,v][t],quit(){for(let e of(cancelAnimationFrame(x),x=0,z.emit("quit"),r))e();if(C={},e.global){for(let e in z)delete l[e];delete l.ENGINE}}};for(let e of"PI,sin,cos,atan2,hypot,tan,abs,ceil,floor,trunc,min,max,pow,sqrt,sign,exp".split(","))z[e]=n[e];function A(){let t=e.loop?e.loop:l;for(let e in C)t[e]&&z.listen(e,t[e]);for(let[e,t]of c)X(e,t);if(e.autoscale&&s(l,"resize",P),e.tapEvents){let e=(e,t)=>[(e-d.offsetLeft)/p,(t-d.offsetTop)/p],t=new Map,a=(e,a,l)=>{let n={x:a,y:l,startX:a,startY:l,ts:performance.now()};return t.set(e,n),n},n=(e,l,n)=>{let i=t.get(e)||a(e);i.x=l,i.y=n},i=e=>e&&performance.now()-e.ts<=300,o=e=>e.preventDefault(),r=!1;s(d,"mousedown",t=>{if(0===t.button){o(t);let[l,n]=e(t.pageX,t.pageY);z.emit("tap",l,n,0),a(0,l,n),r=!0}}),s(d,"mouseup",a=>{if(0===a.button){o(a);let l=t.get(0),[n,s]=e(a.pageX,a.pageY);i(l)&&z.emit("tapped",l.startX,l.startY,0),z.emit("untap",n,s,0),t.delete(0),r=!1}}),s(d,"mousemove",t=>{o(t);let[a,l]=e(t.pageX,t.pageY);z.def("MX",a),z.def("MY",l),r&&(z.emit("tapping",a,l,0),n(0,a,l))}),s(d,"touchstart",t=>{for(let l of(o(t),t.changedTouches)){let[t,n]=e(l.pageX,l.pageY);z.emit("tap",t,n,l.identifier+1),a(l.identifier+1,t,n)}}),s(d,"touchmove",t=>{for(let a of(o(t),t.changedTouches)){let[t,l]=e(a.pageX,a.pageY);z.emit("tapping",t,l,a.identifier+1),n(a.identifier+1,t,l)}});let f=e=>{o(e);let a=[];if(e.targetTouches.length>0)for(let t of e.targetTouches)a.push(t.identifier+1);for(let[e,l]of t)a.includes(e)||(i(l)&&z.emit("tapped",l.startX,l.startY,e),z.emit("untap",l.x,l.y,e),t.delete(e))};s(d,"touchend",f),s(d,"touchcancel",f),s(l,"blur",()=>{for(let[e,a]of(r=!1,t))z.emit("untap",a.x,a.y,e),t.delete(e)})}if(e.keyboardEvents){let e=e=>e.toLowerCase(),t=new Set,a=new Set,n=(t,a)=>a?t.has("space"===e(a)?" ":e(a)):t.size>0;s(l,"keydown",l=>{t.has(e(l.key))||(t.add(e(l.key)),a.add(e(l.key)))}),s(l,"keyup",a=>{t.delete(e(a.key))}),s(l,"blur",()=>t.clear()),z.listen("after:draw",()=>a.clear()),z.def("iskeydown",e=>n(t,e)),z.def("iskeypressed",e=>n(a,e))}f=!0,z.emit("init",z),m=performance.now(),x=o(I)}function I(t){let a=0,l=(t-m)/1e3;if(m=t,e.animate){if(l>.3);else for(w+=l;w>=b;)a++,z.emit("update",b*g,a),z.def("T",z.T+b*g),w-=b;x&&(x=o(I))}else a=1;a&&(z.textalign("start","top"),z.emit("draw"))}function P(){let t=e.width||l.innerWidth,a=e.height||e.width||l.innerHeight;z.def("W",d.width=t),z.def("H",d.height=a),z.def("CX",z.W/2),z.def("CY",z.H/2),e.autoscale&&(d.style.display||(d.style.display="block",d.style.margin="auto"),p=n.min(l.innerWidth/z.W,l.innerHeight/z.H),p=(e.pixelart?~~p:p)||1,d.style.width=z.W*p+"px",d.style.height=z.H*p+"px"),(!e.antialias||e.pixelart)&&(u.imageSmoothingEnabled=!1,d.style.imageRendering="pixelated"),z.emit("resized",p),z.cls(0),e.animate||o(I)}function S(e,t,a,l,n){if(C[e])for(let i of C[e])i(t,a,l,n)}function X(e,t){let a=e(z,t);for(let e in a)z.def(e,a[e])}if(e.global){if(l.ENGINE)throw Error("two global litecanvas detected");Object.assign(l,z),l.ENGINE=z}return e.canvas&&(d=document.querySelector(e.canvas)),d=d||document.createElement("canvas"),z.def("CANVAS",d),u=d.getContext("2d"),s(d,"click",()=>l.focus()),d.style="",P(),d.parentNode||document.body.appendChild(d),"loading"===document.readyState?s(l,"DOMContentLoaded",()=>o(A)):o(A),z}})();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "litecanvas",
3
- "version": "0.81.2",
3
+ "version": "0.82.0",
4
4
  "description": "Lightweight HTML5 canvas 2D game engine suitable for small projects and creative coding. Inspired by PICO-8 and P5/Processing.",
5
5
  "license": "MIT",
6
6
  "author": "Luiz Bills <luizbills@pm.me>",
@@ -24,7 +24,7 @@
24
24
  "main": "src/index.js",
25
25
  "types": "types/index.d.ts",
26
26
  "scripts": {
27
- "test": "npm run build && ava",
27
+ "test": "ava",
28
28
  "dev:test": "ava --watch",
29
29
  "dev": "esbuild src/web.js --bundle --watch --outfile=dist/dist.dev.js --servedir=.",
30
30
  "build": "node script/build.js",
package/src/index.js CHANGED
@@ -35,7 +35,6 @@ export default function litecanvas(settings = {}) {
35
35
  canvas: null,
36
36
  global: true,
37
37
  loop: null,
38
- pauseOnBlur: true,
39
38
  tapEvents: true,
40
39
  keyboardEvents: true,
41
40
  animate: true,
@@ -1155,6 +1154,7 @@ export default function litecanvas(settings = {}) {
1155
1154
  quit() {
1156
1155
  // stop the game loop (update & draw)
1157
1156
  cancelAnimationFrame(_rafid)
1157
+ _rafid = 0
1158
1158
 
1159
1159
  // emit "quit" event to manual clean ups
1160
1160
  instance.emit('quit')
@@ -1436,23 +1436,6 @@ export default function litecanvas(settings = {}) {
1436
1436
  )
1437
1437
  }
1438
1438
 
1439
- // listen browser focus/blur events and pause the update/draw loop
1440
- if (settings.pauseOnBlur) {
1441
- // @ts-ignore
1442
- on(root, 'blur', () => {
1443
- // @ts-ignore
1444
- _rafid = cancelAnimationFrame(_rafid)
1445
- })
1446
-
1447
- // @ts-ignore
1448
- on(root, 'focus', () => {
1449
- if (!_rafid) {
1450
- _accumulated = 0
1451
- _rafid = raf(drawFrame)
1452
- }
1453
- })
1454
- }
1455
-
1456
1439
  _initialized = true
1457
1440
 
1458
1441
  // start the game loop
@@ -1472,24 +1455,26 @@ export default function litecanvas(settings = {}) {
1472
1455
  _lastFrameTime = now
1473
1456
 
1474
1457
  if (settings.animate) {
1475
- // request the next frame
1476
- _rafid = raf(drawFrame)
1477
-
1478
1458
  if (frameTime > 0.3) {
1479
- return console.warn('skipping too long frame')
1480
- }
1481
-
1482
- _accumulated += frameTime
1459
+ console.warn('skipping too long frame')
1460
+ } else {
1461
+ _accumulated += frameTime
1483
1462
 
1484
- while (_accumulated >= _deltaTime) {
1485
- instance.emit('update', _deltaTime * _timeScale)
1486
- instance.def('T', instance.T + _deltaTime * _timeScale)
1487
- updated++
1488
- _accumulated -= _deltaTime
1463
+ while (_accumulated >= _deltaTime) {
1464
+ updated++
1465
+ instance.emit('update', _deltaTime * _timeScale, updated)
1466
+ instance.def('T', instance.T + _deltaTime * _timeScale)
1467
+ _accumulated -= _deltaTime
1468
+ }
1489
1469
  }
1470
+
1471
+ // request the next frame
1472
+ // check if the last ID exists, because
1473
+ // quit() delete it (sets to zero)
1474
+ if (_rafid) _rafid = raf(drawFrame)
1490
1475
  } else {
1491
1476
  // when the canvas is not animated
1492
- // we for one frame when a redraw is triggered
1477
+ // we force one frame when redraws are triggered
1493
1478
  updated = 1
1494
1479
  }
1495
1480
 
@@ -1502,12 +1487,16 @@ export default function litecanvas(settings = {}) {
1502
1487
  }
1503
1488
 
1504
1489
  function setupCanvas() {
1505
- if ('string' === typeof settings.canvas) {
1490
+ if (settings.canvas) {
1491
+ DEV: assert(
1492
+ 'string' === typeof settings.canvas,
1493
+ 'Litecanvas\' option "canvas" should be a string (a selector)'
1494
+ )
1506
1495
  _canvas = document.querySelector(settings.canvas)
1507
- } else {
1508
- _canvas = settings.canvas || document.createElement('canvas')
1509
1496
  }
1510
1497
 
1498
+ _canvas = _canvas || document.createElement('canvas')
1499
+
1511
1500
  DEV: assert(
1512
1501
  _canvas && _canvas.tagName === 'CANVAS',
1513
1502
  'Invalid canvas element'
package/types/types.d.ts CHANGED
@@ -591,10 +591,9 @@ type LitecanvasOptions = {
591
591
  */
592
592
  height?: number
593
593
  /**
594
- * Determines whether the game loop should be paused when the "blur" event happens.
595
- * Default: `true`
594
+ * Used to specify the selector of a custom canvas element
596
595
  */
597
- pauseOnBlur?: boolean
596
+ canvas?: string
598
597
  /**
599
598
  * If `true` (default) scales the canvas to fill the screen, but preserving the aspect ratio.
600
599
  * Only works if a game screen width was specified.
@@ -608,10 +607,7 @@ type LitecanvasOptions = {
608
607
  * If `false` (default), disable the canvas antialias.
609
608
  */
610
609
  antialias?: boolean
611
- /**
612
- * Used to specify the selector of a custom canvas element
613
- */
614
- canvas?: string
610
+
615
611
  /**
616
612
  * If `true` (default), all methods and properties of the engine will be exposed to the global scope (window).
617
613
  */