litecanvas 0.51.0 → 0.52.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
  },
@@ -589,7 +589,6 @@
589
589
  * @param {number} [volume=1]
590
590
  * @param {number} [pitch=0]
591
591
  * @param {number} [randomness=null] an float value between 0 and 1
592
- * @returns {AudioBufferSourceNode}
593
592
  *
594
593
  * @see https://github.com/KilledByAPixel/ZzFX
595
594
  * @see https://github.com/litecanvas/game-engine/blob/main/src/sounds.js
@@ -598,14 +597,14 @@
598
597
  if (navigator.userActivation && !navigator.userActivation.hasBeenActive) {
599
598
  return;
600
599
  }
601
- let z = Array.isArray(sound) ? sound : sounds[sound % sounds.length];
600
+ let sample = Array.isArray(sound) ? sound : sounds[sound % sounds.length];
602
601
  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;
602
+ sample = sample.slice();
603
+ sample[0] = (Number(volume) || 1) * (sample[0] || 1);
604
+ sample[1] = randomness != null ? randomness : sample[1];
605
+ sample[10] = ~~sample[10] + ~~pitch;
607
606
  }
608
- return zzfx(...z);
607
+ zzfx.apply(0, sample);
609
608
  },
610
609
  /** UTILS API */
611
610
  /**
@@ -662,7 +661,7 @@
662
661
  /**
663
662
  * Add a game event listener
664
663
  *
665
- * @param {string} event the event type name
664
+ * @param {string} eventName the event type name
666
665
  * @param {function} callback the function that is called when the event occurs
667
666
  * @param {boolean} [highPriority=false] determines whether the callback will be called before or after the others
668
667
  * @returns {function} a function to remove the listener
@@ -679,13 +678,16 @@
679
678
  /**
680
679
  * Call all listeners attached to a game event
681
680
  *
682
- * @param {string} event The game event type
683
- * @param {...any} args Arguments passed to all listeners
681
+ * @param {string} eventName The event type name
682
+ * @param {*} [arg1] any data to be passed over the listeners
683
+ * @param {*} [arg2] any data to be passed over the listeners
684
+ * @param {*} [arg3] any data to be passed over the listeners
685
+ * @param {*} [arg4] any data to be passed over the listeners
684
686
  */
685
- emit(eventName, ...args) {
686
- _emit("before:" + eventName, ...args);
687
- _emit(eventName, ...args);
688
- _emit("after:" + eventName, ...args);
687
+ emit(eventName, arg1, arg2, arg3, arg4) {
688
+ triggerEvent("before:" + eventName, arg1, arg2, arg3, arg4);
689
+ triggerEvent(eventName, arg1, arg2, arg3, arg4);
690
+ triggerEvent("after:" + eventName, arg1, arg2, arg3, arg4);
689
691
  },
690
692
  /**
691
693
  * Get a color by index
@@ -698,7 +700,7 @@
698
700
  * Create or update a instance variable
699
701
  *
700
702
  * @param {string} key
701
- * @param {any} value
703
+ * @param {*} value
702
704
  */
703
705
  setvar(key, value) {
704
706
  instance[key] = value;
@@ -897,15 +899,14 @@
897
899
  }
898
900
  }
899
901
  function pageResized() {
902
+ const pageWidth = root.innerWidth, pageHeight = root.innerHeight;
900
903
  if (_fullscreen) {
901
- _canvas.width = innerWidth;
902
- _canvas.height = innerHeight;
903
- instance.setvar("WIDTH", innerWidth);
904
- instance.setvar("HEIGHT", innerHeight);
904
+ instance.setvar("WIDTH", _canvas.width = pageWidth);
905
+ instance.setvar("HEIGHT", _canvas.height = pageHeight);
905
906
  } else if (_autoscale) {
906
907
  _scale = Math.min(
907
- innerWidth / instance.WIDTH,
908
- innerHeight / instance.HEIGHT
908
+ pageWidth / instance.WIDTH,
909
+ pageHeight / instance.HEIGHT
909
910
  );
910
911
  _scale = settings.pixelart ? Math.floor(_scale) : _scale;
911
912
  _canvas.style.width = instance.WIDTH * _scale + "px";
@@ -919,10 +920,10 @@
919
920
  }
920
921
  instance.emit("resized", _scale);
921
922
  }
922
- function _emit(eventName, ...args) {
923
+ function triggerEvent(eventName, arg1, arg2, arg3, arg4) {
923
924
  if (!_events[eventName]) return;
924
925
  for (const callback of _events[eventName]) {
925
- callback(...args);
926
+ callback(arg1, arg2, arg3, arg4);
926
927
  }
927
928
  }
928
929
  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:()=>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.52.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
@@ -672,7 +672,6 @@ export default function litecanvas(settings = {}) {
672
672
  * @param {number} [volume=1]
673
673
  * @param {number} [pitch=0]
674
674
  * @param {number} [randomness=null] an float value between 0 and 1
675
- * @returns {AudioBufferSourceNode}
676
675
  *
677
676
  * @see https://github.com/KilledByAPixel/ZzFX
678
677
  * @see https://github.com/litecanvas/game-engine/blob/main/src/sounds.js
@@ -685,15 +684,17 @@ export default function litecanvas(settings = {}) {
685
684
  return
686
685
  }
687
686
 
688
- let z = Array.isArray(sound) ? sound : sounds[sound % sounds.length]
687
+ let sample = Array.isArray(sound)
688
+ ? sound
689
+ : sounds[sound % sounds.length]
689
690
  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
691
+ sample = sample.slice()
692
+ sample[0] = (Number(volume) || 1) * (sample[0] || 1)
693
+ sample[1] = randomness != null ? randomness : sample[1]
694
+ sample[10] = ~~sample[10] + ~~pitch
694
695
  }
695
696
 
696
- return zzfx(...z)
697
+ zzfx.apply(0, sample)
697
698
  },
698
699
 
699
700
  /** UTILS API */
@@ -758,7 +759,7 @@ export default function litecanvas(settings = {}) {
758
759
  /**
759
760
  * Add a game event listener
760
761
  *
761
- * @param {string} event the event type name
762
+ * @param {string} eventName the event type name
762
763
  * @param {function} callback the function that is called when the event occurs
763
764
  * @param {boolean} [highPriority=false] determines whether the callback will be called before or after the others
764
765
  * @returns {function} a function to remove the listener
@@ -778,13 +779,16 @@ export default function litecanvas(settings = {}) {
778
779
  /**
779
780
  * Call all listeners attached to a game event
780
781
  *
781
- * @param {string} event The game event type
782
- * @param {...any} args Arguments passed to all listeners
782
+ * @param {string} eventName The event type name
783
+ * @param {*} [arg1] any data to be passed over the listeners
784
+ * @param {*} [arg2] any data to be passed over the listeners
785
+ * @param {*} [arg3] any data to be passed over the listeners
786
+ * @param {*} [arg4] any data to be passed over the listeners
783
787
  */
784
- emit(eventName, ...args) {
785
- _emit('before:' + eventName, ...args)
786
- _emit(eventName, ...args)
787
- _emit('after:' + eventName, ...args)
788
+ emit(eventName, arg1, arg2, arg3, arg4) {
789
+ triggerEvent('before:' + eventName, arg1, arg2, arg3, arg4)
790
+ triggerEvent(eventName, arg1, arg2, arg3, arg4)
791
+ triggerEvent('after:' + eventName, arg1, arg2, arg3, arg4)
788
792
  },
789
793
 
790
794
  /**
@@ -799,7 +803,7 @@ export default function litecanvas(settings = {}) {
799
803
  * Create or update a instance variable
800
804
  *
801
805
  * @param {string} key
802
- * @param {any} value
806
+ * @param {*} value
803
807
  */
804
808
  setvar(key, value) {
805
809
  instance[key] = value
@@ -1058,15 +1062,16 @@ export default function litecanvas(settings = {}) {
1058
1062
  }
1059
1063
 
1060
1064
  function pageResized() {
1065
+ const pageWidth = root.innerWidth,
1066
+ pageHeight = root.innerHeight
1067
+
1061
1068
  if (_fullscreen) {
1062
- _canvas.width = innerWidth
1063
- _canvas.height = innerHeight
1064
- instance.setvar('WIDTH', innerWidth)
1065
- instance.setvar('HEIGHT', innerHeight)
1069
+ instance.setvar('WIDTH', (_canvas.width = pageWidth))
1070
+ instance.setvar('HEIGHT', (_canvas.height = pageHeight))
1066
1071
  } else if (_autoscale) {
1067
1072
  _scale = Math.min(
1068
- innerWidth / instance.WIDTH,
1069
- innerHeight / instance.HEIGHT
1073
+ pageWidth / instance.WIDTH,
1074
+ pageHeight / instance.HEIGHT
1070
1075
  )
1071
1076
  _scale = settings.pixelart ? Math.floor(_scale) : _scale
1072
1077
  _canvas.style.width = instance.WIDTH * _scale + 'px'
@@ -1085,10 +1090,10 @@ export default function litecanvas(settings = {}) {
1085
1090
  instance.emit('resized', _scale)
1086
1091
  }
1087
1092
 
1088
- function _emit(eventName, ...args) {
1093
+ function triggerEvent(eventName, arg1, arg2, arg3, arg4) {
1089
1094
  if (!_events[eventName]) return
1090
1095
  for (const callback of _events[eventName]) {
1091
- callback(...args)
1096
+ callback(arg1, arg2, arg3, arg4)
1092
1097
  }
1093
1098
  }
1094
1099
 
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