litecanvas 0.61.1 → 0.63.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.js CHANGED
@@ -42,7 +42,7 @@
42
42
 
43
43
  // src/index.js
44
44
  function litecanvas(settings = {}) {
45
- const root = globalThis, PI = Math.PI, TWO_PI = PI * 2, on = (elem, evt, callback) => elem.addEventListener(evt, callback), defaults = {
45
+ const root = globalThis, PI = Math.PI, TWO_PI = PI * 2, raf = requestAnimationFrame, on = (elem, evt, callback) => elem.addEventListener(evt, callback), defaults = {
46
46
  fps: 60,
47
47
  fullscreen: true,
48
48
  width: null,
@@ -59,7 +59,7 @@
59
59
  animate: true
60
60
  };
61
61
  settings = Object.assign(defaults, settings);
62
- let _initialized = false, _plugins = [], _canvas = settings.canvas || document.createElement("canvas"), _fullscreen = settings.fullscreen, _autoscale = settings.autoscale, _animate = settings.animate, _scale = 1, _ctx, _timeScale = 1, _lastFrame, _step = 1 / settings.fps, _stepMs = _step * 1e3, _accumulated = 0, _rafid, _drawCount = 0, _drawTime = 0, _fontFamily = "sans-serif", _fontStyle = "", _fontSize = 32, _rng_seed = Date.now(), _events = {
62
+ let _initialized = false, _plugins = [], _canvas = settings.canvas || document.createElement("canvas"), _fullscreen = settings.fullscreen, _autoscale = settings.autoscale, _animate = settings.animate, _scale = 1, _ctx, _timeScale = 1, _lastFrame, _step = 1 / settings.fps, _stepMs = _step * 1e3, _accumulated = 0, _focused = true, _drawCount = 0, _drawTime = 0, _fontFamily = "sans-serif", _fontStyle = "", _fontSize = 32, _rng_seed = Date.now(), _events = {
63
63
  init: false,
64
64
  update: false,
65
65
  draw: false,
@@ -278,7 +278,6 @@
278
278
  circ(x, y, radius, color) {
279
279
  _ctx.beginPath();
280
280
  _ctx.arc(~~x, ~~y, radius, 0, TWO_PI);
281
- _ctx.closePath();
282
281
  instance.stroke(color);
283
282
  },
284
283
  /**
@@ -292,7 +291,6 @@
292
291
  circfill(x, y, radius, color) {
293
292
  _ctx.beginPath();
294
293
  _ctx.arc(~~x, ~~y, radius, 0, TWO_PI);
295
- _ctx.closePath();
296
294
  instance.fill(color);
297
295
  },
298
296
  /**
@@ -417,10 +415,10 @@
417
415
  * @see https://developer.mozilla.org/en-US/docs/Web/API/OffscreenCanvas
418
416
  */
419
417
  paint(width, height, draw, options = {}) {
420
- const oc = options.canvas || new OffscreenCanvas(1, 1), scale = options.scale || 1, contextBackup = _ctx;
421
- oc.width = width * scale;
422
- oc.height = height * scale;
423
- _ctx = oc.getContext("2d");
418
+ const canvas = options.canvas || new OffscreenCanvas(1, 1), scale = options.scale || 1, contextOriginal = _ctx;
419
+ canvas.width = width * scale;
420
+ canvas.height = height * scale;
421
+ _ctx = canvas.getContext("2d");
424
422
  _ctx.scale(scale, scale);
425
423
  if (Array.isArray(draw)) {
426
424
  let x = 0, y = 0;
@@ -436,10 +434,10 @@
436
434
  x = 0;
437
435
  }
438
436
  } else {
439
- draw(oc, _ctx);
437
+ draw(_ctx);
440
438
  }
441
- _ctx = contextBackup;
442
- return oc;
439
+ _ctx = contextOriginal;
440
+ return canvas;
443
441
  },
444
442
  /** ADVANCED GRAPHICS API */
445
443
  /**
@@ -837,24 +835,23 @@
837
835
  }
838
836
  if (settings.pauseOnBlur) {
839
837
  on(root, "blur", () => {
840
- _rafid = null;
838
+ _focused = false;
841
839
  });
842
840
  on(root, "focus", () => {
843
- if (!_rafid) {
844
- _lastFrame = performance.now();
845
- _rafid = requestAnimationFrame(drawFrame);
846
- }
841
+ _lastFrame = performance.now();
842
+ raf(drawFrame);
843
+ _focused = true;
847
844
  });
848
845
  }
849
846
  instance.emit("init", instance);
850
847
  _lastFrame = performance.now();
851
- _rafid = requestAnimationFrame(drawFrame);
848
+ raf(drawFrame);
852
849
  }
853
850
  function drawFrame(now) {
854
851
  let ticks = 0, t = now - _lastFrame;
855
852
  _lastFrame = now;
856
853
  _accumulated += t;
857
- while (_accumulated >= _stepMs) {
854
+ while (_accumulated > _stepMs) {
858
855
  instance.emit("update", _step * _timeScale);
859
856
  instance.setvar("ELAPSED", instance.ELAPSED + _step * _timeScale);
860
857
  _accumulated -= _stepMs;
@@ -871,8 +868,8 @@
871
868
  _drawTime -= 1e3;
872
869
  }
873
870
  }
874
- if (_rafid && _animate) {
875
- _rafid = requestAnimationFrame(drawFrame);
871
+ if (_focused && _animate) {
872
+ raf(drawFrame);
876
873
  }
877
874
  }
878
875
  function setupCanvas() {
@@ -913,8 +910,7 @@
913
910
  }
914
911
  instance.emit("resized", _scale);
915
912
  if (!_animate) {
916
- _lastFrame = performance.now();
917
- requestAnimationFrame(drawFrame);
913
+ raf(drawFrame);
918
914
  }
919
915
  }
920
916
  function triggerEvent(eventName, arg1, arg2, arg3, arg4) {
package/dist/dist.min.js CHANGED
@@ -1 +1 @@
1
- (()=>{var e=/* @__PURE__ */new AudioContext,t=(t=1,a=.05,n=220,l=0,r=0,i=.1,o=0,s=1,c=0,f=0,p=0,u=0,d=0,g=0,h=0,m=0,v=0,T=1,x=0,E=0,y=0)=>{let b=Math,w=2*b.PI,H=c*=500*w/44100/44100,D=n*=(1-a+2*a*b.random(a=[]))*w/44100,A=0,I=0,S=0,k=1,C=0,P=0,F=0,O=y<0?-1:1,X=w*O*y*2/44100,L=b.cos(X),W=b.sin,z=W(X)/4,Y=1+z,M=-2*L/Y,_=(1-z)/Y,B=(1+O*L)/2/Y,G=-(O+L)/Y,R=0,N=0,j=0,q=0;for(l=44100*l+9,x*=44100,r*=44100,i*=44100,v*=44100,f*=500*w/85766121e6,h*=w/44100,p*=w/44100,u*=44100,d=44100*d|0,t*=.3*(globalThis.zzfxV||1),O=l+x+r+i+v|0;S<O;a[S++]=F*t)++P%(100*m|0)||(F=o?1<o?2<o?3<o?W(A*A):b.max(b.min(b.tan(A),1),-1):1-(2*A/w%2+2)%2:1-4*b.abs(b.round(A/w)-A/w):W(A),F=(d?1-E+E*W(w*S/d):1)*(F<0?-1:1)*b.abs(F)**s*(S<l?S/l:S<l+x?1-(S-l)/x*(1-T):S<l+x+r?T:S<O-v?(O-S-v)/i*T:0),F=v?F/2+(v>S?0:(S<O-v?1:(O-S)/v)*a[S-v|0]/2/t):F,y&&(F=q=B*R+G*(R=N)+B*(N=F)-_*j-M*(j=q))),A+=(X=(n+=c+=f)*b.cos(h*I++))+X*g*W(S**5),k&&++k>u&&(n+=p,D+=p,k=0),!d||++C%d||(n=D,c=H,k=k||1);(t=e.createBuffer(1,O,44100)).getChannelData(0).set(a),(n=e.createBufferSource()).buffer=t,n.connect(e.destination),n.start()},a=["#111","#6a7799","#aec2c2","#FFF1E8","#d82800","#f8d878","#155fd9","#3cbcfc","#327345","#63c64d","#6844fc","#ac7c00"];globalThis.litecanvas=function(e={}){let n=globalThis,l=Math.PI,r=2*l,i=(e,t,a)=>e.addEventListener(t,a);e=Object.assign({fps:60,fullscreen:!0,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 o=!1,s=[],c=e.canvas||document.createElement("canvas"),f=e.fullscreen,p=e.autoscale,u=e.animate,d=1,g,h=1,m,v=1/e.fps,T=1e3*v,x=0,E,y=0,b=0,w="sans-serif",H="",D=32,A=Date.now(),I={init:!1,update:!1,draw:!1,resized:!1,tap:!1,untap:!1,tapping:!1,tapped:!1},S={settings:Object.assign({},e),colors:a},k={WIDTH:e.width,HEIGHT:e.height||e.width,CANVAS:null,ELAPSED:0,FPS:e.fps,CENTERX:0,CENTERY:0,MOUSEX:-1,MOUSEY:-1,DEFAULT_SFX:[.5,,1675,,.06,.2,1,1.8,,,637,.06],PI:l,TWO_PI:r,HALF_PI:.5*l,lerp:(e,t,a)=>e+a*(t-e),deg2rad:e=>l/180*e,rad2deg:e=>180/l*e,clamp:(e,t,a)=>e<t?t:e>a?a:e,wrap:(e,t,a)=>e-(a-t)*Math.floor((e-t)/(a-t)),map(e,t,a,n,l,r=!1){let i=(e-t)/(a-t)*(l-n)+n;return r?k.clamp(i,n,l):i},norm:(e,t,a)=>k.map(e,t,a,0,1),rand:(e=0,t=1)=>(A=(1664525*A+0x3c6ef35f)%0x100000000)/0x100000000*(t-e)+e,randi:(e=0,t=1)=>k.floor(k.rand(e,t+1)),seed:e=>null==e?A:A=~~e,cls(e){null==e?g.clearRect(0,0,k.WIDTH,k.HEIGHT):k.rectfill(0,0,k.WIDTH,k.HEIGHT,e)},rect(e,t,a,n,l=0,r=null){g.beginPath(),g[r?"roundRect":"rect"](~~e,~~t,a,n,r),k.stroke(l)},rectfill(e,t,a,n,l=0,r=null){g.beginPath(),g[r?"roundRect":"rect"](~~e,~~t,a,n,r),k.fill(l)},circ(e,t,a,n){g.beginPath(),g.arc(~~e,~~t,a,0,r),g.closePath(),k.stroke(n)},circfill(e,t,a,n){g.beginPath(),g.arc(~~e,~~t,a,0,r),g.closePath(),k.fill(n)},line(e,t,a,n,l){g.beginPath(),g.moveTo(~~e,~~t),g.lineTo(~~a,~~n),k.stroke(l)},linewidth(e){g.lineWidth=e},linedash(e,t=0){g.setLineDash(Array.isArray(e)?e:[e]),g.lineDashOffset=t},text(e,t,a,n=3){g.font=`${H} ${D}px ${w}`,g.fillStyle=k.getcolor(n),g.fillText(a,~~e,~~t)},textfont(e){w=e},textsize(e){D=e},textstyle(e){H=e||""},textalign(e,t){e&&(g.textAlign=e),t&&(g.textBaseline=t)},textmetrics(e,t=D){g.font=`${H} ${t}px ${w}`;let a=g.measureText(e);return a.height=a.actualBoundingBoxAscent+a.actualBoundingBoxDescent,a},image(e,t,a){g.drawImage(a,~~e,~~t)},paint(e,t,a,n={}){let l=n.canvas||new OffscreenCanvas(1,1),r=n.scale||1,i=g;if(l.width=e*r,l.height=t*r,(g=l.getContext("2d")).scale(r,r),Array.isArray(a)){let e=0,t=0;for(let n of(g.imageSmoothingEnabled=!1,a)){for(let a of n)" "!==a&&"."!==a&&k.rectfill(e,t,1,1,parseInt(a,16)),e++;t++,e=0}}else a(l,g);return g=i,l},ctx:e=>(e&&(g=e),g),push:()=>g.save(),pop:()=>g.restore(),translate:(e,t)=>g.translate(~~e,~~t),scale:(e,t)=>g.scale(e,t||e),rotate:e=>g.rotate(e),transform:(e,t,a,n,l,r,i=!0)=>g[i?"setTransform":"transform"](e,t,a,n,l,r),alpha(e){g.globalAlpha=k.clamp(e,0,1)},path:e=>new Path2D(e),fill(e,t){g.fillStyle=k.getcolor(e),t?g.fill(t):g.fill()},stroke(e,t){g.strokeStyle=k.getcolor(e),t?g.stroke(t):g.stroke()},clip(e){g.clip(e)},sfx:(e,a=0,l=1)=>!(n.zzfxV<=0)&&(!navigator.userActivation||!!navigator.userActivation.hasBeenActive)&&(e=e||k.DEFAULT_SFX,(a>0||1!==l)&&((e=e.slice())[0]=l*(e[0]||1),e[10]=~~e[10]+a),t.apply(0,e),e),volume(e){n.zzfxV=+e},colrect:(e,t,a,n,l,r,i,o)=>e<l+i&&e+a>l&&t<r+o&&t+n>r,colcirc:(e,t,a,n,l,r)=>(n-e)**2+(l-t)**2<=(a+r)**2,timescale(e){h=e},use(e,t={}){e.__conf=t,o?X(e):s.push(e)},listen:(e,t)=>(I[e]=I[e]||[],I[e].push(t),()=>{I[e]=I[e].filter(e=>t!==e)}),emit(e,t,a,n,l){O("before:"+e,t,a,n,l),O(e,t,a,n,l),O("after:"+e,t,a,n,l)},getcolor:e=>a[~~e%a.length],setvar(t,a){k[t]=a,e.global&&(n[t]=a)},resize(e,t){k.setvar("WIDTH",c.width=e),k.setvar("HEIGHT",c.height=t||e),F()}};for(let e of["sin","cos","atan2","hypot","tan","abs","ceil","round","floor","trunc","min","max","pow","sqrt","sign","exp"])k[e]=Math[e];function C(){o=!0,c="string"==typeof c?document.querySelector(c):c,k.setvar("CANVAS",c),g=c.getContext("2d"),k.WIDTH>0&&(f=!1),c.width=k.WIDTH,c.height=k.HEIGHT||k.WIDTH,c.parentNode||document.body.appendChild(c),c.style.display="block",f?(c.style.position="absolute",c.style.inset=0):p&&(c.style.margin="auto");let t=e.loop?e.loop:n;for(let e of Object.keys(I))t[e]&&k.listen(e,t[e]);for(let e of s)X(e);if(i(n,"resize",F),F(),e.tapEvents){let e=(e,t)=>[(e-c.offsetLeft)/d,(t-c.offsetTop)/d],t=/* @__PURE__ */new Map,a=(e,a,n)=>{let l={x:a,y:n,startX:a,startY:n,ts:performance.now()};return t.set(e,l),l},l=(e,n,l)=>{let r=t.get(e)||a(e);r.x=n,r.y=l},r=e=>e&&performance.now()-e.ts<=200,o=!1;i(c,"mousedown",t=>{t.preventDefault();let[n,l]=e(t.pageX,t.pageY);k.emit("tap",n,l,0),a(0,n,l),o=!0}),i(c,"mousemove",t=>{t.preventDefault();let[a,n]=e(t.pageX,t.pageY);k.setvar("MOUSEX",a),k.setvar("MOUSEY",n),o&&(k.emit("tapping",a,n,0),l(0,a,n))}),i(c,"mouseup",a=>{a.preventDefault();let n=t.get(0),[l,i]=e(a.pageX,a.pageY);r(n)&&k.emit("tapped",n.startX,n.startY,0),k.emit("untap",l,i,0),t.delete(0),o=!1}),i(c,"touchstart",t=>{for(let n of(t.preventDefault(),t.changedTouches)){let[t,l]=e(n.pageX,n.pageY);k.emit("tap",t,l,n.identifier+1),a(n.identifier+1,t,l)}}),i(c,"touchmove",t=>{for(let a of(t.preventDefault(),t.changedTouches)){let[t,n]=e(a.pageX,a.pageY);k.emit("tapping",t,n,a.identifier+1),l(a.identifier+1,t,n)}});let s=e=>{e.preventDefault();let a=[];if(e.targetTouches.length>0)for(let t of e.targetTouches)a.push(t.identifier+1);for(let[e,n]of t)a.includes(e)||(r(n)&&k.emit("tapped",n.startX,n.startY,e),k.emit("untap",n.x,n.y,e),t.delete(e))};i(c,"touchend",s),i(c,"touchcancel",s),i(n,"blur",()=>{for(let[e,a]of(o=!1,t))k.emit("untap",a.x,a.y,e),t.delete(e)})}if(e.keyboardEvents){let e=/* @__PURE__ */new Set;k.setvar("iskeydown",t=>"any"===t?e.size>0:e.has(t.toLowerCase())),i(n,"keydown",t=>{e.add(t.key.toLowerCase())}),i(n,"keyup",t=>{e.delete(t.key.toLowerCase())}),i(n,"blur",()=>e.clear())}e.pauseOnBlur&&(i(n,"blur",()=>{E=null}),i(n,"focus",()=>{E||(m=performance.now(),E=requestAnimationFrame(P))})),k.emit("init",k),m=performance.now(),E=requestAnimationFrame(P)}function P(e){let t=0,a=e-m;for(m=e,x+=a;x>=T;)k.emit("update",v*h),k.setvar("ELAPSED",k.ELAPSED+v*h),x-=T,t++;(t||!u)&&(k.textalign("start","top"),k.emit("draw"),y++,(b+=T*t)+x>=1e3&&(k.setvar("FPS",y),y=0,b-=1e3)),E&&u&&(E=requestAnimationFrame(P))}function F(){let t=n.innerWidth,a=n.innerHeight;f?(k.setvar("WIDTH",c.width=t),k.setvar("HEIGHT",c.height=a)):p&&(d=Math.min(t/k.WIDTH,a/k.HEIGHT),d=(e.pixelart?~~d:d)||1,c.style.width=k.WIDTH*d+"px",c.style.height=k.HEIGHT*d+"px"),k.setvar("CENTERX",k.WIDTH/2),k.setvar("CENTERY",k.HEIGHT/2),(!e.antialias||e.pixelart)&&(g.imageSmoothingEnabled=!1,c.style.imageRendering="pixelated"),k.emit("resized",d),u||(m=performance.now(),requestAnimationFrame(P))}function O(e,t,a,n,l){if(I[e])for(let r of I[e])r(t,a,n,l)}function X(e){let t=e(k,S,e.__conf);if("object"==typeof t)for(let[e,a]of Object.entries(t))k.setvar(e,a)}if(e.global){if(n.__litecanvas)throw"global litecanvas already instantiated";Object.assign(n,k),n.__litecanvas=k}return"loading"===document.readyState?i(n,"DOMContentLoaded",C):C(),k}})();
1
+ (()=>{var e=/* @__PURE__ */new AudioContext,t=(t=1,a=.05,l=220,n=0,r=0,i=.1,o=0,s=1,c=0,f=0,p=0,u=0,d=0,g=0,h=0,m=0,v=0,T=1,x=0,E=0,y=0)=>{let b=Math,w=2*b.PI,H=c*=500*w/44100/44100,D=l*=(1-a+2*a*b.random(a=[]))*w/44100,I=0,A=0,S=0,k=1,C=0,O=0,P=0,X=y<0?-1:1,L=w*X*y*2/44100,W=b.cos(L),z=b.sin,Y=z(L)/4,F=1+Y,M=-2*W/F,_=(1-Y)/F,B=(1+X*W)/2/F,G=-(X+W)/F,R=0,N=0,j=0,U=0;for(n=44100*n+9,x*=44100,r*=44100,i*=44100,v*=44100,f*=500*w/85766121e6,h*=w/44100,p*=w/44100,u*=44100,d=44100*d|0,t*=.3*(globalThis.zzfxV||1),X=n+x+r+i+v|0;S<X;a[S++]=P*t)++O%(100*m|0)||(P=o?1<o?2<o?3<o?z(I*I):b.max(b.min(b.tan(I),1),-1):1-(2*I/w%2+2)%2:1-4*b.abs(b.round(I/w)-I/w):z(I),P=(d?1-E+E*z(w*S/d):1)*(P<0?-1:1)*b.abs(P)**s*(S<n?S/n:S<n+x?1-(S-n)/x*(1-T):S<n+x+r?T:S<X-v?(X-S-v)/i*T:0),P=v?P/2+(v>S?0:(S<X-v?1:(X-S)/v)*a[S-v|0]/2/t):P,y&&(P=U=B*R+G*(R=N)+B*(N=P)-_*j-M*(j=U))),I+=(L=(l+=c+=f)*b.cos(h*A++))+L*g*z(S**5),k&&++k>u&&(l+=p,D+=p,k=0),!d||++C%d||(l=D,c=H,k=k||1);(t=e.createBuffer(1,X,44100)).getChannelData(0).set(a),(l=e.createBufferSource()).buffer=t,l.connect(e.destination),l.start()},a=["#111","#6a7799","#aec2c2","#FFF1E8","#d82800","#f8d878","#155fd9","#3cbcfc","#327345","#63c64d","#6844fc","#ac7c00"];globalThis.litecanvas=function(e={}){let l=globalThis,n=Math.PI,r=2*n,i=requestAnimationFrame,o=(e,t,a)=>e.addEventListener(t,a);e=Object.assign({fps:60,fullscreen:!0,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 s=!1,c=[],f=e.canvas||document.createElement("canvas"),p=e.fullscreen,u=e.autoscale,d=e.animate,g=1,h,m=1,v,T=1/e.fps,x=1e3*T,E=0,y=!0,b=0,w=0,H="sans-serif",D="",I=32,A=Date.now(),S={init:!1,update:!1,draw:!1,resized:!1,tap:!1,untap:!1,tapping:!1,tapped:!1},k={settings:Object.assign({},e),colors:a},C={WIDTH:e.width,HEIGHT:e.height||e.width,CANVAS:null,ELAPSED:0,FPS:e.fps,CENTERX:0,CENTERY:0,MOUSEX:-1,MOUSEY:-1,DEFAULT_SFX:[.5,,1675,,.06,.2,1,1.8,,,637,.06],PI:n,TWO_PI:r,HALF_PI:.5*n,lerp:(e,t,a)=>e+a*(t-e),deg2rad:e=>n/180*e,rad2deg:e=>180/n*e,clamp:(e,t,a)=>e<t?t:e>a?a:e,wrap:(e,t,a)=>e-(a-t)*Math.floor((e-t)/(a-t)),map(e,t,a,l,n,r=!1){let i=(e-t)/(a-t)*(n-l)+l;return r?C.clamp(i,l,n):i},norm:(e,t,a)=>C.map(e,t,a,0,1),rand:(e=0,t=1)=>(A=(1664525*A+0x3c6ef35f)%0x100000000)/0x100000000*(t-e)+e,randi:(e=0,t=1)=>C.floor(C.rand(e,t+1)),seed:e=>null==e?A:A=~~e,cls(e){null==e?h.clearRect(0,0,C.WIDTH,C.HEIGHT):C.rectfill(0,0,C.WIDTH,C.HEIGHT,e)},rect(e,t,a,l,n=0,r=null){h.beginPath(),h[r?"roundRect":"rect"](~~e,~~t,a,l,r),C.stroke(n)},rectfill(e,t,a,l,n=0,r=null){h.beginPath(),h[r?"roundRect":"rect"](~~e,~~t,a,l,r),C.fill(n)},circ(e,t,a,l){h.beginPath(),h.arc(~~e,~~t,a,0,r),C.stroke(l)},circfill(e,t,a,l){h.beginPath(),h.arc(~~e,~~t,a,0,r),C.fill(l)},line(e,t,a,l,n){h.beginPath(),h.moveTo(~~e,~~t),h.lineTo(~~a,~~l),C.stroke(n)},linewidth(e){h.lineWidth=e},linedash(e,t=0){h.setLineDash(Array.isArray(e)?e:[e]),h.lineDashOffset=t},text(e,t,a,l=3){h.font=`${D} ${I}px ${H}`,h.fillStyle=C.getcolor(l),h.fillText(a,~~e,~~t)},textfont(e){H=e},textsize(e){I=e},textstyle(e){D=e||""},textalign(e,t){e&&(h.textAlign=e),t&&(h.textBaseline=t)},textmetrics(e,t=I){h.font=`${D} ${t}px ${H}`;let a=h.measureText(e);return a.height=a.actualBoundingBoxAscent+a.actualBoundingBoxDescent,a},image(e,t,a){h.drawImage(a,~~e,~~t)},paint(e,t,a,l={}){let n=l.canvas||new OffscreenCanvas(1,1),r=l.scale||1,i=h;if(n.width=e*r,n.height=t*r,(h=n.getContext("2d")).scale(r,r),Array.isArray(a)){let e=0,t=0;for(let l of(h.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(h);return h=i,n},ctx:e=>(e&&(h=e),h),push:()=>h.save(),pop:()=>h.restore(),translate:(e,t)=>h.translate(~~e,~~t),scale:(e,t)=>h.scale(e,t||e),rotate:e=>h.rotate(e),transform:(e,t,a,l,n,r,i=!0)=>h[i?"setTransform":"transform"](e,t,a,l,n,r),alpha(e){h.globalAlpha=C.clamp(e,0,1)},path:e=>new Path2D(e),fill(e,t){h.fillStyle=C.getcolor(e),t?h.fill(t):h.fill()},stroke(e,t){h.strokeStyle=C.getcolor(e),t?h.stroke(t):h.stroke()},clip(e){h.clip(e)},sfx:(e,a=0,n=1)=>!(l.zzfxV<=0)&&(!navigator.userActivation||!!navigator.userActivation.hasBeenActive)&&(e=e||C.DEFAULT_SFX,(a>0||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},colrect:(e,t,a,l,n,r,i,o)=>e<n+i&&e+a>n&&t<r+o&&t+l>r,colcirc:(e,t,a,l,n,r)=>(l-e)**2+(n-t)**2<=(a+r)**2,timescale(e){m=e},use(e,t={}){e.__conf=t,s?W(e):c.push(e)},listen:(e,t)=>(S[e]=S[e]||[],S[e].push(t),()=>{S[e]=S[e].filter(e=>t!==e)}),emit(e,t,a,l,n){L("before:"+e,t,a,l,n),L(e,t,a,l,n),L("after:"+e,t,a,l,n)},getcolor:e=>a[~~e%a.length],setvar(t,a){C[t]=a,e.global&&(l[t]=a)},resize(e,t){C.setvar("WIDTH",f.width=e),C.setvar("HEIGHT",f.height=t||e),X()}};for(let e of["sin","cos","atan2","hypot","tan","abs","ceil","round","floor","trunc","min","max","pow","sqrt","sign","exp"])C[e]=Math[e];function O(){s=!0,f="string"==typeof f?document.querySelector(f):f,C.setvar("CANVAS",f),h=f.getContext("2d"),C.WIDTH>0&&(p=!1),f.width=C.WIDTH,f.height=C.HEIGHT||C.WIDTH,f.parentNode||document.body.appendChild(f),f.style.display="block",p?(f.style.position="absolute",f.style.inset=0):u&&(f.style.margin="auto");let t=e.loop?e.loop:l;for(let e of Object.keys(S))t[e]&&C.listen(e,t[e]);for(let e of c)W(e);if(o(l,"resize",X),X(),e.tapEvents){let e=(e,t)=>[(e-f.offsetLeft)/g,(t-f.offsetTop)/g],t=/* @__PURE__ */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 r=t.get(e)||a(e);r.x=l,r.y=n},r=e=>e&&performance.now()-e.ts<=200,i=!1;o(f,"mousedown",t=>{t.preventDefault();let[l,n]=e(t.pageX,t.pageY);C.emit("tap",l,n,0),a(0,l,n),i=!0}),o(f,"mousemove",t=>{t.preventDefault();let[a,l]=e(t.pageX,t.pageY);C.setvar("MOUSEX",a),C.setvar("MOUSEY",l),i&&(C.emit("tapping",a,l,0),n(0,a,l))}),o(f,"mouseup",a=>{a.preventDefault();let l=t.get(0),[n,o]=e(a.pageX,a.pageY);r(l)&&C.emit("tapped",l.startX,l.startY,0),C.emit("untap",n,o,0),t.delete(0),i=!1}),o(f,"touchstart",t=>{for(let l of(t.preventDefault(),t.changedTouches)){let[t,n]=e(l.pageX,l.pageY);C.emit("tap",t,n,l.identifier+1),a(l.identifier+1,t,n)}}),o(f,"touchmove",t=>{for(let a of(t.preventDefault(),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 s=e=>{e.preventDefault();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)||(r(l)&&C.emit("tapped",l.startX,l.startY,e),C.emit("untap",l.x,l.y,e),t.delete(e))};o(f,"touchend",s),o(f,"touchcancel",s),o(l,"blur",()=>{for(let[e,a]of(i=!1,t))C.emit("untap",a.x,a.y,e),t.delete(e)})}if(e.keyboardEvents){let e=/* @__PURE__ */new Set;C.setvar("iskeydown",t=>"any"===t?e.size>0:e.has(t.toLowerCase())),o(l,"keydown",t=>{e.add(t.key.toLowerCase())}),o(l,"keyup",t=>{e.delete(t.key.toLowerCase())}),o(l,"blur",()=>e.clear())}e.pauseOnBlur&&(o(l,"blur",()=>{y=!1}),o(l,"focus",()=>{v=performance.now(),i(P),y=!0})),C.emit("init",C),v=performance.now(),i(P)}function P(e){let t=0,a=e-v;for(v=e,E+=a;E>x;)C.emit("update",T*m),C.setvar("ELAPSED",C.ELAPSED+T*m),E-=x,t++;(t||!d)&&(C.textalign("start","top"),C.emit("draw"),b++,(w+=x*t)+E>=1e3&&(C.setvar("FPS",b),b=0,w-=1e3)),y&&d&&i(P)}function X(){let t=l.innerWidth,a=l.innerHeight;p?(C.setvar("WIDTH",f.width=t),C.setvar("HEIGHT",f.height=a)):u&&(g=Math.min(t/C.WIDTH,a/C.HEIGHT),g=(e.pixelart?~~g:g)||1,f.style.width=C.WIDTH*g+"px",f.style.height=C.HEIGHT*g+"px"),C.setvar("CENTERX",C.WIDTH/2),C.setvar("CENTERY",C.HEIGHT/2),(!e.antialias||e.pixelart)&&(h.imageSmoothingEnabled=!1,f.style.imageRendering="pixelated"),C.emit("resized",g),d||i(P)}function L(e,t,a,l,n){if(S[e])for(let r of S[e])r(t,a,l,n)}function W(e){let t=e(C,k,e.__conf);if("object"==typeof t)for(let[e,a]of Object.entries(t))C.setvar(e,a)}if(e.global){if(l.__litecanvas)throw"global litecanvas already instantiated";Object.assign(l,C),l.__litecanvas=C}return"loading"===document.readyState?o(l,"DOMContentLoaded",O):O(),C}})();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "litecanvas",
3
- "version": "0.61.1",
3
+ "version": "0.63.0",
4
4
  "description": "Lightweight HTML5 canvas engine suitable for small games and animations.",
5
5
  "license": "MIT",
6
6
  "author": "Luiz Bills <luizbills@pm.me>",
package/src/index.js CHANGED
@@ -12,6 +12,7 @@ export default function litecanvas(settings = {}) {
12
12
  const root = globalThis,
13
13
  PI = Math.PI,
14
14
  TWO_PI = PI * 2,
15
+ raf = requestAnimationFrame,
15
16
  /** @type {(elem:HTMLElement, evt:string, callback:(event:Event)=>void)=>void} */
16
17
  on = (elem, evt, callback) => elem.addEventListener(evt, callback),
17
18
  /** @type {LitecanvasOptions} */
@@ -62,7 +63,7 @@ export default function litecanvas(settings = {}) {
62
63
  /** @type {number} */
63
64
  _accumulated = 0,
64
65
  /** @type {number} */
65
- _rafid,
66
+ _focused = true,
66
67
  /** @type {number} */
67
68
  _drawCount = 0,
68
69
  /** @type {number} */
@@ -336,7 +337,6 @@ export default function litecanvas(settings = {}) {
336
337
  circ(x, y, radius, color) {
337
338
  _ctx.beginPath()
338
339
  _ctx.arc(~~x, ~~y, radius, 0, TWO_PI)
339
- _ctx.closePath()
340
340
  instance.stroke(color)
341
341
  },
342
342
 
@@ -351,7 +351,6 @@ export default function litecanvas(settings = {}) {
351
351
  circfill(x, y, radius, color) {
352
352
  _ctx.beginPath()
353
353
  _ctx.arc(~~x, ~~y, radius, 0, TWO_PI)
354
- _ctx.closePath()
355
354
  instance.fill(color)
356
355
  },
357
356
 
@@ -490,13 +489,13 @@ export default function litecanvas(settings = {}) {
490
489
  * @see https://developer.mozilla.org/en-US/docs/Web/API/OffscreenCanvas
491
490
  */
492
491
  paint(width, height, draw, options = {}) {
493
- const oc = options.canvas || new OffscreenCanvas(1, 1),
492
+ const canvas = options.canvas || new OffscreenCanvas(1, 1),
494
493
  scale = options.scale || 1,
495
- contextBackup = _ctx
494
+ contextOriginal = _ctx
496
495
 
497
- oc.width = width * scale
498
- oc.height = height * scale
499
- _ctx = oc.getContext('2d')
496
+ canvas.width = width * scale
497
+ canvas.height = height * scale
498
+ _ctx = canvas.getContext('2d')
500
499
 
501
500
  _ctx.scale(scale, scale)
502
501
 
@@ -519,12 +518,12 @@ export default function litecanvas(settings = {}) {
519
518
  x = 0
520
519
  }
521
520
  } else {
522
- draw(oc, _ctx)
521
+ draw(_ctx)
523
522
  }
524
523
 
525
- _ctx = contextBackup // restore the context
524
+ _ctx = contextOriginal // restore the context
526
525
 
527
- return oc
526
+ return canvas
528
527
  },
529
528
 
530
529
  /** ADVANCED GRAPHICS API */
@@ -622,6 +621,7 @@ export default function litecanvas(settings = {}) {
622
621
  * @param {Path2D} [path]
623
622
  */
624
623
  fill(color, path) {
624
+ // _ctx.closePath()
625
625
  _ctx.fillStyle = instance.getcolor(color)
626
626
  if (path) {
627
627
  _ctx.fill(path)
@@ -637,6 +637,7 @@ export default function litecanvas(settings = {}) {
637
637
  * @param {Path2D} [path]
638
638
  */
639
639
  stroke(color, path) {
640
+ // _ctx.closePath()
640
641
  _ctx.strokeStyle = instance.getcolor(color)
641
642
  if (path) {
642
643
  _ctx.stroke(path)
@@ -1010,20 +1011,21 @@ export default function litecanvas(settings = {}) {
1010
1011
  // listen browser focus/blur events and pause the update/draw loop
1011
1012
  if (settings.pauseOnBlur) {
1012
1013
  on(root, 'blur', () => {
1013
- _rafid = null
1014
+ _focused = false
1014
1015
  })
1016
+
1015
1017
  on(root, 'focus', () => {
1016
- if (!_rafid) {
1017
- _lastFrame = performance.now()
1018
- _rafid = requestAnimationFrame(drawFrame)
1019
- }
1018
+ _lastFrame = performance.now()
1019
+ raf(drawFrame)
1020
+ _focused = true
1020
1021
  })
1021
1022
  }
1022
1023
 
1023
1024
  // start the game loop
1024
1025
  instance.emit('init', instance)
1026
+
1025
1027
  _lastFrame = performance.now()
1026
- _rafid = requestAnimationFrame(drawFrame)
1028
+ raf(drawFrame)
1027
1029
  }
1028
1030
 
1029
1031
  /**
@@ -1036,7 +1038,7 @@ export default function litecanvas(settings = {}) {
1036
1038
  _lastFrame = now
1037
1039
  _accumulated += t
1038
1040
 
1039
- while (_accumulated >= _stepMs) {
1041
+ while (_accumulated > _stepMs) {
1040
1042
  instance.emit('update', _step * _timeScale)
1041
1043
  instance.setvar('ELAPSED', instance.ELAPSED + _step * _timeScale)
1042
1044
  _accumulated -= _stepMs
@@ -1044,10 +1046,11 @@ export default function litecanvas(settings = {}) {
1044
1046
  }
1045
1047
 
1046
1048
  if (ticks || !_animate) {
1047
- // default custom values for textAlign & textBaseline
1049
+ // default values for textAlign & textBaseline
1048
1050
  instance.textalign('start', 'top')
1049
1051
 
1050
1052
  instance.emit('draw')
1053
+
1051
1054
  _drawCount++
1052
1055
  _drawTime += _stepMs * ticks
1053
1056
 
@@ -1058,8 +1061,8 @@ export default function litecanvas(settings = {}) {
1058
1061
  }
1059
1062
  }
1060
1063
 
1061
- if (_rafid && _animate) {
1062
- _rafid = requestAnimationFrame(drawFrame)
1064
+ if (_focused && _animate) {
1065
+ raf(drawFrame)
1063
1066
  }
1064
1067
  }
1065
1068
 
@@ -1119,8 +1122,7 @@ export default function litecanvas(settings = {}) {
1119
1122
  instance.emit('resized', _scale)
1120
1123
 
1121
1124
  if (!_animate) {
1122
- _lastFrame = performance.now()
1123
- requestAnimationFrame(drawFrame)
1125
+ raf(drawFrame)
1124
1126
  }
1125
1127
  }
1126
1128
 
package/types/index.d.ts CHANGED
@@ -382,6 +382,7 @@ declare global {
382
382
  draw: string[] | drawCallback,
383
383
  options?: {
384
384
  scale?: number
385
+ canvas?: HTMLCanvasElement | OffscreenCanvas
385
386
  }
386
387
  ): OffscreenCanvas
387
388
 
@@ -606,10 +607,19 @@ declare global {
606
607
  /**
607
608
  * Call all listeners attached to a game event
608
609
  *
609
- * @param {string} event The game event type
610
- * @param {...any} args Arguments passed to all listeners
611
- */
612
- function emit(event: string, ...args: any[]): void
610
+ * @param event The game event type
611
+ * @param arg1 any data to be passed over the listeners
612
+ * @param arg2 any data to be passed over the listeners
613
+ * @param arg3 any data to be passed over the listeners
614
+ * @param arg4 any data to be passed over the listeners
615
+ */
616
+ function emit(
617
+ event: string,
618
+ arg1: any,
619
+ arg2: any,
620
+ arg3: any,
621
+ arg4: any
622
+ ): void
613
623
  /**
614
624
  * Get the color value
615
625
  *
package/types/types.d.ts CHANGED
@@ -365,6 +365,7 @@ type LitecanvasInstance = {
365
365
  draw: string[] | drawCallback,
366
366
  options?: {
367
367
  scale?: number
368
+ canvas?: HTMLCanvasElement | OffscreenCanvas
368
369
  }
369
370
  ): OffscreenCanvas
370
371
 
@@ -590,10 +591,13 @@ type LitecanvasInstance = {
590
591
  /**
591
592
  * Call all listeners attached to a game event
592
593
  *
593
- * @param {string} event The game event type
594
- * @param {...any} args Arguments passed to all listeners
594
+ * @param event The game event type
595
+ * @param arg1 any data to be passed over the listeners
596
+ * @param arg2 any data to be passed over the listeners
597
+ * @param arg3 any data to be passed over the listeners
598
+ * @param arg4 any data to be passed over the listeners
595
599
  */
596
- emit(event: string, ...args: any[]): void
600
+ emit(event: string, arg1: any, arg2: any, arg3: any, arg4: any): void
597
601
  /**
598
602
  * Get the color value
599
603
  *