litecanvas 0.47.2 → 0.50.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,13 +43,13 @@
43
43
  // src/sounds.js
44
44
  var sounds = [
45
45
  // 0 - pickup
46
- [0.8, 0, 2e3, 0.01, 0.05, , 1, 2, , , -600, 0.05, , , , , , 0.5, 0.05],
46
+ [0.8, , 2e3, 0.01, 0.05, , 1, 2, , , -600, 0.05, , , , , , 0.5, 0.05],
47
47
  // 1 - hit
48
- [0.5, 0, 375, 0.02, 0.01, 0.2, 1, , , , , , , 0.4, , 0.1, , 0.6, 0.1],
48
+ [0.5, , 375, 0.02, 0.01, 0.2, 1, , , , , , , 0.4, , 0.1, , 0.6, 0.1],
49
49
  // 2 - jump
50
- [, 0, 360, 0.01, , 0.08, 1, 1.7, 12, 32, , , , , , , , 0.63, 0.02, , 99],
50
+ [, , 360, 0.01, , 0.08, 1, 1.7, 12, 32, , , , , , , , 0.63, 0.02, , 99],
51
51
  // 3 - warning
52
- [1.2, 0, 240, 0.02, 0.15, 0.15, 1, 4, , , , , 0.05, , , , , 0.6, 0.15]
52
+ [1.2, , 240, 0.02, 0.15, 0.15, 1, 4, , , , , 0.05, , , , , 0.6, 0.15]
53
53
  ];
54
54
 
55
55
  // src/index.js
@@ -280,7 +280,7 @@
280
280
  * @param {number} radius
281
281
  * @param {number} [color=0] the color index (generally from 0 to 7)
282
282
  */
283
- circ(x, y, radius, color = 0) {
283
+ circ(x, y, radius, color) {
284
284
  _ctx.beginPath();
285
285
  _ctx.arc(~~x, ~~y, radius, 0, TWO_PI);
286
286
  _ctx.closePath();
@@ -294,7 +294,7 @@
294
294
  * @param {number} radius
295
295
  * @param {number} [color=0] the color index (generally from 0 to 7)
296
296
  */
297
- circfill(x, y, radius, color = 0) {
297
+ circfill(x, y, radius, color) {
298
298
  _ctx.beginPath();
299
299
  _ctx.arc(~~x, ~~y, radius, 0, TWO_PI);
300
300
  _ctx.closePath();
@@ -309,7 +309,7 @@
309
309
  * @param {number} y2
310
310
  * @param {number} [color=0] the color index (generally from 0 to 7)
311
311
  */
312
- line(x1, y1, x2, y2, color = 0) {
312
+ line(x1, y1, x2, y2, color) {
313
313
  _ctx.beginPath();
314
314
  _ctx.moveTo(~~x1, ~~y1);
315
315
  _ctx.lineTo(~~x2, ~~y2);
@@ -497,13 +497,13 @@
497
497
  */
498
498
  transform: (a, b, c, d, e, f, resetFirst = true) => _ctx[resetFirst ? "setTransform" : "transform"](a, b, c, d, e, f),
499
499
  /**
500
- * Sets the alpha (transparency) value to apply when drawing new shapes and images
500
+ * Sets the alpha (opacity) value to apply when drawing new shapes and images
501
501
  *
502
502
  * @param {number} alpha float from 0 to 1 (e.g: 0.5 = 50% transparent)
503
503
  * @see https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/globalAlpha
504
504
  */
505
- alpha(alpha) {
506
- _ctx.globalAlpha = alpha;
505
+ alpha(value) {
506
+ _ctx.globalAlpha = instance.clamp(value, 0, 1);
507
507
  },
508
508
  /**
509
509
  * Returns a newly instantiated Path2D object, optionally with another
@@ -518,7 +518,7 @@
518
518
  /**
519
519
  * Fills the current or given path with a given color.
520
520
  *
521
- * @param {number} color
521
+ * @param {number} [color=0]
522
522
  * @param {Path2D} [path]
523
523
  */
524
524
  fill(color, path) {
@@ -528,7 +528,7 @@
528
528
  /**
529
529
  * Outlines the current or given path with a given color.
530
530
  *
531
- * @param {number} color
531
+ * @param {number} [color=0]
532
532
  * @param {Path2D} [path]
533
533
  */
534
534
  stroke(color, path) {
@@ -582,16 +582,19 @@
582
582
  },
583
583
  /** SOUND API */
584
584
  /**
585
- * Play a defined sound or a ZzFX array of params
585
+ * Play a predefined sound or a ZzFX array of params.
586
+ * By default has 4 predefined sounds.
586
587
  *
587
- * @param {number|number[]} [sound=0] the sound index (from 0 to 7) or a ZzFX array of params
588
+ * @param {number|number[]} [sound=0] the sound index (from 0 to 3) or a ZzFX array of params
588
589
  * @param {number} [volume=1]
589
590
  * @param {number} [pitch=0]
590
- * @param {number} [randomness=0]
591
+ * @param {number} [randomness=null] an float value between 0 and 1
591
592
  * @returns {AudioBufferSourceNode}
593
+ *
592
594
  * @see https://github.com/KilledByAPixel/ZzFX
595
+ * @see https://github.com/litecanvas/game-engine/blob/main/src/sounds.js
593
596
  */
594
- sfx(sound = 0, volume = 1, pitch = 0, randomness = 0) {
597
+ sfx(sound = 0, volume = 1, pitch = 0, randomness = null) {
595
598
  if (navigator.userActivation && !navigator.userActivation.hasBeenActive) {
596
599
  return;
597
600
  }
@@ -599,7 +602,7 @@
599
602
  if (volume !== 1 || pitch || randomness) {
600
603
  z = [...z];
601
604
  z[0] = (Number(volume) || 1) * (z[0] || 1);
602
- z[1] = randomness > 0 ? randomness : 0;
605
+ z[1] = randomness != null ? randomness : z[1];
603
606
  z[10] = ~~z[10] + ~~pitch;
604
607
  }
605
608
  return zzfx(...z);
@@ -688,7 +691,7 @@
688
691
  /**
689
692
  * Get a color by index
690
693
  *
691
- * @param {number} index The color number
694
+ * @param {number} [index=0] The color number
692
695
  * @returns {string} the color code
693
696
  */
694
697
  getcolor: (index) => colors[~~index % colors.length],
package/dist/dist.min.js CHANGED
@@ -1,2 +1,2 @@
1
- (()=>{var U=(u=1,m=.05,H=220,b=0,T=0,N=.1,X=0,$=1,c=0,G=0,R=0,v=0,C=0,k=0,o=0,F=0,y=0,Y=1,S=0,M=0,A=0)=>{let _=Math,E=2*_.PI,h=44100,L=c*=500*E/h/h,B=H*=(1-m+2*m*_.random(m=[]))*E/h,D=0,z=0,x=0,n=1,V=0,j=0,w=0,I=A<0?-1:1,W=E*I*A*2/h,e=_.cos(W),t=_.sin,a=t(W)/4,r=1+a,s=-2*e/r,d=(1-a)/r,g=(1+I*e)/2/r,P=-(I+e)/r,i=g,f=0,l=0,p=0,O=0;for(b=h*b+9,S*=h,T*=h,N*=h,y*=h,G*=500*E/h**3,o*=E/h,R*=E/h,v*=h,C=h*C|0,u*=globalThis.zzfxV||.3,I=b+S+T+N+y|0;x<I;m[x++]=w*u)++j%(100*F|0)||(w=X?1<X?2<X?3<X?t(D*D):_.max(_.min(_.tan(D),1),-1):1-(2*D/E%2+2)%2:1-4*_.abs(_.round(D/E)-D/E):t(D),w=(C?1-M+M*t(E*x/C):1)*(w<0?-1:1)*_.abs(w)**$*(x<b?x/b:x<b+S?1-(x-b)/S*(1-Y):x<b+S+T?Y:x<I-y?(I-x-y)/N*Y:0),w=y?w/2+(y>x?0:(x<I-y?1:(I-x)/y)*m[x-y|0]/2/u):w,A&&(w=O=i*f+P*(f=l)+g*(l=w)-d*p-s*(p=O))),W=(H+=c+=G)*_.cos(o*z++),D+=W+W*k*t(x**5),n&&++n>v&&(H+=R,B+=R,n=0),!C||++V%C||(H=B,c=L,n=n||1);u=K.createBuffer(1,I,h),u.getChannelData(0).set(m),H=K.createBufferSource(),H.buffer=u,H.connect(K.destination),H.start()},K=new AudioContext;var q=["#18161c","#6a7799","#aec2c2","#f3eade","#f04f78","#fcf660","#2f328f","#4b80ca","#327345","#63c64d","#703075","#a56243"];var J=[[.8,0,2e3,.01,.05,,1,2,,,-600,.05,,,,,,.5,.05],[.5,0,375,.02,.01,.2,1,,,,,,,.4,,.1,,.6,.1],[,0,360,.01,,.08,1,1.7,12,32,,,,,,,,.63,.02,,99],[1.2,0,240,.02,.15,.15,1,4,,,,,.05,,,,,.6,.15]];function Q(u={}){let m=globalThis,H=Math.PI,b=H*2,T=(e,t,a)=>e.addEventListener(t,a);u=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},u);let X=!1,$=[],c=u.canvas||document.createElement("canvas"),G=u.fullscreen,R=u.autoscale,v=1,C,k,o,F=1,y,Y=1/u.fps,S=Y*1e3,M=0,A,_=0,E=0,h="sans-serif",L="",B=32,D=Date.now(),z={init:!1,update:!1,draw:!1,resized:!1,tap:!1,untap:!1,tapping:!1,tapped:!1},x={settings:Object.assign({},u),colors:q,sounds:J},n={WIDTH:u.width,HEIGHT:u.height||u.width,CANVAS:null,ELAPSED:0,FPS:u.fps,CENTERX:null,CENTERY:null,PI:H,TWO_PI:b,HALF_PI:H*.5,lerp:(e,t,a)=>e+a*(t-e),deg2rad:e=>H/180*e,rad2deg:e=>180/H*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,r,s,d=!1){let g=(e-t)/(a-t)*(s-r)+r;return d?n.clamp(g,r,s):g},norm:(e,t,a)=>n.map(e,t,a,0,1),rand:(e=0,t=1)=>(D=(1664525*D+1013904223)%4294967296,D/4294967296*(t-e)+e),randi:(e=0,t=1)=>n.floor(n.rand()*(t-e+1)+e),seed:e=>e==null?D:D=~~e,cls(e){e==null?o.clearRect(0,0,n.WIDTH,n.HEIGHT):n.rectfill(0,0,n.WIDTH,n.HEIGHT,e)},rect(e,t,a,r,s=0,d=null){o.beginPath(),o[d?"roundRect":"rect"](~~e,~~t,a,r,d),n.stroke(s)},rectfill(e,t,a,r,s=0,d=null){o.beginPath(),o[d?"roundRect":"rect"](~~e,~~t,a,r,d),n.fill(s)},circ(e,t,a,r=0){o.beginPath(),o.arc(~~e,~~t,a,0,b),o.closePath(),n.stroke(r)},circfill(e,t,a,r=0){o.beginPath(),o.arc(~~e,~~t,a,0,b),o.closePath(),n.fill(r)},line(e,t,a,r,s=0){o.beginPath(),o.moveTo(~~e,~~t),o.lineTo(~~a,~~r),n.stroke(s)},linewidth(e){o.lineWidth=e},linedash(e,t=0){o.setLineDash(Array.isArray(e)?e:[e]),o.lineDashOffset=t},text(e,t,a,r=3){o.font=`${L||""} ${B}px ${h}`,o.fillStyle=n.getcolor(r),o.fillText(a,~~e,~~t)},textfont(e){h=e},textsize(e){B=e},textstyle(e){L=e},textalign(e,t){e&&(o.textAlign=e),t&&(o.textBaseline=t)},textmetrics(e,t){return o.font=`${L||""} ${t||B}px ${h}`,metrics=o.measureText(e),metrics.height=metrics.actualBoundingBoxAscent+metrics.actualBoundingBoxDescent,metrics},image(e,t,a){o.drawImage(a,~~e,~~t)},paint(e,t,a,r={}){let s=new OffscreenCanvas(e,t),d=o,g=r.scale||1;if(s.width=e*g,s.height=t*g,o=s.getContext("2d"),o.scale(g,g),Array.isArray(a)){let P=0,i=0;o.imageSmoothingEnabled=!1;for(let f of a){for(let l of f)l!==" "&&l!=="."&&n.rectfill(P,i,1,1,parseInt(l,16)),P++;i++,P=0}}else a(s,o);return o=d,s},ctx:()=>o,push:()=>o.save(),pop:()=>o.restore(),translate:(e,t)=>o.translate(e,t),scale:(e,t)=>o.scale(e,t||e),rotate:e=>o.rotate(e),transform:(e,t,a,r,s,d,g=!0)=>o[g?"setTransform":"transform"](e,t,a,r,s,d),alpha(e){o.globalAlpha=e},path:e=>new Path2D(e),fill(e,t){o.fillStyle=n.getcolor(e),o.fill(t)},stroke(e,t){o.strokeStyle=n.getcolor(e),t?o.stroke(t):o.stroke()},cliprect(e,t,a,r){o.beginPath(),o.rect(e,t,a,r),o.clip()},clipcirc(e,t,a){o.beginPath(),o.arc(e,t,a,0,b),o.clip()},blendmode(e){o.globalCompositeOperation=e},sfx(e=0,t=1,a=0,r=0){if(navigator.userActivation&&!navigator.userActivation.hasBeenActive)return;let s=Array.isArray(e)?e:J[e%J.length];return(t!==1||a||r)&&(s=[...s],s[0]=(Number(t)||1)*(s[0]||1),s[1]=r>0?r:0,s[10]=~~s[10]+~~a),U(...s)},colrect:(e,t,a,r,s,d,g,P)=>e<s+g&&e+a>s&&t<d+P&&t+r>d,colcirc:(e,t,a,r,s,d)=>(r-e)**2+(s-t)**2<=(a+d)**2,mousepos:()=>[C,k],timescale(e){F=e},use(e,t={}){e.__conf=t,X?W(e):$.push(e)},listen(e,t,a=!1){z[e]=z[e]||[[],[]];let r=z[e][a?0:1].push(t);return()=>{z[e][a?0:1].splice(r-1,1)}},emit(e,...t){if(z[e])for(let a of z[e])for(let r of a)r(...t)},getcolor:e=>q[~~e%q.length],setvar(e,t){n[e]=t,u.global&&(m[e]=t)},resize(e,t){n.setvar("WIDTH",c.width=e),n.setvar("HEIGHT",c.height=t||e),I()}};for(let e of["sin","cos","atan2","hypot","tan","abs","ceil","round","floor","trunc","min","max","pow","sqrt","sign","exp"])n[e]=Math[e];function V(){X=!0,w();let e=u.loop?u.loop:m;for(let t of Object.keys(z))e[t]&&n.listen(t,e[t]);for(let t of $)W(t);if(T(m,"resize",I),I(),u.tapEvents){let t=(i,f)=>[(i-c.offsetLeft)/v,(f-c.offsetTop)/v],a=new Map,r=(i,f,l)=>{let p={x:f,y:l,startX:f,startY:l,ts:performance.now()};return a.set(i,p),p},s=(i,f,l)=>{let p=a.get(i)||r(i);p.x=f,p.y=l},d=i=>i&&performance.now()-i.ts<=200,g=!1;T(c,"mousedown",i=>{i.preventDefault();let[f,l]=t(i.pageX,i.pageY);n.emit("tap",f,l,0),r(0,f,l),g=!0}),T(c,"mousemove",i=>{i.preventDefault();let[f,l]=[C,k]=t(i.pageX,i.pageY);g&&(n.emit("tapping",f,l,0),s(0,f,l))}),T(c,"mouseup",i=>{i.preventDefault();let f=a.get(0),[l,p]=t(i.pageX,i.pageY);d(f)&&n.emit("tapped",f.startX,f.startY,0),n.emit("untap",l,p,0),a.delete(0),g=!1}),T(c,"touchstart",i=>{i.preventDefault();let f=i.changedTouches;for(let l of f){let[p,O]=t(l.pageX,l.pageY);n.emit("tap",p,O,l.identifier+1),r(l.identifier+1,p,O)}}),T(c,"touchmove",i=>{i.preventDefault();let f=i.changedTouches;for(let l of f){let[p,O]=t(l.pageX,l.pageY);n.emit("tapping",p,O,l.identifier+1),s(l.identifier+1,p,O)}});let P=i=>{i.preventDefault();let f=[];if(i.targetTouches.length>0)for(let l of i.targetTouches)f.push(l.identifier+1);for(let[l,p]of a)f.includes(l)||(d(p)&&n.emit("tapped",p.startX,p.startY,l),n.emit("untap",p.x,p.y,l),a.delete(l))};T(c,"touchend",P),T(c,"touchcancel",P),T(m,"blur",()=>{if(g=!1,a.size!==0)for(let[i,f]of a)n.emit("untap",f.x,f.y,i),a.delete(i)})}u.pauseOnBlur&&(T(m,"blur",()=>{A=null}),T(m,"focus",()=>{A||(y=performance.now(),A=requestAnimationFrame(j))})),n.emit("init"),y=performance.now(),A=requestAnimationFrame(j)}function j(e){let t=0,a=e-y;for(y=e,M+=a;M>=S;)n.emit("update",Y*F),n.setvar("ELAPSED",n.ELAPSED+Y*F),M-=S,t++;t&&(n.textalign("start","top"),n.emit("draw"),_++,E+=S*t,E+M>=1e3&&(n.setvar("FPS",_),_=0,E-=1e3)),A&&(A=requestAnimationFrame(j))}function w(){c=typeof c=="string"?document.querySelector(c):c,n.setvar("CANVAS",c),o=c.getContext("2d"),n.WIDTH>0&&(G=!1),c.width=n.WIDTH,c.height=n.HEIGHT||n.WIDTH,c.parentNode||document.body.appendChild(c),c.style.display="block",G?(c.style.position="absolute",c.style.inset=0):R&&(c.style.margin="auto")}function I(){G?(c.width=innerWidth,c.height=innerHeight,n.setvar("WIDTH",innerWidth),n.setvar("HEIGHT",innerHeight)):R&&(v=Math.min(innerWidth/n.WIDTH,innerHeight/n.HEIGHT),v=u.pixelart?Math.floor(v):v,c.style.width=n.WIDTH*v+"px",c.style.height=n.HEIGHT*v+"px"),n.setvar("CENTERX",n.WIDTH/2),n.setvar("CENTERY",n.HEIGHT/2),(!u.antialias||u.pixelart)&&(o.imageSmoothingEnabled=!1,c.style.imageRendering="pixelated"),n.emit("resized",v)}function W(e){let t=e(n,x,e.__conf);if(typeof t=="object")for(let[a,r]of Object.entries(t))n.setvar(a,r)}if(u.global){if(m.__litecanvas)throw"Cannot instantiate litecanvas globally twice";Object.assign(m,n),m.__litecanvas=n}return document.readyState==="loading"?T(m,"DOMContentLoaded",V):V(),n}globalThis.litecanvas=Q;})();
1
+ (()=>{var U=(u=1,g=.05,H=220,b=0,T=0,N=.1,X=0,$=1,c=0,G=0,R=0,v=0,C=0,k=0,o=0,F=0,y=0,Y=1,S=0,M=0,A=0)=>{let _=Math,E=2*_.PI,h=44100,L=c*=500*E/h/h,B=H*=(1-g+2*g*_.random(g=[]))*E/h,D=0,z=0,x=0,a=1,V=0,j=0,w=0,I=A<0?-1:1,W=E*I*A*2/h,e=_.cos(W),t=_.sin,n=t(W)/4,r=1+n,s=-2*e/r,d=(1-n)/r,m=(1+I*e)/2/r,P=-(I+e)/r,i=m,f=0,l=0,p=0,O=0;for(b=h*b+9,S*=h,T*=h,N*=h,y*=h,G*=500*E/h**3,o*=E/h,R*=E/h,v*=h,C=h*C|0,u*=globalThis.zzfxV||.3,I=b+S+T+N+y|0;x<I;g[x++]=w*u)++j%(100*F|0)||(w=X?1<X?2<X?3<X?t(D*D):_.max(_.min(_.tan(D),1),-1):1-(2*D/E%2+2)%2:1-4*_.abs(_.round(D/E)-D/E):t(D),w=(C?1-M+M*t(E*x/C):1)*(w<0?-1:1)*_.abs(w)**$*(x<b?x/b:x<b+S?1-(x-b)/S*(1-Y):x<b+S+T?Y:x<I-y?(I-x-y)/N*Y:0),w=y?w/2+(y>x?0:(x<I-y?1:(I-x)/y)*g[x-y|0]/2/u):w,A&&(w=O=i*f+P*(f=l)+m*(l=w)-d*p-s*(p=O))),W=(H+=c+=G)*_.cos(o*z++),D+=W+W*k*t(x**5),a&&++a>v&&(H+=R,B+=R,a=0),!C||++V%C||(H=B,c=L,a=a||1);u=K.createBuffer(1,I,h),u.getChannelData(0).set(g),H=K.createBufferSource(),H.buffer=u,H.connect(K.destination),H.start()},K=new AudioContext;var q=["#18161c","#6a7799","#aec2c2","#f3eade","#f04f78","#fcf660","#2f328f","#4b80ca","#327345","#63c64d","#703075","#a56243"];var J=[[.8,,2e3,.01,.05,,1,2,,,-600,.05,,,,,,.5,.05],[.5,,375,.02,.01,.2,1,,,,,,,.4,,.1,,.6,.1],[,,360,.01,,.08,1,1.7,12,32,,,,,,,,.63,.02,,99],[1.2,,240,.02,.15,.15,1,4,,,,,.05,,,,,.6,.15]];function Q(u={}){let g=globalThis,H=Math.PI,b=H*2,T=(e,t,n)=>e.addEventListener(t,n);u=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},u);let X=!1,$=[],c=u.canvas||document.createElement("canvas"),G=u.fullscreen,R=u.autoscale,v=1,C,k,o,F=1,y,Y=1/u.fps,S=Y*1e3,M=0,A,_=0,E=0,h="sans-serif",L="",B=32,D=Date.now(),z={init:!1,update:!1,draw:!1,resized:!1,tap:!1,untap:!1,tapping:!1,tapped:!1},x={settings:Object.assign({},u),colors:q,sounds:J},a={WIDTH:u.width,HEIGHT:u.height||u.width,CANVAS:null,ELAPSED:0,FPS:u.fps,CENTERX:null,CENTERY:null,PI:H,TWO_PI:b,HALF_PI:H*.5,lerp:(e,t,n)=>e+n*(t-e),deg2rad:e=>H/180*e,rad2deg:e=>180/H*e,clamp:(e,t,n)=>e<t?t:e>n?n:e,wrap:(e,t,n)=>e-(n-t)*Math.floor((e-t)/(n-t)),map(e,t,n,r,s,d=!1){let m=(e-t)/(n-t)*(s-r)+r;return d?a.clamp(m,r,s):m},norm:(e,t,n)=>a.map(e,t,n,0,1),rand:(e=0,t=1)=>(D=(1664525*D+1013904223)%4294967296,D/4294967296*(t-e)+e),randi:(e=0,t=1)=>a.floor(a.rand()*(t-e+1)+e),seed:e=>e==null?D:D=~~e,cls(e){e==null?o.clearRect(0,0,a.WIDTH,a.HEIGHT):a.rectfill(0,0,a.WIDTH,a.HEIGHT,e)},rect(e,t,n,r,s=0,d=null){o.beginPath(),o[d?"roundRect":"rect"](~~e,~~t,n,r,d),a.stroke(s)},rectfill(e,t,n,r,s=0,d=null){o.beginPath(),o[d?"roundRect":"rect"](~~e,~~t,n,r,d),a.fill(s)},circ(e,t,n,r){o.beginPath(),o.arc(~~e,~~t,n,0,b),o.closePath(),a.stroke(r)},circfill(e,t,n,r){o.beginPath(),o.arc(~~e,~~t,n,0,b),o.closePath(),a.fill(r)},line(e,t,n,r,s){o.beginPath(),o.moveTo(~~e,~~t),o.lineTo(~~n,~~r),a.stroke(s)},linewidth(e){o.lineWidth=e},linedash(e,t=0){o.setLineDash(Array.isArray(e)?e:[e]),o.lineDashOffset=t},text(e,t,n,r=3){o.font=`${L||""} ${B}px ${h}`,o.fillStyle=a.getcolor(r),o.fillText(n,~~e,~~t)},textfont(e){h=e},textsize(e){B=e},textstyle(e){L=e},textalign(e,t){e&&(o.textAlign=e),t&&(o.textBaseline=t)},textmetrics(e,t){return o.font=`${L||""} ${t||B}px ${h}`,metrics=o.measureText(e),metrics.height=metrics.actualBoundingBoxAscent+metrics.actualBoundingBoxDescent,metrics},image(e,t,n){o.drawImage(n,~~e,~~t)},paint(e,t,n,r={}){let s=new OffscreenCanvas(e,t),d=o,m=r.scale||1;if(s.width=e*m,s.height=t*m,o=s.getContext("2d"),o.scale(m,m),Array.isArray(n)){let P=0,i=0;o.imageSmoothingEnabled=!1;for(let f of n){for(let l of f)l!==" "&&l!=="."&&a.rectfill(P,i,1,1,parseInt(l,16)),P++;i++,P=0}}else n(s,o);return o=d,s},ctx:()=>o,push:()=>o.save(),pop:()=>o.restore(),translate:(e,t)=>o.translate(e,t),scale:(e,t)=>o.scale(e,t||e),rotate:e=>o.rotate(e),transform:(e,t,n,r,s,d,m=!0)=>o[m?"setTransform":"transform"](e,t,n,r,s,d),alpha(e){o.globalAlpha=a.clamp(e,0,1)},path:e=>new Path2D(e),fill(e,t){o.fillStyle=a.getcolor(e),o.fill(t)},stroke(e,t){o.strokeStyle=a.getcolor(e),t?o.stroke(t):o.stroke()},cliprect(e,t,n,r){o.beginPath(),o.rect(e,t,n,r),o.clip()},clipcirc(e,t,n){o.beginPath(),o.arc(e,t,n,0,b),o.clip()},blendmode(e){o.globalCompositeOperation=e},sfx(e=0,t=1,n=0,r=null){if(navigator.userActivation&&!navigator.userActivation.hasBeenActive)return;let s=Array.isArray(e)?e:J[e%J.length];return(t!==1||n||r)&&(s=[...s],s[0]=(Number(t)||1)*(s[0]||1),s[1]=r??s[1],s[10]=~~s[10]+~~n),U(...s)},colrect:(e,t,n,r,s,d,m,P)=>e<s+m&&e+n>s&&t<d+P&&t+r>d,colcirc:(e,t,n,r,s,d)=>(r-e)**2+(s-t)**2<=(n+d)**2,mousepos:()=>[C,k],timescale(e){F=e},use(e,t={}){e.__conf=t,X?W(e):$.push(e)},listen(e,t,n=!1){z[e]=z[e]||[[],[]];let r=z[e][n?0:1].push(t);return()=>{z[e][n?0:1].splice(r-1,1)}},emit(e,...t){if(z[e])for(let n of z[e])for(let r of n)r(...t)},getcolor:e=>q[~~e%q.length],setvar(e,t){a[e]=t,u.global&&(g[e]=t)},resize(e,t){a.setvar("WIDTH",c.width=e),a.setvar("HEIGHT",c.height=t||e),I()}};for(let e of["sin","cos","atan2","hypot","tan","abs","ceil","round","floor","trunc","min","max","pow","sqrt","sign","exp"])a[e]=Math[e];function V(){X=!0,w();let e=u.loop?u.loop:g;for(let t of Object.keys(z))e[t]&&a.listen(t,e[t]);for(let t of $)W(t);if(T(g,"resize",I),I(),u.tapEvents){let t=(i,f)=>[(i-c.offsetLeft)/v,(f-c.offsetTop)/v],n=new Map,r=(i,f,l)=>{let p={x:f,y:l,startX:f,startY:l,ts:performance.now()};return n.set(i,p),p},s=(i,f,l)=>{let p=n.get(i)||r(i);p.x=f,p.y=l},d=i=>i&&performance.now()-i.ts<=200,m=!1;T(c,"mousedown",i=>{i.preventDefault();let[f,l]=t(i.pageX,i.pageY);a.emit("tap",f,l,0),r(0,f,l),m=!0}),T(c,"mousemove",i=>{i.preventDefault();let[f,l]=[C,k]=t(i.pageX,i.pageY);m&&(a.emit("tapping",f,l,0),s(0,f,l))}),T(c,"mouseup",i=>{i.preventDefault();let f=n.get(0),[l,p]=t(i.pageX,i.pageY);d(f)&&a.emit("tapped",f.startX,f.startY,0),a.emit("untap",l,p,0),n.delete(0),m=!1}),T(c,"touchstart",i=>{i.preventDefault();let f=i.changedTouches;for(let l of f){let[p,O]=t(l.pageX,l.pageY);a.emit("tap",p,O,l.identifier+1),r(l.identifier+1,p,O)}}),T(c,"touchmove",i=>{i.preventDefault();let f=i.changedTouches;for(let l of f){let[p,O]=t(l.pageX,l.pageY);a.emit("tapping",p,O,l.identifier+1),s(l.identifier+1,p,O)}});let P=i=>{i.preventDefault();let f=[];if(i.targetTouches.length>0)for(let l of i.targetTouches)f.push(l.identifier+1);for(let[l,p]of n)f.includes(l)||(d(p)&&a.emit("tapped",p.startX,p.startY,l),a.emit("untap",p.x,p.y,l),n.delete(l))};T(c,"touchend",P),T(c,"touchcancel",P),T(g,"blur",()=>{if(m=!1,n.size!==0)for(let[i,f]of n)a.emit("untap",f.x,f.y,i),n.delete(i)})}u.pauseOnBlur&&(T(g,"blur",()=>{A=null}),T(g,"focus",()=>{A||(y=performance.now(),A=requestAnimationFrame(j))})),a.emit("init"),y=performance.now(),A=requestAnimationFrame(j)}function j(e){let t=0,n=e-y;for(y=e,M+=n;M>=S;)a.emit("update",Y*F),a.setvar("ELAPSED",a.ELAPSED+Y*F),M-=S,t++;t&&(a.textalign("start","top"),a.emit("draw"),_++,E+=S*t,E+M>=1e3&&(a.setvar("FPS",_),_=0,E-=1e3)),A&&(A=requestAnimationFrame(j))}function w(){c=typeof c=="string"?document.querySelector(c):c,a.setvar("CANVAS",c),o=c.getContext("2d"),a.WIDTH>0&&(G=!1),c.width=a.WIDTH,c.height=a.HEIGHT||a.WIDTH,c.parentNode||document.body.appendChild(c),c.style.display="block",G?(c.style.position="absolute",c.style.inset=0):R&&(c.style.margin="auto")}function I(){G?(c.width=innerWidth,c.height=innerHeight,a.setvar("WIDTH",innerWidth),a.setvar("HEIGHT",innerHeight)):R&&(v=Math.min(innerWidth/a.WIDTH,innerHeight/a.HEIGHT),v=u.pixelart?Math.floor(v):v,c.style.width=a.WIDTH*v+"px",c.style.height=a.HEIGHT*v+"px"),a.setvar("CENTERX",a.WIDTH/2),a.setvar("CENTERY",a.HEIGHT/2),(!u.antialias||u.pixelart)&&(o.imageSmoothingEnabled=!1,c.style.imageRendering="pixelated"),a.emit("resized",v)}function W(e){let t=e(a,x,e.__conf);if(typeof t=="object")for(let[n,r]of Object.entries(t))a.setvar(n,r)}if(u.global){if(g.__litecanvas)throw"Cannot instantiate litecanvas globally twice";Object.assign(g,a),g.__litecanvas=a}return document.readyState==="loading"?T(g,"DOMContentLoaded",V):V(),a}globalThis.litecanvas=Q;})();
2
2
  //# sourceMappingURL=dist.min.js.map
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../src/zzfx.js", "../src/palette.js", "../src/sounds.js", "../src/index.js", "../src/web.js"],
4
- "sourcesContent": ["// ZzFXMicro - Zuper Zmall Zound Zynth - v1.3.0 by Frank Force | https://github.com/KilledByAPixel/ZzFX\nexport const zzfx = (\n p = 1,\n k = 0.05,\n b = 220,\n e = 0,\n r = 0,\n t = 0.1,\n q = 0,\n D = 1,\n u = 0,\n y = 0,\n v = 0,\n z = 0,\n l = 0,\n E = 0,\n A = 0,\n F = 0,\n c = 0,\n w = 1,\n m = 0,\n B = 0,\n N = 0\n) => {\n let M = Math,\n d = 2 * M.PI,\n R = 44100,\n G = (u *= (500 * d) / R / R),\n C = (b *= ((1 - k + 2 * k * M.random((k = []))) * d) / R),\n g = 0,\n H = 0,\n a = 0,\n n = 1,\n I = 0,\n J = 0,\n f = 0,\n h = N < 0 ? -1 : 1,\n x = (d * h * N * 2) / R,\n L = M.cos(x),\n Z = M.sin,\n K = Z(x) / 4,\n O = 1 + K,\n X = (-2 * L) / O,\n Y = (1 - K) / O,\n P = (1 + h * L) / 2 / O,\n Q = -(h + L) / O,\n S = P,\n T = 0,\n U = 0,\n V = 0,\n W = 0\n e = R * e + 9\n m *= R\n r *= R\n t *= R\n c *= R\n y *= (500 * d) / R ** 3\n A *= d / R\n v *= d / R\n z *= R\n l = (R * l) | 0\n p *= globalThis.zzfxV || 0.3\n for (h = (e + m + r + t + c) | 0; a < h; k[a++] = f * p)\n ++J % ((100 * F) | 0) ||\n ((f = q\n ? 1 < q\n ? 2 < q\n ? 3 < q\n ? Z(g * g)\n : M.max(M.min(M.tan(g), 1), -1)\n : 1 - (((((2 * g) / d) % 2) + 2) % 2)\n : 1 - 4 * M.abs(M.round(g / d) - g / d)\n : Z(g)),\n (f =\n (l ? 1 - B + B * Z((d * a) / l) : 1) *\n (f < 0 ? -1 : 1) *\n M.abs(f) ** D *\n (a < e\n ? a / e\n : a < e + m\n ? 1 - ((a - e) / m) * (1 - w)\n : a < e + m + r\n ? w\n : a < h - c\n ? ((h - a - c) / t) * w\n : 0)),\n (f = c\n ? f / 2 +\n (c > a\n ? 0\n : ((a < h - c ? 1 : (h - a) / c) * k[(a - c) | 0]) /\n 2 /\n p)\n : f),\n N\n ? (f = W =\n S * T + Q * (T = U) + P * (U = f) - Y * V - X * (V = W))\n : 0),\n (x = (b += u += y) * M.cos(A * H++)),\n (g += x + x * E * Z(a ** 5)),\n n && ++n > z && ((b += v), (C += v), (n = 0)),\n !l || ++I % l || ((b = C), (u = G), (n = n || 1))\n p = zzfxX.createBuffer(1, h, R)\n p.getChannelData(0).set(k)\n b = zzfxX.createBufferSource()\n b.buffer = p\n b.connect(zzfxX.destination)\n b.start()\n}\n\nconst zzfxX = /** @__PURE__ */ new AudioContext()\n", "// Default colors inspired by https://lospec.com/palette-list/trirampo\nexport const colors = [\n '#18161c',\n '#6a7799',\n '#aec2c2',\n '#f3eade',\n\n '#f04f78',\n '#fcf660',\n '#2f328f',\n '#4b80ca',\n\n '#327345',\n '#63c64d',\n '#703075',\n '#a56243',\n]\n", "// prettier-ignore\nexport const sounds = [\n // 0 - pickup\n [0.8, 0, 2e3, 0.01, 0.05, , 1, 2, , , -600, 0.05, , , , , , 0.5, 0.05],\n // 1 - hit\n [0.5, 0, 375, 0.02, 0.01, 0.2, 1, , , , , , , 0.4, , 0.1, , 0.6, 0.1],\n // 2 - jump\n [, 0, 360, 0.01, , 0.08, 1, 1.7, 12, 32, , , , , , , , 0.63, 0.02, , 99],\n // 3 - warning\n [1.2, 0, 240, 0.02, 0.15, 0.15, 1, 4, , , , , 0.05, , , , , 0.6, 0.15],\n]\n", "/* litecanvas v0.47.2 | https://github.com/litecanvas/game-engine */\nimport { zzfx } from './zzfx.js'\nimport { colors } from './palette.js'\nimport { sounds } from './sounds.js'\n\n/**\n * The litecanvas constructor\n *\n * @param {LitecanvasOptions} [settings]\n * @returns {LitecanvasInstance}\n */\nexport default function litecanvas(settings = {}) {\n // helpers\n const root = globalThis,\n PI = Math.PI,\n TWO_PI = PI * 2,\n /** @type {(elem:HTMLElement, evt:string, callback:Function)=>void} */\n on = (elem, evt, callback) => elem.addEventListener(evt, callback),\n /** @type {LitecanvasOptions} */\n defaults = {\n fps: 60,\n fullscreen: true,\n width: null,\n height: null,\n autoscale: true,\n pixelart: false,\n antialias: true,\n canvas: null,\n global: true,\n loop: null,\n tapEvents: true,\n pauseOnBlur: true,\n }\n\n // setup the settings default values\n settings = Object.assign(defaults, settings)\n\n let /** @type {boolean} */\n _initialized = false,\n /** @type {function[]} */\n _plugins = [],\n /** @type {HTMLCanvasElement|string} _canvas */\n _canvas = settings.canvas || document.createElement('canvas'),\n /** @type {boolean} */\n _fullscreen = settings.fullscreen,\n /** @type {boolean} */\n _autoscale = settings.autoscale,\n /** @type {number} */\n _scale = 1,\n /** @type {number?} */\n _mouseX,\n /** @type {number?} */\n _mouseY,\n /** @type {CanvasRenderingContext2D} */\n _ctx,\n /** @type {number} */\n _timeScale = 1,\n /** @type {number} */\n _lastFrame,\n /** @type {number} */\n _step = 1 / settings.fps,\n /** @type {number} */\n _stepMs = _step * 1000,\n /** @type {number} */\n _accumulated = 0,\n /** @type {number} */\n _rafid,\n /** @type {number} */\n _drawCount = 0,\n /** @type {number} */\n _drawTime = 0,\n /** @type {string} */\n _fontFamily = 'sans-serif',\n /** @type {string} */\n _fontStyle = '',\n /** @type {number} */\n _fontSize = 32,\n /** @type {number} */\n _rng_seed = Date.now(),\n /**\n * default game events\n */\n _events = {\n init: false,\n update: false,\n draw: false,\n resized: false,\n tap: false,\n untap: false,\n tapping: false,\n tapped: false,\n },\n /**\n * Helpers to be used by plugins\n *\n * @type {LitecanvasPluginHelpers}\n */\n _helpers = {\n settings: Object.assign({}, settings),\n colors,\n sounds,\n }\n\n /** @type {LitecanvasInstance} */\n const instance = {\n /** @type {number} */\n WIDTH: settings.width,\n /** @type {number} */\n HEIGHT: settings.height || settings.width,\n /** @type {HTMLCanvasElement} */\n CANVAS: null,\n /** @type {number} */\n ELAPSED: 0,\n /** @type {number} */\n FPS: settings.fps,\n /** @type {number} */\n CENTERX: null,\n /** @type {number} */\n CENTERY: null,\n\n /** MATH API */\n /**\n * The value of the mathematical constant PI (\u03C0).\n * Approximately 3.14159\n *\n * @type {number}\n */\n PI,\n\n /**\n * Twice the value of the mathematical constant PI (\u03C0).\n * Approximately 6.28318\n *\n * Note: TWO_PI radians equals 360\u00B0, PI radians equals 180\u00B0,\n * HALF_PI radians equals 90\u00B0, and HALF_PI/2 radians equals 45\u00B0.\n *\n * @type {number}\n */\n TWO_PI,\n\n /**\n * Half the value of the mathematical constant PI (\u03C0).\n * Approximately 1.57079\n *\n * @type {number}\n */\n HALF_PI: PI * 0.5,\n\n /**\n * Calculates a linear (interpolation) value over t%.\n *\n * @param {number} start\n * @param {number} end\n * @param {number} t The progress in percentage, where 0 = 0% and 1 = 100%.\n * @returns {number} The unterpolated value\n * @tutorial https://gamedev.net/tutorials/programming/general-and-gameplay-programming/a-brief-introduction-to-lerp-r4954/\n */\n lerp: (start, end, t) => start + t * (end - start),\n\n /**\n * Convert degrees to radians\n *\n * @param {number} degs\n * @returns {number} the value in radians\n */\n deg2rad: (degs) => (PI / 180) * degs,\n\n /**\n * Convert radians to degrees\n *\n * @param {number} rads\n * @returns {number} the value in degrees\n */\n rad2deg: (rads) => (180 / PI) * rads,\n\n /**\n * Constrains a number between `min` and `max`.\n *\n * @param {number} value\n * @param {number} min\n * @param {number} max\n * @returns {number}\n */\n clamp: (value, min, max) => {\n if (value < min) return min\n if (value > max) return max\n return value\n },\n\n /**\n * Wraps a number between `min` (inclusive) and `max` (exclusive).\n *\n * @param {number} value\n * @param {number} min\n * @param {number} max\n * @returns {number}\n */\n wrap: (value, min, max) =>\n value - (max - min) * Math.floor((value - min) / (max - min)),\n\n /**\n * Re-maps a number from one range to another.\n *\n * @param {number} value the value to be remapped.\n * @param {number} min1 lower bound of the value's current range.\n * @param {number} max1 upper bound of the value's current range.\n * @param {number} min2 lower bound of the value's target range.\n * @param {number} max2 upper bound of the value's target range.\n * @param {boolean} [withinBounds=false] constrain the value to the newly mapped range\n * @returns {number} the remapped number\n */\n map(value, min1, max1, min2, max2, withinBounds = false) {\n // prettier-ignore\n const result = ((value - min1) / (max1 - min1)) * (max2 - min2) + min2\n return !withinBounds ? result : instance.clamp(result, min2, max2)\n },\n\n /**\n * Maps a number from one range to a value between 0 and 1.\n * Identical to `map(value, min, max, 0, 1)`.\n * Note: Numbers outside the range are not clamped to 0 and 1.\n *\n * @param {number} value\n * @param {number} min\n * @param {number} min\n * @returns {number} the normalized number.\n */\n norm: (value, min, max) => instance.map(value, min, max, 0, 1),\n\n /** RNG API */\n /**\n * Generates a pseudorandom float between min (inclusive) and max (exclusive)\n * using the Linear Congruential Generator (LCG) algorithm.\n *\n * @param {number} [min=0.0]\n * @param {number} [max=1.0]\n * @returns {number} the random number\n */\n rand: (min = 0.0, max = 1.0) => {\n const a = 1664525\n const c = 1013904223\n const m = 4294967296\n\n _rng_seed = (a * _rng_seed + c) % m\n\n return (_rng_seed / m) * (max - min) + min\n },\n\n /**\n * Generates a pseudorandom integer between min (inclusive) and max (inclusive)\n *\n * @param {number} [min=0]\n * @param {number} [max=1]\n * @returns {number} the random number\n */\n randi: (min = 0, max = 1) =>\n instance.floor(instance.rand() * (max - min + 1) + min),\n\n /**\n * If a value is passed, initializes the random number generator with an explicit seed value.\n * Otherwise, returns the current seed state.\n *\n * @param {number} value\n * @returns {number} the seed state\n */\n seed: (value) => {\n return null == value ? _rng_seed : (_rng_seed = ~~value)\n },\n\n /** BASIC GRAPHICS API */\n /**\n * Clear the game screen\n *\n * @param {number|null} color The background color (from 0 to 7) or null (for transparent)\n */\n cls(color) {\n if (null == color) {\n _ctx.clearRect(0, 0, instance.WIDTH, instance.HEIGHT)\n } else {\n instance.rectfill(0, 0, instance.WIDTH, instance.HEIGHT, color)\n }\n },\n\n /**\n * Draw a rectangle outline\n *\n * @param {number} x\n * @param {number} y\n * @param {number} width\n * @param {number} height\n * @param {number} [color=0] the color index (generally from 0 to 7)\n * @param {number|number[]} [radii] A number or list specifying the radii used to draw a rounded-borders rectangle\n */\n rect(x, y, width, height, color = 0, radii = null) {\n _ctx.beginPath()\n _ctx[radii ? 'roundRect' : 'rect'](~~x, ~~y, width, height, radii)\n instance.stroke(color)\n },\n\n /**\n * Draw a color-filled rectangle\n *\n * @param {number} x\n * @param {number} y\n * @param {number} width\n * @param {number} height\n * @param {number} [color=0] the color index (generally from 0 to 7)\n * @param {number|number[]} [radii] A number or list specifying the radii used to draw a rounded-borders rectangle\n */\n rectfill(x, y, width, height, color = 0, radii = null) {\n _ctx.beginPath()\n _ctx[radii ? 'roundRect' : 'rect'](~~x, ~~y, width, height, radii)\n instance.fill(color)\n },\n\n /**\n * Draw a circle outline\n *\n * @param {number} x\n * @param {number} y\n * @param {number} radius\n * @param {number} [color=0] the color index (generally from 0 to 7)\n */\n circ(x, y, radius, color = 0) {\n _ctx.beginPath()\n _ctx.arc(~~x, ~~y, radius, 0, TWO_PI)\n _ctx.closePath()\n instance.stroke(color)\n },\n\n /**\n * Draw a color-filled circle\n *\n * @param {number} x\n * @param {number} y\n * @param {number} radius\n * @param {number} [color=0] the color index (generally from 0 to 7)\n */\n circfill(x, y, radius, color = 0) {\n _ctx.beginPath()\n _ctx.arc(~~x, ~~y, radius, 0, TWO_PI)\n _ctx.closePath()\n instance.fill(color)\n },\n\n /**\n * Draw a line\n *\n * @param {number} x1\n * @param {number} y1\n * @param {number} x2\n * @param {number} y2\n * @param {number} [color=0] the color index (generally from 0 to 7)\n */\n line(x1, y1, x2, y2, color = 0) {\n _ctx.beginPath()\n _ctx.moveTo(~~x1, ~~y1)\n _ctx.lineTo(~~x2, ~~y2)\n instance.stroke(color)\n },\n\n /**\n * Sets the thickness of lines\n *\n * @param {number} value\n * @see https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/lineWidth\n */\n linewidth(value) {\n _ctx.lineWidth = value\n },\n\n /**\n * Sets the line dash pattern used when drawing lines\n *\n * @param {number|number[]} segments the line dash pattern\n * @param {number} [offset=0] the line dash offset, or \"phase\".\n * @see https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/setLineDash\n * @see https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/lineDashOffset\n */\n linedash(segments, offset = 0) {\n _ctx.setLineDash(Array.isArray(segments) ? segments : [segments])\n _ctx.lineDashOffset = offset\n },\n\n /** TEXT RENDERING API */\n /**\n * Draw text\n *\n * @param {number} x\n * @param {number} y\n * @param {string} text the text message\n * @param {number} [color=3] the color index (generally from 0 to 7)\n */\n text(x, y, text, color = 3) {\n _ctx.font = `${_fontStyle || ''} ${_fontSize}px ${_fontFamily}`\n _ctx.fillStyle = instance.getcolor(color)\n _ctx.fillText(text, ~~x, ~~y)\n },\n\n /**\n * Set the font family\n *\n * @param {string} fontFamily\n */\n textfont(fontFamily) {\n _fontFamily = fontFamily\n },\n\n /**\n * Set the font size\n *\n * @param {string} size\n */\n textsize(size) {\n _fontSize = size\n },\n\n /**\n * Sets whether a font should be styled with a normal, italic, or bold.\n *\n * @param {string} style\n */\n textstyle(style) {\n _fontStyle = style\n },\n\n /**\n * Sets the alignment used when drawing texts\n *\n * @param {string} align the horizontal alignment. Possible values: \"left\", \"right\", \"center\", \"start\" or \"end\"\n * @param {string} baseline the vertical alignment. Possible values: \"top\", \"bottom\", \"middle\", \"hanging\" or \"ideographic\"\n * @see https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/textBaseline\n * @see https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/textAlign\n */\n textalign(align, baseline) {\n if (align) _ctx.textAlign = align\n if (baseline) _ctx.textBaseline = baseline\n },\n\n /**\n * Returns a TextMetrics object that contains information about the measured text (such as its width, for example)\n *\n * @param {string} text\n * @param {number} [size]\n * @returns {TextMetrics}\n * @see https://developer.mozilla.org/en-US/docs/Web/API/TextMetrics\n */\n textmetrics(text, size) {\n // prettier-ignore\n _ctx.font = `${_fontStyle || ''} ${(size || _fontSize)}px ${_fontFamily}`\n metrics = _ctx.measureText(text)\n metrics.height =\n metrics.actualBoundingBoxAscent +\n metrics.actualBoundingBoxDescent\n return metrics\n },\n\n /** IMAGE GRAPHICS API */\n /**\n * Draw an image\n *\n * @param {number} x\n * @param {number} y\n * @param {OffscreenCanvas|HTMLImageElement|HTMLCanvasElement} image\n */\n image(x, y, image) {\n _ctx.drawImage(image, ~~x, ~~y)\n },\n\n /**\n * Creates a offscreen canvas to draw on it\n *\n * @param {number} width\n * @param {number} height\n * @param {string[]|drawCallback} draw\n * @param {{scale?:number}} [options]\n * @returns {OffscreenCanvas}\n * @see https://developer.mozilla.org/en-US/docs/Web/API/OffscreenCanvas\n */\n paint(width, height, draw, options = {}) {\n const offscreenCanvas = new OffscreenCanvas(width, height),\n ctxOriginal = _ctx,\n scale = options.scale || 1\n\n offscreenCanvas.width = width * scale\n offscreenCanvas.height = height * scale\n _ctx = offscreenCanvas.getContext('2d')\n\n _ctx.scale(scale, scale)\n\n // is pixelart?\n if (Array.isArray(draw)) {\n let x = 0,\n y = 0\n\n _ctx.imageSmoothingEnabled = false\n\n for (const str of draw) {\n for (const color of str) {\n if (' ' !== color && '.' !== color) {\n // support for 16-color palettes using hex (from 0 to f)\n instance.rectfill(x, y, 1, 1, parseInt(color, 16))\n }\n x++\n }\n y++\n x = 0\n }\n } else {\n draw(offscreenCanvas, _ctx)\n }\n\n _ctx = ctxOriginal // restore the context\n\n return offscreenCanvas\n },\n\n /** ADVANCED GRAPHICS API */\n /**\n * Get the canvas context\n *\n * @returns {CanvasRenderingContext2D}\n */\n ctx: () => _ctx,\n\n /**\n * saves the current drawing style settings and transformations\n * @see https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/save\n */\n push: () => _ctx.save(),\n\n /**\n * restores the drawing style settings and transformations\n * @see https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/restore\n */\n pop: () => _ctx.restore(),\n\n /**\n * Adds a translation transformation to the current matrix\n *\n * @param {number} x\n * @param {number} y\n */\n translate: (x, y) => _ctx.translate(x, y),\n\n /**\n * Adds a scaling transformation to the canvas units horizontally and/or vertically.\n *\n * @param {number} x\n * @param {number} [y]\n */\n scale: (x, y) => _ctx.scale(x, y || x),\n\n /**\n * Adds a rotation to the transformation matrix\n *\n * @param {number} radians\n */\n rotate: (radians) => _ctx.rotate(radians),\n\n /**\n * Adds a transformation that skews to the transformation matrix\n *\n * @param {number} a\n * @param {number} b\n * @param {number} c\n * @param {number} d\n * @param {number} e\n * @param {number} f\n * @param {boolean} [resetFirst=true] `false` to use _ctx.transform(); by default use _ctx.setTransform()\n * @see https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/setTransform\n */\n transform: (a, b, c, d, e, f, resetFirst = true) =>\n _ctx[resetFirst ? 'setTransform' : 'transform'](a, b, c, d, e, f),\n\n /**\n * Sets the alpha (transparency) value to apply when drawing new shapes and images\n *\n * @param {number} alpha float from 0 to 1 (e.g: 0.5 = 50% transparent)\n * @see https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/globalAlpha\n */\n alpha(alpha) {\n _ctx.globalAlpha = alpha\n },\n\n /**\n * Returns a newly instantiated Path2D object, optionally with another\n * path as an argument (creates a copy), or optionally with a string\n * consisting of SVG path data.\n *\n * @param {Path2D|string} [arg]\n * @returns Path2D\n * @see https://developer.mozilla.org/en-US/docs/Web/API/Path2D/Path2D\n */\n path: (arg) => new Path2D(arg),\n\n /**\n * Fills the current or given path with a given color.\n *\n * @param {number} color\n * @param {Path2D} [path]\n */\n fill(color, path) {\n _ctx.fillStyle = instance.getcolor(color)\n _ctx.fill(path)\n },\n\n /**\n * Outlines the current or given path with a given color.\n *\n * @param {number} color\n * @param {Path2D} [path]\n */\n stroke(color, path) {\n _ctx.strokeStyle = instance.getcolor(color)\n path ? _ctx.stroke(path) : _ctx.stroke()\n },\n\n /**\n * Create a retangular clipping region.\n *\n * Note: Clip paths cannot be reverted directly. You must save your\n * canvas state using push() before calling cliprect(), and restore it\n * once you have finished drawing in the clipped area using pop().\n *\n * @param {number} x\n * @param {number} y\n * @param {number} width\n * @param {number} height\n * @see https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/clip\n */\n cliprect(x, y, width, height) {\n _ctx.beginPath()\n _ctx.rect(x, y, width, height)\n _ctx.clip()\n },\n\n /**\n * Create a circular clipping region.\n *\n * Note: Clip paths cannot be reverted directly. You must save your\n * canvas state using push() before calling clipcirc(), and restore it\n * once you have finished drawing in the clipped area using pop().\n *\n * @param {number} x\n * @param {number} y\n * @param {number} radius\n * @see https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/clip\n */\n clipcirc(x, y, radius) {\n _ctx.beginPath()\n _ctx.arc(x, y, radius, 0, TWO_PI)\n _ctx.clip()\n },\n\n /**\n * Sets the type of compositing operation to apply when drawing new shapes.\n * Default value = 'source-over'.\n *\n * @param {string} value\n * @see https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/globalCompositeOperation\n */\n blendmode(value) {\n _ctx.globalCompositeOperation = value\n },\n\n /** SOUND API */\n /**\n * Play a defined sound or a ZzFX array of params\n *\n * @param {number|number[]} [sound=0] the sound index (from 0 to 7) or a ZzFX array of params\n * @param {number} [volume=1]\n * @param {number} [pitch=0]\n * @param {number} [randomness=0]\n * @returns {AudioBufferSourceNode}\n * @see https://github.com/KilledByAPixel/ZzFX\n */\n sfx(sound = 0, volume = 1, pitch = 0, randomness = 0) {\n if (\n navigator.userActivation &&\n !navigator.userActivation.hasBeenActive\n ) {\n return\n }\n\n let z = Array.isArray(sound) ? sound : sounds[sound % sounds.length]\n if (volume !== 1 || pitch || randomness) {\n z = [...z] // clone the sound to not modify the original\n z[0] = (Number(volume) || 1) * (z[0] || 1)\n z[1] = randomness > 0 ? randomness : 0\n z[10] = ~~z[10] + ~~pitch\n }\n\n return zzfx(...z)\n },\n\n /** UTILS API */\n /**\n * Check a collision between two rectangles\n *\n * @param {number} x1 first rectangle position X\n * @param {number} y1 first rectangle position Y\n * @param {number} w1 first rectangle width\n * @param {number} h1 first rectangle height\n * @param {number} x2 second rectangle position X\n * @param {number} y2 second rectangle position Y\n * @param {number} w2 second rectangle width\n * @param {number} h2 second rectangle height\n * @returns {boolean}\n */\n colrect: (x1, y1, w1, h1, x2, y2, w2, h2) =>\n x1 < x2 + w2 && x1 + w1 > x2 && y1 < y2 + h2 && y1 + h1 > y2,\n\n /**\n * Check a collision between two circles\n *\n * @param {number} x1 first circle position X\n * @param {number} y1 first circle position Y\n * @param {number} r1 first circle position radius\n * @param {number} x2 second circle position X\n * @param {number} y2 second circle position Y\n * @param {number} r2 second circle position radius\n * @returns {boolean}\n */\n colcirc: (x1, y1, r1, x2, y2, r2) =>\n (x2 - x1) ** 2 + (y2 - y1) ** 2 <= (r1 + r2) ** 2,\n\n /**\n * Get the mouse position\n * @returns number[]\n */\n mousepos: () => [_mouseX, _mouseY],\n\n /**\n * The scale of the game's delta time (dt).\n * Values higher than 1 increase the speed of time, while values smaller than 1 decrease it.\n * A value of 0 freezes time and is effectively equivalent to pausing.\n *\n * @param {number} value\n */\n timescale(value) {\n _timeScale = value\n },\n\n /** PLUGINS API */\n /**\n * Prepares a plugin to be loaded\n *\n * @param {pluginCallback} callback\n */\n use(callback, config = {}) {\n callback.__conf = config\n _initialized ? loadPlugin(callback) : _plugins.push(callback)\n },\n\n /**\n * Add a game event listener\n *\n * @param {string} event the event type name\n * @param {function} callback the function that is called when the event occurs\n * @param {boolean} [highPriority=false] determines whether the callback will be called before or after the others\n * @returns {function} a function to remove the listener\n */\n listen(event, callback, highPriority = false) {\n _events[event] = _events[event] || [[], []]\n const size = _events[event][highPriority ? 0 : 1].push(callback)\n\n // return a function to remove this event listener\n return () => {\n _events[event][highPriority ? 0 : 1].splice(size - 1, 1)\n }\n },\n\n /**\n * Call all listeners attached to a game event\n *\n * @param {string} event The game event type\n * @param {...any} args Arguments passed to all listeners\n */\n emit(event, ...args) {\n if (!_events[event]) return\n for (const list of _events[event]) {\n for (const callback of list) {\n callback(...args)\n }\n }\n },\n\n /**\n * Get a color by index\n *\n * @param {number} index The color number\n * @returns {string} the color code\n */\n getcolor: (index) => colors[~~index % colors.length],\n\n /**\n * Create or update a instance variable\n *\n * @param {string} key\n * @param {any} value\n */\n setvar(key, value) {\n instance[key] = value\n if (settings.global) {\n root[key] = value\n }\n },\n\n /**\n * Resizes the game canvas and emit the \"resized\" event\n *\n * @param {number} width\n * @param {number} height\n */\n resize(width, height) {\n instance.setvar('WIDTH', (_canvas.width = width))\n instance.setvar('HEIGHT', (_canvas.height = height || width))\n pageResized()\n },\n }\n\n /** Copy some functions from native `Math` object */\n for (const k of [\n 'sin',\n 'cos',\n 'atan2',\n 'hypot',\n 'tan',\n 'abs',\n 'ceil',\n 'round',\n 'floor',\n 'trunc',\n 'min',\n 'max',\n 'pow',\n 'sqrt',\n 'sign',\n 'exp',\n ]) {\n // import some native Math functions\n instance[k] = Math[k]\n }\n\n function init() {\n _initialized = true\n setupCanvas()\n\n // add listeners for default events\n const source = settings.loop ? settings.loop : root\n for (const event of Object.keys(_events)) {\n if (source[event]) instance.listen(event, source[event])\n }\n\n // load plugins\n for (const plugin of _plugins) {\n loadPlugin(plugin)\n }\n\n // listen window resize event\n on(root, 'resize', pageResized)\n pageResized()\n\n // default mouse/touch handlers\n if (settings.tapEvents) {\n const _getXY = (pageX, pageY) => [\n (pageX - _canvas.offsetLeft) / _scale,\n (pageY - _canvas.offsetTop) / _scale,\n ],\n _taps = new Map(),\n _registerTap = (id, x, y) => {\n const tap = {\n x,\n y,\n startX: x,\n startY: y,\n // timestamp\n ts: performance.now(),\n }\n _taps.set(id, tap)\n return tap\n },\n _updateTap = (id, x, y) => {\n const tap = _taps.get(id) || _registerTap(id)\n tap.x = x\n tap.y = y\n },\n _checkTapped = (tap) => tap && performance.now() - tap.ts <= 200\n\n let _pressingMouse = false\n\n on(_canvas, 'mousedown', (ev) => {\n ev.preventDefault()\n const [x, y] = _getXY(ev.pageX, ev.pageY)\n instance.emit('tap', x, y, 0)\n _registerTap(0, x, y)\n _pressingMouse = true\n })\n\n on(_canvas, 'mousemove', (ev) => {\n ev.preventDefault()\n const [x, y] = ([_mouseX, _mouseY] = _getXY(ev.pageX, ev.pageY))\n if (!_pressingMouse) return\n instance.emit('tapping', x, y, 0)\n _updateTap(0, x, y)\n })\n\n on(_canvas, 'mouseup', (ev) => {\n ev.preventDefault()\n const tap = _taps.get(0)\n const [x, y] = _getXY(ev.pageX, ev.pageY)\n if (_checkTapped(tap)) {\n instance.emit('tapped', tap.startX, tap.startY, 0)\n }\n instance.emit('untap', x, y, 0)\n _taps.delete(0)\n _pressingMouse = false\n })\n\n on(_canvas, 'touchstart', (ev) => {\n ev.preventDefault()\n /** @type {TouchList} touches */\n const touches = ev.changedTouches\n for (const touch of touches) {\n const [x, y] = _getXY(touch.pageX, touch.pageY)\n instance.emit('tap', x, y, touch.identifier + 1)\n _registerTap(touch.identifier + 1, x, y)\n }\n })\n\n on(_canvas, 'touchmove', (ev) => {\n ev.preventDefault()\n /** @type {TouchList} touches */\n const touches = ev.changedTouches\n for (const touch of touches) {\n const [x, y] = _getXY(touch.pageX, touch.pageY)\n instance.emit('tapping', x, y, touch.identifier + 1)\n _updateTap(touch.identifier + 1, x, y)\n }\n })\n\n const _touchEndHandler = (ev) => {\n ev.preventDefault()\n const existing = []\n\n if (ev.targetTouches.length > 0) {\n for (const touch of ev.targetTouches) {\n existing.push(touch.identifier + 1)\n }\n }\n\n for (const [id, tap] of _taps) {\n if (existing.includes(id)) continue\n if (_checkTapped(tap)) {\n instance.emit('tapped', tap.startX, tap.startY, id)\n }\n instance.emit('untap', tap.x, tap.y, id)\n _taps.delete(id)\n }\n }\n\n on(_canvas, 'touchend', _touchEndHandler)\n on(_canvas, 'touchcancel', _touchEndHandler)\n\n on(root, 'blur', () => {\n _pressingMouse = false\n\n if (_taps.size === 0) return\n\n for (const [id, tap] of _taps) {\n instance.emit('untap', tap.x, tap.y, id)\n _taps.delete(id)\n }\n })\n }\n\n // listen browser focus/blur events and pause the update/draw loop\n if (settings.pauseOnBlur) {\n on(root, 'blur', () => {\n _rafid = null\n })\n on(root, 'focus', () => {\n if (!_rafid) {\n _lastFrame = performance.now()\n _rafid = requestAnimationFrame(drawFrame)\n }\n })\n }\n\n // start the game loop\n instance.emit('init')\n _lastFrame = performance.now()\n _rafid = requestAnimationFrame(drawFrame)\n }\n\n /**\n * @param {number} now\n */\n function drawFrame(now) {\n let ticks = 0,\n t = now - _lastFrame\n\n _lastFrame = now\n _accumulated += t\n\n while (_accumulated >= _stepMs) {\n instance.emit('update', _step * _timeScale)\n instance.setvar('ELAPSED', instance.ELAPSED + _step * _timeScale)\n _accumulated -= _stepMs\n ticks++\n }\n\n if (ticks) {\n // default custom values for textAlign & textBaseline\n instance.textalign('start', 'top')\n\n instance.emit('draw')\n _drawCount++\n _drawTime += _stepMs * ticks\n\n if (_drawTime + _accumulated >= 1000) {\n instance.setvar('FPS', _drawCount)\n _drawCount = 0\n _drawTime -= 1000\n }\n }\n\n if (_rafid) _rafid = requestAnimationFrame(drawFrame)\n }\n\n function setupCanvas() {\n _canvas =\n 'string' === typeof _canvas\n ? document.querySelector(_canvas)\n : _canvas\n\n instance.setvar('CANVAS', _canvas)\n _ctx = _canvas.getContext('2d')\n\n // disable fullscreen if a width is specified\n if (instance.WIDTH > 0) _fullscreen = false\n\n _canvas.width = instance.WIDTH\n _canvas.height = instance.HEIGHT || instance.WIDTH\n\n if (!_canvas.parentNode) document.body.appendChild(_canvas)\n\n // canvas CSS tweaks\n _canvas.style.display = 'block'\n if (_fullscreen) {\n _canvas.style.position = 'absolute'\n _canvas.style.inset = 0\n } else if (_autoscale) {\n _canvas.style.margin = 'auto'\n }\n }\n\n function pageResized() {\n if (_fullscreen) {\n _canvas.width = innerWidth\n _canvas.height = innerHeight\n instance.setvar('WIDTH', innerWidth)\n instance.setvar('HEIGHT', innerHeight)\n } else if (_autoscale) {\n _scale = Math.min(\n innerWidth / instance.WIDTH,\n innerHeight / instance.HEIGHT\n )\n _scale = settings.pixelart ? Math.floor(_scale) : _scale\n _canvas.style.width = instance.WIDTH * _scale + 'px'\n _canvas.style.height = instance.HEIGHT * _scale + 'px'\n }\n\n instance.setvar('CENTERX', instance.WIDTH / 2)\n instance.setvar('CENTERY', instance.HEIGHT / 2)\n\n // restore canvas image rendering properties\n if (!settings.antialias || settings.pixelart) {\n _ctx.imageSmoothingEnabled = false\n _canvas.style.imageRendering = 'pixelated'\n }\n\n instance.emit('resized', _scale)\n }\n\n /**\n * @param {pluginCallback} callback\n */\n function loadPlugin(callback) {\n const pluginData = callback(instance, _helpers, callback.__conf)\n if ('object' === typeof pluginData) {\n for (const [key, value] of Object.entries(pluginData)) {\n instance.setvar(key, value)\n }\n }\n }\n\n if (settings.global) {\n if (root.__litecanvas) {\n throw 'Cannot instantiate litecanvas globally twice'\n }\n Object.assign(root, instance)\n root.__litecanvas = instance\n }\n\n if ('loading' === document.readyState) {\n on(root, 'DOMContentLoaded', init)\n } else {\n init()\n }\n\n return instance\n}\n", "import litecanvas from './index.js'\n\nglobalThis.litecanvas = litecanvas\n"],
5
- "mappings": "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",
6
- "names": ["zzfx", "p", "k", "b", "e", "r", "t", "q", "D", "u", "y", "v", "z", "l", "E", "A", "c", "w", "m", "B", "N", "M", "d", "R", "G", "C", "g", "H", "a", "I", "J", "f", "h", "x", "L", "Z", "K", "O", "X", "Y", "P", "Q", "S", "T", "U", "V", "W", "zzfxX", "colors", "sounds", "litecanvas", "settings", "root", "PI", "TWO_PI", "on", "elem", "evt", "callback", "_initialized", "_plugins", "_canvas", "_fullscreen", "_autoscale", "_scale", "_mouseX", "_mouseY", "_ctx", "_timeScale", "_lastFrame", "_step", "_stepMs", "_accumulated", "_rafid", "_drawCount", "_drawTime", "_fontFamily", "_fontStyle", "_fontSize", "_rng_seed", "_events", "_helpers", "colors", "sounds", "instance", "start", "end", "t", "degs", "rads", "value", "min", "max", "min1", "max1", "min2", "max2", "withinBounds", "result", "color", "x", "y", "width", "height", "radii", "radius", "x1", "y1", "x2", "y2", "segments", "offset", "text", "fontFamily", "size", "style", "align", "baseline", "image", "draw", "options", "offscreenCanvas", "ctxOriginal", "scale", "str", "radians", "a", "b", "c", "d", "e", "f", "resetFirst", "alpha", "arg", "path", "sound", "volume", "pitch", "randomness", "z", "zzfx", "w1", "h1", "w2", "h2", "r1", "r2", "config", "loadPlugin", "event", "highPriority", "args", "list", "index", "key", "pageResized", "k", "init", "setupCanvas", "source", "plugin", "_getXY", "pageX", "pageY", "_taps", "_registerTap", "id", "tap", "_updateTap", "_checkTapped", "_pressingMouse", "ev", "touches", "touch", "_touchEndHandler", "existing", "drawFrame", "now", "ticks", "pluginData", "litecanvas"]
4
+ "sourcesContent": ["// ZzFXMicro - Zuper Zmall Zound Zynth - v1.3.0 by Frank Force | https://github.com/KilledByAPixel/ZzFX\nexport const zzfx = (\n p = 1,\n k = 0.05,\n b = 220,\n e = 0,\n r = 0,\n t = 0.1,\n q = 0,\n D = 1,\n u = 0,\n y = 0,\n v = 0,\n z = 0,\n l = 0,\n E = 0,\n A = 0,\n F = 0,\n c = 0,\n w = 1,\n m = 0,\n B = 0,\n N = 0\n) => {\n let M = Math,\n d = 2 * M.PI,\n R = 44100,\n G = (u *= (500 * d) / R / R),\n C = (b *= ((1 - k + 2 * k * M.random((k = []))) * d) / R),\n g = 0,\n H = 0,\n a = 0,\n n = 1,\n I = 0,\n J = 0,\n f = 0,\n h = N < 0 ? -1 : 1,\n x = (d * h * N * 2) / R,\n L = M.cos(x),\n Z = M.sin,\n K = Z(x) / 4,\n O = 1 + K,\n X = (-2 * L) / O,\n Y = (1 - K) / O,\n P = (1 + h * L) / 2 / O,\n Q = -(h + L) / O,\n S = P,\n T = 0,\n U = 0,\n V = 0,\n W = 0\n e = R * e + 9\n m *= R\n r *= R\n t *= R\n c *= R\n y *= (500 * d) / R ** 3\n A *= d / R\n v *= d / R\n z *= R\n l = (R * l) | 0\n p *= globalThis.zzfxV || 0.3\n for (h = (e + m + r + t + c) | 0; a < h; k[a++] = f * p)\n ++J % ((100 * F) | 0) ||\n ((f = q\n ? 1 < q\n ? 2 < q\n ? 3 < q\n ? Z(g * g)\n : M.max(M.min(M.tan(g), 1), -1)\n : 1 - (((((2 * g) / d) % 2) + 2) % 2)\n : 1 - 4 * M.abs(M.round(g / d) - g / d)\n : Z(g)),\n (f =\n (l ? 1 - B + B * Z((d * a) / l) : 1) *\n (f < 0 ? -1 : 1) *\n M.abs(f) ** D *\n (a < e\n ? a / e\n : a < e + m\n ? 1 - ((a - e) / m) * (1 - w)\n : a < e + m + r\n ? w\n : a < h - c\n ? ((h - a - c) / t) * w\n : 0)),\n (f = c\n ? f / 2 +\n (c > a\n ? 0\n : ((a < h - c ? 1 : (h - a) / c) * k[(a - c) | 0]) /\n 2 /\n p)\n : f),\n N\n ? (f = W =\n S * T + Q * (T = U) + P * (U = f) - Y * V - X * (V = W))\n : 0),\n (x = (b += u += y) * M.cos(A * H++)),\n (g += x + x * E * Z(a ** 5)),\n n && ++n > z && ((b += v), (C += v), (n = 0)),\n !l || ++I % l || ((b = C), (u = G), (n = n || 1))\n p = zzfxX.createBuffer(1, h, R)\n p.getChannelData(0).set(k)\n b = zzfxX.createBufferSource()\n b.buffer = p\n b.connect(zzfxX.destination)\n b.start()\n}\n\nconst zzfxX = /** @__PURE__ */ new AudioContext()\n", "// Default colors inspired by https://lospec.com/palette-list/trirampo\nexport const colors = [\n '#18161c',\n '#6a7799',\n '#aec2c2',\n '#f3eade',\n\n '#f04f78',\n '#fcf660',\n '#2f328f',\n '#4b80ca',\n\n '#327345',\n '#63c64d',\n '#703075',\n '#a56243',\n]\n", "// prettier-ignore\nexport const sounds = [\n // 0 - pickup\n [0.8,, 2e3, 0.01, 0.05, , 1, 2, , , -600, 0.05, , , , , , 0.5, 0.05],\n // 1 - hit\n [0.5,, 375, 0.02, 0.01, 0.2, 1, , , , , , , 0.4, , 0.1, , 0.6, 0.1],\n // 2 - jump\n [,, 360, 0.01, , 0.08, 1, 1.7, 12, 32, , , , , , , , 0.63, 0.02, , 99],\n // 3 - warning\n [1.2,, 240, 0.02, 0.15, 0.15, 1, 4, , , , , 0.05, , , , , 0.6, 0.15],\n]\n", "import { zzfx } from './zzfx.js'\nimport { colors } from './palette.js'\nimport { sounds } from './sounds.js'\nimport './types.js'\n\n/**\n * The litecanvas constructor\n *\n * @param {LitecanvasOptions} [settings]\n * @returns {LitecanvasInstance}\n */\nexport default function litecanvas(settings = {}) {\n const root = globalThis,\n PI = Math.PI,\n TWO_PI = PI * 2,\n /** @type {(elem:HTMLElement, evt:string, callback:(event:Event)=>boolean?)=>void} */\n on = (elem, evt, callback) => elem.addEventListener(evt, callback),\n /** @type {LitecanvasOptions} */\n defaults = {\n fps: 60,\n fullscreen: true,\n width: null,\n height: null,\n autoscale: true,\n pixelart: false,\n antialias: true,\n canvas: null,\n global: true,\n loop: null,\n tapEvents: true,\n pauseOnBlur: true,\n }\n\n // setup the settings default values\n settings = Object.assign(defaults, settings)\n\n let /** @type {boolean} */\n _initialized = false,\n /** @type {function[]} */\n _plugins = [],\n /** @type {HTMLCanvasElement|string} _canvas */\n _canvas = settings.canvas || document.createElement('canvas'),\n /** @type {boolean} */\n _fullscreen = settings.fullscreen,\n /** @type {boolean} */\n _autoscale = settings.autoscale,\n /** @type {number} */\n _scale = 1,\n /** @type {number?} */\n _mouseX,\n /** @type {number?} */\n _mouseY,\n /** @type {CanvasRenderingContext2D} */\n _ctx,\n /** @type {number} */\n _timeScale = 1,\n /** @type {number} */\n _lastFrame,\n /** @type {number} */\n _step = 1 / settings.fps,\n /** @type {number} */\n _stepMs = _step * 1000,\n /** @type {number} */\n _accumulated = 0,\n /** @type {number} */\n _rafid,\n /** @type {number} */\n _drawCount = 0,\n /** @type {number} */\n _drawTime = 0,\n /** @type {string} */\n _fontFamily = 'sans-serif',\n /** @type {string} */\n _fontStyle = '',\n /** @type {number} */\n _fontSize = 32,\n /** @type {number} */\n _rng_seed = Date.now(),\n /**\n * default game events\n */\n _events = {\n init: false,\n update: false,\n draw: false,\n resized: false,\n tap: false,\n untap: false,\n tapping: false,\n tapped: false,\n },\n /**\n * Helpers to be used by plugins\n *\n * @type {LitecanvasPluginHelpers}\n */\n _helpers = {\n settings: Object.assign({}, settings),\n colors,\n sounds,\n }\n\n /** @type {LitecanvasInstance} */\n const instance = {\n /** @type {number} */\n WIDTH: settings.width,\n /** @type {number} */\n HEIGHT: settings.height || settings.width,\n /** @type {HTMLCanvasElement} */\n CANVAS: null,\n /** @type {number} */\n ELAPSED: 0,\n /** @type {number} */\n FPS: settings.fps,\n /** @type {number} */\n CENTERX: null,\n /** @type {number} */\n CENTERY: null,\n\n /** MATH API */\n /**\n * The value of the mathematical constant PI (\u03C0).\n * Approximately 3.14159\n *\n * @type {number}\n */\n PI,\n\n /**\n * Twice the value of the mathematical constant PI (\u03C0).\n * Approximately 6.28318\n *\n * Note: TWO_PI radians equals 360\u00B0, PI radians equals 180\u00B0,\n * HALF_PI radians equals 90\u00B0, and HALF_PI/2 radians equals 45\u00B0.\n *\n * @type {number}\n */\n TWO_PI,\n\n /**\n * Half the value of the mathematical constant PI (\u03C0).\n * Approximately 1.57079\n *\n * @type {number}\n */\n HALF_PI: PI * 0.5,\n\n /**\n * Calculates a linear (interpolation) value over t%.\n *\n * @param {number} start\n * @param {number} end\n * @param {number} t The progress in percentage, where 0 = 0% and 1 = 100%.\n * @returns {number} The unterpolated value\n * @tutorial https://gamedev.net/tutorials/programming/general-and-gameplay-programming/a-brief-introduction-to-lerp-r4954/\n */\n lerp: (start, end, t) => start + t * (end - start),\n\n /**\n * Convert degrees to radians\n *\n * @param {number} degs\n * @returns {number} the value in radians\n */\n deg2rad: (degs) => (PI / 180) * degs,\n\n /**\n * Convert radians to degrees\n *\n * @param {number} rads\n * @returns {number} the value in degrees\n */\n rad2deg: (rads) => (180 / PI) * rads,\n\n /**\n * Constrains a number between `min` and `max`.\n *\n * @param {number} value\n * @param {number} min\n * @param {number} max\n * @returns {number}\n */\n clamp: (value, min, max) => {\n if (value < min) return min\n if (value > max) return max\n return value\n },\n\n /**\n * Wraps a number between `min` (inclusive) and `max` (exclusive).\n *\n * @param {number} value\n * @param {number} min\n * @param {number} max\n * @returns {number}\n */\n wrap: (value, min, max) =>\n value - (max - min) * Math.floor((value - min) / (max - min)),\n\n /**\n * Re-maps a number from one range to another.\n *\n * @param {number} value the value to be remapped.\n * @param {number} min1 lower bound of the value's current range.\n * @param {number} max1 upper bound of the value's current range.\n * @param {number} min2 lower bound of the value's target range.\n * @param {number} max2 upper bound of the value's target range.\n * @param {boolean} [withinBounds=false] constrain the value to the newly mapped range\n * @returns {number} the remapped number\n */\n map(value, min1, max1, min2, max2, withinBounds = false) {\n // prettier-ignore\n const result = ((value - min1) / (max1 - min1)) * (max2 - min2) + min2\n return !withinBounds ? result : instance.clamp(result, min2, max2)\n },\n\n /**\n * Maps a number from one range to a value between 0 and 1.\n * Identical to `map(value, min, max, 0, 1)`.\n * Note: Numbers outside the range are not clamped to 0 and 1.\n *\n * @param {number} value\n * @param {number} min\n * @param {number} min\n * @returns {number} the normalized number.\n */\n norm: (value, min, max) => instance.map(value, min, max, 0, 1),\n\n /** RNG API */\n /**\n * Generates a pseudorandom float between min (inclusive) and max (exclusive)\n * using the Linear Congruential Generator (LCG) algorithm.\n *\n * @param {number} [min=0.0]\n * @param {number} [max=1.0]\n * @returns {number} the random number\n */\n rand: (min = 0.0, max = 1.0) => {\n const a = 1664525\n const c = 1013904223\n const m = 4294967296\n\n _rng_seed = (a * _rng_seed + c) % m\n\n return (_rng_seed / m) * (max - min) + min\n },\n\n /**\n * Generates a pseudorandom integer between min (inclusive) and max (inclusive)\n *\n * @param {number} [min=0]\n * @param {number} [max=1]\n * @returns {number} the random number\n */\n randi: (min = 0, max = 1) =>\n instance.floor(instance.rand() * (max - min + 1) + min),\n\n /**\n * If a value is passed, initializes the random number generator with an explicit seed value.\n * Otherwise, returns the current seed state.\n *\n * @param {number} value\n * @returns {number} the seed state\n */\n seed: (value) => {\n return null == value ? _rng_seed : (_rng_seed = ~~value)\n },\n\n /** BASIC GRAPHICS API */\n /**\n * Clear the game screen\n *\n * @param {number|null} color The background color (from 0 to 7) or null (for transparent)\n */\n cls(color) {\n if (null == color) {\n _ctx.clearRect(0, 0, instance.WIDTH, instance.HEIGHT)\n } else {\n instance.rectfill(0, 0, instance.WIDTH, instance.HEIGHT, color)\n }\n },\n\n /**\n * Draw a rectangle outline\n *\n * @param {number} x\n * @param {number} y\n * @param {number} width\n * @param {number} height\n * @param {number} [color=0] the color index (generally from 0 to 7)\n * @param {number|number[]} [radii] A number or list specifying the radii used to draw a rounded-borders rectangle\n */\n rect(x, y, width, height, color = 0, radii = null) {\n _ctx.beginPath()\n _ctx[radii ? 'roundRect' : 'rect'](~~x, ~~y, width, height, radii)\n instance.stroke(color)\n },\n\n /**\n * Draw a color-filled rectangle\n *\n * @param {number} x\n * @param {number} y\n * @param {number} width\n * @param {number} height\n * @param {number} [color=0] the color index (generally from 0 to 7)\n * @param {number|number[]} [radii] A number or list specifying the radii used to draw a rounded-borders rectangle\n */\n rectfill(x, y, width, height, color = 0, radii = null) {\n _ctx.beginPath()\n _ctx[radii ? 'roundRect' : 'rect'](~~x, ~~y, width, height, radii)\n instance.fill(color)\n },\n\n /**\n * Draw a circle outline\n *\n * @param {number} x\n * @param {number} y\n * @param {number} radius\n * @param {number} [color=0] the color index (generally from 0 to 7)\n */\n circ(x, y, radius, color) {\n _ctx.beginPath()\n _ctx.arc(~~x, ~~y, radius, 0, TWO_PI)\n _ctx.closePath()\n instance.stroke(color)\n },\n\n /**\n * Draw a color-filled circle\n *\n * @param {number} x\n * @param {number} y\n * @param {number} radius\n * @param {number} [color=0] the color index (generally from 0 to 7)\n */\n circfill(x, y, radius, color) {\n _ctx.beginPath()\n _ctx.arc(~~x, ~~y, radius, 0, TWO_PI)\n _ctx.closePath()\n instance.fill(color)\n },\n\n /**\n * Draw a line\n *\n * @param {number} x1\n * @param {number} y1\n * @param {number} x2\n * @param {number} y2\n * @param {number} [color=0] the color index (generally from 0 to 7)\n */\n line(x1, y1, x2, y2, color) {\n _ctx.beginPath()\n _ctx.moveTo(~~x1, ~~y1)\n _ctx.lineTo(~~x2, ~~y2)\n instance.stroke(color)\n },\n\n /**\n * Sets the thickness of lines\n *\n * @param {number} value\n * @see https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/lineWidth\n */\n linewidth(value) {\n _ctx.lineWidth = value\n },\n\n /**\n * Sets the line dash pattern used when drawing lines\n *\n * @param {number|number[]} segments the line dash pattern\n * @param {number} [offset=0] the line dash offset, or \"phase\".\n * @see https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/setLineDash\n * @see https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/lineDashOffset\n */\n linedash(segments, offset = 0) {\n _ctx.setLineDash(Array.isArray(segments) ? segments : [segments])\n _ctx.lineDashOffset = offset\n },\n\n /** TEXT RENDERING API */\n /**\n * Draw text\n *\n * @param {number} x\n * @param {number} y\n * @param {string} text the text message\n * @param {number} [color=3] the color index (generally from 0 to 7)\n */\n text(x, y, text, color = 3) {\n _ctx.font = `${_fontStyle || ''} ${_fontSize}px ${_fontFamily}`\n _ctx.fillStyle = instance.getcolor(color)\n _ctx.fillText(text, ~~x, ~~y)\n },\n\n /**\n * Set the font family\n *\n * @param {string} fontFamily\n */\n textfont(fontFamily) {\n _fontFamily = fontFamily\n },\n\n /**\n * Set the font size\n *\n * @param {string} size\n */\n textsize(size) {\n _fontSize = size\n },\n\n /**\n * Sets whether a font should be styled with a normal, italic, or bold.\n *\n * @param {string} style\n */\n textstyle(style) {\n _fontStyle = style\n },\n\n /**\n * Sets the alignment used when drawing texts\n *\n * @param {string} align the horizontal alignment. Possible values: \"left\", \"right\", \"center\", \"start\" or \"end\"\n * @param {string} baseline the vertical alignment. Possible values: \"top\", \"bottom\", \"middle\", \"hanging\" or \"ideographic\"\n * @see https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/textBaseline\n * @see https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/textAlign\n */\n textalign(align, baseline) {\n if (align) _ctx.textAlign = align\n if (baseline) _ctx.textBaseline = baseline\n },\n\n /**\n * Returns a TextMetrics object that contains information about the measured text (such as its width, for example)\n *\n * @param {string} text\n * @param {number} [size]\n * @returns {TextMetrics}\n * @see https://developer.mozilla.org/en-US/docs/Web/API/TextMetrics\n */\n textmetrics(text, size) {\n // prettier-ignore\n _ctx.font = `${_fontStyle || ''} ${(size || _fontSize)}px ${_fontFamily}`\n metrics = _ctx.measureText(text)\n metrics.height =\n metrics.actualBoundingBoxAscent +\n metrics.actualBoundingBoxDescent\n return metrics\n },\n\n /** IMAGE GRAPHICS API */\n /**\n * Draw an image\n *\n * @param {number} x\n * @param {number} y\n * @param {OffscreenCanvas|HTMLImageElement|HTMLCanvasElement} image\n */\n image(x, y, image) {\n _ctx.drawImage(image, ~~x, ~~y)\n },\n\n /**\n * Creates a offscreen canvas to draw on it\n *\n * @param {number} width\n * @param {number} height\n * @param {string[]|drawCallback} draw\n * @param {{scale?:number}} [options]\n * @returns {OffscreenCanvas}\n * @see https://developer.mozilla.org/en-US/docs/Web/API/OffscreenCanvas\n */\n paint(width, height, draw, options = {}) {\n const offscreenCanvas = new OffscreenCanvas(width, height),\n ctxOriginal = _ctx,\n scale = options.scale || 1\n\n offscreenCanvas.width = width * scale\n offscreenCanvas.height = height * scale\n _ctx = offscreenCanvas.getContext('2d')\n\n _ctx.scale(scale, scale)\n\n // is pixelart?\n if (Array.isArray(draw)) {\n let x = 0,\n y = 0\n\n _ctx.imageSmoothingEnabled = false\n\n for (const str of draw) {\n for (const color of str) {\n if (' ' !== color && '.' !== color) {\n // support for 16-color palettes using hex (from 0 to f)\n instance.rectfill(x, y, 1, 1, parseInt(color, 16))\n }\n x++\n }\n y++\n x = 0\n }\n } else {\n draw(offscreenCanvas, _ctx)\n }\n\n _ctx = ctxOriginal // restore the context\n\n return offscreenCanvas\n },\n\n /** ADVANCED GRAPHICS API */\n /**\n * Get the canvas context\n *\n * @returns {CanvasRenderingContext2D}\n */\n ctx: () => _ctx,\n\n /**\n * saves the current drawing style settings and transformations\n * @see https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/save\n */\n push: () => _ctx.save(),\n\n /**\n * restores the drawing style settings and transformations\n * @see https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/restore\n */\n pop: () => _ctx.restore(),\n\n /**\n * Adds a translation transformation to the current matrix\n *\n * @param {number} x\n * @param {number} y\n */\n translate: (x, y) => _ctx.translate(x, y),\n\n /**\n * Adds a scaling transformation to the canvas units horizontally and/or vertically.\n *\n * @param {number} x\n * @param {number} [y]\n */\n scale: (x, y) => _ctx.scale(x, y || x),\n\n /**\n * Adds a rotation to the transformation matrix\n *\n * @param {number} radians\n */\n rotate: (radians) => _ctx.rotate(radians),\n\n /**\n * Adds a transformation that skews to the transformation matrix\n *\n * @param {number} a\n * @param {number} b\n * @param {number} c\n * @param {number} d\n * @param {number} e\n * @param {number} f\n * @param {boolean} [resetFirst=true] `false` to use _ctx.transform(); by default use _ctx.setTransform()\n * @see https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/setTransform\n */\n transform: (a, b, c, d, e, f, resetFirst = true) =>\n _ctx[resetFirst ? 'setTransform' : 'transform'](a, b, c, d, e, f),\n\n /**\n * Sets the alpha (opacity) value to apply when drawing new shapes and images\n *\n * @param {number} alpha float from 0 to 1 (e.g: 0.5 = 50% transparent)\n * @see https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/globalAlpha\n */\n alpha(value) {\n _ctx.globalAlpha = instance.clamp(value, 0, 1)\n },\n\n /**\n * Returns a newly instantiated Path2D object, optionally with another\n * path as an argument (creates a copy), or optionally with a string\n * consisting of SVG path data.\n *\n * @param {Path2D|string} [arg]\n * @returns Path2D\n * @see https://developer.mozilla.org/en-US/docs/Web/API/Path2D/Path2D\n */\n path: (arg) => new Path2D(arg),\n\n /**\n * Fills the current or given path with a given color.\n *\n * @param {number} [color=0]\n * @param {Path2D} [path]\n */\n fill(color, path) {\n _ctx.fillStyle = instance.getcolor(color)\n _ctx.fill(path)\n },\n\n /**\n * Outlines the current or given path with a given color.\n *\n * @param {number} [color=0]\n * @param {Path2D} [path]\n */\n stroke(color, path) {\n _ctx.strokeStyle = instance.getcolor(color)\n path ? _ctx.stroke(path) : _ctx.stroke()\n },\n\n /**\n * Create a retangular clipping region.\n *\n * Note: Clip paths cannot be reverted directly. You must save your\n * canvas state using push() before calling cliprect(), and restore it\n * once you have finished drawing in the clipped area using pop().\n *\n * @param {number} x\n * @param {number} y\n * @param {number} width\n * @param {number} height\n * @see https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/clip\n */\n cliprect(x, y, width, height) {\n _ctx.beginPath()\n _ctx.rect(x, y, width, height)\n _ctx.clip()\n },\n\n /**\n * Create a circular clipping region.\n *\n * Note: Clip paths cannot be reverted directly. You must save your\n * canvas state using push() before calling clipcirc(), and restore it\n * once you have finished drawing in the clipped area using pop().\n *\n * @param {number} x\n * @param {number} y\n * @param {number} radius\n * @see https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/clip\n */\n clipcirc(x, y, radius) {\n _ctx.beginPath()\n _ctx.arc(x, y, radius, 0, TWO_PI)\n _ctx.clip()\n },\n\n /**\n * Sets the type of compositing operation to apply when drawing new shapes.\n * Default value = 'source-over'.\n *\n * @param {string} value\n * @see https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/globalCompositeOperation\n */\n blendmode(value) {\n _ctx.globalCompositeOperation = value\n },\n\n /** SOUND API */\n /**\n * Play a predefined sound or a ZzFX array of params.\n * By default has 4 predefined sounds.\n *\n * @param {number|number[]} [sound=0] the sound index (from 0 to 3) or a ZzFX array of params\n * @param {number} [volume=1]\n * @param {number} [pitch=0]\n * @param {number} [randomness=null] an float value between 0 and 1\n * @returns {AudioBufferSourceNode}\n *\n * @see https://github.com/KilledByAPixel/ZzFX\n * @see https://github.com/litecanvas/game-engine/blob/main/src/sounds.js\n */\n sfx(sound = 0, volume = 1, pitch = 0, randomness = null) {\n if (\n navigator.userActivation &&\n !navigator.userActivation.hasBeenActive\n ) {\n return\n }\n\n let z = Array.isArray(sound) ? sound : sounds[sound % sounds.length]\n if (volume !== 1 || pitch || randomness) {\n z = [...z] // clone the sound to not modify the original\n z[0] = (Number(volume) || 1) * (z[0] || 1)\n z[1] = randomness != null ? randomness : z[1]\n z[10] = ~~z[10] + ~~pitch\n }\n\n return zzfx(...z)\n },\n\n /** UTILS API */\n /**\n * Check a collision between two rectangles\n *\n * @param {number} x1 first rectangle position X\n * @param {number} y1 first rectangle position Y\n * @param {number} w1 first rectangle width\n * @param {number} h1 first rectangle height\n * @param {number} x2 second rectangle position X\n * @param {number} y2 second rectangle position Y\n * @param {number} w2 second rectangle width\n * @param {number} h2 second rectangle height\n * @returns {boolean}\n */\n colrect: (x1, y1, w1, h1, x2, y2, w2, h2) =>\n x1 < x2 + w2 && x1 + w1 > x2 && y1 < y2 + h2 && y1 + h1 > y2,\n\n /**\n * Check a collision between two circles\n *\n * @param {number} x1 first circle position X\n * @param {number} y1 first circle position Y\n * @param {number} r1 first circle position radius\n * @param {number} x2 second circle position X\n * @param {number} y2 second circle position Y\n * @param {number} r2 second circle position radius\n * @returns {boolean}\n */\n colcirc: (x1, y1, r1, x2, y2, r2) =>\n (x2 - x1) ** 2 + (y2 - y1) ** 2 <= (r1 + r2) ** 2,\n\n /**\n * Get the mouse position\n * @returns number[]\n */\n mousepos: () => [_mouseX, _mouseY],\n\n /**\n * The scale of the game's delta time (dt).\n * Values higher than 1 increase the speed of time, while values smaller than 1 decrease it.\n * A value of 0 freezes time and is effectively equivalent to pausing.\n *\n * @param {number} value\n */\n timescale(value) {\n _timeScale = value\n },\n\n /** PLUGINS API */\n /**\n * Prepares a plugin to be loaded\n *\n * @param {pluginCallback} callback\n */\n use(callback, config = {}) {\n callback.__conf = config\n _initialized ? loadPlugin(callback) : _plugins.push(callback)\n },\n\n /**\n * Add a game event listener\n *\n * @param {string} event the event type name\n * @param {function} callback the function that is called when the event occurs\n * @param {boolean} [highPriority=false] determines whether the callback will be called before or after the others\n * @returns {function} a function to remove the listener\n */\n listen(event, callback, highPriority = false) {\n _events[event] = _events[event] || [[], []]\n const size = _events[event][highPriority ? 0 : 1].push(callback)\n\n // return a function to remove this event listener\n return () => {\n _events[event][highPriority ? 0 : 1].splice(size - 1, 1)\n }\n },\n\n /**\n * Call all listeners attached to a game event\n *\n * @param {string} event The game event type\n * @param {...any} args Arguments passed to all listeners\n */\n emit(event, ...args) {\n if (!_events[event]) return\n for (const list of _events[event]) {\n for (const callback of list) {\n callback(...args)\n }\n }\n },\n\n /**\n * Get a color by index\n *\n * @param {number} [index=0] The color number\n * @returns {string} the color code\n */\n getcolor: (index) => colors[~~index % colors.length],\n\n /**\n * Create or update a instance variable\n *\n * @param {string} key\n * @param {any} value\n */\n setvar(key, value) {\n instance[key] = value\n if (settings.global) {\n root[key] = value\n }\n },\n\n /**\n * Resizes the game canvas and emit the \"resized\" event\n *\n * @param {number} width\n * @param {number} height\n */\n resize(width, height) {\n instance.setvar('WIDTH', (_canvas.width = width))\n instance.setvar('HEIGHT', (_canvas.height = height || width))\n pageResized()\n },\n }\n\n /** Copy some functions from native `Math` object */\n for (const k of [\n 'sin',\n 'cos',\n 'atan2',\n 'hypot',\n 'tan',\n 'abs',\n 'ceil',\n 'round',\n 'floor',\n 'trunc',\n 'min',\n 'max',\n 'pow',\n 'sqrt',\n 'sign',\n 'exp',\n ]) {\n // import some native Math functions\n instance[k] = Math[k]\n }\n\n function init() {\n _initialized = true\n setupCanvas()\n\n // add listeners for default events\n const source = settings.loop ? settings.loop : root\n for (const event of Object.keys(_events)) {\n if (source[event]) instance.listen(event, source[event])\n }\n\n // load plugins\n for (const plugin of _plugins) {\n loadPlugin(plugin)\n }\n\n // listen window resize event\n on(root, 'resize', pageResized)\n pageResized()\n\n // default mouse/touch handlers\n if (settings.tapEvents) {\n const _getXY = (pageX, pageY) => [\n (pageX - _canvas.offsetLeft) / _scale,\n (pageY - _canvas.offsetTop) / _scale,\n ],\n _taps = new Map(),\n _registerTap = (id, x, y) => {\n const tap = {\n x,\n y,\n startX: x,\n startY: y,\n // timestamp\n ts: performance.now(),\n }\n _taps.set(id, tap)\n return tap\n },\n _updateTap = (id, x, y) => {\n const tap = _taps.get(id) || _registerTap(id)\n tap.x = x\n tap.y = y\n },\n _checkTapped = (tap) => tap && performance.now() - tap.ts <= 200\n\n let _pressingMouse = false\n\n on(_canvas, 'mousedown', (ev) => {\n ev.preventDefault()\n const [x, y] = _getXY(ev.pageX, ev.pageY)\n instance.emit('tap', x, y, 0)\n _registerTap(0, x, y)\n _pressingMouse = true\n })\n\n on(_canvas, 'mousemove', (ev) => {\n ev.preventDefault()\n const [x, y] = ([_mouseX, _mouseY] = _getXY(ev.pageX, ev.pageY))\n if (!_pressingMouse) return\n instance.emit('tapping', x, y, 0)\n _updateTap(0, x, y)\n })\n\n on(_canvas, 'mouseup', (ev) => {\n ev.preventDefault()\n const tap = _taps.get(0)\n const [x, y] = _getXY(ev.pageX, ev.pageY)\n if (_checkTapped(tap)) {\n instance.emit('tapped', tap.startX, tap.startY, 0)\n }\n instance.emit('untap', x, y, 0)\n _taps.delete(0)\n _pressingMouse = false\n })\n\n on(_canvas, 'touchstart', (ev) => {\n ev.preventDefault()\n /** @type {TouchList} touches */\n const touches = ev.changedTouches\n for (const touch of touches) {\n const [x, y] = _getXY(touch.pageX, touch.pageY)\n instance.emit('tap', x, y, touch.identifier + 1)\n _registerTap(touch.identifier + 1, x, y)\n }\n })\n\n on(_canvas, 'touchmove', (ev) => {\n ev.preventDefault()\n /** @type {TouchList} touches */\n const touches = ev.changedTouches\n for (const touch of touches) {\n const [x, y] = _getXY(touch.pageX, touch.pageY)\n instance.emit('tapping', x, y, touch.identifier + 1)\n _updateTap(touch.identifier + 1, x, y)\n }\n })\n\n const _touchEndHandler = (ev) => {\n ev.preventDefault()\n const existing = []\n\n if (ev.targetTouches.length > 0) {\n for (const touch of ev.targetTouches) {\n existing.push(touch.identifier + 1)\n }\n }\n\n for (const [id, tap] of _taps) {\n if (existing.includes(id)) continue\n if (_checkTapped(tap)) {\n instance.emit('tapped', tap.startX, tap.startY, id)\n }\n instance.emit('untap', tap.x, tap.y, id)\n _taps.delete(id)\n }\n }\n\n on(_canvas, 'touchend', _touchEndHandler)\n on(_canvas, 'touchcancel', _touchEndHandler)\n\n on(root, 'blur', () => {\n _pressingMouse = false\n\n if (_taps.size === 0) return\n\n for (const [id, tap] of _taps) {\n instance.emit('untap', tap.x, tap.y, id)\n _taps.delete(id)\n }\n })\n }\n\n // listen browser focus/blur events and pause the update/draw loop\n if (settings.pauseOnBlur) {\n on(root, 'blur', () => {\n _rafid = null\n })\n on(root, 'focus', () => {\n if (!_rafid) {\n _lastFrame = performance.now()\n _rafid = requestAnimationFrame(drawFrame)\n }\n })\n }\n\n // start the game loop\n instance.emit('init')\n _lastFrame = performance.now()\n _rafid = requestAnimationFrame(drawFrame)\n }\n\n /**\n * @param {number} now\n */\n function drawFrame(now) {\n let ticks = 0,\n t = now - _lastFrame\n\n _lastFrame = now\n _accumulated += t\n\n while (_accumulated >= _stepMs) {\n instance.emit('update', _step * _timeScale)\n instance.setvar('ELAPSED', instance.ELAPSED + _step * _timeScale)\n _accumulated -= _stepMs\n ticks++\n }\n\n if (ticks) {\n // default custom values for textAlign & textBaseline\n instance.textalign('start', 'top')\n\n instance.emit('draw')\n _drawCount++\n _drawTime += _stepMs * ticks\n\n if (_drawTime + _accumulated >= 1000) {\n instance.setvar('FPS', _drawCount)\n _drawCount = 0\n _drawTime -= 1000\n }\n }\n\n if (_rafid) _rafid = requestAnimationFrame(drawFrame)\n }\n\n function setupCanvas() {\n _canvas =\n 'string' === typeof _canvas\n ? document.querySelector(_canvas)\n : _canvas\n\n instance.setvar('CANVAS', _canvas)\n _ctx = _canvas.getContext('2d')\n\n // disable fullscreen if a width is specified\n if (instance.WIDTH > 0) _fullscreen = false\n\n _canvas.width = instance.WIDTH\n _canvas.height = instance.HEIGHT || instance.WIDTH\n\n if (!_canvas.parentNode) document.body.appendChild(_canvas)\n\n // canvas CSS tweaks\n _canvas.style.display = 'block'\n if (_fullscreen) {\n _canvas.style.position = 'absolute'\n _canvas.style.inset = 0\n } else if (_autoscale) {\n _canvas.style.margin = 'auto'\n }\n }\n\n function pageResized() {\n if (_fullscreen) {\n _canvas.width = innerWidth\n _canvas.height = innerHeight\n instance.setvar('WIDTH', innerWidth)\n instance.setvar('HEIGHT', innerHeight)\n } else if (_autoscale) {\n _scale = Math.min(\n innerWidth / instance.WIDTH,\n innerHeight / instance.HEIGHT\n )\n _scale = settings.pixelart ? Math.floor(_scale) : _scale\n _canvas.style.width = instance.WIDTH * _scale + 'px'\n _canvas.style.height = instance.HEIGHT * _scale + 'px'\n }\n\n instance.setvar('CENTERX', instance.WIDTH / 2)\n instance.setvar('CENTERY', instance.HEIGHT / 2)\n\n // restore canvas image rendering properties\n if (!settings.antialias || settings.pixelart) {\n _ctx.imageSmoothingEnabled = false\n _canvas.style.imageRendering = 'pixelated'\n }\n\n instance.emit('resized', _scale)\n }\n\n /**\n * @param {pluginCallback} callback\n */\n function loadPlugin(callback) {\n const pluginData = callback(instance, _helpers, callback.__conf)\n if ('object' === typeof pluginData) {\n for (const [key, value] of Object.entries(pluginData)) {\n instance.setvar(key, value)\n }\n }\n }\n\n if (settings.global) {\n if (root.__litecanvas) {\n throw 'Cannot instantiate litecanvas globally twice'\n }\n Object.assign(root, instance)\n root.__litecanvas = instance\n }\n\n if ('loading' === document.readyState) {\n on(root, 'DOMContentLoaded', init)\n } else {\n init()\n }\n\n return instance\n}\n", "import litecanvas from './index.js'\n\nglobalThis.litecanvas = litecanvas\n"],
5
+ "mappings": "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",
6
+ "names": ["zzfx", "p", "k", "b", "e", "r", "t", "q", "D", "u", "y", "v", "z", "l", "E", "A", "c", "w", "m", "B", "N", "M", "d", "R", "G", "C", "g", "H", "a", "n", "I", "J", "f", "h", "x", "L", "Z", "K", "O", "X", "Y", "P", "Q", "S", "T", "U", "V", "W", "zzfxX", "colors", "sounds", "litecanvas", "settings", "root", "PI", "TWO_PI", "on", "elem", "evt", "callback", "_initialized", "_plugins", "_canvas", "_fullscreen", "_autoscale", "_scale", "_mouseX", "_mouseY", "_ctx", "_timeScale", "_lastFrame", "_step", "_stepMs", "_accumulated", "_rafid", "_drawCount", "_drawTime", "_fontFamily", "_fontStyle", "_fontSize", "_rng_seed", "_events", "_helpers", "colors", "sounds", "instance", "start", "end", "t", "degs", "rads", "value", "min", "max", "min1", "max1", "min2", "max2", "withinBounds", "result", "color", "x", "y", "width", "height", "radii", "radius", "x1", "y1", "x2", "y2", "segments", "offset", "text", "fontFamily", "size", "style", "align", "baseline", "image", "draw", "options", "offscreenCanvas", "ctxOriginal", "scale", "str", "radians", "a", "b", "c", "d", "e", "f", "resetFirst", "arg", "path", "sound", "volume", "pitch", "randomness", "z", "zzfx", "w1", "h1", "w2", "h2", "r1", "r2", "config", "loadPlugin", "event", "highPriority", "args", "list", "index", "key", "pageResized", "k", "init", "setupCanvas", "source", "plugin", "_getXY", "pageX", "pageY", "_taps", "_registerTap", "id", "tap", "_updateTap", "_checkTapped", "_pressingMouse", "ev", "touches", "touch", "_touchEndHandler", "existing", "drawFrame", "now", "ticks", "pluginData", "litecanvas"]
7
7
  }
@@ -0,0 +1 @@
1
+ (()=>{var U=(u=1,m=.05,H=220,b=0,T=0,N=.1,X=0,$=1,c=0,G=0,R=0,v=0,C=0,k=0,o=0,F=0,y=0,Y=1,S=0,M=0,A=0)=>{let _=Math,E=2*_.PI,h=44100,L=c*=500*E/h/h,B=H*=(1-m+2*m*_.random(m=[]))*E/h,D=0,z=0,x=0,n=1,V=0,j=0,w=0,I=A<0?-1:1,W=E*I*A*2/h,e=_.cos(W),t=_.sin,a=t(W)/4,r=1+a,s=-2*e/r,d=(1-a)/r,g=(1+I*e)/2/r,P=-(I+e)/r,i=g,f=0,l=0,p=0,O=0;for(b=h*b+9,S*=h,T*=h,N*=h,y*=h,G*=500*E/h**3,o*=E/h,R*=E/h,v*=h,C=h*C|0,u*=globalThis.zzfxV||.3,I=b+S+T+N+y|0;x<I;m[x++]=w*u)++j%(100*F|0)||(w=X?1<X?2<X?3<X?t(D*D):_.max(_.min(_.tan(D),1),-1):1-(2*D/E%2+2)%2:1-4*_.abs(_.round(D/E)-D/E):t(D),w=(C?1-M+M*t(E*x/C):1)*(w<0?-1:1)*_.abs(w)**$*(x<b?x/b:x<b+S?1-(x-b)/S*(1-Y):x<b+S+T?Y:x<I-y?(I-x-y)/N*Y:0),w=y?w/2+(y>x?0:(x<I-y?1:(I-x)/y)*m[x-y|0]/2/u):w,A&&(w=O=i*f+P*(f=l)+g*(l=w)-d*p-s*(p=O))),W=(H+=c+=G)*_.cos(o*z++),D+=W+W*k*t(x**5),n&&++n>v&&(H+=R,B+=R,n=0),!C||++V%C||(H=B,c=L,n=n||1);u=K.createBuffer(1,I,h),u.getChannelData(0).set(m),H=K.createBufferSource(),H.buffer=u,H.connect(K.destination),H.start()},K=new AudioContext;var q=["#18161c","#6a7799","#aec2c2","#f3eade","#f04f78","#fcf660","#2f328f","#4b80ca","#327345","#63c64d","#703075","#a56243"];var J=[[.8,,2e3,.01,.05,,1,2,,,-600,.05,,,,,,.5,.05],[.5,,375,.02,.01,.2,1,,,,,,,.4,,.1,,.6,.1],[,,360,.01,,.08,1,1.7,12,32,,,,,,,,.63,.02,,99],[1.2,,240,.02,.15,.15,1,4,,,,,.05,,,,,.6,.15]];function Q(u={}){let m=globalThis,H=Math.PI,b=H*2,T=(e,t,a)=>e.addEventListener(t,a);u=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},u);let X=!1,$=[],c=u.canvas||document.createElement("canvas"),G=u.fullscreen,R=u.autoscale,v=1,C,k,o,F=1,y,Y=1/u.fps,S=Y*1e3,M=0,A,_=0,E=0,h="sans-serif",L="",B=32,D=Date.now(),z={init:!1,update:!1,draw:!1,resized:!1,tap:!1,untap:!1,tapping:!1,tapped:!1},x={settings:Object.assign({},u),colors:q,sounds:J},n={WIDTH:u.width,HEIGHT:u.height||u.width,CANVAS:null,ELAPSED:0,FPS:u.fps,CENTERX:null,CENTERY:null,PI:H,TWO_PI:b,HALF_PI:H*.5,lerp:(e,t,a)=>e+a*(t-e),deg2rad:e=>H/180*e,rad2deg:e=>180/H*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,r,s,d=!1){let g=(e-t)/(a-t)*(s-r)+r;return d?n.clamp(g,r,s):g},norm:(e,t,a)=>n.map(e,t,a,0,1),rand:(e=0,t=1)=>(D=(1664525*D+1013904223)%4294967296,D/4294967296*(t-e)+e),randi:(e=0,t=1)=>n.floor(n.rand()*(t-e+1)+e),seed:e=>e==null?D:D=~~e,cls(e){e==null?o.clearRect(0,0,n.WIDTH,n.HEIGHT):n.rectfill(0,0,n.WIDTH,n.HEIGHT,e)},rect(e,t,a,r,s=0,d=null){o.beginPath(),o[d?"roundRect":"rect"](~~e,~~t,a,r,d),n.stroke(s)},rectfill(e,t,a,r,s=0,d=null){o.beginPath(),o[d?"roundRect":"rect"](~~e,~~t,a,r,d),n.fill(s)},circ(e,t,a,r=0){o.beginPath(),o.arc(~~e,~~t,a,0,b),o.closePath(),n.stroke(r)},circfill(e,t,a,r=0){o.beginPath(),o.arc(~~e,~~t,a,0,b),o.closePath(),n.fill(r)},line(e,t,a,r,s=0){o.beginPath(),o.moveTo(~~e,~~t),o.lineTo(~~a,~~r),n.stroke(s)},linewidth(e){o.lineWidth=e},linedash(e,t=0){o.setLineDash(Array.isArray(e)?e:[e]),o.lineDashOffset=t},text(e,t,a,r=3){o.font=`${L||""} ${B}px ${h}`,o.fillStyle=n.getcolor(r),o.fillText(a,~~e,~~t)},textfont(e){h=e},textsize(e){B=e},textstyle(e){L=e},textalign(e,t){e&&(o.textAlign=e),t&&(o.textBaseline=t)},textmetrics(e,t=B){return o.font=`${L||""} ${t}px ${h}`,metrics=o.measureText(e),metrics.height=metrics.actualBoundingBoxAscent+metrics.actualBoundingBoxDescent,metrics},image(e,t,a){o.drawImage(a,~~e,~~t)},paint(e,t,a,r={}){let s=new OffscreenCanvas(e,t),d=o,g=r.scale||1;if(s.width=e*g,s.height=t*g,o=s.getContext("2d"),o.scale(g,g),Array.isArray(a)){let P=0,i=0;o.imageSmoothingEnabled=!1;for(let f of a){for(let l of f)l!==" "&&l!=="."&&n.rectfill(P,i,1,1,parseInt(l,16)),P++;i++,P=0}}else a(s,o);return o=d,s},ctx:()=>o,push:()=>o.save(),pop:()=>o.restore(),translate:(e,t)=>o.translate(e,t),scale:(e,t=e)=>o.scale(e,t),rotate:e=>o.rotate(e),transform:(e,t,a,r,s,d,g=!0)=>o[g?"setTransform":"transform"](e,t,a,r,s,d),alpha(e){o.globalAlpha=e},path:e=>new Path2D(e),fill(e,t){o.fillStyle=n.getcolor(e),o.fill(t)},stroke(e,t){o.strokeStyle=n.getcolor(e),t?o.stroke(t):o.stroke()},cliprect(e,t,a,r){o.beginPath(),o.rect(e,t,a,r),o.clip()},clipcirc(e,t,a){o.beginPath(),o.arc(e,t,a,0,b),o.clip()},blendmode(e){o.globalCompositeOperation=e},sfx(e=0,t=1,a=0,r=null){if(navigator.userActivation&&!navigator.userActivation.hasBeenActive)return;let s=Array.isArray(e)?e:J[e%J.length];return(t!==1||a||r)&&(s=[...s],s[0]=(Number(t)||1)*(s[0]||1),s[1]=r??s[1],s[10]=~~s[10]+~~a),U(...s)},colrect:(e,t,a,r,s,d,g,P)=>e<s+g&&e+a>s&&t<d+P&&t+r>d,colcirc:(e,t,a,r,s,d)=>(r-e)**2+(s-t)**2<=(a+d)**2,mousepos:()=>[C,k],timescale(e){F=e},use(e,t={}){e.__conf=t,X?W(e):$.push(e)},listen(e,t,a=!1){z[e]=z[e]||[[],[]];let r=z[e][a?0:1].push(t);return()=>{z[e][a?0:1].splice(r-1,1)}},emit(e,...t){if(z[e])for(let a of z[e])for(let r of a)r(...t)},getcolor:e=>q[~~e%q.length],setvar(e,t){n[e]=t,u.global&&(m[e]=t)},resize(e,t){n.setvar("WIDTH",c.width=e),n.setvar("HEIGHT",c.height=t||e),I()}};for(let e of["sin","cos","atan2","hypot","tan","abs","ceil","round","floor","trunc","min","max","pow","sqrt","sign","exp"])n[e]=Math[e];function V(){X=!0,w();let e=u.loop?u.loop:m;for(let t of Object.keys(z))e[t]&&n.listen(t,e[t]);for(let t of $)W(t);if(T(m,"resize",I),I(),u.tapEvents){let t=(i,f)=>[(i-c.offsetLeft)/v,(f-c.offsetTop)/v],a=new Map,r=(i,f,l)=>{let p={x:f,y:l,startX:f,startY:l,ts:performance.now()};return a.set(i,p),p},s=(i,f,l)=>{let p=a.get(i)||r(i);p.x=f,p.y=l},d=i=>i&&performance.now()-i.ts<=200,g=!1;T(c,"mousedown",i=>{i.preventDefault();let[f,l]=t(i.pageX,i.pageY);n.emit("tap",f,l,0),r(0,f,l),g=!0}),T(c,"mousemove",i=>{i.preventDefault();let[f,l]=[C,k]=t(i.pageX,i.pageY);g&&(n.emit("tapping",f,l,0),s(0,f,l))}),T(c,"mouseup",i=>{i.preventDefault();let f=a.get(0),[l,p]=t(i.pageX,i.pageY);d(f)&&n.emit("tapped",f.startX,f.startY,0),n.emit("untap",l,p,0),a.delete(0),g=!1}),T(c,"touchstart",i=>{i.preventDefault();let f=i.changedTouches;for(let l of f){let[p,O]=t(l.pageX,l.pageY);n.emit("tap",p,O,l.identifier+1),r(l.identifier+1,p,O)}}),T(c,"touchmove",i=>{i.preventDefault();let f=i.changedTouches;for(let l of f){let[p,O]=t(l.pageX,l.pageY);n.emit("tapping",p,O,l.identifier+1),s(l.identifier+1,p,O)}});let P=i=>{i.preventDefault();let f=[];if(i.targetTouches.length>0)for(let l of i.targetTouches)f.push(l.identifier+1);for(let[l,p]of a)f.includes(l)||(d(p)&&n.emit("tapped",p.startX,p.startY,l),n.emit("untap",p.x,p.y,l),a.delete(l))};T(c,"touchend",P),T(c,"touchcancel",P),T(m,"blur",()=>{if(g=!1,a.size!==0)for(let[i,f]of a)n.emit("untap",f.x,f.y,i),a.delete(i)})}u.pauseOnBlur&&(T(m,"blur",()=>{A=null}),T(m,"focus",()=>{A||(y=performance.now(),A=requestAnimationFrame(j))})),n.emit("init"),y=performance.now(),A=requestAnimationFrame(j)}function j(e){let t=0,a=e-y;for(y=e,M+=a;M>=S;)n.emit("update",Y*F),n.setvar("ELAPSED",n.ELAPSED+Y*F),M-=S,t++;t&&(n.textalign("start","top"),n.emit("draw"),_++,E+=S*t,E+M>=1e3&&(n.setvar("FPS",_),_=0,E-=1e3)),A&&(A=requestAnimationFrame(j))}function w(){c=typeof c=="string"?document.querySelector(c):c,n.setvar("CANVAS",c),o=c.getContext("2d"),n.WIDTH>0&&(G=!1),c.width=n.WIDTH,c.height=n.HEIGHT||n.WIDTH,c.parentNode||document.body.appendChild(c),c.style.display="block",G?(c.style.position="absolute",c.style.inset=0):R&&(c.style.margin="auto")}function I(){G?(c.width=innerWidth,c.height=innerHeight,n.setvar("WIDTH",innerWidth),n.setvar("HEIGHT",innerHeight)):R&&(v=Math.min(innerWidth/n.WIDTH,innerHeight/n.HEIGHT),v=u.pixelart?Math.floor(v):v,c.style.width=n.WIDTH*v+"px",c.style.height=n.HEIGHT*v+"px"),n.setvar("CENTERX",n.WIDTH/2),n.setvar("CENTERY",n.HEIGHT/2),(!u.antialias||u.pixelart)&&(o.imageSmoothingEnabled=!1,c.style.imageRendering="pixelated"),n.emit("resized",v)}function W(e){let t=e(n,x,e.__conf);if(typeof t=="object")for(let[a,r]of Object.entries(t))n.setvar(a,r)}if(u.global){if(m.__litecanvas)throw"Cannot instantiate litecanvas globally twice";Object.assign(m,n),m.__litecanvas=n}return document.readyState==="loading"?T(m,"DOMContentLoaded",V):V(),n}globalThis.litecanvas=Q;})();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "litecanvas",
3
- "version": "0.47.2",
3
+ "version": "0.50.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>",
@@ -17,9 +17,9 @@
17
17
  "bugs": {
18
18
  "url": "https://github.com/litecanvas/game-engine/issues"
19
19
  },
20
- "types": "types/index.d.ts",
21
- "main": "src/index.js",
22
20
  "type": "module",
21
+ "main": "src/index.js",
22
+ "types": "types/index.d.ts",
23
23
  "scripts": {
24
24
  "test": "ava",
25
25
  "dev:test": "ava --watch",
package/src/index.js CHANGED
@@ -1,7 +1,7 @@
1
- /* litecanvas v0.47.2 | https://github.com/litecanvas/game-engine */
2
1
  import { zzfx } from './zzfx.js'
3
2
  import { colors } from './palette.js'
4
3
  import { sounds } from './sounds.js'
4
+ import './types.js'
5
5
 
6
6
  /**
7
7
  * The litecanvas constructor
@@ -10,11 +10,10 @@ import { sounds } from './sounds.js'
10
10
  * @returns {LitecanvasInstance}
11
11
  */
12
12
  export default function litecanvas(settings = {}) {
13
- // helpers
14
13
  const root = globalThis,
15
14
  PI = Math.PI,
16
15
  TWO_PI = PI * 2,
17
- /** @type {(elem:HTMLElement, evt:string, callback:Function)=>void} */
16
+ /** @type {(elem:HTMLElement, evt:string, callback:(event:Event)=>boolean?)=>void} */
18
17
  on = (elem, evt, callback) => elem.addEventListener(evt, callback),
19
18
  /** @type {LitecanvasOptions} */
20
19
  defaults = {
@@ -321,7 +320,7 @@ export default function litecanvas(settings = {}) {
321
320
  * @param {number} radius
322
321
  * @param {number} [color=0] the color index (generally from 0 to 7)
323
322
  */
324
- circ(x, y, radius, color = 0) {
323
+ circ(x, y, radius, color) {
325
324
  _ctx.beginPath()
326
325
  _ctx.arc(~~x, ~~y, radius, 0, TWO_PI)
327
326
  _ctx.closePath()
@@ -336,7 +335,7 @@ export default function litecanvas(settings = {}) {
336
335
  * @param {number} radius
337
336
  * @param {number} [color=0] the color index (generally from 0 to 7)
338
337
  */
339
- circfill(x, y, radius, color = 0) {
338
+ circfill(x, y, radius, color) {
340
339
  _ctx.beginPath()
341
340
  _ctx.arc(~~x, ~~y, radius, 0, TWO_PI)
342
341
  _ctx.closePath()
@@ -352,7 +351,7 @@ export default function litecanvas(settings = {}) {
352
351
  * @param {number} y2
353
352
  * @param {number} [color=0] the color index (generally from 0 to 7)
354
353
  */
355
- line(x1, y1, x2, y2, color = 0) {
354
+ line(x1, y1, x2, y2, color) {
356
355
  _ctx.beginPath()
357
356
  _ctx.moveTo(~~x1, ~~y1)
358
357
  _ctx.lineTo(~~x2, ~~y2)
@@ -574,13 +573,13 @@ export default function litecanvas(settings = {}) {
574
573
  _ctx[resetFirst ? 'setTransform' : 'transform'](a, b, c, d, e, f),
575
574
 
576
575
  /**
577
- * Sets the alpha (transparency) value to apply when drawing new shapes and images
576
+ * Sets the alpha (opacity) value to apply when drawing new shapes and images
578
577
  *
579
578
  * @param {number} alpha float from 0 to 1 (e.g: 0.5 = 50% transparent)
580
579
  * @see https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/globalAlpha
581
580
  */
582
- alpha(alpha) {
583
- _ctx.globalAlpha = alpha
581
+ alpha(value) {
582
+ _ctx.globalAlpha = instance.clamp(value, 0, 1)
584
583
  },
585
584
 
586
585
  /**
@@ -597,7 +596,7 @@ export default function litecanvas(settings = {}) {
597
596
  /**
598
597
  * Fills the current or given path with a given color.
599
598
  *
600
- * @param {number} color
599
+ * @param {number} [color=0]
601
600
  * @param {Path2D} [path]
602
601
  */
603
602
  fill(color, path) {
@@ -608,7 +607,7 @@ export default function litecanvas(settings = {}) {
608
607
  /**
609
608
  * Outlines the current or given path with a given color.
610
609
  *
611
- * @param {number} color
610
+ * @param {number} [color=0]
612
611
  * @param {Path2D} [path]
613
612
  */
614
613
  stroke(color, path) {
@@ -666,16 +665,19 @@ export default function litecanvas(settings = {}) {
666
665
 
667
666
  /** SOUND API */
668
667
  /**
669
- * Play a defined sound or a ZzFX array of params
668
+ * Play a predefined sound or a ZzFX array of params.
669
+ * By default has 4 predefined sounds.
670
670
  *
671
- * @param {number|number[]} [sound=0] the sound index (from 0 to 7) or a ZzFX array of params
671
+ * @param {number|number[]} [sound=0] the sound index (from 0 to 3) or a ZzFX array of params
672
672
  * @param {number} [volume=1]
673
673
  * @param {number} [pitch=0]
674
- * @param {number} [randomness=0]
674
+ * @param {number} [randomness=null] an float value between 0 and 1
675
675
  * @returns {AudioBufferSourceNode}
676
+ *
676
677
  * @see https://github.com/KilledByAPixel/ZzFX
678
+ * @see https://github.com/litecanvas/game-engine/blob/main/src/sounds.js
677
679
  */
678
- sfx(sound = 0, volume = 1, pitch = 0, randomness = 0) {
680
+ sfx(sound = 0, volume = 1, pitch = 0, randomness = null) {
679
681
  if (
680
682
  navigator.userActivation &&
681
683
  !navigator.userActivation.hasBeenActive
@@ -687,7 +689,7 @@ export default function litecanvas(settings = {}) {
687
689
  if (volume !== 1 || pitch || randomness) {
688
690
  z = [...z] // clone the sound to not modify the original
689
691
  z[0] = (Number(volume) || 1) * (z[0] || 1)
690
- z[1] = randomness > 0 ? randomness : 0
692
+ z[1] = randomness != null ? randomness : z[1]
691
693
  z[10] = ~~z[10] + ~~pitch
692
694
  }
693
695
 
@@ -789,7 +791,7 @@ export default function litecanvas(settings = {}) {
789
791
  /**
790
792
  * Get a color by index
791
793
  *
792
- * @param {number} index The color number
794
+ * @param {number} [index=0] The color number
793
795
  * @returns {string} the color code
794
796
  */
795
797
  getcolor: (index) => colors[~~index % colors.length],
package/src/sounds.js CHANGED
@@ -1,11 +1,11 @@
1
1
  // prettier-ignore
2
2
  export const sounds = [
3
3
  // 0 - pickup
4
- [0.8, 0, 2e3, 0.01, 0.05, , 1, 2, , , -600, 0.05, , , , , , 0.5, 0.05],
4
+ [0.8,, 2e3, 0.01, 0.05, , 1, 2, , , -600, 0.05, , , , , , 0.5, 0.05],
5
5
  // 1 - hit
6
- [0.5, 0, 375, 0.02, 0.01, 0.2, 1, , , , , , , 0.4, , 0.1, , 0.6, 0.1],
6
+ [0.5,, 375, 0.02, 0.01, 0.2, 1, , , , , , , 0.4, , 0.1, , 0.6, 0.1],
7
7
  // 2 - jump
8
- [, 0, 360, 0.01, , 0.08, 1, 1.7, 12, 32, , , , , , , , 0.63, 0.02, , 99],
8
+ [,, 360, 0.01, , 0.08, 1, 1.7, 12, 32, , , , , , , , 0.63, 0.02, , 99],
9
9
  // 3 - warning
10
- [1.2, 0, 240, 0.02, 0.15, 0.15, 1, 4, , , , , 0.05, , , , , 0.6, 0.15],
10
+ [1.2,, 240, 0.02, 0.15, 0.15, 1, 4, , , , , 0.05, , , , , 0.6, 0.15],
11
11
  ]
package/src/types.js CHANGED
@@ -27,10 +27,10 @@
27
27
  * @property {(dt: number) => void} [update]
28
28
  * @property {() => void} [draw]
29
29
  * @property {() => void} [resized]
30
- * @property {(x: number, y: number, id: number) => void} [tap]
31
- * @property {(x: number, y: number, id: number) => void} [untap]
32
- * @property {(x: number, y: number, id: number) => void} [tapping]
33
- * @property {(x: number, y: number, id: number) => void} [tapped]
30
+ * @property {(tapX: number, tapY: number, tapId: number) => void} [tap]
31
+ * @property {(tapX: number, tapY: number, tapId: number) => void} [untap]
32
+ * @property {(tapX: number, tapY: number, tapId: number) => void} [tapping]
33
+ * @property {(tapX: number, tapY: number, tapId: number) => void} [tapped]
34
34
  */
35
35
 
36
36
  /**
package/types/index.d.ts CHANGED
@@ -503,14 +503,16 @@ declare global {
503
503
  function blendmode(value: string): void
504
504
  /** SOUND API */
505
505
  /**
506
- * Play a defined sound or a ZzFX array of params
506
+ * Play a predefined sound or a ZzFX array of params.
507
+ * By default has 4 predefined sounds.
507
508
  *
508
- * @param {number|number[]} [sound=0] the sound index (from 0 to 7) or a ZzFX array of params
509
- * @param {number} [volume=1]
510
- * @param {number} [pitch=0]
511
- * @param {number} [randomness=0]
509
+ * @param {number|number[]} [sound=0] the sound index (from 0 to 3) or a ZzFX array of params
510
+ * @param {number} [volume=1] the volume factor
511
+ * @param {number} [pitch=0] a value to increment/decrement the pitch
512
+ * @param {number} [randomness=null] an float between 0 and 1
512
513
  * @returns {AudioBufferSourceNode}
513
514
  * @see https://github.com/KilledByAPixel/ZzFX
515
+ * @see https://github.com/litecanvas/game-engine/blob/main/src/sounds.js
514
516
  */
515
517
  function sfx(
516
518
  sound?: number | number[],
@@ -586,10 +588,10 @@ declare global {
586
588
  /**
587
589
  * Add a game loop event listener
588
590
  *
589
- * @param {string} event should be "init", "update", "draw" or "resized"
591
+ * @param {string} event The game event type
590
592
  * @param {function} callback the function that is called when the event occurs
591
593
  * @param {boolean} [highPriority=false] determines whether the callback will be called before or after the others
592
- * @returns {function?} a function to remove the listener or `undefined` if passed a invalid event
594
+ * @returns {function?} a function to remove the listener
593
595
  */
594
596
  function listen(
595
597
  event: string,
package/types/types.d.ts CHANGED
@@ -489,14 +489,16 @@ type LitecanvasInstance = {
489
489
 
490
490
  /** SOUND API */
491
491
  /**
492
- * Play a defined sound or a ZzFX array of params
492
+ * Play a predefined sound or a ZzFX array of params.
493
+ * By default has 4 predefined sounds.
493
494
  *
494
- * @param {number|number[]} [sound=0] the sound index (from 0 to 7) or a ZzFX array of params
495
- * @param {number} [volume=1]
496
- * @param {number} [pitch=0]
497
- * @param {number} [randomness=0]
495
+ * @param {number|number[]} [sound=0] the sound index (from 0 to 3) or a ZzFX array of params
496
+ * @param {number} [volume=1] the volume factor
497
+ * @param {number} [pitch=0] a value to increment/decrement the pitch
498
+ * @param {number} [randomness=null] an float between 0 and 1
498
499
  * @returns {AudioBufferSourceNode}
499
500
  * @see https://github.com/KilledByAPixel/ZzFX
501
+ * @see https://github.com/litecanvas/game-engine/blob/main/src/sounds.js
500
502
  */
501
503
  sfx(
502
504
  sound?: number | number[],
@@ -573,10 +575,10 @@ type LitecanvasInstance = {
573
575
  /**
574
576
  * Add a game loop event listener
575
577
  *
576
- * @param {string} event should be "init", "update", "draw" or "resized"
578
+ * @param {string} event The game event type
577
579
  * @param {function} callback the function that is called when the event occurs
578
580
  * @param {boolean} [highPriority=false] determines whether the callback will be called before or after the others
579
- * @returns {function?} a function to remove the listener or `undefined` if passed a invalid event
581
+ * @returns {function?} a function to remove the listener
580
582
  */
581
583
  listen(
582
584
  event: string,
@@ -668,6 +670,10 @@ type LitecanvasOptions = {
668
670
  * - `window.update(dt: number): void`
669
671
  * - `window.draw(): void`
670
672
  * - `window.resized(): void`
673
+ * - `window.tap(tapX: number, tapY: number, tapId: number): void`
674
+ * - `window.untap(tapX: number, tapY: number, tapId: number): void`
675
+ * - `window.tapped(tapX: number, tapY: number, tapId: number): void`
676
+ * - `window.tapping(tapX: number, tapY: number, tapId: number): void`
671
677
  */
672
678
  loop?: LitecanvasGameLoop
673
679
  }
@@ -677,6 +683,10 @@ type LitecanvasGameLoop = {
677
683
  update?: (dt: number) => void
678
684
  draw?: () => void
679
685
  resized?: () => void
686
+ tap?: (tapX: number, tapY: number, tapId: number) => void
687
+ untap?: (tapX: number, tapY: number, tapId: number) => void
688
+ tapped?: (tapX: number, tapY: number, tapId: number) => void
689
+ tapping?: (tapX: number, tapY: number, tapId: number) => void
680
690
  }
681
691
 
682
692
  type drawCallback = (