litecanvas 0.92.2 → 0.93.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/dist.dev.js CHANGED
@@ -32,7 +32,7 @@
32
32
  };
33
33
 
34
34
  // src/version.js
35
- var version = "0.92.2";
35
+ var version = "0.93.0";
36
36
 
37
37
  // src/index.js
38
38
  function litecanvas(settings = {}) {
@@ -44,7 +44,6 @@
44
44
  height: null,
45
45
  autoscale: true,
46
46
  pixelart: false,
47
- antialias: false,
48
47
  canvas: null,
49
48
  global: true,
50
49
  loop: null,
@@ -811,7 +810,7 @@
811
810
  );
812
811
  DEV: assert(isNumber(pitchSlide), "[litecanvas] sfx() 2nd param must be a number");
813
812
  DEV: assert(isNumber(volumeFactor), "[litecanvas] sfx() 3rd param must be a number");
814
- if (root.zzfxV <= 0 || navigator.userActivation && !navigator.userActivation.hasBeenActive) {
813
+ if (!root.zzfxV || navigator.userActivation && !navigator.userActivation.hasBeenActive) {
815
814
  return false;
816
815
  }
817
816
  zzfxParams = zzfxParams || _defaultSound;
@@ -830,7 +829,10 @@
830
829
  * @param {number} value
831
830
  */
832
831
  volume(value) {
833
- DEV: assert(isNumber(value), "[litecanvas] volume() 1st param must be a number");
832
+ DEV: assert(
833
+ isNumber(value) && value >= 0,
834
+ "[litecanvas] volume() 1st param must be a positive number or zero"
835
+ );
834
836
  root.zzfxV = value;
835
837
  },
836
838
  /** PLUGINS API */
@@ -1318,7 +1320,7 @@
1318
1320
  '[litecanvas] litecanvas() option "canvas" should be a canvas element or string (CSS selector)'
1319
1321
  );
1320
1322
  _ctx = _canvas.getContext("2d");
1321
- on(_canvas, "click", () => root.focus());
1323
+ on(_canvas, "click", () => focus());
1322
1324
  _canvas.style = "";
1323
1325
  resizeCanvas();
1324
1326
  if (!_canvas.parentNode) {
@@ -1339,7 +1341,7 @@
1339
1341
  null == settings.height || settings.width > 0 && settings.height > 0,
1340
1342
  '[litecanvas] litecanvas() option "width" is required when the option "height" is defined'
1341
1343
  );
1342
- const width = settings.width || root.innerWidth, height = settings.height || settings.width || root.innerHeight;
1344
+ const width = settings.width > 0 ? settings.width : innerWidth, height = settings.width > 0 ? settings.height || settings.width : innerHeight;
1343
1345
  instance.def("W", width);
1344
1346
  instance.def("H", height);
1345
1347
  _canvas.width = width;
@@ -1350,13 +1352,12 @@
1350
1352
  _canvas.style.display = "block";
1351
1353
  _canvas.style.margin = "auto";
1352
1354
  }
1353
- _scale = math.min(root.innerWidth / width, root.innerHeight / height);
1355
+ _scale = math.min(innerWidth / width, innerHeight / height);
1354
1356
  _scale = maxScale > 1 && _scale > maxScale ? maxScale : _scale;
1355
- _scale = (settings.pixelart ? ~~_scale : _scale) || 1;
1356
1357
  _canvas.style.width = width * _scale + "px";
1357
1358
  _canvas.style.height = height * _scale + "px";
1358
1359
  }
1359
- if (!settings.antialias || settings.pixelart) {
1360
+ if (settings.pixelart) {
1360
1361
  _ctx.imageSmoothingEnabled = false;
1361
1362
  _canvas.style.imageRendering = "pixelated";
1362
1363
  }
package/dist/dist.js CHANGED
@@ -36,7 +36,6 @@
36
36
  height: null,
37
37
  autoscale: true,
38
38
  pixelart: false,
39
- antialias: false,
40
39
  canvas: null,
41
40
  global: true,
42
41
  loop: null,
@@ -558,7 +557,7 @@
558
557
  * @see https://github.com/KilledByAPixel/ZzFX
559
558
  */
560
559
  sfx(zzfxParams, pitchSlide = 0, volumeFactor = 1) {
561
- if (root.zzfxV <= 0 || navigator.userActivation && !navigator.userActivation.hasBeenActive) {
560
+ if (!root.zzfxV || navigator.userActivation && !navigator.userActivation.hasBeenActive) {
562
561
  return false;
563
562
  }
564
563
  zzfxParams = zzfxParams || _defaultSound;
@@ -1006,7 +1005,7 @@
1006
1005
  }
1007
1006
  _canvas = _canvas || document.createElement("canvas");
1008
1007
  _ctx = _canvas.getContext("2d");
1009
- on(_canvas, "click", () => root.focus());
1008
+ on(_canvas, "click", () => focus());
1010
1009
  _canvas.style = "";
1011
1010
  resizeCanvas();
1012
1011
  if (!_canvas.parentNode) {
@@ -1015,7 +1014,7 @@
1015
1014
  _canvas.oncontextmenu = () => false;
1016
1015
  }
1017
1016
  function resizeCanvas() {
1018
- const width = settings.width || root.innerWidth, height = settings.height || settings.width || root.innerHeight;
1017
+ const width = settings.width > 0 ? settings.width : innerWidth, height = settings.width > 0 ? settings.height || settings.width : innerHeight;
1019
1018
  instance.def("W", width);
1020
1019
  instance.def("H", height);
1021
1020
  _canvas.width = width;
@@ -1026,13 +1025,12 @@
1026
1025
  _canvas.style.display = "block";
1027
1026
  _canvas.style.margin = "auto";
1028
1027
  }
1029
- _scale = math.min(root.innerWidth / width, root.innerHeight / height);
1028
+ _scale = math.min(innerWidth / width, innerHeight / height);
1030
1029
  _scale = maxScale > 1 && _scale > maxScale ? maxScale : _scale;
1031
- _scale = (settings.pixelart ? ~~_scale : _scale) || 1;
1032
1030
  _canvas.style.width = width * _scale + "px";
1033
1031
  _canvas.style.height = height * _scale + "px";
1034
1032
  }
1035
- if (!settings.antialias || settings.pixelart) {
1033
+ if (settings.pixelart) {
1036
1034
  _ctx.imageSmoothingEnabled = false;
1037
1035
  _canvas.style.imageRendering = "pixelated";
1038
1036
  }
package/dist/dist.min.js CHANGED
@@ -1 +1 @@
1
- (()=>{var e=["#111","#6a7799","#aec2c2","#FFF1E8","#e83b3b","#fabc20","#155fd9","#3cbcfc","#327345","#63c64d","#6c2c1f","#ac7c00"];globalThis.litecanvas=function(t={}){let a=window,i=Math,l=2*i.PI,n=requestAnimationFrame,o=[],r=(e,t,a)=>{e.addEventListener(t,a,!1),o.push(()=>e.removeEventListener(t,a,!1))},s=e=>e.beginPath(),f=(e=>{let t=new AudioContext;return e.zzfxV=1,(a=1,i=.05,l=220,n=0,o=0,r=.1,s=0,f=1,c=0,d=0,u=0,p=0,m=0,h=0,g=0,x=0,v=0,w=1,y=0,b=0,k=0)=>{let E=Math,z=2*E.PI,T=c*=500*z/44100/44100,C=l*=(1-i+2*i*E.random(i=[]))*z/44100,I=0,A=0,L=0,S=1,M=0,N=0,P=0,D=k<0?-1:1,F=z*D*k*2/44100,q=E.cos(F),B=E.sin,H=B(F)/4,O=1+H,V=-2*q/O,W=(1-H)/O,R=(1+D*q)/2/O,G=-(D+q)/O,X=0,Y=0,$=0,j=0;for(n=44100*n+9,y*=44100,o*=44100,r*=44100,v*=44100,d*=500*z/85766121e6,g*=z/44100,u*=z/44100,p*=44100,m=44100*m|0,a*=.3*e.zzfxV,D=n+y+o+r+v|0;L<D;i[L++]=P*a)++N%(100*x|0)||(P=s?1<s?2<s?3<s?B(I*I):E.max(E.min(E.tan(I),1),-1):1-(2*I/z%2+2)%2:1-4*E.abs(E.round(I/z)-I/z):B(I),P=(m?1-b+b*B(z*L/m):1)*(P<0?-1:1)*E.abs(P)**f*(L<n?L/n:L<n+y?1-(L-n)/y*(1-w):L<n+y+o?w:L<D-v?(D-L-v)/r*w:0),P=v?P/2+(v>L?0:(L<D-v?1:(D-L)/v)*i[L-v|0]/2/a):P,k&&(P=j=R*X+G*(X=Y)+R*(Y=P)-W*$-V*($=j))),I+=(F=(l+=c+=d)*E.cos(g*A++))+F*h*B(L**5),S&&++S>p&&(l+=u,C+=u,S=0),!m||++M%m||(l=C,c=T,S=S||1);(a=t.createBuffer(1,D,44100)).getChannelData(0).set(i),(l=t.createBufferSource()).buffer=a,l.connect(t.destination),l.start()}})(a);t=Object.assign({width:null,height:null,autoscale:!0,pixelart:!1,antialias:!1,canvas:null,global:!0,loop:null,tapEvents:!0,keyboardEvents:!0,animate:!0},t);let c=!1,d=[],u,p=1,m,h=.5,g=1,x,v=1/60,w=0,y,b="sans-serif",k=20,E=Date.now(),z=e,T=[.5,0,1750,,,.3,1,,,,600,.1],C={},I={W:0,H:0,T:0,MX:-1,MY:-1,TWO_PI:l,HALF_PI:l/4,lerp:(e,t,a)=>a*(t-e)+e,deg2rad:e=>i.PI/180*e,rad2deg:e=>180/i.PI*e,round:(e,t=0)=>{if(!t)return i.round(e);let a=10**t;return i.round(e*a)/a},clamp:(e,t,a)=>e<t?t:e>a?a:e,wrap:(e,t,a)=>e-(a-t)*i.floor((e-t)/(a-t)),map(e,t,a,i,l,n){let o=(e-t)/(a-t)*(l-i)+i;return n?I.clamp(o,i,l):o},norm:(e,t,a)=>I.map(e,t,a,0,1),wave:(e,t,a,i=Math.sin)=>e+(i(a)+1)/2*(t-e),rand:(e=0,t=1)=>(E=(1664525*E+0x3c6ef35f)%0x100000000)/0x100000000*(t-e)+e,randi:(e=0,t=1)=>i.floor(I.rand(e,t+1)),rseed(e){E=~~e},cls(e){null==e?m.clearRect(0,0,m.canvas.width,m.canvas.height):I.rectfill(0,0,m.canvas.width,m.canvas.height,e)},rect(e,t,a,i,l,n){s(m),m[n?"roundRect":"rect"](~~e-h,~~t-h,~~a+2*h,~~i+2*h,n),I.stroke(l)},rectfill(e,t,a,i,l,n){s(m),m[n?"roundRect":"rect"](~~e,~~t,~~a,~~i,n),I.fill(l)},circ(e,t,a,i){s(m),m.arc(~~e,~~t,~~a,0,l),I.stroke(i)},circfill(e,t,a,i){s(m),m.arc(~~e,~~t,~~a,0,l),I.fill(i)},oval(e,t,a,i,n){s(m),m.ellipse(~~e,~~t,~~a,~~i,0,0,l),I.stroke(n)},ovalfill(e,t,a,i,n){s(m),m.ellipse(~~e,~~t,~~a,~~i,0,0,l),I.fill(n)},line(e,t,a,i,l){s(m);let n=.5*(0!==h&&~~e==~~a),o=.5*(0!==h&&~~t==~~i);m.moveTo(~~e+n,~~t+o),m.lineTo(~~a+n,~~i+o),I.stroke(l)},linewidth(e){m.lineWidth=~~e,h=.5*(0!=~~e%2)},linedash(e,t=0){m.setLineDash(e),m.lineDashOffset=t},text(e,t,a,i=3,l="normal"){m.font=`${l} ${k}px ${b}`,m.fillStyle=z[~~i%z.length],m.fillText(a,~~e,~~t)},textfont(e){b=e},textsize(e){k=e},textalign(e,t){e&&(m.textAlign=e),t&&(m.textBaseline=t)},image(e,t,a){m.drawImage(a,~~e,~~t)},paint(e,t,a,i={}){let l=i.canvas||new OffscreenCanvas(1,1),n=i.scale||1,o=m;if(l.width=e*n,l.height=t*n,(m=l.getContext("2d")).scale(n,n),Array.isArray(a)){let e=0,t=0;for(let i of(m.imageSmoothingEnabled=!1,a)){for(let a of i)" "!==a&&"."!==a&&I.rectfill(e,t,1,1,parseInt(a,16)),e++;t++,e=0}}else a(m);return m=o,l.transferToImageBitmap()},ctx:e=>(e&&(m=e),m),push:()=>m.save(),pop:()=>m.restore(),translate:(e,t)=>m.translate(~~e,~~t),scale:(e,t)=>m.scale(e,t||e),rotate:e=>m.rotate(e),alpha(e){m.globalAlpha=I.clamp(e,0,1)},fill(e){m.fillStyle=z[~~e%z.length],m.fill()},stroke(e){m.strokeStyle=z[~~e%z.length],m.stroke()},clip(e){s(m),e(m),m.clip()},sfx:(e,t=0,i=1)=>!(a.zzfxV<=0)&&(!navigator.userActivation||!!navigator.userActivation.hasBeenActive)&&(e=e||T,(0!==t||1!==i)&&((e=e.slice())[0]=i*(e[0]||1),e[10]=~~e[10]+t),f.apply(0,e),e),volume(e){a.zzfxV=e},canvas:()=>u,use(e,t={}){c?N(e,t):d.push([e,t])},listen:(e,t)=>(C[e=e.toLowerCase()]=C[e]||new Set,C[e].add(t),()=>C&&C[e].delete(t)),emit(e,t,a,i,l){c&&(M("before:"+(e=e.toLowerCase()),t,a,i,l),M(e,t,a,i,l),M("after:"+e,t,a,i,l))},pal(t=e){z=t},def(e,i){I[e]=i,t.global&&(a[e]=i)},timescale(e){g=e},framerate(e){v=1/~~e},stat(e){let i={index:e,value:[t,c,v,p,C,z,T,g,a.zzfxV,E,k,b][e]};return I.emit("stat",i),i.value},quit(){for(let e of(I.pause(),I.emit("quit"),C={},o))e();if(t.global){for(let e in I)delete a[e];delete a.ENGINE}c=!1},pause(){cancelAnimationFrame(y),y=0},resume(){!y&&c&&(y=n(L))},paused:()=>!y};for(let e of"PI,sin,cos,atan2,hypot,tan,abs,ceil,floor,trunc,min,max,pow,sqrt,sign,exp".split(","))I[e]=i[e];function A(){let e=t.loop?t.loop:a;for(let t of"init,update,draw,tap,untap,tapping,tapped,resized".split(","))e[t]&&I.listen(t,e[t]);for(let[e,t]of d)N(e,t);if(t.autoscale&&r(a,"resize",S),t.tapEvents){let e=e=>[(e.pageX-u.offsetLeft)/p,(e.pageY-u.offsetTop)/p],t=new Map,i=(e,a,i)=>{let l={x:a,y:i,xi:a,yi:i,t:performance.now()};return t.set(e,l),l},l=(e,a,l)=>{let n=t.get(e)||i(e);n.x=a,n.y=l},n=e=>e&&performance.now()-e.t<=300,o=e=>e.preventDefault(),s=!1;r(u,"mousedown",t=>{if(0===t.button){o(t);let[a,l]=e(t);I.emit("tap",a,l,0),i(0,a,l),s=!0}}),r(u,"mouseup",a=>{if(0===a.button){o(a);let i=t.get(0),[l,r]=e(a);n(i)&&I.emit("tapped",i.xi,i.yi,0),I.emit("untap",l,r,0),t.delete(0),s=!1}}),r(a,"mousemove",t=>{o(t);let[a,i]=e(t);I.def("MX",a),I.def("MY",i),s&&(I.emit("tapping",a,i,0),l(0,a,i))}),r(u,"touchstart",t=>{for(let a of(o(t),t.changedTouches)){let[t,l]=e(a);I.emit("tap",t,l,a.identifier+1),i(a.identifier+1,t,l)}}),r(u,"touchmove",t=>{for(let a of(o(t),t.changedTouches)){let[t,i]=e(a);I.emit("tapping",t,i,a.identifier+1),l(a.identifier+1,t,i)}});let f=e=>{o(e);let a=[];if(e.targetTouches.length>0)for(let t of e.targetTouches)a.push(t.identifier+1);for(let[e,i]of t)a.includes(e)||(n(i)&&I.emit("tapped",i.xi,i.yi,e),I.emit("untap",i.x,i.y,e),t.delete(e))};r(u,"touchend",f),r(u,"touchcancel",f),r(a,"blur",()=>{for(let[e,a]of(s=!1,t))I.emit("untap",a.x,a.y,e),t.delete(e)})}if(t.keyboardEvents){let e=new Set,t=new Set,i=(e,t="")=>(t=t.toLowerCase())?e.has("space"===t?" ":t):e.size>0;r(a,"keydown",a=>{let i=a.key.toLowerCase();e.has(i)||(e.add(i),t.add(i))}),r(a,"keyup",t=>{e.delete(t.key.toLowerCase())}),r(a,"blur",()=>e.clear()),I.listen("after:update",()=>t.clear()),I.def("iskeydown",t=>i(e,t)),I.def("iskeypressed",e=>i(t,e))}c=!0,I.emit("init",I),x=performance.now(),I.resume()}function L(e){if(!t.animate)return I.emit("draw");let a=0,i=(e-x)/1e3;if(x=e,i<.1)for(w+=i;w>=v;)a++,I.emit("update",v*g,a),I.def("T",I.T+v*g),w-=v;a&&I.emit("draw"),y&&(y=n(L))}function S(){let e=t.width||a.innerWidth,l=t.height||t.width||a.innerHeight;if(I.def("W",e),I.def("H",l),u.width=e,u.height=l,t.autoscale){let n=+t.autoscale;u.style.display||(u.style.display="block",u.style.margin="auto"),p=i.min(a.innerWidth/e,a.innerHeight/l),p=n>1&&p>n?n:p,p=(t.pixelart?~~p:p)||1,u.style.width=e*p+"px",u.style.height=l*p+"px"}(!t.antialias||t.pixelart)&&(m.imageSmoothingEnabled=!1,u.style.imageRendering="pixelated"),I.textalign("start","top"),I.emit("resized",p),I.cls(0),t.animate||n(L)}function M(e,t,a,i,l){if(C[e])for(let n of C[e])n(t,a,i,l)}function N(e,t){let a=e(I,t);for(let e in a)I.def(e,a[e])}if(t.global){if(a.ENGINE)throw Error("only one global litecanvas is allowed");Object.assign(a,I),a.ENGINE=I}return m=(u=(u="string"==typeof t.canvas?document.querySelector(t.canvas):t.canvas)||document.createElement("canvas")).getContext("2d"),r(u,"click",()=>a.focus()),u.style="",S(),u.parentNode||document.body.appendChild(u),u.oncontextmenu=()=>!1,"loading"===document.readyState?r(a,"DOMContentLoaded",()=>n(A)):n(A),I}})();
1
+ (()=>{var e=["#111","#6a7799","#aec2c2","#FFF1E8","#e83b3b","#fabc20","#155fd9","#3cbcfc","#327345","#63c64d","#6c2c1f","#ac7c00"];globalThis.litecanvas=function(t={}){let a=window,i=Math,l=2*i.PI,n=requestAnimationFrame,o=[],r=(e,t,a)=>{e.addEventListener(t,a,!1),o.push(()=>e.removeEventListener(t,a,!1))},s=e=>e.beginPath(),f=(e=>{let t=new AudioContext;return e.zzfxV=1,(a=1,i=.05,l=220,n=0,o=0,r=.1,s=0,f=1,c=0,d=0,u=0,p=0,m=0,h=0,g=0,w=0,v=0,x=1,y=0,b=0,k=0)=>{let E=Math,z=2*E.PI,T=c*=500*z/44100/44100,C=l*=(1-i+2*i*E.random(i=[]))*z/44100,I=0,A=0,L=0,S=1,M=0,N=0,P=0,D=k<0?-1:1,F=z*D*k*2/44100,q=E.cos(F),B=E.sin,H=B(F)/4,O=1+H,V=-2*q/O,W=(1-H)/O,R=(1+D*q)/2/O,G=-(D+q)/O,X=0,Y=0,$=0,j=0;for(n=44100*n+9,y*=44100,o*=44100,r*=44100,v*=44100,d*=500*z/85766121e6,g*=z/44100,u*=z/44100,p*=44100,m=44100*m|0,a*=.3*e.zzfxV,D=n+y+o+r+v|0;L<D;i[L++]=P*a)++N%(100*w|0)||(P=s?1<s?2<s?3<s?B(I*I):E.max(E.min(E.tan(I),1),-1):1-(2*I/z%2+2)%2:1-4*E.abs(E.round(I/z)-I/z):B(I),P=(m?1-b+b*B(z*L/m):1)*(P<0?-1:1)*E.abs(P)**f*(L<n?L/n:L<n+y?1-(L-n)/y*(1-x):L<n+y+o?x:L<D-v?(D-L-v)/r*x:0),P=v?P/2+(v>L?0:(L<D-v?1:(D-L)/v)*i[L-v|0]/2/a):P,k&&(P=j=R*X+G*(X=Y)+R*(Y=P)-W*$-V*($=j))),I+=(F=(l+=c+=d)*E.cos(g*A++))+F*h*B(L**5),S&&++S>p&&(l+=u,C+=u,S=0),!m||++M%m||(l=C,c=T,S=S||1);(a=t.createBuffer(1,D,44100)).getChannelData(0).set(i),(l=t.createBufferSource()).buffer=a,l.connect(t.destination),l.start()}})(a);t=Object.assign({width:null,height:null,autoscale:!0,pixelart:!1,canvas:null,global:!0,loop:null,tapEvents:!0,keyboardEvents:!0,animate:!0},t);let c=!1,d=[],u,p=1,m,h=.5,g=1,w,v=1/60,x=0,y,b="sans-serif",k=20,E=Date.now(),z=e,T=[.5,0,1750,,,.3,1,,,,600,.1],C={},I={W:0,H:0,T:0,MX:-1,MY:-1,TWO_PI:l,HALF_PI:l/4,lerp:(e,t,a)=>a*(t-e)+e,deg2rad:e=>i.PI/180*e,rad2deg:e=>180/i.PI*e,round:(e,t=0)=>{if(!t)return i.round(e);let a=10**t;return i.round(e*a)/a},clamp:(e,t,a)=>e<t?t:e>a?a:e,wrap:(e,t,a)=>e-(a-t)*i.floor((e-t)/(a-t)),map(e,t,a,i,l,n){let o=(e-t)/(a-t)*(l-i)+i;return n?I.clamp(o,i,l):o},norm:(e,t,a)=>I.map(e,t,a,0,1),wave:(e,t,a,i=Math.sin)=>e+(i(a)+1)/2*(t-e),rand:(e=0,t=1)=>(E=(1664525*E+0x3c6ef35f)%0x100000000)/0x100000000*(t-e)+e,randi:(e=0,t=1)=>i.floor(I.rand(e,t+1)),rseed(e){E=~~e},cls(e){null==e?m.clearRect(0,0,m.canvas.width,m.canvas.height):I.rectfill(0,0,m.canvas.width,m.canvas.height,e)},rect(e,t,a,i,l,n){s(m),m[n?"roundRect":"rect"](~~e-h,~~t-h,~~a+2*h,~~i+2*h,n),I.stroke(l)},rectfill(e,t,a,i,l,n){s(m),m[n?"roundRect":"rect"](~~e,~~t,~~a,~~i,n),I.fill(l)},circ(e,t,a,i){s(m),m.arc(~~e,~~t,~~a,0,l),I.stroke(i)},circfill(e,t,a,i){s(m),m.arc(~~e,~~t,~~a,0,l),I.fill(i)},oval(e,t,a,i,n){s(m),m.ellipse(~~e,~~t,~~a,~~i,0,0,l),I.stroke(n)},ovalfill(e,t,a,i,n){s(m),m.ellipse(~~e,~~t,~~a,~~i,0,0,l),I.fill(n)},line(e,t,a,i,l){s(m);let n=.5*(0!==h&&~~e==~~a),o=.5*(0!==h&&~~t==~~i);m.moveTo(~~e+n,~~t+o),m.lineTo(~~a+n,~~i+o),I.stroke(l)},linewidth(e){m.lineWidth=~~e,h=.5*(0!=~~e%2)},linedash(e,t=0){m.setLineDash(e),m.lineDashOffset=t},text(e,t,a,i=3,l="normal"){m.font=`${l} ${k}px ${b}`,m.fillStyle=z[~~i%z.length],m.fillText(a,~~e,~~t)},textfont(e){b=e},textsize(e){k=e},textalign(e,t){e&&(m.textAlign=e),t&&(m.textBaseline=t)},image(e,t,a){m.drawImage(a,~~e,~~t)},paint(e,t,a,i={}){let l=i.canvas||new OffscreenCanvas(1,1),n=i.scale||1,o=m;if(l.width=e*n,l.height=t*n,(m=l.getContext("2d")).scale(n,n),Array.isArray(a)){let e=0,t=0;for(let i of(m.imageSmoothingEnabled=!1,a)){for(let a of i)" "!==a&&"."!==a&&I.rectfill(e,t,1,1,parseInt(a,16)),e++;t++,e=0}}else a(m);return m=o,l.transferToImageBitmap()},ctx:e=>(e&&(m=e),m),push:()=>m.save(),pop:()=>m.restore(),translate:(e,t)=>m.translate(~~e,~~t),scale:(e,t)=>m.scale(e,t||e),rotate:e=>m.rotate(e),alpha(e){m.globalAlpha=I.clamp(e,0,1)},fill(e){m.fillStyle=z[~~e%z.length],m.fill()},stroke(e){m.strokeStyle=z[~~e%z.length],m.stroke()},clip(e){s(m),e(m),m.clip()},sfx:(e,t=0,i=1)=>!!a.zzfxV&&(!navigator.userActivation||!!navigator.userActivation.hasBeenActive)&&(e=e||T,(0!==t||1!==i)&&((e=e.slice())[0]=i*(e[0]||1),e[10]=~~e[10]+t),f.apply(0,e),e),volume(e){a.zzfxV=e},canvas:()=>u,use(e,t={}){c?N(e,t):d.push([e,t])},listen:(e,t)=>(C[e=e.toLowerCase()]=C[e]||new Set,C[e].add(t),()=>C&&C[e].delete(t)),emit(e,t,a,i,l){c&&(M("before:"+(e=e.toLowerCase()),t,a,i,l),M(e,t,a,i,l),M("after:"+e,t,a,i,l))},pal(t=e){z=t},def(e,i){I[e]=i,t.global&&(a[e]=i)},timescale(e){g=e},framerate(e){v=1/~~e},stat(e){let i={index:e,value:[t,c,v,p,C,z,T,g,a.zzfxV,E,k,b][e]};return I.emit("stat",i),i.value},quit(){for(let e of(I.pause(),I.emit("quit"),C={},o))e();if(t.global){for(let e in I)delete a[e];delete a.ENGINE}c=!1},pause(){cancelAnimationFrame(y),y=0},resume(){!y&&c&&(y=n(L))},paused:()=>!y};for(let e of"PI,sin,cos,atan2,hypot,tan,abs,ceil,floor,trunc,min,max,pow,sqrt,sign,exp".split(","))I[e]=i[e];function A(){let e=t.loop?t.loop:a;for(let t of"init,update,draw,tap,untap,tapping,tapped,resized".split(","))e[t]&&I.listen(t,e[t]);for(let[e,t]of d)N(e,t);if(t.autoscale&&r(a,"resize",S),t.tapEvents){let e=e=>[(e.pageX-u.offsetLeft)/p,(e.pageY-u.offsetTop)/p],t=new Map,i=(e,a,i)=>{let l={x:a,y:i,xi:a,yi:i,t:performance.now()};return t.set(e,l),l},l=(e,a,l)=>{let n=t.get(e)||i(e);n.x=a,n.y=l},n=e=>e&&performance.now()-e.t<=300,o=e=>e.preventDefault(),s=!1;r(u,"mousedown",t=>{if(0===t.button){o(t);let[a,l]=e(t);I.emit("tap",a,l,0),i(0,a,l),s=!0}}),r(u,"mouseup",a=>{if(0===a.button){o(a);let i=t.get(0),[l,r]=e(a);n(i)&&I.emit("tapped",i.xi,i.yi,0),I.emit("untap",l,r,0),t.delete(0),s=!1}}),r(a,"mousemove",t=>{o(t);let[a,i]=e(t);I.def("MX",a),I.def("MY",i),s&&(I.emit("tapping",a,i,0),l(0,a,i))}),r(u,"touchstart",t=>{for(let a of(o(t),t.changedTouches)){let[t,l]=e(a);I.emit("tap",t,l,a.identifier+1),i(a.identifier+1,t,l)}}),r(u,"touchmove",t=>{for(let a of(o(t),t.changedTouches)){let[t,i]=e(a);I.emit("tapping",t,i,a.identifier+1),l(a.identifier+1,t,i)}});let f=e=>{o(e);let a=[];if(e.targetTouches.length>0)for(let t of e.targetTouches)a.push(t.identifier+1);for(let[e,i]of t)a.includes(e)||(n(i)&&I.emit("tapped",i.xi,i.yi,e),I.emit("untap",i.x,i.y,e),t.delete(e))};r(u,"touchend",f),r(u,"touchcancel",f),r(a,"blur",()=>{for(let[e,a]of(s=!1,t))I.emit("untap",a.x,a.y,e),t.delete(e)})}if(t.keyboardEvents){let e=new Set,t=new Set,i=(e,t="")=>(t=t.toLowerCase())?e.has("space"===t?" ":t):e.size>0;r(a,"keydown",a=>{let i=a.key.toLowerCase();e.has(i)||(e.add(i),t.add(i))}),r(a,"keyup",t=>{e.delete(t.key.toLowerCase())}),r(a,"blur",()=>e.clear()),I.listen("after:update",()=>t.clear()),I.def("iskeydown",t=>i(e,t)),I.def("iskeypressed",e=>i(t,e))}c=!0,I.emit("init",I),w=performance.now(),I.resume()}function L(e){if(!t.animate)return I.emit("draw");let a=0,i=(e-w)/1e3;if(w=e,i<.1)for(x+=i;x>=v;)a++,I.emit("update",v*g,a),I.def("T",I.T+v*g),x-=v;a&&I.emit("draw"),y&&(y=n(L))}function S(){let e=t.width>0?t.width:innerWidth,a=t.width>0?t.height||t.width:innerHeight;if(I.def("W",e),I.def("H",a),u.width=e,u.height=a,t.autoscale){let l=+t.autoscale;u.style.display||(u.style.display="block",u.style.margin="auto"),p=i.min(innerWidth/e,innerHeight/a),p=l>1&&p>l?l:p,u.style.width=e*p+"px",u.style.height=a*p+"px"}t.pixelart&&(m.imageSmoothingEnabled=!1,u.style.imageRendering="pixelated"),I.textalign("start","top"),I.emit("resized",p),I.cls(0),t.animate||n(L)}function M(e,t,a,i,l){if(C[e])for(let n of C[e])n(t,a,i,l)}function N(e,t){let a=e(I,t);for(let e in a)I.def(e,a[e])}if(t.global){if(a.ENGINE)throw Error("only one global litecanvas is allowed");Object.assign(a,I),a.ENGINE=I}return m=(u=(u="string"==typeof t.canvas?document.querySelector(t.canvas):t.canvas)||document.createElement("canvas")).getContext("2d"),r(u,"click",()=>focus()),u.style="",S(),u.parentNode||document.body.appendChild(u),u.oncontextmenu=()=>!1,"loading"===document.readyState?r(a,"DOMContentLoaded",()=>n(A)):n(A),I}})();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "litecanvas",
3
- "version": "0.92.2",
3
+ "version": "0.93.0",
4
4
  "description": "Lightweight HTML5 canvas 2D game engine suitable for small projects and creative coding. Inspired by PICO-8 and P5/Processing.",
5
5
  "license": "MIT",
6
6
  "author": "Luiz Bills <luizbills@pm.me>",
@@ -17,21 +17,23 @@
17
17
  "main": "./src/index.js",
18
18
  "module": "./src/index.js",
19
19
  "types": "./types/index.d.ts",
20
+ "unpkg": "./dist/dist.dev.js",
20
21
  "keywords": [
21
- "game engine",
22
- "game development",
23
- "2d",
22
+ "tiny",
23
+ "micro",
24
+ "javascript",
25
+ "html5",
24
26
  "canvas",
27
+ "2d",
28
+ "game",
25
29
  "gamedev",
26
30
  "js13k",
27
- "creative-coding",
28
- "pico-8",
29
- "p5"
31
+ "creative coding"
30
32
  ],
31
33
  "devDependencies": {
32
- "@litecanvas/jsdom-extras": "^2.0.0",
34
+ "@litecanvas/jsdom-extras": "^2.0.1",
33
35
  "@size-limit/preset-small-lib": "^11.2.0",
34
- "@swc/core": "^1.12.11",
36
+ "@swc/core": "^1.13.0",
35
37
  "@types/jsdom": "^21.1.7",
36
38
  "ava": "^6.4.1",
37
39
  "esbuild": "^0.25.6",
@@ -51,7 +53,7 @@
51
53
  "prepublishOnly": "npm test",
52
54
  "test": "ava --timeout=1s --fast-fail --tap | tap-min",
53
55
  "test:watch": "ava --watch",
54
- "dev": "esbuild src/web.js --bundle --watch --outfile=dist/dist.dev.js --servedir=.",
56
+ "dev": "esbuild src/web.js --bundle --watch --outfile=samples/dist.js --servedir=samples",
55
57
  "build": "npm run genversion && node script/build.js && size-limit",
56
58
  "format": "prettier -w src/* samples/* types/* script/* types/*",
57
59
  "check-types": "npx ts types/*",
package/src/index.js CHANGED
@@ -33,7 +33,6 @@ export default function litecanvas(settings = {}) {
33
33
  height: null,
34
34
  autoscale: true,
35
35
  pixelart: false,
36
- antialias: false,
37
36
  canvas: null,
38
37
  global: true,
39
38
  loop: null,
@@ -945,7 +944,7 @@ export default function litecanvas(settings = {}) {
945
944
  DEV: assert(isNumber(volumeFactor), '[litecanvas] sfx() 3rd param must be a number')
946
945
 
947
946
  if (
948
- root.zzfxV <= 0 ||
947
+ !root.zzfxV ||
949
948
  (navigator.userActivation && !navigator.userActivation.hasBeenActive)
950
949
  ) {
951
950
  return false
@@ -972,7 +971,10 @@ export default function litecanvas(settings = {}) {
972
971
  * @param {number} value
973
972
  */
974
973
  volume(value) {
975
- DEV: assert(isNumber(value), '[litecanvas] volume() 1st param must be a number')
974
+ DEV: assert(
975
+ isNumber(value) && value >= 0,
976
+ '[litecanvas] volume() 1st param must be a positive number or zero'
977
+ )
976
978
 
977
979
  root.zzfxV = value
978
980
  },
@@ -1564,7 +1566,7 @@ export default function litecanvas(settings = {}) {
1564
1566
 
1565
1567
  _ctx = _canvas.getContext('2d')
1566
1568
 
1567
- on(_canvas, 'click', () => root.focus())
1569
+ on(_canvas, 'click', () => focus())
1568
1570
 
1569
1571
  /** @ts-ignore */
1570
1572
  _canvas.style = ''
@@ -1592,8 +1594,8 @@ export default function litecanvas(settings = {}) {
1592
1594
  '[litecanvas] litecanvas() option "width" is required when the option "height" is defined'
1593
1595
  )
1594
1596
 
1595
- const width = settings.width || root.innerWidth,
1596
- height = settings.height || settings.width || root.innerHeight
1597
+ const width = settings.width > 0 ? settings.width : innerWidth,
1598
+ height = settings.width > 0 ? settings.height || settings.width : innerHeight
1597
1599
 
1598
1600
  instance.def('W', width)
1599
1601
  instance.def('H', height)
@@ -1608,29 +1610,30 @@ export default function litecanvas(settings = {}) {
1608
1610
  _canvas.style.margin = 'auto'
1609
1611
  }
1610
1612
 
1611
- _scale = math.min(root.innerWidth / width, root.innerHeight / height)
1613
+ _scale = math.min(innerWidth / width, innerHeight / height)
1612
1614
  _scale = maxScale > 1 && _scale > maxScale ? maxScale : _scale
1613
- _scale = (settings.pixelart ? ~~_scale : _scale) || 1
1614
1615
 
1615
1616
  _canvas.style.width = width * _scale + 'px'
1616
1617
  _canvas.style.height = height * _scale + 'px'
1617
1618
  }
1618
1619
 
1619
- // restore canvas image rendering properties
1620
- if (!settings.antialias || settings.pixelart) {
1620
+ // set canvas image rendering properties
1621
+ if (settings.pixelart) {
1621
1622
  _ctx.imageSmoothingEnabled = false
1622
1623
  _canvas.style.imageRendering = 'pixelated'
1623
1624
  }
1624
1625
 
1625
- // reset the default text align and baseline
1626
+ // set the default text align and baseline
1626
1627
  instance.textalign('start', 'top')
1627
1628
 
1628
1629
  // trigger "resized" event
1630
+ // note: not triggered before the "init" event
1629
1631
  instance.emit('resized', _scale)
1630
1632
 
1633
+ // paint a temporary background
1631
1634
  instance.cls(0)
1632
1635
 
1633
- // force redraw
1636
+ // force redraw when the canvas is not animated
1634
1637
  if (!settings.animate) {
1635
1638
  raf(drawFrame)
1636
1639
  }
package/src/version.js CHANGED
@@ -1,2 +1,2 @@
1
1
  // Generated by genversion.
2
- export const version = '0.92.2'
2
+ export const version = '0.93.0'
package/types/types.d.ts CHANGED
@@ -594,19 +594,18 @@ type LitecanvasOptions = {
594
594
  canvas?: HTMLCanvasElement | string
595
595
  /**
596
596
  * If `true` (default) scales the canvas to fill the screen, but preserving the aspect ratio.
597
- * Instead of `true`, you can pass a number to limit the maximum scale factor of the canvas.
597
+ * Instead of `true`, you can pass a number to determine the maximum scale.
598
598
  *
599
599
  * Note: Only works if the option "width" was specified.
600
600
  */
601
601
  autoscale?: boolean | number
602
602
  /**
603
603
  * If `true`, the pixel art images won't look blurry.
604
+ * Also, disables canvas built-in antialias.
605
+ *
606
+ * Default: `false`
604
607
  */
605
608
  pixelart?: boolean
606
- /**
607
- * If `false` (default), disable the canvas antialias.
608
- */
609
- antialias?: boolean
610
609
  /**
611
610
  * If `true` (default), all methods and properties of the engine will be exposed to the global scope (window).
612
611
  */