litecanvas 0.90.0 → 0.92.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/README.md CHANGED
@@ -28,22 +28,16 @@ Litecanvas is a lightweight HTML5 canvas 2D engine suitable for small web games,
28
28
 
29
29
  ## Getting Started
30
30
 
31
- You can try our [online playground](https://litecanvas.github.io) or just installing the [basic template](https://github.com/litecanvas/template):
31
+ You can try our [online playground](https://litecanvas.github.io) or install the [basic template](https://github.com/litecanvas/template):
32
32
 
33
33
  ```sh
34
- # requires Node.js
34
+ # requires Node.js & NPM
35
35
  npx tiged litecanvas/template my-game
36
36
  cd my-game
37
37
  npm install
38
38
  npm run dev
39
39
  ```
40
40
 
41
- If you prefer, you can manually install via [NPM](https://www.npmjs.com/package/litecanvas):
42
-
43
- ```
44
- npm install litecanvas
45
- ```
46
-
47
41
  ### Show me the code!
48
42
 
49
43
  ```js
package/dist/dist.dev.js CHANGED
@@ -32,7 +32,7 @@
32
32
  };
33
33
 
34
34
  // src/version.js
35
- var version = "0.90.0";
35
+ var version = "0.92.0";
36
36
 
37
37
  // src/index.js
38
38
  function litecanvas(settings = {}) {
@@ -811,10 +811,7 @@
811
811
  );
812
812
  DEV: assert(isNumber(pitchSlide), "[litecanvas] sfx() 2nd param must be a number");
813
813
  DEV: assert(isNumber(volumeFactor), "[litecanvas] sfx() 3rd param must be a number");
814
- if (
815
- // @ts-ignore
816
- root.zzfxV <= 0 || navigator.userActivation && !navigator.userActivation.hasBeenActive
817
- ) {
814
+ if (root.zzfxV <= 0 || navigator.userActivation && !navigator.userActivation.hasBeenActive) {
818
815
  return false;
819
816
  }
820
817
  zzfxParams = zzfxParams || _defaultSound;
@@ -926,7 +923,9 @@
926
923
  def(key, value) {
927
924
  DEV: assert("string" === typeof key, "[litecanvas] def() 1st param must be a string");
928
925
  DEV: if (null == value) {
929
- console.warn(`def: key "${key}" was defined as ${value} but now is null`);
926
+ console.warn(
927
+ `[litecanvas] def() changed the key "${key}" to null (previous value was ${instance[key]})`
928
+ );
930
929
  }
931
930
  instance[key] = value;
932
931
  if (settings.global) {
@@ -985,8 +984,7 @@
985
984
  // 7
986
985
  _timeScale,
987
986
  // 8
988
- // @ts-ignore
989
- root.zzfxV || 1,
987
+ root.zzfxV,
990
988
  // 9
991
989
  _rngSeed,
992
990
  // 10
@@ -1060,12 +1058,11 @@
1060
1058
  if (settings.tapEvents) {
1061
1059
  const _getXY = (
1062
1060
  /**
1063
- * @param {number} pageX
1064
- * @param {number} pageY
1061
+ * @param {MouseEvent | Touch} ev
1065
1062
  */
1066
- (pageX, pageY) => [
1067
- (pageX - _canvas.offsetLeft) / _scale,
1068
- (pageY - _canvas.offsetTop) / _scale
1063
+ (ev) => [
1064
+ (ev.pageX - _canvas.offsetLeft) / _scale,
1065
+ (ev.pageY - _canvas.offsetTop) / _scale
1069
1066
  ]
1070
1067
  ), _taps = /* @__PURE__ */ new Map(), _registerTap = (
1071
1068
  /**
@@ -1121,7 +1118,7 @@
1121
1118
  (ev) => {
1122
1119
  if (ev.button === 0) {
1123
1120
  preventDefault(ev);
1124
- const [x, y] = _getXY(ev.pageX, ev.pageY);
1121
+ const [x, y] = _getXY(ev);
1125
1122
  instance.emit("tap", x, y, 0);
1126
1123
  _registerTap(0, x, y);
1127
1124
  _pressingMouse = true;
@@ -1138,7 +1135,7 @@
1138
1135
  if (ev.button === 0) {
1139
1136
  preventDefault(ev);
1140
1137
  const tap = _taps.get(0);
1141
- const [x, y] = _getXY(ev.pageX, ev.pageY);
1138
+ const [x, y] = _getXY(ev);
1142
1139
  if (_checkTapped(tap)) {
1143
1140
  instance.emit("tapped", tap.xi, tap.yi, 0);
1144
1141
  }
@@ -1149,14 +1146,14 @@
1149
1146
  }
1150
1147
  );
1151
1148
  on(
1152
- _canvas,
1149
+ root,
1153
1150
  "mousemove",
1154
1151
  /**
1155
1152
  * @param {MouseEvent} ev
1156
1153
  */
1157
1154
  (ev) => {
1158
1155
  preventDefault(ev);
1159
- const [x, y] = _getXY(ev.pageX, ev.pageY);
1156
+ const [x, y] = _getXY(ev);
1160
1157
  instance.def("MX", x);
1161
1158
  instance.def("MY", y);
1162
1159
  if (!_pressingMouse) return;
@@ -1174,7 +1171,7 @@
1174
1171
  preventDefault(ev);
1175
1172
  const touches = ev.changedTouches;
1176
1173
  for (const touch of touches) {
1177
- const [x, y] = _getXY(touch.pageX, touch.pageY);
1174
+ const [x, y] = _getXY(touch);
1178
1175
  instance.emit("tap", x, y, touch.identifier + 1);
1179
1176
  _registerTap(touch.identifier + 1, x, y);
1180
1177
  }
@@ -1190,7 +1187,7 @@
1190
1187
  preventDefault(ev);
1191
1188
  const touches = ev.changedTouches;
1192
1189
  for (const touch of touches) {
1193
- const [x, y] = _getXY(touch.pageX, touch.pageY);
1190
+ const [x, y] = _getXY(touch);
1194
1191
  instance.emit("tapping", x, y, touch.identifier + 1);
1195
1192
  _updateTap(touch.identifier + 1, x, y);
1196
1193
  }
package/dist/dist.js CHANGED
@@ -558,10 +558,7 @@
558
558
  * @see https://github.com/KilledByAPixel/ZzFX
559
559
  */
560
560
  sfx(zzfxParams, pitchSlide = 0, volumeFactor = 1) {
561
- if (
562
- // @ts-ignore
563
- root.zzfxV <= 0 || navigator.userActivation && !navigator.userActivation.hasBeenActive
564
- ) {
561
+ if (root.zzfxV <= 0 || navigator.userActivation && !navigator.userActivation.hasBeenActive) {
565
562
  return false;
566
563
  }
567
564
  zzfxParams = zzfxParams || _defaultSound;
@@ -694,8 +691,7 @@
694
691
  // 7
695
692
  _timeScale,
696
693
  // 8
697
- // @ts-ignore
698
- root.zzfxV || 1,
694
+ root.zzfxV,
699
695
  // 9
700
696
  _rngSeed,
701
697
  // 10
@@ -766,12 +762,11 @@
766
762
  if (settings.tapEvents) {
767
763
  const _getXY = (
768
764
  /**
769
- * @param {number} pageX
770
- * @param {number} pageY
765
+ * @param {MouseEvent | Touch} ev
771
766
  */
772
- (pageX, pageY) => [
773
- (pageX - _canvas.offsetLeft) / _scale,
774
- (pageY - _canvas.offsetTop) / _scale
767
+ (ev) => [
768
+ (ev.pageX - _canvas.offsetLeft) / _scale,
769
+ (ev.pageY - _canvas.offsetTop) / _scale
775
770
  ]
776
771
  ), _taps = /* @__PURE__ */ new Map(), _registerTap = (
777
772
  /**
@@ -827,7 +822,7 @@
827
822
  (ev) => {
828
823
  if (ev.button === 0) {
829
824
  preventDefault(ev);
830
- const [x, y] = _getXY(ev.pageX, ev.pageY);
825
+ const [x, y] = _getXY(ev);
831
826
  instance.emit("tap", x, y, 0);
832
827
  _registerTap(0, x, y);
833
828
  _pressingMouse = true;
@@ -844,7 +839,7 @@
844
839
  if (ev.button === 0) {
845
840
  preventDefault(ev);
846
841
  const tap = _taps.get(0);
847
- const [x, y] = _getXY(ev.pageX, ev.pageY);
842
+ const [x, y] = _getXY(ev);
848
843
  if (_checkTapped(tap)) {
849
844
  instance.emit("tapped", tap.xi, tap.yi, 0);
850
845
  }
@@ -855,14 +850,14 @@
855
850
  }
856
851
  );
857
852
  on(
858
- _canvas,
853
+ root,
859
854
  "mousemove",
860
855
  /**
861
856
  * @param {MouseEvent} ev
862
857
  */
863
858
  (ev) => {
864
859
  preventDefault(ev);
865
- const [x, y] = _getXY(ev.pageX, ev.pageY);
860
+ const [x, y] = _getXY(ev);
866
861
  instance.def("MX", x);
867
862
  instance.def("MY", y);
868
863
  if (!_pressingMouse) return;
@@ -880,7 +875,7 @@
880
875
  preventDefault(ev);
881
876
  const touches = ev.changedTouches;
882
877
  for (const touch of touches) {
883
- const [x, y] = _getXY(touch.pageX, touch.pageY);
878
+ const [x, y] = _getXY(touch);
884
879
  instance.emit("tap", x, y, touch.identifier + 1);
885
880
  _registerTap(touch.identifier + 1, x, y);
886
881
  }
@@ -896,7 +891,7 @@
896
891
  preventDefault(ev);
897
892
  const touches = ev.changedTouches;
898
893
  for (const touch of touches) {
899
- const [x, y] = _getXY(touch.pageX, touch.pageY);
894
+ const [x, y] = _getXY(touch);
900
895
  instance.emit("tapping", x, y, touch.identifier + 1);
901
896
  _updateTap(touch.identifier + 1, x, y);
902
897
  }
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,p=0,u=0,m=0,g=0,h=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,X=k<0?-1:1,Y=z*X*k*2/44100,D=E.cos(Y),F=E.sin,q=F(Y)/4,B=1+q,H=-2*D/B,O=(1-q)/B,V=(1+X*D)/2/B,W=-(X+D)/B,R=0,G=0,$=0,j=0;for(n=44100*n+9,y*=44100,o*=44100,r*=44100,v*=44100,d*=500*z/85766121e6,h*=z/44100,p*=z/44100,u*=44100,m=44100*m|0,a*=.3*e.zzfxV,X=n+y+o+r+v|0;L<X;i[L++]=P*a)++N%(100*x|0)||(P=s?1<s?2<s?3<s?F(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):F(I),P=(m?1-b+b*F(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<X-v?(X-L-v)/r*w:0),P=v?P/2+(v>L?0:(L<X-v?1:(X-L)/v)*i[L-v|0]/2/a):P,k&&(P=j=V*R+W*(R=G)+V*(G=P)-O*$-H*($=j))),I+=(Y=(l+=c+=d)*E.cos(h*A++))+Y*g*F(L**5),S&&++S>u&&(l+=p,C+=p,S=0),!m||++M%m||(l=C,c=T,S=S||1);(a=t.createBuffer(1,X,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=[],p,u=1,m,g=.5,h=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-g,~~t-g,~~a+2*g,~~i+2*g,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!==g&&~~e==~~a),o=.5*(0!==g&&~~t==~~i);m.moveTo(~~e+n,~~t+o),m.lineTo(~~a+n,~~i+o),I.stroke(l)},linewidth(e){m.lineWidth=~~e,g=.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:()=>p,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){h=e},framerate(e){v=1/~~e},stat(e){let i={index:e,value:[t,c,v,u,C,z,T,h,a.zzfxV||1,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,t)=>[(e-p.offsetLeft)/u,(t-p.offsetTop)/u],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(p,"mousedown",t=>{if(0===t.button){o(t);let[a,l]=e(t.pageX,t.pageY);I.emit("tap",a,l,0),i(0,a,l),s=!0}}),r(p,"mouseup",a=>{if(0===a.button){o(a);let i=t.get(0),[l,r]=e(a.pageX,a.pageY);n(i)&&I.emit("tapped",i.xi,i.yi,0),I.emit("untap",l,r,0),t.delete(0),s=!1}}),r(p,"mousemove",t=>{o(t);let[a,i]=e(t.pageX,t.pageY);I.def("MX",a),I.def("MY",i),s&&(I.emit("tapping",a,i,0),l(0,a,i))}),r(p,"touchstart",t=>{for(let a of(o(t),t.changedTouches)){let[t,l]=e(a.pageX,a.pageY);I.emit("tap",t,l,a.identifier+1),i(a.identifier+1,t,l)}}),r(p,"touchmove",t=>{for(let a of(o(t),t.changedTouches)){let[t,i]=e(a.pageX,a.pageY);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(p,"touchend",f),r(p,"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*h,a),I.def("T",I.T+v*h),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),p.width=e,p.height=l,t.autoscale){let n=+t.autoscale;p.style.display||(p.style.display="block",p.style.margin="auto"),u=i.min(a.innerWidth/e,a.innerHeight/l),u=n>1&&u>n?n:u,u=(t.pixelart?~~u:u)||1,p.style.width=e*u+"px",p.style.height=l*u+"px"}(!t.antialias||t.pixelart)&&(m.imageSmoothingEnabled=!1,p.style.imageRendering="pixelated"),I.textalign("start","top"),I.emit("resized",u),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=(p=(p="string"==typeof t.canvas?document.querySelector(t.canvas):t.canvas)||document.createElement("canvas")).getContext("2d"),r(p,"click",()=>a.focus()),p.style="",S(),p.parentNode||document.body.appendChild(p),p.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,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}})();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "litecanvas",
3
- "version": "0.90.0",
3
+ "version": "0.92.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>",
@@ -14,8 +14,25 @@
14
14
  "url": "https://github.com/litecanvas/game-engine/issues"
15
15
  },
16
16
  "type": "module",
17
- "main": "src/index.js",
18
- "types": "types/index.d.ts",
17
+ "main": "./src/index.js",
18
+ "module": "./src/index.js",
19
+ "types": "./types/index.d.ts",
20
+ "exports": {
21
+ ".": {
22
+ "import": {
23
+ "types": "./types/index.d.ts",
24
+ "default": "./src/index.js"
25
+ }
26
+ },
27
+ "./global": "./src/index.js"
28
+ },
29
+ "typesVersions": {
30
+ "*": {
31
+ "./global": [
32
+ "./types/global.d.ts"
33
+ ]
34
+ }
35
+ },
19
36
  "keywords": [
20
37
  "canvas",
21
38
  "2d",
@@ -33,7 +50,7 @@
33
50
  "@size-limit/preset-small-lib": "^11.2.0",
34
51
  "@swc/core": "^1.12.11",
35
52
  "@types/jsdom": "^21.1.7",
36
- "ava": "^6.4.0",
53
+ "ava": "^6.4.1",
37
54
  "esbuild": "^0.25.6",
38
55
  "genversion": "^3.2.0",
39
56
  "gzip-size": "^7.0.0",
package/src/index.js CHANGED
@@ -87,7 +87,7 @@ export default function litecanvas(settings = {}) {
87
87
  */
88
88
  _eventListeners = {}
89
89
 
90
- /** @type {Omit<LitecanvasInstance,'PI'|'sin'|'cos'|'atan2'|'hypot'|'tan'|'abs'|'ceil'|'floor'|'trunc'|'min'|'max'|'pow'|'sqrt'|'sign'|'exp'|'iskeydown'|'iskeypressed'>} */
90
+ /** @type {LitecanvasInstance} */
91
91
  const instance = {
92
92
  /** @type {number} */
93
93
  W: 0,
@@ -945,7 +945,6 @@ export default function litecanvas(settings = {}) {
945
945
  DEV: assert(isNumber(volumeFactor), '[litecanvas] sfx() 3rd param must be a number')
946
946
 
947
947
  if (
948
- // @ts-ignore
949
948
  root.zzfxV <= 0 ||
950
949
  (navigator.userActivation && !navigator.userActivation.hasBeenActive)
951
950
  ) {
@@ -975,7 +974,6 @@ export default function litecanvas(settings = {}) {
975
974
  volume(value) {
976
975
  DEV: assert(isNumber(value), '[litecanvas] volume() 1st param must be a number')
977
976
 
978
- // @ts-ignore
979
977
  root.zzfxV = value
980
978
  },
981
979
 
@@ -1082,7 +1080,9 @@ export default function litecanvas(settings = {}) {
1082
1080
  def(key, value) {
1083
1081
  DEV: assert('string' === typeof key, '[litecanvas] def() 1st param must be a string')
1084
1082
  DEV: if (null == value) {
1085
- console.warn(`def: key "${key}" was defined as ${value} but now is null`)
1083
+ console.warn(
1084
+ `[litecanvas] def() changed the key "${key}" to null (previous value was ${instance[key]})`
1085
+ )
1086
1086
  }
1087
1087
 
1088
1088
  instance[key] = value
@@ -1148,8 +1148,7 @@ export default function litecanvas(settings = {}) {
1148
1148
  // 7
1149
1149
  _timeScale,
1150
1150
  // 8
1151
- // @ts-ignore
1152
- root.zzfxV || 1,
1151
+ root.zzfxV,
1153
1152
  // 9
1154
1153
  _rngSeed,
1155
1154
  // 10
@@ -1189,7 +1188,6 @@ export default function litecanvas(settings = {}) {
1189
1188
  for (const key in instance) {
1190
1189
  delete root[key]
1191
1190
  }
1192
- // @ts-ignore
1193
1191
  delete root.ENGINE
1194
1192
  }
1195
1193
 
@@ -1254,12 +1252,11 @@ export default function litecanvas(settings = {}) {
1254
1252
  if (settings.tapEvents) {
1255
1253
  const _getXY =
1256
1254
  /**
1257
- * @param {number} pageX
1258
- * @param {number} pageY
1255
+ * @param {MouseEvent | Touch} ev
1259
1256
  */
1260
- (pageX, pageY) => [
1261
- (pageX - _canvas.offsetLeft) / _scale,
1262
- (pageY - _canvas.offsetTop) / _scale,
1257
+ (ev) => [
1258
+ (ev.pageX - _canvas.offsetLeft) / _scale,
1259
+ (ev.pageY - _canvas.offsetTop) / _scale,
1263
1260
  ],
1264
1261
  _taps = new Map(),
1265
1262
  _registerTap =
@@ -1317,7 +1314,7 @@ export default function litecanvas(settings = {}) {
1317
1314
  (ev) => {
1318
1315
  if (ev.button === 0) {
1319
1316
  preventDefault(ev)
1320
- const [x, y] = _getXY(ev.pageX, ev.pageY)
1317
+ const [x, y] = _getXY(ev)
1321
1318
  instance.emit('tap', x, y, 0)
1322
1319
  _registerTap(0, x, y)
1323
1320
  _pressingMouse = true
@@ -1335,7 +1332,7 @@ export default function litecanvas(settings = {}) {
1335
1332
  if (ev.button === 0) {
1336
1333
  preventDefault(ev)
1337
1334
  const tap = _taps.get(0)
1338
- const [x, y] = _getXY(ev.pageX, ev.pageY)
1335
+ const [x, y] = _getXY(ev)
1339
1336
  if (_checkTapped(tap)) {
1340
1337
  instance.emit('tapped', tap.xi, tap.yi, 0)
1341
1338
  }
@@ -1347,7 +1344,7 @@ export default function litecanvas(settings = {}) {
1347
1344
  )
1348
1345
 
1349
1346
  on(
1350
- _canvas,
1347
+ root,
1351
1348
  'mousemove',
1352
1349
  /**
1353
1350
  * @param {MouseEvent} ev
@@ -1355,7 +1352,7 @@ export default function litecanvas(settings = {}) {
1355
1352
  (ev) => {
1356
1353
  preventDefault(ev)
1357
1354
 
1358
- const [x, y] = _getXY(ev.pageX, ev.pageY)
1355
+ const [x, y] = _getXY(ev)
1359
1356
  instance.def('MX', x)
1360
1357
  instance.def('MY', y)
1361
1358
 
@@ -1377,7 +1374,7 @@ export default function litecanvas(settings = {}) {
1377
1374
  /** @type {TouchList} touches */
1378
1375
  const touches = ev.changedTouches
1379
1376
  for (const touch of touches) {
1380
- const [x, y] = _getXY(touch.pageX, touch.pageY)
1377
+ const [x, y] = _getXY(touch)
1381
1378
  instance.emit('tap', x, y, touch.identifier + 1)
1382
1379
  _registerTap(touch.identifier + 1, x, y)
1383
1380
  }
@@ -1394,7 +1391,7 @@ export default function litecanvas(settings = {}) {
1394
1391
  preventDefault(ev)
1395
1392
  const touches = ev.changedTouches
1396
1393
  for (const touch of touches) {
1397
- const [x, y] = _getXY(touch.pageX, touch.pageY)
1394
+ const [x, y] = _getXY(touch)
1398
1395
  instance.emit('tapping', x, y, touch.identifier + 1)
1399
1396
  _updateTap(touch.identifier + 1, x, y)
1400
1397
  }
@@ -1569,7 +1566,7 @@ export default function litecanvas(settings = {}) {
1569
1566
 
1570
1567
  on(_canvas, 'click', () => root.focus())
1571
1568
 
1572
- // @ts-ignore
1569
+ /** @ts-ignore */
1573
1570
  _canvas.style = ''
1574
1571
 
1575
1572
  resizeCanvas()
@@ -1658,7 +1655,6 @@ export default function litecanvas(settings = {}) {
1658
1655
  * @param {*} config
1659
1656
  */
1660
1657
  function loadPlugin(callback, config) {
1661
- // @ts-ignore
1662
1658
  const pluginData = callback(instance, config)
1663
1659
 
1664
1660
  DEV: assert(
@@ -1672,12 +1668,10 @@ export default function litecanvas(settings = {}) {
1672
1668
  }
1673
1669
 
1674
1670
  if (settings.global) {
1675
- // @ts-ignore
1676
1671
  if (root.ENGINE) {
1677
1672
  throw new Error('only one global litecanvas is allowed')
1678
1673
  }
1679
1674
  Object.assign(root, instance)
1680
- // @ts-ignore
1681
1675
  root.ENGINE = instance
1682
1676
  }
1683
1677
 
@@ -1692,6 +1686,5 @@ export default function litecanvas(settings = {}) {
1692
1686
  raf(init)
1693
1687
  }
1694
1688
 
1695
- // @ts-ignore
1696
1689
  return instance
1697
1690
  }
package/src/version.js CHANGED
@@ -1,2 +1,2 @@
1
1
  // Generated by genversion.
2
- export const version = '0.90.0';
2
+ export const version = '0.92.0';
package/src/web.js CHANGED
@@ -1,6 +1,3 @@
1
1
  import litecanvas from './index.js'
2
2
 
3
- /**
4
- * @global
5
- */
6
3
  globalThis.litecanvas = litecanvas