litecanvas 0.51.0 → 0.53.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
@@ -43,9 +43,9 @@
43
43
  // src/sounds.js
44
44
  var sounds = [
45
45
  // 0 - pickup
46
- [0.5, , 1675, , 0.06, 0.2, 1, 1.8, , , 837, 0.06],
46
+ [0.5, , 1675, , 0.06, 0.2, 1, 1.8, , , 637, 0.06],
47
47
  // 1 - hit
48
- [1.5, , 820, , , , , 1.5, , 0.3, , 0.1, 1.6, , , 0.1, 0.2],
48
+ [0.7, , 820, , , , , 1.5, , 0.3, , 0.1, 1.6, , , 0.1, 0.2],
49
49
  // 2 - jump
50
50
  [0.7, , 360, 0.01, , 0.08, 1, 1.7, 12, 32, , , , , , , , 0.63, 0.02, , 99],
51
51
  // 3 - powerup
@@ -396,7 +396,7 @@
396
396
  */
397
397
  textmetrics(text, size) {
398
398
  _ctx.font = `${_fontStyle || ""} ${size || _fontSize}px ${_fontFamily}`;
399
- metrics = _ctx.measureText(text);
399
+ const metrics = _ctx.measureText(text);
400
400
  metrics.height = metrics.actualBoundingBoxAscent + metrics.actualBoundingBoxDescent;
401
401
  return metrics;
402
402
  },
@@ -448,11 +448,18 @@
448
448
  },
449
449
  /** ADVANCED GRAPHICS API */
450
450
  /**
451
- * Get the canvas context
451
+ * Get or set the canvas context 2D
452
452
  *
453
+ * @param {CanvasRenderingContext2D} [context]
453
454
  * @returns {CanvasRenderingContext2D}
455
+ * @see https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D
454
456
  */
455
- ctx: () => _ctx,
457
+ ctx: (context) => {
458
+ if (context) {
459
+ _ctx = context;
460
+ }
461
+ return _ctx;
462
+ },
456
463
  /**
457
464
  * saves the current drawing style settings and transformations
458
465
  * @see https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/save
@@ -469,7 +476,7 @@
469
476
  * @param {number} x
470
477
  * @param {number} y
471
478
  */
472
- translate: (x, y) => _ctx.translate(x, y),
479
+ translate: (x, y) => _ctx.translate(~~x, ~~y),
473
480
  /**
474
481
  * Adds a scaling transformation to the canvas units horizontally and/or vertically.
475
482
  *
@@ -589,7 +596,6 @@
589
596
  * @param {number} [volume=1]
590
597
  * @param {number} [pitch=0]
591
598
  * @param {number} [randomness=null] an float value between 0 and 1
592
- * @returns {AudioBufferSourceNode}
593
599
  *
594
600
  * @see https://github.com/KilledByAPixel/ZzFX
595
601
  * @see https://github.com/litecanvas/game-engine/blob/main/src/sounds.js
@@ -598,14 +604,14 @@
598
604
  if (navigator.userActivation && !navigator.userActivation.hasBeenActive) {
599
605
  return;
600
606
  }
601
- let z = Array.isArray(sound) ? sound : sounds[sound % sounds.length];
607
+ let sample = Array.isArray(sound) ? sound : sounds[sound % sounds.length];
602
608
  if (volume !== 1 || pitch || randomness) {
603
- z = [...z];
604
- z[0] = (Number(volume) || 1) * (z[0] || 1);
605
- z[1] = randomness != null ? randomness : z[1];
606
- z[10] = ~~z[10] + ~~pitch;
609
+ sample = sample.slice();
610
+ sample[0] = (Number(volume) || 1) * (sample[0] || 1);
611
+ sample[1] = randomness != null ? randomness : sample[1];
612
+ sample[10] = ~~sample[10] + ~~pitch;
607
613
  }
608
- return zzfx(...z);
614
+ zzfx.apply(0, sample);
609
615
  },
610
616
  /** UTILS API */
611
617
  /**
@@ -662,7 +668,7 @@
662
668
  /**
663
669
  * Add a game event listener
664
670
  *
665
- * @param {string} event the event type name
671
+ * @param {string} eventName the event type name
666
672
  * @param {function} callback the function that is called when the event occurs
667
673
  * @param {boolean} [highPriority=false] determines whether the callback will be called before or after the others
668
674
  * @returns {function} a function to remove the listener
@@ -679,13 +685,16 @@
679
685
  /**
680
686
  * Call all listeners attached to a game event
681
687
  *
682
- * @param {string} event The game event type
683
- * @param {...any} args Arguments passed to all listeners
688
+ * @param {string} eventName The event type name
689
+ * @param {*} [arg1] any data to be passed over the listeners
690
+ * @param {*} [arg2] any data to be passed over the listeners
691
+ * @param {*} [arg3] any data to be passed over the listeners
692
+ * @param {*} [arg4] any data to be passed over the listeners
684
693
  */
685
- emit(eventName, ...args) {
686
- _emit("before:" + eventName, ...args);
687
- _emit(eventName, ...args);
688
- _emit("after:" + eventName, ...args);
694
+ emit(eventName, arg1, arg2, arg3, arg4) {
695
+ triggerEvent("before:" + eventName, arg1, arg2, arg3, arg4);
696
+ triggerEvent(eventName, arg1, arg2, arg3, arg4);
697
+ triggerEvent("after:" + eventName, arg1, arg2, arg3, arg4);
689
698
  },
690
699
  /**
691
700
  * Get a color by index
@@ -698,7 +707,7 @@
698
707
  * Create or update a instance variable
699
708
  *
700
709
  * @param {string} key
701
- * @param {any} value
710
+ * @param {*} value
702
711
  */
703
712
  setvar(key, value) {
704
713
  instance[key] = value;
@@ -897,15 +906,14 @@
897
906
  }
898
907
  }
899
908
  function pageResized() {
909
+ const pageWidth = root.innerWidth, pageHeight = root.innerHeight;
900
910
  if (_fullscreen) {
901
- _canvas.width = innerWidth;
902
- _canvas.height = innerHeight;
903
- instance.setvar("WIDTH", innerWidth);
904
- instance.setvar("HEIGHT", innerHeight);
911
+ instance.setvar("WIDTH", _canvas.width = pageWidth);
912
+ instance.setvar("HEIGHT", _canvas.height = pageHeight);
905
913
  } else if (_autoscale) {
906
914
  _scale = Math.min(
907
- innerWidth / instance.WIDTH,
908
- innerHeight / instance.HEIGHT
915
+ pageWidth / instance.WIDTH,
916
+ pageHeight / instance.HEIGHT
909
917
  );
910
918
  _scale = settings.pixelart ? Math.floor(_scale) : _scale;
911
919
  _canvas.style.width = instance.WIDTH * _scale + "px";
@@ -919,10 +927,10 @@
919
927
  }
920
928
  instance.emit("resized", _scale);
921
929
  }
922
- function _emit(eventName, ...args) {
930
+ function triggerEvent(eventName, arg1, arg2, arg3, arg4) {
923
931
  if (!_events[eventName]) return;
924
932
  for (const callback of _events[eventName]) {
925
- callback(...args);
933
+ callback(arg1, arg2, arg3, arg4);
926
934
  }
927
935
  }
928
936
  function loadPlugin(callback) {
package/dist/dist.min.js CHANGED
@@ -1 +1 @@
1
- (()=>{var e=(e=1,a=.05,n=220,l=0,i=0,r=.1,o=0,s=1,c=0,f=0,p=0,u=0,g=0,h=0,d=0,m=0,v=0,b=1,T=0,x=0,H=0)=>{let y=Math,E=2*y.PI,D=c*=500*E/44100/44100,w=n*=(1-a+2*a*y.random(a=[]))*E/44100,I=0,A=0,P=0,C=1,S=0,W=0,O=0,B=H<0?-1:1,X=E*B*H*2/44100,Y=y.cos(X),k=y.sin,G=k(X)/4,_=1+G,z=-2*Y/_,L=(1-G)/_,M=(1+B*Y)/2/_,N=-(B+Y)/_,R=0,j=0,F=0,$=0;for(l=44100*l+9,T*=44100,i*=44100,r*=44100,v*=44100,f*=500*E/85766121e6,d*=E/44100,p*=E/44100,u*=44100,g=44100*g|0,e*=globalThis.zzfxV||.3,B=l+T+i+r+v|0;P<B;a[P++]=O*e)++W%(100*m|0)||(O=o?1<o?2<o?3<o?k(I*I):y.max(y.min(y.tan(I),1),-1):1-(2*I/E%2+2)%2:1-4*y.abs(y.round(I/E)-I/E):k(I),O=(g?1-x+x*k(E*P/g):1)*(O<0?-1:1)*y.abs(O)**s*(P<l?P/l:P<l+T?1-(P-l)/T*(1-b):P<l+T+i?b:P<B-v?(B-P-v)/r*b:0),O=v?O/2+(v>P?0:(P<B-v?1:(B-P)/v)*a[P-v|0]/2/e):O,H&&(O=$=M*R+N*(R=j)+M*(j=O)-L*F-z*(F=$))),I+=(X=(n+=c+=f)*y.cos(d*A++))+X*h*k(P**5),C&&++C>u&&(n+=p,w+=p,C=0),!g||++S%g||(n=w,c=D,C=C||1);(e=t.createBuffer(1,B,44100)).getChannelData(0).set(a),(n=t.createBufferSource()).buffer=e,n.connect(t.destination),n.start()},t=/* @__PURE__ */new AudioContext,a=["#18161c","#6a7799","#aec2c2","#f3eade","#f04f78","#fcf660","#2f328f","#4b80ca","#327345","#63c64d","#703075","#a56243"],n=[[.5,,1675,,.06,.2,1,1.8,,,837,.06],[1.5,,820,,,,,1.5,,.3,,.1,1.6,,,.1,.2],[.7,,360,.01,,.08,1,1.7,12,32,,,,,,,,.63,.02,,99],[,,300,.02,.1,,1,3.2,,,100,.08,.1,,,,,.6,.25,.3]];globalThis.litecanvas=function(t={}){let l=globalThis,i=Math.PI,r=2*i,o=(e,t,a)=>e.addEventListener(t,a);t=Object.assign({fps:60,fullscreen:!0,width:null,height:null,autoscale:!0,pixelart:!1,antialias:!0,canvas:null,global:!0,loop:null,tapEvents:!0,pauseOnBlur:!0},t);let s=!1,c=[],f=t.canvas||document.createElement("canvas"),p=t.fullscreen,u=t.autoscale,g=1,h,d,m,v=1,b,T=1/t.fps,x=1e3*T,H=0,y,E=0,D=0,w="sans-serif",I="",A=32,P=Date.now(),C={init:!1,update:!1,draw:!1,resized:!1,tap:!1,untap:!1,tapping:!1,tapped:!1},S={settings:Object.assign({},t),colors:a,sounds:n},W={WIDTH:t.width,HEIGHT:t.height||t.width,CANVAS:null,ELAPSED:0,FPS:t.fps,CENTERX:null,CENTERY:null,PI:i,TWO_PI:r,HALF_PI:.5*i,lerp:(e,t,a)=>e+a*(t-e),deg2rad:e=>i/180*e,rad2deg:e=>180/i*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,i=!1){let r=(e-t)/(a-t)*(l-n)+n;return i?W.clamp(r,n,l):r},norm:(e,t,a)=>W.map(e,t,a,0,1),rand:(e=0,t=1)=>(P=(1664525*P+0x3c6ef35f)%0x100000000)/0x100000000*(t-e)+e,randi:(e=0,t=1)=>W.floor(W.rand()*(t-e+1)+e),seed:e=>null==e?P:P=~~e,cls(e){null==e?m.clearRect(0,0,W.WIDTH,W.HEIGHT):W.rectfill(0,0,W.WIDTH,W.HEIGHT,e)},rect(e,t,a,n,l=0,i=null){m.beginPath(),m[i?"roundRect":"rect"](~~e,~~t,a,n,i),W.stroke(l)},rectfill(e,t,a,n,l=0,i=null){m.beginPath(),m[i?"roundRect":"rect"](~~e,~~t,a,n,i),W.fill(l)},circ(e,t,a,n){m.beginPath(),m.arc(~~e,~~t,a,0,r),m.closePath(),W.stroke(n)},circfill(e,t,a,n){m.beginPath(),m.arc(~~e,~~t,a,0,r),m.closePath(),W.fill(n)},line(e,t,a,n,l){m.beginPath(),m.moveTo(~~e,~~t),m.lineTo(~~a,~~n),W.stroke(l)},linewidth(e){m.lineWidth=e},linedash(e,t=0){m.setLineDash(Array.isArray(e)?e:[e]),m.lineDashOffset=t},text(e,t,a,n=3){m.font=`${I||""} ${A}px ${w}`,m.fillStyle=W.getcolor(n),m.fillText(a,~~e,~~t)},textfont(e){w=e},textsize(e){A=e},textstyle(e){I=e},textalign(e,t){e&&(m.textAlign=e),t&&(m.textBaseline=t)},textmetrics:(e,t)=>(m.font=`${I||""} ${t||A}px ${w}`,(metrics=m.measureText(e)).height=metrics.actualBoundingBoxAscent+metrics.actualBoundingBoxDescent,metrics),image(e,t,a){m.drawImage(a,~~e,~~t)},paint(e,t,a,n={}){let l=new OffscreenCanvas(e,t),i=m,r=n.scale||1;if(l.width=e*r,l.height=t*r,(m=l.getContext("2d")).scale(r,r),Array.isArray(a)){let e=0,t=0;for(let n of(m.imageSmoothingEnabled=!1,a)){for(let a of n)" "!==a&&"."!==a&&W.rectfill(e,t,1,1,parseInt(a,16)),e++;t++,e=0}}else a(l,m);return m=i,l},ctx:()=>m,push:()=>m.save(),pop:()=>m.restore(),translate:(e,t)=>m.translate(e,t),scale:(e,t)=>m.scale(e,t||e),rotate:e=>m.rotate(e),transform:(e,t,a,n,l,i,r=!0)=>m[r?"setTransform":"transform"](e,t,a,n,l,i),alpha(e){m.globalAlpha=W.clamp(e,0,1)},path:e=>new Path2D(e),fill(e,t){m.fillStyle=W.getcolor(e),m.fill(t)},stroke(e,t){m.strokeStyle=W.getcolor(e),t?m.stroke(t):m.stroke()},cliprect(e,t,a,n){m.beginPath(),m.rect(e,t,a,n),m.clip()},clipcirc(e,t,a){m.beginPath(),m.arc(e,t,a,0,r),m.clip()},blendmode(e){m.globalCompositeOperation=e},sfx(t=0,a=1,l=0,i=null){if(navigator.userActivation&&!navigator.userActivation.hasBeenActive)return;let r=Array.isArray(t)?t:n[t%n.length];return(1!==a||l||i)&&((r=[...r])[0]=(Number(a)||1)*(r[0]||1),r[1]=null!=i?i:r[1],r[10]=~~r[10]+~~l),e(...r)},colrect:(e,t,a,n,l,i,r,o)=>e<l+r&&e+a>l&&t<i+o&&t+n>i,colcirc:(e,t,a,n,l,i)=>(n-e)**2+(l-t)**2<=(a+i)**2,mousepos:()=>[h,d],timescale(e){v=e},use(e,t={}){e.__conf=t,s?k(e):c.push(e)},listen:(e,t)=>(C[e]=C[e]||[],C[e].push(t),()=>{C[e]=C[e].filter(e=>t!==e)}),emit(e,...t){Y("before:"+e,...t),Y(e,...t),Y("after:"+e,...t)},getcolor:e=>a[~~e%a.length],setvar(e,a){W[e]=a,t.global&&(l[e]=a)},resize(e,t){W.setvar("WIDTH",f.width=e),W.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"])W[e]=Math[e];function O(){s=!0,f="string"==typeof f?document.querySelector(f):f,W.setvar("CANVAS",f),m=f.getContext("2d"),W.WIDTH>0&&(p=!1),f.width=W.WIDTH,f.height=W.HEIGHT||W.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 e=t.loop?t.loop:l;for(let t of Object.keys(C))e[t]&&W.listen(t,e[t]);for(let e of c)k(e);if(o(l,"resize",X),X(),t.tapEvents){let e=(e,t)=>[(e-f.offsetLeft)/g,(t-f.offsetTop)/g],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},n=(e,n,l)=>{let i=t.get(e)||a(e);i.x=n,i.y=l},i=e=>e&&performance.now()-e.ts<=200,r=!1;o(f,"mousedown",t=>{t.preventDefault();let[n,l]=e(t.pageX,t.pageY);W.emit("tap",n,l,0),a(0,n,l),r=!0}),o(f,"mousemove",t=>{t.preventDefault();let[a,l]=[h,d]=e(t.pageX,t.pageY);r&&(W.emit("tapping",a,l,0),n(0,a,l))}),o(f,"mouseup",a=>{a.preventDefault();let n=t.get(0),[l,o]=e(a.pageX,a.pageY);i(n)&&W.emit("tapped",n.startX,n.startY,0),W.emit("untap",l,o,0),t.delete(0),r=!1}),o(f,"touchstart",t=>{for(let n of(t.preventDefault(),t.changedTouches)){let[t,l]=e(n.pageX,n.pageY);W.emit("tap",t,l,n.identifier+1),a(n.identifier+1,t,l)}}),o(f,"touchmove",t=>{for(let a of(t.preventDefault(),t.changedTouches)){let[t,l]=e(a.pageX,a.pageY);W.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,n]of t)a.includes(e)||(i(n)&&W.emit("tapped",n.startX,n.startY,e),W.emit("untap",n.x,n.y,e),t.delete(e))};o(f,"touchend",s),o(f,"touchcancel",s),o(l,"blur",()=>{if(r=!1,0!==t.size)for(let[e,a]of t)W.emit("untap",a.x,a.y,e),t.delete(e)})}t.pauseOnBlur&&(o(l,"blur",()=>{y=null}),o(l,"focus",()=>{y||(b=performance.now(),y=requestAnimationFrame(B))})),W.emit("init"),b=performance.now(),y=requestAnimationFrame(B)}function B(e){let t=0,a=e-b;for(b=e,H+=a;H>=x;)W.emit("update",T*v),W.setvar("ELAPSED",W.ELAPSED+T*v),H-=x,t++;t&&(W.textalign("start","top"),W.emit("draw"),E++,(D+=x*t)+H>=1e3&&(W.setvar("FPS",E),E=0,D-=1e3)),y&&(y=requestAnimationFrame(B))}function X(){p?(f.width=innerWidth,f.height=innerHeight,W.setvar("WIDTH",innerWidth),W.setvar("HEIGHT",innerHeight)):u&&(g=Math.min(innerWidth/W.WIDTH,innerHeight/W.HEIGHT),g=t.pixelart?Math.floor(g):g,f.style.width=W.WIDTH*g+"px",f.style.height=W.HEIGHT*g+"px"),W.setvar("CENTERX",W.WIDTH/2),W.setvar("CENTERY",W.HEIGHT/2),(!t.antialias||t.pixelart)&&(m.imageSmoothingEnabled=!1,f.style.imageRendering="pixelated"),W.emit("resized",g)}function Y(e,...t){if(C[e])for(let a of C[e])a(...t)}function k(e){let t=e(W,S,e.__conf);if("object"==typeof t)for(let[e,a]of Object.entries(t))W.setvar(e,a)}if(t.global){if(l.__litecanvas)throw"Cannot instantiate litecanvas globally twice";Object.assign(l,W),l.__litecanvas=W}return"loading"===document.readyState?o(l,"DOMContentLoaded",O):O(),W}})();
1
+ (()=>{var e=(e=1,a=.05,l=220,n=0,i=0,r=.1,o=0,s=1,c=0,f=0,p=0,u=0,g=0,d=0,h=0,m=0,v=0,b=1,T=0,x=0,H=0)=>{let y=Math,E=2*y.PI,D=c*=500*E/44100/44100,w=l*=(1-a+2*a*y.random(a=[]))*E/44100,I=0,A=0,P=0,C=1,S=0,W=0,O=0,B=H<0?-1:1,X=E*B*H*2/44100,Y=y.cos(X),k=y.sin,G=k(X)/4,_=1+G,z=-2*Y/_,L=(1-G)/_,M=(1+B*Y)/2/_,N=-(B+Y)/_,R=0,j=0,F=0,$=0;for(n=44100*n+9,T*=44100,i*=44100,r*=44100,v*=44100,f*=500*E/85766121e6,h*=E/44100,p*=E/44100,u*=44100,g=44100*g|0,e*=globalThis.zzfxV||.3,B=n+T+i+r+v|0;P<B;a[P++]=O*e)++W%(100*m|0)||(O=o?1<o?2<o?3<o?k(I*I):y.max(y.min(y.tan(I),1),-1):1-(2*I/E%2+2)%2:1-4*y.abs(y.round(I/E)-I/E):k(I),O=(g?1-x+x*k(E*P/g):1)*(O<0?-1:1)*y.abs(O)**s*(P<n?P/n:P<n+T?1-(P-n)/T*(1-b):P<n+T+i?b:P<B-v?(B-P-v)/r*b:0),O=v?O/2+(v>P?0:(P<B-v?1:(B-P)/v)*a[P-v|0]/2/e):O,H&&(O=$=M*R+N*(R=j)+M*(j=O)-L*F-z*(F=$))),I+=(X=(l+=c+=f)*y.cos(h*A++))+X*d*k(P**5),C&&++C>u&&(l+=p,w+=p,C=0),!g||++S%g||(l=w,c=D,C=C||1);(e=t.createBuffer(1,B,44100)).getChannelData(0).set(a),(l=t.createBufferSource()).buffer=e,l.connect(t.destination),l.start()},t=/* @__PURE__ */new AudioContext,a=["#18161c","#6a7799","#aec2c2","#f3eade","#f04f78","#fcf660","#2f328f","#4b80ca","#327345","#63c64d","#703075","#a56243"],l=[[.5,,1675,,.06,.2,1,1.8,,,637,.06],[.7,,820,,,,,1.5,,.3,,.1,1.6,,,.1,.2],[.7,,360,.01,,.08,1,1.7,12,32,,,,,,,,.63,.02,,99],[,,300,.02,.1,,1,3.2,,,100,.08,.1,,,,,.6,.25,.3]];globalThis.litecanvas=function(t={}){let n=globalThis,i=Math.PI,r=2*i,o=(e,t,a)=>e.addEventListener(t,a);t=Object.assign({fps:60,fullscreen:!0,width:null,height:null,autoscale:!0,pixelart:!1,antialias:!0,canvas:null,global:!0,loop:null,tapEvents:!0,pauseOnBlur:!0},t);let s=!1,c=[],f=t.canvas||document.createElement("canvas"),p=t.fullscreen,u=t.autoscale,g=1,d,h,m,v=1,b,T=1/t.fps,x=1e3*T,H=0,y,E=0,D=0,w="sans-serif",I="",A=32,P=Date.now(),C={init:!1,update:!1,draw:!1,resized:!1,tap:!1,untap:!1,tapping:!1,tapped:!1},S={settings:Object.assign({},t),colors:a,sounds:l},W={WIDTH:t.width,HEIGHT:t.height||t.width,CANVAS:null,ELAPSED:0,FPS:t.fps,CENTERX:null,CENTERY:null,PI:i,TWO_PI:r,HALF_PI:.5*i,lerp:(e,t,a)=>e+a*(t-e),deg2rad:e=>i/180*e,rad2deg:e=>180/i*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,i=!1){let r=(e-t)/(a-t)*(n-l)+l;return i?W.clamp(r,l,n):r},norm:(e,t,a)=>W.map(e,t,a,0,1),rand:(e=0,t=1)=>(P=(1664525*P+0x3c6ef35f)%0x100000000)/0x100000000*(t-e)+e,randi:(e=0,t=1)=>W.floor(W.rand()*(t-e+1)+e),seed:e=>null==e?P:P=~~e,cls(e){null==e?m.clearRect(0,0,W.WIDTH,W.HEIGHT):W.rectfill(0,0,W.WIDTH,W.HEIGHT,e)},rect(e,t,a,l,n=0,i=null){m.beginPath(),m[i?"roundRect":"rect"](~~e,~~t,a,l,i),W.stroke(n)},rectfill(e,t,a,l,n=0,i=null){m.beginPath(),m[i?"roundRect":"rect"](~~e,~~t,a,l,i),W.fill(n)},circ(e,t,a,l){m.beginPath(),m.arc(~~e,~~t,a,0,r),m.closePath(),W.stroke(l)},circfill(e,t,a,l){m.beginPath(),m.arc(~~e,~~t,a,0,r),m.closePath(),W.fill(l)},line(e,t,a,l,n){m.beginPath(),m.moveTo(~~e,~~t),m.lineTo(~~a,~~l),W.stroke(n)},linewidth(e){m.lineWidth=e},linedash(e,t=0){m.setLineDash(Array.isArray(e)?e:[e]),m.lineDashOffset=t},text(e,t,a,l=3){m.font=`${I||""} ${A}px ${w}`,m.fillStyle=W.getcolor(l),m.fillText(a,~~e,~~t)},textfont(e){w=e},textsize(e){A=e},textstyle(e){I=e},textalign(e,t){e&&(m.textAlign=e),t&&(m.textBaseline=t)},textmetrics(e,t){m.font=`${I||""} ${t||A}px ${w}`;let a=m.measureText(e);return a.height=a.actualBoundingBoxAscent+a.actualBoundingBoxDescent,a},image(e,t,a){m.drawImage(a,~~e,~~t)},paint(e,t,a,l={}){let n=new OffscreenCanvas(e,t),i=m,r=l.scale||1;if(n.width=e*r,n.height=t*r,(m=n.getContext("2d")).scale(r,r),Array.isArray(a)){let e=0,t=0;for(let l of(m.imageSmoothingEnabled=!1,a)){for(let a of l)" "!==a&&"."!==a&&W.rectfill(e,t,1,1,parseInt(a,16)),e++;t++,e=0}}else a(n,m);return m=i,n},ctx:e=>(e&&(m=e),m),push:()=>m.save(),pop:()=>m.restore(),translate:(e,t)=>m.translate(~~e,~~t),scale:(e,t)=>m.scale(e,t||e),rotate:e=>m.rotate(e),transform:(e,t,a,l,n,i,r=!0)=>m[r?"setTransform":"transform"](e,t,a,l,n,i),alpha(e){m.globalAlpha=W.clamp(e,0,1)},path:e=>new Path2D(e),fill(e,t){m.fillStyle=W.getcolor(e),m.fill(t)},stroke(e,t){m.strokeStyle=W.getcolor(e),t?m.stroke(t):m.stroke()},cliprect(e,t,a,l){m.beginPath(),m.rect(e,t,a,l),m.clip()},clipcirc(e,t,a){m.beginPath(),m.arc(e,t,a,0,r),m.clip()},blendmode(e){m.globalCompositeOperation=e},sfx(t=0,a=1,n=0,i=null){if(navigator.userActivation&&!navigator.userActivation.hasBeenActive)return;let r=Array.isArray(t)?t:l[t%l.length];(1!==a||n||i)&&((r=r.slice())[0]=(Number(a)||1)*(r[0]||1),r[1]=null!=i?i:r[1],r[10]=~~r[10]+~~n),e.apply(0,r)},colrect:(e,t,a,l,n,i,r,o)=>e<n+r&&e+a>n&&t<i+o&&t+l>i,colcirc:(e,t,a,l,n,i)=>(l-e)**2+(n-t)**2<=(a+i)**2,mousepos:()=>[d,h],timescale(e){v=e},use(e,t={}){e.__conf=t,s?k(e):c.push(e)},listen:(e,t)=>(C[e]=C[e]||[],C[e].push(t),()=>{C[e]=C[e].filter(e=>t!==e)}),emit(e,t,a,l,n){Y("before:"+e,t,a,l,n),Y(e,t,a,l,n),Y("after:"+e,t,a,l,n)},getcolor:e=>a[~~e%a.length],setvar(e,a){W[e]=a,t.global&&(n[e]=a)},resize(e,t){W.setvar("WIDTH",f.width=e),W.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"])W[e]=Math[e];function O(){s=!0,f="string"==typeof f?document.querySelector(f):f,W.setvar("CANVAS",f),m=f.getContext("2d"),W.WIDTH>0&&(p=!1),f.width=W.WIDTH,f.height=W.HEIGHT||W.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 e=t.loop?t.loop:n;for(let t of Object.keys(C))e[t]&&W.listen(t,e[t]);for(let e of c)k(e);if(o(n,"resize",X),X(),t.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},l=(e,l,n)=>{let i=t.get(e)||a(e);i.x=l,i.y=n},i=e=>e&&performance.now()-e.ts<=200,r=!1;o(f,"mousedown",t=>{t.preventDefault();let[l,n]=e(t.pageX,t.pageY);W.emit("tap",l,n,0),a(0,l,n),r=!0}),o(f,"mousemove",t=>{t.preventDefault();let[a,n]=[d,h]=e(t.pageX,t.pageY);r&&(W.emit("tapping",a,n,0),l(0,a,n))}),o(f,"mouseup",a=>{a.preventDefault();let l=t.get(0),[n,o]=e(a.pageX,a.pageY);i(l)&&W.emit("tapped",l.startX,l.startY,0),W.emit("untap",n,o,0),t.delete(0),r=!1}),o(f,"touchstart",t=>{for(let l of(t.preventDefault(),t.changedTouches)){let[t,n]=e(l.pageX,l.pageY);W.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,n]=e(a.pageX,a.pageY);W.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,l]of t)a.includes(e)||(i(l)&&W.emit("tapped",l.startX,l.startY,e),W.emit("untap",l.x,l.y,e),t.delete(e))};o(f,"touchend",s),o(f,"touchcancel",s),o(n,"blur",()=>{if(r=!1,0!==t.size)for(let[e,a]of t)W.emit("untap",a.x,a.y,e),t.delete(e)})}t.pauseOnBlur&&(o(n,"blur",()=>{y=null}),o(n,"focus",()=>{y||(b=performance.now(),y=requestAnimationFrame(B))})),W.emit("init"),b=performance.now(),y=requestAnimationFrame(B)}function B(e){let t=0,a=e-b;for(b=e,H+=a;H>=x;)W.emit("update",T*v),W.setvar("ELAPSED",W.ELAPSED+T*v),H-=x,t++;t&&(W.textalign("start","top"),W.emit("draw"),E++,(D+=x*t)+H>=1e3&&(W.setvar("FPS",E),E=0,D-=1e3)),y&&(y=requestAnimationFrame(B))}function X(){let e=n.innerWidth,a=n.innerHeight;p?(W.setvar("WIDTH",f.width=e),W.setvar("HEIGHT",f.height=a)):u&&(g=Math.min(e/W.WIDTH,a/W.HEIGHT),g=t.pixelart?Math.floor(g):g,f.style.width=W.WIDTH*g+"px",f.style.height=W.HEIGHT*g+"px"),W.setvar("CENTERX",W.WIDTH/2),W.setvar("CENTERY",W.HEIGHT/2),(!t.antialias||t.pixelart)&&(m.imageSmoothingEnabled=!1,f.style.imageRendering="pixelated"),W.emit("resized",g)}function Y(e,t,a,l,n){if(C[e])for(let i of C[e])i(t,a,l,n)}function k(e){let t=e(W,S,e.__conf);if("object"==typeof t)for(let[e,a]of Object.entries(t))W.setvar(e,a)}if(t.global){if(n.__litecanvas)throw"Cannot instantiate litecanvas globally twice";Object.assign(n,W),n.__litecanvas=W}return"loading"===document.readyState?o(n,"DOMContentLoaded",O):O(),W}})();
package/package.json CHANGED
@@ -1,13 +1,14 @@
1
1
  {
2
2
  "name": "litecanvas",
3
- "version": "0.51.0",
3
+ "version": "0.53.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>",
7
7
  "contributors": [],
8
8
  "devDependencies": {
9
9
  "ava": "^6.1.3",
10
- "esbuild": "^0.23.1"
10
+ "esbuild": "^0.23.1",
11
+ "@swc/core": "^1.7.26"
11
12
  },
12
13
  "homepage": "https://litecanvas.github.io/about.html",
13
14
  "repository": {
@@ -50,8 +51,5 @@
50
51
  "tests/**/*",
51
52
  "!tests/_mocks"
52
53
  ]
53
- },
54
- "dependencies": {
55
- "@swc/core": "^1.7.26"
56
54
  }
57
55
  }
package/src/index.js CHANGED
@@ -13,7 +13,7 @@ export default function litecanvas(settings = {}) {
13
13
  const root = globalThis,
14
14
  PI = Math.PI,
15
15
  TWO_PI = PI * 2,
16
- /** @type {(elem:HTMLElement, evt:string, callback:(event:Event)=>boolean?)=>void} */
16
+ /** @type {(elem:HTMLElement, evt:string, callback:(event:Event)=>void)=>void} */
17
17
  on = (elem, evt, callback) => elem.addEventListener(evt, callback),
18
18
  /** @type {LitecanvasOptions} */
19
19
  defaults = {
@@ -447,7 +447,7 @@ export default function litecanvas(settings = {}) {
447
447
  textmetrics(text, size) {
448
448
  // prettier-ignore
449
449
  _ctx.font = `${_fontStyle || ''} ${(size || _fontSize)}px ${_fontFamily}`
450
- metrics = _ctx.measureText(text)
450
+ const metrics = _ctx.measureText(text)
451
451
  metrics.height =
452
452
  metrics.actualBoundingBoxAscent +
453
453
  metrics.actualBoundingBoxDescent
@@ -516,11 +516,18 @@ export default function litecanvas(settings = {}) {
516
516
 
517
517
  /** ADVANCED GRAPHICS API */
518
518
  /**
519
- * Get the canvas context
519
+ * Get or set the canvas context 2D
520
520
  *
521
+ * @param {CanvasRenderingContext2D} [context]
521
522
  * @returns {CanvasRenderingContext2D}
523
+ * @see https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D
522
524
  */
523
- ctx: () => _ctx,
525
+ ctx: (context) => {
526
+ if (context) {
527
+ _ctx = context
528
+ }
529
+ return _ctx
530
+ },
524
531
 
525
532
  /**
526
533
  * saves the current drawing style settings and transformations
@@ -540,7 +547,7 @@ export default function litecanvas(settings = {}) {
540
547
  * @param {number} x
541
548
  * @param {number} y
542
549
  */
543
- translate: (x, y) => _ctx.translate(x, y),
550
+ translate: (x, y) => _ctx.translate(~~x, ~~y),
544
551
 
545
552
  /**
546
553
  * Adds a scaling transformation to the canvas units horizontally and/or vertically.
@@ -672,7 +679,6 @@ export default function litecanvas(settings = {}) {
672
679
  * @param {number} [volume=1]
673
680
  * @param {number} [pitch=0]
674
681
  * @param {number} [randomness=null] an float value between 0 and 1
675
- * @returns {AudioBufferSourceNode}
676
682
  *
677
683
  * @see https://github.com/KilledByAPixel/ZzFX
678
684
  * @see https://github.com/litecanvas/game-engine/blob/main/src/sounds.js
@@ -685,15 +691,17 @@ export default function litecanvas(settings = {}) {
685
691
  return
686
692
  }
687
693
 
688
- let z = Array.isArray(sound) ? sound : sounds[sound % sounds.length]
694
+ let sample = Array.isArray(sound)
695
+ ? sound
696
+ : sounds[sound % sounds.length]
689
697
  if (volume !== 1 || pitch || randomness) {
690
- z = [...z] // clone the sound to not modify the original
691
- z[0] = (Number(volume) || 1) * (z[0] || 1)
692
- z[1] = randomness != null ? randomness : z[1]
693
- z[10] = ~~z[10] + ~~pitch
698
+ sample = sample.slice()
699
+ sample[0] = (Number(volume) || 1) * (sample[0] || 1)
700
+ sample[1] = randomness != null ? randomness : sample[1]
701
+ sample[10] = ~~sample[10] + ~~pitch
694
702
  }
695
703
 
696
- return zzfx(...z)
704
+ zzfx.apply(0, sample)
697
705
  },
698
706
 
699
707
  /** UTILS API */
@@ -758,7 +766,7 @@ export default function litecanvas(settings = {}) {
758
766
  /**
759
767
  * Add a game event listener
760
768
  *
761
- * @param {string} event the event type name
769
+ * @param {string} eventName the event type name
762
770
  * @param {function} callback the function that is called when the event occurs
763
771
  * @param {boolean} [highPriority=false] determines whether the callback will be called before or after the others
764
772
  * @returns {function} a function to remove the listener
@@ -778,13 +786,16 @@ export default function litecanvas(settings = {}) {
778
786
  /**
779
787
  * Call all listeners attached to a game event
780
788
  *
781
- * @param {string} event The game event type
782
- * @param {...any} args Arguments passed to all listeners
789
+ * @param {string} eventName The event type name
790
+ * @param {*} [arg1] any data to be passed over the listeners
791
+ * @param {*} [arg2] any data to be passed over the listeners
792
+ * @param {*} [arg3] any data to be passed over the listeners
793
+ * @param {*} [arg4] any data to be passed over the listeners
783
794
  */
784
- emit(eventName, ...args) {
785
- _emit('before:' + eventName, ...args)
786
- _emit(eventName, ...args)
787
- _emit('after:' + eventName, ...args)
795
+ emit(eventName, arg1, arg2, arg3, arg4) {
796
+ triggerEvent('before:' + eventName, arg1, arg2, arg3, arg4)
797
+ triggerEvent(eventName, arg1, arg2, arg3, arg4)
798
+ triggerEvent('after:' + eventName, arg1, arg2, arg3, arg4)
788
799
  },
789
800
 
790
801
  /**
@@ -799,7 +810,7 @@ export default function litecanvas(settings = {}) {
799
810
  * Create or update a instance variable
800
811
  *
801
812
  * @param {string} key
802
- * @param {any} value
813
+ * @param {*} value
803
814
  */
804
815
  setvar(key, value) {
805
816
  instance[key] = value
@@ -1058,15 +1069,16 @@ export default function litecanvas(settings = {}) {
1058
1069
  }
1059
1070
 
1060
1071
  function pageResized() {
1072
+ const pageWidth = root.innerWidth,
1073
+ pageHeight = root.innerHeight
1074
+
1061
1075
  if (_fullscreen) {
1062
- _canvas.width = innerWidth
1063
- _canvas.height = innerHeight
1064
- instance.setvar('WIDTH', innerWidth)
1065
- instance.setvar('HEIGHT', innerHeight)
1076
+ instance.setvar('WIDTH', (_canvas.width = pageWidth))
1077
+ instance.setvar('HEIGHT', (_canvas.height = pageHeight))
1066
1078
  } else if (_autoscale) {
1067
1079
  _scale = Math.min(
1068
- innerWidth / instance.WIDTH,
1069
- innerHeight / instance.HEIGHT
1080
+ pageWidth / instance.WIDTH,
1081
+ pageHeight / instance.HEIGHT
1070
1082
  )
1071
1083
  _scale = settings.pixelart ? Math.floor(_scale) : _scale
1072
1084
  _canvas.style.width = instance.WIDTH * _scale + 'px'
@@ -1085,10 +1097,10 @@ export default function litecanvas(settings = {}) {
1085
1097
  instance.emit('resized', _scale)
1086
1098
  }
1087
1099
 
1088
- function _emit(eventName, ...args) {
1100
+ function triggerEvent(eventName, arg1, arg2, arg3, arg4) {
1089
1101
  if (!_events[eventName]) return
1090
1102
  for (const callback of _events[eventName]) {
1091
- callback(...args)
1103
+ callback(arg1, arg2, arg3, arg4)
1092
1104
  }
1093
1105
  }
1094
1106
 
package/src/sounds.js CHANGED
@@ -1,9 +1,9 @@
1
1
  // prettier-ignore
2
2
  export const sounds = [
3
3
  // 0 - pickup
4
- [0.5, , 1675, , 0.06, 0.2, 1, 1.8, , , 837, 0.06],
4
+ [0.5, , 1675, , 0.06, 0.2, 1, 1.8, , , 637, 0.06],
5
5
  // 1 - hit
6
- [1.5, , 820, , , , , 1.5, , 0.3, , 0.1, 1.6, , , 0.1, 0.2],
6
+ [0.7, , 820, , , , , 1.5, , 0.3, , 0.1, 1.6, , , 0.1, 0.2],
7
7
  // 2 - jump
8
8
  [0.7, , 360, 0.01, , 0.08, 1, 1.7, 12, 32, , , , , , , , 0.63, 0.02, , 99],
9
9
  // 3 - powerup
package/src/types.js CHANGED
@@ -43,14 +43,14 @@
43
43
  /**
44
44
  * @typedef LitecanvasPluginHelpers
45
45
  * @type {object}
46
- * @property {string[]} colors - the instance color palette
47
- * @property {number[][]} sounds - the instance ZzFX sounds
48
- * @property {LitecanvasOptions} settings - an copy of this instance settings
46
+ * @property {string[]} colors The instance color palette
47
+ * @property {number[][]} sounds The instance ZzFX sounds
48
+ * @property {LitecanvasOptions} settings An copy of this instance settings
49
49
  */
50
50
 
51
51
  /**
52
52
  * @callback pluginCallback
53
- * @param {LitecanvasInstance} instance - The litecanvas instance
53
+ * @param {LitecanvasInstance} instance The litecanvas instance
54
54
  * @param {LitecanvasPluginHelpers} helpers
55
55
  * @returns
56
56
  */
package/types/index.d.ts CHANGED
@@ -379,11 +379,10 @@ declare global {
379
379
  ): OffscreenCanvas
380
380
  /** ADVANCED GRAPHICS API */
381
381
  /**
382
- * Get the canvas context
383
- *
384
- * @returns {CanvasRenderingContext2D}
382
+ * Get or set the canvas context 2D
383
+ * @see https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D
385
384
  */
386
- function ctx(): CanvasRenderingContext2D
385
+ function ctx(value?: CanvasRenderingContext2D): CanvasRenderingContext2D
387
386
  /**
388
387
  * saves the current drawing style settings and transformations
389
388
  * @see https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/save
@@ -593,10 +592,7 @@ declare global {
593
592
  * @param {boolean} [highPriority=false] determines whether the callback will be called before or after the others
594
593
  * @returns {function?} a function to remove the listener
595
594
  */
596
- function listen(
597
- event: string,
598
- callback: Function
599
- ): Function | null
595
+ function listen(event: string, callback: Function): Function | null
600
596
  /**
601
597
  * Call all listeners attached to a game event
602
598
  *
package/types/types.d.ts CHANGED
@@ -364,11 +364,10 @@ type LitecanvasInstance = {
364
364
 
365
365
  /** ADVANCED GRAPHICS API */
366
366
  /**
367
- * Get the canvas context
368
- *
369
- * @returns {CanvasRenderingContext2D}
367
+ * Get or set the canvas context 2D
368
+ * @see https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D
370
369
  */
371
- ctx(): CanvasRenderingContext2D
370
+ ctx(value?: CanvasRenderingContext2D): CanvasRenderingContext2D
372
371
  /**
373
372
  * saves the current drawing style settings and transformations
374
373
  * @see https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/save