litecanvas 0.205.0 → 0.206.1

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
@@ -115,7 +115,7 @@
115
115
  var assert = (condition, message = "Assertion failed") => {
116
116
  if (!condition) throw new Error("[litecanvas] " + message);
117
117
  };
118
- var version = "0.205.0";
118
+ var version = "0.206.1";
119
119
  function litecanvas(settings = {}) {
120
120
  const root = window,
121
121
  math = Math,
@@ -146,8 +146,9 @@
146
146
  keyboardEvents: true,
147
147
  };
148
148
  settings = Object.assign(defaults, settings);
149
- let _initialized = false,
150
- _paused = true,
149
+ let _loop = settings.loop,
150
+ _initialized = false,
151
+ _paused,
151
152
  _canvas,
152
153
  _canvasScale = 1,
153
154
  _ctx,
@@ -156,7 +157,7 @@
156
157
  _lastFrameTime,
157
158
  _fpsInterval = 1e3 / 60,
158
159
  _accumulated,
159
- _rafid,
160
+ _rafid = 0,
160
161
  _defaultTextColor = 3,
161
162
  _fontFamily = "sans-serif",
162
163
  _fontSize = 20,
@@ -165,8 +166,6 @@
165
166
  _colorPalette = defaultPalette,
166
167
  _colorPaletteState = [],
167
168
  _defaultSound = [0.5, 0, 1750, , , 0.3, 1, , , , 600, 0.1],
168
- _mathFunctions =
169
- "PI,sin,cos,atan2,hypot,tan,abs,ceil,floor,trunc,min,max,pow,sqrt,sign,exp",
170
169
  _eventListeners = {};
171
170
  const instance = {
172
171
  W: 0,
@@ -846,17 +845,17 @@
846
845
  callback(_ctx);
847
846
  _ctx.clip();
848
847
  },
849
- sfx(zzfxParams, pitchSlide = 0, volumeFactor = 1) {
848
+ sfx(zzfxParams, pitchSlide, volumeFactor) {
850
849
  DEV: assert(
851
850
  null == zzfxParams || Array.isArray(zzfxParams),
852
851
  loggerPrefix + "sfx() 1st param must be an array",
853
852
  );
854
853
  DEV: assert(
855
- isNumber(pitchSlide),
854
+ null == pitchSlide || isNumber(pitchSlide),
856
855
  loggerPrefix + "sfx() 2nd param must be a number",
857
856
  );
858
857
  DEV: assert(
859
- isNumber(volumeFactor),
858
+ null == volumeFactor || isNumber(volumeFactor),
860
859
  loggerPrefix + "sfx() 3rd param must be a number",
861
860
  );
862
861
  if (
@@ -865,10 +864,10 @@
865
864
  ) {
866
865
  return false;
867
866
  }
868
- zzfxParams = zzfxParams || _defaultSound;
869
- if (pitchSlide !== 0 || volumeFactor !== 1) {
867
+ zzfxParams ||= _defaultSound;
868
+ if (pitchSlide || volumeFactor) {
870
869
  zzfxParams = zzfxParams.slice();
871
- zzfxParams[0] = volumeFactor * (zzfxParams[0] || 1);
870
+ zzfxParams[0] = (volumeFactor || 1) * (zzfxParams[0] || 1);
872
871
  zzfxParams[10] = ~~zzfxParams[10] + pitchSlide;
873
872
  }
874
873
  zzfx.apply(0, zzfxParams);
@@ -930,7 +929,7 @@
930
929
  eventName = lowerCase(eventName);
931
930
  triggerEvent("before:" + eventName, arg1, arg2, arg3, arg4);
932
931
  if (
933
- !settings.loop &&
932
+ !_loop &&
934
933
  root[eventName] !== instance[eventName] &&
935
934
  "function" === typeof root[eventName]
936
935
  ) {
@@ -1033,7 +1032,7 @@
1033
1032
  pause() {
1034
1033
  if (!_paused) {
1035
1034
  _paused = true;
1036
- cancelAnimationFrame(_rafid);
1035
+ _rafid = ~~cancelAnimationFrame(_rafid);
1037
1036
  instance.emit("paused");
1038
1037
  }
1039
1038
  },
@@ -1044,10 +1043,8 @@
1044
1043
  'resume() cannot be called before the "init" event and neither after the quit() function',
1045
1044
  );
1046
1045
  if (_initialized && _paused) {
1046
+ startGameLoop();
1047
1047
  _paused = false;
1048
- _accumulated = _fpsInterval;
1049
- _lastFrameTime = perf.now();
1050
- _rafid = raf(drawFrame);
1051
1048
  instance.emit("resumed");
1052
1049
  }
1053
1050
  },
@@ -1073,9 +1070,18 @@
1073
1070
  );
1074
1071
  },
1075
1072
  };
1076
- for (const k of _mathFunctions.split(",")) {
1073
+ const mathProps =
1074
+ "PI,sin,cos,atan2,hypot,tan,abs,ceil,floor,trunc,min,max,pow,sqrt,sign,exp";
1075
+ for (const k of mathProps.split(",")) {
1077
1076
  instance[k] = math[k];
1078
1077
  }
1078
+ function startGameLoop() {
1079
+ if (!_rafid) {
1080
+ _accumulated = 0;
1081
+ _lastFrameTime = perf.now();
1082
+ _rafid = raf(drawFrame);
1083
+ }
1084
+ }
1079
1085
  function init() {
1080
1086
  if (settings.autoscale) {
1081
1087
  on(root, "resize", resizeCanvas);
@@ -1216,8 +1222,10 @@
1216
1222
  instance.def("lastkey", () => _lastKey);
1217
1223
  }
1218
1224
  _initialized = true;
1219
- instance.resume();
1220
1225
  instance.emit("init", instance);
1226
+ if (!_paused) {
1227
+ startGameLoop();
1228
+ }
1221
1229
  }
1222
1230
  function drawFrame() {
1223
1231
  _rafid = raf(drawFrame);
@@ -1237,18 +1245,13 @@
1237
1245
  instance.emit("draw", _ctx);
1238
1246
  if (updated > 1) {
1239
1247
  _accumulated = 0;
1240
- DEV: console.warn(
1241
- loggerPrefix +
1242
- "the last frame updated " +
1243
- updated +
1244
- " times. This can drop the FPS if it keeps happening.",
1245
- );
1246
1248
  }
1247
1249
  }
1248
1250
  }
1249
1251
  function setupCanvas() {
1252
+ const d = document;
1250
1253
  if ("string" === typeof settings.canvas) {
1251
- _canvas = document.querySelector(settings.canvas);
1254
+ _canvas = d.querySelector(settings.canvas);
1252
1255
  DEV: assert(
1253
1256
  null != _canvas,
1254
1257
  loggerPrefix +
@@ -1257,7 +1260,7 @@
1257
1260
  } else {
1258
1261
  _canvas = settings.canvas;
1259
1262
  }
1260
- _canvas = _canvas || document.createElement("canvas");
1263
+ _canvas = _canvas || d.createElement("canvas");
1261
1264
  DEV: assert(
1262
1265
  _canvas instanceof HTMLElement && "CANVAS" === _canvas.tagName,
1263
1266
  loggerPrefix +
@@ -1267,7 +1270,7 @@
1267
1270
  on(_canvas, "click", () => focus());
1268
1271
  resizeCanvas();
1269
1272
  if (!_canvas.parentNode) {
1270
- document.body.appendChild(_canvas);
1273
+ d.body.appendChild(_canvas);
1271
1274
  }
1272
1275
  _canvas.style.imageRendering = "pixelated";
1273
1276
  _canvas.oncontextmenu = () => false;
@@ -1345,13 +1348,12 @@
1345
1348
  DEV: console.info(loggerPrefix + `version ${version} started`);
1346
1349
  DEV: console.debug(loggerPrefix + `litecanvas() options =`, settings);
1347
1350
  setupCanvas();
1348
- if (settings.loop) {
1349
- for (const eventName in settings.loop) {
1350
- if (settings.loop[eventName])
1351
- instance.listen(eventName, settings.loop[eventName]);
1351
+ if (_loop) {
1352
+ for (const eventName in _loop) {
1353
+ if (_loop[eventName]) instance.listen(eventName, _loop[eventName]);
1352
1354
  }
1353
1355
  }
1354
- _rafid = raf(init);
1356
+ raf(init);
1355
1357
  return instance;
1356
1358
  }
1357
1359
  window.litecanvas = litecanvas;
package/dist/dist.js CHANGED
@@ -142,8 +142,9 @@
142
142
  keyboardEvents: true,
143
143
  };
144
144
  settings = Object.assign(defaults, settings);
145
- let _initialized = false,
146
- _paused = true,
145
+ let _loop = settings.loop,
146
+ _initialized = false,
147
+ _paused,
147
148
  _canvas,
148
149
  _canvasScale = 1,
149
150
  _ctx,
@@ -152,7 +153,7 @@
152
153
  _lastFrameTime,
153
154
  _fpsInterval = 1e3 / 60,
154
155
  _accumulated,
155
- _rafid,
156
+ _rafid = 0,
156
157
  _defaultTextColor = 3,
157
158
  _fontFamily = "sans-serif",
158
159
  _fontSize = 20,
@@ -161,8 +162,6 @@
161
162
  _colorPalette = defaultPalette,
162
163
  _colorPaletteState = [],
163
164
  _defaultSound = [0.5, 0, 1750, , , 0.3, 1, , , , 600, 0.1],
164
- _mathFunctions =
165
- "PI,sin,cos,atan2,hypot,tan,abs,ceil,floor,trunc,min,max,pow,sqrt,sign,exp",
166
165
  _eventListeners = {};
167
166
  const instance = {
168
167
  W: 0,
@@ -385,17 +384,17 @@
385
384
  callback(_ctx);
386
385
  _ctx.clip();
387
386
  },
388
- sfx(zzfxParams, pitchSlide = 0, volumeFactor = 1) {
387
+ sfx(zzfxParams, pitchSlide, volumeFactor) {
389
388
  if (
390
389
  !root.zzfxV ||
391
390
  (navigator.userActivation && !navigator.userActivation.hasBeenActive)
392
391
  ) {
393
392
  return false;
394
393
  }
395
- zzfxParams = zzfxParams || _defaultSound;
396
- if (pitchSlide !== 0 || volumeFactor !== 1) {
394
+ zzfxParams ||= _defaultSound;
395
+ if (pitchSlide || volumeFactor) {
397
396
  zzfxParams = zzfxParams.slice();
398
- zzfxParams[0] = volumeFactor * (zzfxParams[0] || 1);
397
+ zzfxParams[0] = (volumeFactor || 1) * (zzfxParams[0] || 1);
399
398
  zzfxParams[10] = ~~zzfxParams[10] + pitchSlide;
400
399
  }
401
400
  zzfx.apply(0, zzfxParams);
@@ -424,7 +423,7 @@
424
423
  eventName = lowerCase(eventName);
425
424
  triggerEvent("before:" + eventName, arg1, arg2, arg3, arg4);
426
425
  if (
427
- !settings.loop &&
426
+ !_loop &&
428
427
  root[eventName] !== instance[eventName] &&
429
428
  "function" === typeof root[eventName]
430
429
  ) {
@@ -482,16 +481,14 @@
482
481
  pause() {
483
482
  if (!_paused) {
484
483
  _paused = true;
485
- cancelAnimationFrame(_rafid);
484
+ _rafid = ~~cancelAnimationFrame(_rafid);
486
485
  instance.emit("paused");
487
486
  }
488
487
  },
489
488
  resume() {
490
489
  if (_initialized && _paused) {
490
+ startGameLoop();
491
491
  _paused = false;
492
- _accumulated = _fpsInterval;
493
- _lastFrameTime = perf.now();
494
- _rafid = raf(drawFrame);
495
492
  instance.emit("resumed");
496
493
  }
497
494
  },
@@ -514,9 +511,18 @@
514
511
  }
515
512
  },
516
513
  };
517
- for (const k of _mathFunctions.split(",")) {
514
+ const mathProps =
515
+ "PI,sin,cos,atan2,hypot,tan,abs,ceil,floor,trunc,min,max,pow,sqrt,sign,exp";
516
+ for (const k of mathProps.split(",")) {
518
517
  instance[k] = math[k];
519
518
  }
519
+ function startGameLoop() {
520
+ if (!_rafid) {
521
+ _accumulated = 0;
522
+ _lastFrameTime = perf.now();
523
+ _rafid = raf(drawFrame);
524
+ }
525
+ }
520
526
  function init() {
521
527
  if (settings.autoscale) {
522
528
  on(root, "resize", resizeCanvas);
@@ -647,8 +653,10 @@
647
653
  instance.def("lastkey", () => _lastKey);
648
654
  }
649
655
  _initialized = true;
650
- instance.resume();
651
656
  instance.emit("init", instance);
657
+ if (!_paused) {
658
+ startGameLoop();
659
+ }
652
660
  }
653
661
  function drawFrame() {
654
662
  _rafid = raf(drawFrame);
@@ -672,17 +680,18 @@
672
680
  }
673
681
  }
674
682
  function setupCanvas() {
683
+ const d = document;
675
684
  if ("string" === typeof settings.canvas) {
676
- _canvas = document.querySelector(settings.canvas);
685
+ _canvas = d.querySelector(settings.canvas);
677
686
  } else {
678
687
  _canvas = settings.canvas;
679
688
  }
680
- _canvas = _canvas || document.createElement("canvas");
689
+ _canvas = _canvas || d.createElement("canvas");
681
690
  _ctx = _canvas.getContext("2d");
682
691
  on(_canvas, "click", () => focus());
683
692
  resizeCanvas();
684
693
  if (!_canvas.parentNode) {
685
- document.body.appendChild(_canvas);
694
+ d.body.appendChild(_canvas);
686
695
  }
687
696
  _canvas.style.imageRendering = "pixelated";
688
697
  _canvas.oncontextmenu = () => false;
@@ -736,13 +745,12 @@
736
745
  root.ENGINE = instance;
737
746
  }
738
747
  setupCanvas();
739
- if (settings.loop) {
740
- for (const eventName in settings.loop) {
741
- if (settings.loop[eventName])
742
- instance.listen(eventName, settings.loop[eventName]);
748
+ if (_loop) {
749
+ for (const eventName in _loop) {
750
+ if (_loop[eventName]) instance.listen(eventName, _loop[eventName]);
743
751
  }
744
752
  }
745
- _rafid = raf(init);
753
+ raf(init);
746
754
  return instance;
747
755
  }
748
756
  window.litecanvas = litecanvas;
package/dist/dist.min.js CHANGED
@@ -1 +1 @@
1
- (()=>{var e=["#211e20","#555568","#a0a08b","#e9efec"];window.litecanvas=function(t={}){let l,a=window,n=Math,i=performance,o=2*n.PI,r=requestAnimationFrame,s=[],f=(e,t,l)=>{e.addEventListener(t,l,!1),s.push(()=>e.removeEventListener(t,l,!1))},c=(l=new AudioContext,a.zzfxV=1,(e=1,t=.05,n=220,i=0,o=0,r=.1,s=0,f=1,c=0,d=0,p=0,u=0,h=0,m=0,g=0,w=0,v=0,x=1,y=0,b=0,k=0)=>{let E=Math,P=2*E.PI,T=c*=500*P/44100/44100,z=n*=(1-t+2*t*E.random(t=[]))*P/44100,C=0,I=0,L=0,D=1,A=0,S=0,H=0,M=k<0?-1:1,N=P*M*k*2/44100,W=E.cos(N),q=E.sin,B=q(N)/4,V=1+B,O=-2*W/V,R=(1-B)/V,F=(1+M*W)/2/V,G=-(M+W)/V,X=0,Y=0,$=0,j=0;for(i=44100*i+9,y*=44100,o*=44100,r*=44100,v*=44100,d*=500*P/85766121e6,g*=P/44100,p*=P/44100,u*=44100,h=44100*h|0,e*=.3*a.zzfxV,M=i+y+o+r+v|0;L<M;t[L++]=H*e)++S%(100*w|0)||(H=s?1<s?2<s?3<s?q(C*C):E.max(E.min(E.tan(C),1),-1):1-(2*C/P%2+2)%2:1-4*E.abs(E.round(C/P)-C/P):q(C),H=(h?1-b+b*q(P*L/h):1)*(H<0?-1:1)*E.abs(H)**f*(L<i?L/i:L<i+y?1-(L-i)/y*(1-x):L<i+y+o?x:L<M-v?(M-L-v)/r*x:0),H=v?H/2+(v>L?0:(L<M-v?1:(M-L)/v)*t[L-v|0]/2/e):H,k&&(H=j=F*X+G*(X=Y)+F*(Y=H)-R*$-O*($=j))),C+=(N=(n+=c+=d)*E.cos(g*I++))+N*m*q(L**5),D&&++D>u&&(n+=p,z+=p,D=0),!h||++A%h||(n=z,c=T,D=D||1);(e=l.createBuffer(1,M,44100)).getChannelData(0).set(t),(n=l.createBufferSource()).buffer=e,n.connect(l.destination),n.start()});t=Object.assign({width:null,height:null,autoscale:!0,canvas:null,global:!0,loop:null,tapEvents:!0,keyboardEvents:!0},t);let d=!1,p=!0,u,h=1,m,g=.5,w=1,v,x=1e3/60,y,b,k=3,E="sans-serif",P=20,T=1.2,z=Date.now(),C=e,I=[],L=[.5,0,1750,,,.3,1,,,,600,.1],D={},A={W:0,H:0,T:0,MX:-1,MY:-1,TWO_PI:o,HALF_PI:o/4,lerp:(e,t,l)=>e+l*(t-e),deg2rad:e=>n.PI/180*e,rad2deg:e=>180/n.PI*e,round:(e,t=0)=>{if(!t)return n.round(e);let l=10**t;return n.round(e*l)/l},clamp:(e,t,l)=>e<t?t:e>l?l:e,dist:(e,t,l,a)=>n.hypot(l-e,a-t),wrap:(e,t,l)=>e-(l-t)*n.floor((e-t)/(l-t)),map(e,t,l,a,n,i){let o=(e-t)/(l-t)*(n-a)+a;return i?A.clamp(o,a,n):o},norm:(e,t,l)=>A.map(e,t,l,0,1),rand:(e=0,t=1)=>(z=(1664525*z+0x3c6ef35f)%0x100000000)/0x100000000*(t-e)+e,randi:(e=0,t=1)=>~~A.rand(e,t+1),rseed(e){z=~~e},cls(e){null==e?m.clearRect(0,0,A.W,A.H):A.rectfill(0,0,A.W,A.H,e)},rect(e,t,l,a,n,i){m.beginPath(),m[i?"roundRect":"rect"](~~e-g,~~t-g,~~l+2*g,~~a+2*g,i),A.stroke(n)},rectfill(e,t,l,a,n,i){m.beginPath(),m[i?"roundRect":"rect"](~~e,~~t,~~l,~~a,i),A.fill(n)},circ(e,t,l,a){m.beginPath(),m.arc(~~e,~~t,~~l,0,o),A.stroke(a)},circfill(e,t,l,a){m.beginPath(),m.arc(~~e,~~t,~~l,0,o),A.fill(a)},oval(e,t,l,a,n){m.beginPath(),m.ellipse(~~e,~~t,~~l,~~a,0,0,o),A.stroke(n)},ovalfill(e,t,l,a,n){m.beginPath(),m.ellipse(~~e,~~t,~~l,~~a,0,0,o),A.fill(n)},shape(e){m.beginPath();for(let t=0;t<e.length;t+=2)0===t?m.moveTo(~~e[t],~~e[t+1]):m.lineTo(~~e[t],~~e[t+1]);m.lineTo(~~e[0],~~e[1])},line(e,t,l,a,n){m.beginPath();let i=.5*(0!==g&&~~e==~~l),o=.5*(0!==g&&~~t==~~a);m.moveTo(~~e+i,~~t+o),m.lineTo(~~l+i,~~a+o),A.stroke(n)},linewidth(e){m.lineWidth=~~e,g=.5*(0!=~~e%2)},linedash(e,t=0){m.setLineDash(e),m.lineDashOffset=t},text(e,t,l,a=k,n="normal"){m.font=`${n} ${P}px ${E}`,m.fillStyle=N(a);let i=(""+l).split("\n");for(let l=0;l<i.length;l++)m.fillText(i[l],~~e,~~t+P*T*l)},textgap(e){T=e},textfont(e){E=e},textsize(e){P=e},textalign(e,t){e&&(m.textAlign=e),t&&(m.textBaseline=t)},image(e,t,l){m.drawImage(l,~~e,~~t)},spr(e,t,l){let a=l.trim().split("\n");for(let l=0;l<a.length;l++){let n=a[l].trim();for(let a=0;a<n.length;a++){let i=n[a];"."!==i&&" "!==i&&A.rectfill(e+a,t+l,1,1,parseInt(i,36)||0)}}},paint(e,t,l,a={}){let n=a.canvas||new OffscreenCanvas(1,1),i=a.scale||1,o=m;return n.width=e*i,n.height=t*i,(m=n.getContext("2d")).scale(i,i),l(m),m=o,n.transferToImageBitmap()},ctx:e=>(e&&(m=e),m),push(){m.save()},pop(){m.restore()},translate(e,t){m.translate(~~e,~~t)},scale(e,t=e){m.scale(e,t)},rotate(e){m.rotate(e)},alpha(e){m.globalAlpha=A.clamp(e,0,1)},fill(e){m.fillStyle=N(e),m.fill()},stroke(e){m.strokeStyle=N(e),m.stroke()},clip(e){m.beginPath(),e(m),m.clip()},sfx:(e,t=0,l=1)=>!!a.zzfxV&&(!navigator.userActivation||!!navigator.userActivation.hasBeenActive)&&(e=e||L,(0!==t||1!==l)&&((e=e.slice())[0]=l*(e[0]||1),e[10]=~~e[10]+t),c.apply(0,e),e),volume(e){a.zzfxV=e},canvas:()=>u,use(e,t={}){var l=e,a=t;let n=l(A,a);for(let e in n)A.def(e,n[e])},listen:(e,t)=>{D[e=e.toLowerCase()]=D[e]||new Set,D[e].add(t)},unlisten:(e,t)=>{D[e=e.toLowerCase()]&&D[e].delete(t)},emit:(e,l,n,i,o)=>(d&&(M("before:"+(e=e.toLowerCase()),l,n,i,o),t.loop||a[e]===A[e]||"function"!=typeof a[e]||a[e](l,n,i,o),M(e,l,n,i,o),M("after:"+e,l,n,i,o)),l),pal(t,l=3){C=t||e,I=[],k=l,A.emit("pal",C,k)},palc(e,t){null==e?I=[]:I[e]=t},def(e,l){A[e]=l,t.global&&(a[e]=l)},timescale(e){w=e},framerate(e){x=1e3/~~e},stat:e=>[t,d,x/1e3,h,D,C,L,w,a.zzfxV,z,P,E,I,T][e],pause(){p||(p=!0,cancelAnimationFrame(b),A.emit("paused"))},resume(){d&&p&&(p=!1,y=x,v=i.now(),b=r(S),A.emit("resumed"))},ispaused:()=>p,quit(){for(let e of(A.emit("quit"),A.pause(),d=!1,D={},s))e();if(t.global){for(let e in A)delete a[e];delete a.ENGINE}}};for(let e of"PI,sin,cos,atan2,hypot,tan,abs,ceil,floor,trunc,min,max,pow,sqrt,sign,exp".split(","))A[e]=n[e];function S(){b=r(S);let e=i.now(),t=0,l=e-v;for(v=e,y+=l<100?l:x;y>=x;){t++,y-=x;let e=x/1e3*w;A.emit("update",e,t),A.def("T",A.T+e)}t&&(A.emit("draw",m),t>1&&(y=0))}function H(){let e=t.width>0?t.width:innerWidth,l=t.width>0?t.height||t.width:innerHeight;if(A.def("W",e),A.def("H",l),u.width=e,u.height=l,t.autoscale){let a=+t.autoscale;u.style.display||(u.style.display="block",u.style.margin="auto"),h=n.min(innerWidth/e,innerHeight/l),h=a>1&&h>a?a:h,u.style.width=e*h+"px",u.style.height=l*h+"px"}m.imageSmoothingEnabled=!1,A.textalign("start","top"),A.emit("resized",h)}function M(e,t,l,a,n){if(D[e])for(let i of D[e])i(t,l,a,n)}function N(e){return C[~~(I[e]??e)%C.length]}if(t.global){if(a.ENGINE)throw Error("only one global litecanvas is allowed");Object.assign(a,A),a.ENGINE=A}if(m=(u=(u="string"==typeof t.canvas?document.querySelector(t.canvas):t.canvas)||document.createElement("canvas")).getContext("2d"),f(u,"click",()=>focus()),H(),u.parentNode||document.body.appendChild(u),u.style.imageRendering="pixelated",u.oncontextmenu=()=>!1,t.loop)for(let e in t.loop)t.loop[e]&&A.listen(e,t.loop[e]);return b=r(function(){if(t.autoscale&&f(a,"resize",H),t.tapEvents){let e=e=>[(e.pageX-u.offsetLeft)/h,(e.pageY-u.offsetTop)/h],t=new Map,l=(e,l,a)=>{let n={x:l,y:a,xi:l,yi:a,t:i.now()};return t.set(e,n),n},n=(e,a,n)=>{let i=t.get(e)||l(e);i.x=a,i.y=n},o=e=>e&&i.now()-e.t<=300,r=!1;f(u,"mousedown",t=>{if(0===t.button){t.preventDefault();let[a,n]=e(t);A.emit("tap",a,n,0),l(0,a,n),r=!0}}),f(u,"mouseup",l=>{if(0===l.button){l.preventDefault();let a=t.get(0),[n,i]=e(l);o(a)&&A.emit("tapped",a.xi,a.yi,0),A.emit("untap",n,i,0),t.delete(0),r=!1}}),f(a,"mousemove",t=>{t.preventDefault();let[l,a]=e(t);A.def("MX",l),A.def("MY",a),r&&(A.emit("tapping",l,a,0),n(0,l,a))}),f(u,"touchstart",t=>{for(let a of(t.preventDefault(),t.changedTouches)){let[t,n]=e(a);A.emit("tap",t,n,a.identifier+1),l(a.identifier+1,t,n)}}),f(u,"touchmove",t=>{for(let l of(t.preventDefault(),t.changedTouches)){let[t,a]=e(l);A.emit("tapping",t,a,l.identifier+1),n(l.identifier+1,t,a)}});let s=e=>{e.preventDefault();let l=[];if(e.targetTouches.length>0)for(let t of e.targetTouches)l.push(t.identifier+1);for(let[e,a]of t)l.includes(e)||(o(a)&&A.emit("tapped",a.xi,a.yi,e),A.emit("untap",a.x,a.y,e),t.delete(e))};f(u,"touchend",s),f(u,"touchcancel",s),f(a,"blur",()=>{for(let[e,l]of(r=!1,t))A.emit("untap",l.x,l.y,e),t.delete(e)})}if(t.keyboardEvents){let e=new Set,t=new Set,l=(e,t="")=>(t=t.toLowerCase())?e.has("space"===t?" ":t):e.size>0,n="";f(a,"keydown",l=>{let a=l.key.toLowerCase();e.has(a)||(e.add(a),t.add(a),n=" "===a?"space":a)}),f(a,"keyup",t=>{e.delete(t.key.toLowerCase())}),f(a,"blur",()=>e.clear()),A.listen("after:update",()=>t.clear()),A.def("iskeydown",t=>l(e,t)),A.def("iskeypressed",e=>l(t,e)),A.def("lastkey",()=>n)}d=!0,A.resume(),A.emit("init",A)}),A}})();
1
+ (()=>{var e=["#211e20","#555568","#a0a08b","#e9efec"];window.litecanvas=function(t={}){let a,l,n=window,i=Math,o=performance,r=2*i.PI,s=requestAnimationFrame,f=[],c=(e,t,a)=>{e.addEventListener(t,a,!1),f.push(()=>e.removeEventListener(t,a,!1))},d=(a=new AudioContext,n.zzfxV=1,(e=1,t=.05,l=220,i=0,o=0,r=.1,s=0,f=1,c=0,d=0,u=0,p=0,h=0,m=0,g=0,w=0,v=0,x=1,y=0,b=0,k=0)=>{let E=Math,P=2*E.PI,T=c*=500*P/44100/44100,z=l*=(1-t+2*t*E.random(t=[]))*P/44100,C=0,I=0,L=0,D=1,A=0,S=0,H=0,M=k<0?-1:1,N=P*M*k*2/44100,W=E.cos(N),q=E.sin,B=q(N)/4,V=1+B,O=-2*W/V,R=(1-B)/V,F=(1+M*W)/2/V,G=-(M+W)/V,X=0,Y=0,$=0,j=0;for(i=44100*i+9,y*=44100,o*=44100,r*=44100,v*=44100,d*=500*P/85766121e6,g*=P/44100,u*=P/44100,p*=44100,h=44100*h|0,e*=.3*n.zzfxV,M=i+y+o+r+v|0;L<M;t[L++]=H*e)++S%(100*w|0)||(H=s?1<s?2<s?3<s?q(C*C):E.max(E.min(E.tan(C),1),-1):1-(2*C/P%2+2)%2:1-4*E.abs(E.round(C/P)-C/P):q(C),H=(h?1-b+b*q(P*L/h):1)*(H<0?-1:1)*E.abs(H)**f*(L<i?L/i:L<i+y?1-(L-i)/y*(1-x):L<i+y+o?x:L<M-v?(M-L-v)/r*x:0),H=v?H/2+(v>L?0:(L<M-v?1:(M-L)/v)*t[L-v|0]/2/e):H,k&&(H=j=F*X+G*(X=Y)+F*(Y=H)-R*$-O*($=j))),C+=(N=(l+=c+=d)*E.cos(g*I++))+N*m*q(L**5),D&&++D>p&&(l+=u,z+=u,D=0),!h||++A%h||(l=z,c=T,D=D||1);(e=a.createBuffer(1,M,44100)).getChannelData(0).set(t),(l=a.createBufferSource()).buffer=e,l.connect(a.destination),l.start()}),u=(t=Object.assign({width:null,height:null,autoscale:!0,canvas:null,global:!0,loop:null,tapEvents:!0,keyboardEvents:!0},t)).loop,p=!1,h,m,g=1,w,v=.5,x=1,y,b=1e3/60,k,E=0,P=3,T="sans-serif",z=20,C=1.2,I=Date.now(),L=e,D=[],A=[.5,0,1750,,,.3,1,,,,600,.1],S={},H={W:0,H:0,T:0,MX:-1,MY:-1,TWO_PI:r,HALF_PI:r/4,lerp:(e,t,a)=>e+a*(t-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,dist:(e,t,a,l)=>i.hypot(a-e,l-t),wrap:(e,t,a)=>e-(a-t)*i.floor((e-t)/(a-t)),map(e,t,a,l,n,i){let o=(e-t)/(a-t)*(n-l)+l;return i?H.clamp(o,l,n):o},norm:(e,t,a)=>H.map(e,t,a,0,1),rand:(e=0,t=1)=>(I=(1664525*I+0x3c6ef35f)%0x100000000)/0x100000000*(t-e)+e,randi:(e=0,t=1)=>~~H.rand(e,t+1),rseed(e){I=~~e},cls(e){null==e?w.clearRect(0,0,H.W,H.H):H.rectfill(0,0,H.W,H.H,e)},rect(e,t,a,l,n,i){w.beginPath(),w[i?"roundRect":"rect"](~~e-v,~~t-v,~~a+2*v,~~l+2*v,i),H.stroke(n)},rectfill(e,t,a,l,n,i){w.beginPath(),w[i?"roundRect":"rect"](~~e,~~t,~~a,~~l,i),H.fill(n)},circ(e,t,a,l){w.beginPath(),w.arc(~~e,~~t,~~a,0,r),H.stroke(l)},circfill(e,t,a,l){w.beginPath(),w.arc(~~e,~~t,~~a,0,r),H.fill(l)},oval(e,t,a,l,n){w.beginPath(),w.ellipse(~~e,~~t,~~a,~~l,0,0,r),H.stroke(n)},ovalfill(e,t,a,l,n){w.beginPath(),w.ellipse(~~e,~~t,~~a,~~l,0,0,r),H.fill(n)},shape(e){w.beginPath();for(let t=0;t<e.length;t+=2)0===t?w.moveTo(~~e[t],~~e[t+1]):w.lineTo(~~e[t],~~e[t+1]);w.lineTo(~~e[0],~~e[1])},line(e,t,a,l,n){w.beginPath();let i=.5*(0!==v&&~~e==~~a),o=.5*(0!==v&&~~t==~~l);w.moveTo(~~e+i,~~t+o),w.lineTo(~~a+i,~~l+o),H.stroke(n)},linewidth(e){w.lineWidth=~~e,v=.5*(0!=~~e%2)},linedash(e,t=0){w.setLineDash(e),w.lineDashOffset=t},text(e,t,a,l=P,n="normal"){w.font=`${n} ${z}px ${T}`,w.fillStyle=B(l);let i=(""+a).split("\n");for(let a=0;a<i.length;a++)w.fillText(i[a],~~e,~~t+z*C*a)},textgap(e){C=e},textfont(e){T=e},textsize(e){z=e},textalign(e,t){e&&(w.textAlign=e),t&&(w.textBaseline=t)},image(e,t,a){w.drawImage(a,~~e,~~t)},spr(e,t,a){let l=a.trim().split("\n");for(let a=0;a<l.length;a++){let n=l[a].trim();for(let l=0;l<n.length;l++){let i=n[l];"."!==i&&" "!==i&&H.rectfill(e+l,t+a,1,1,parseInt(i,36)||0)}}},paint(e,t,a,l={}){let n=l.canvas||new OffscreenCanvas(1,1),i=l.scale||1,o=w;return n.width=e*i,n.height=t*i,(w=n.getContext("2d")).scale(i,i),a(w),w=o,n.transferToImageBitmap()},ctx:e=>(e&&(w=e),w),push(){w.save()},pop(){w.restore()},translate(e,t){w.translate(~~e,~~t)},scale(e,t=e){w.scale(e,t)},rotate(e){w.rotate(e)},alpha(e){w.globalAlpha=H.clamp(e,0,1)},fill(e){w.fillStyle=B(e),w.fill()},stroke(e){w.strokeStyle=B(e),w.stroke()},clip(e){w.beginPath(),e(w),w.clip()},sfx:(e,t,a)=>!!n.zzfxV&&(!navigator.userActivation||!!navigator.userActivation.hasBeenActive)&&(e||=A,(t||a)&&((e=e.slice())[0]=(a||1)*(e[0]||1),e[10]=~~e[10]+t),d.apply(0,e),e),volume(e){n.zzfxV=e},canvas:()=>m,use(e,t={}){var a=e,l=t;let n=a(H,l);for(let e in n)H.def(e,n[e])},listen:(e,t)=>{S[e=e.toLowerCase()]=S[e]||new Set,S[e].add(t)},unlisten:(e,t)=>{S[e=e.toLowerCase()]&&S[e].delete(t)},emit:(e,t,a,l,i)=>(p&&(q("before:"+(e=e.toLowerCase()),t,a,l,i),u||n[e]===H[e]||"function"!=typeof n[e]||n[e](t,a,l,i),q(e,t,a,l,i),q("after:"+e,t,a,l,i)),t),pal(t,a=3){L=t||e,D=[],P=a,H.emit("pal",L,P)},palc(e,t){null==e?D=[]:D[e]=t},def(e,a){H[e]=a,t.global&&(n[e]=a)},timescale(e){x=e},framerate(e){b=1e3/~~e},stat:e=>[t,p,b/1e3,g,S,L,A,x,n.zzfxV,I,z,T,D,C][e],pause(){h||(h=!0,E=~~cancelAnimationFrame(E),H.emit("paused"))},resume(){p&&h&&(M(),h=!1,H.emit("resumed"))},ispaused:()=>h,quit(){for(let e of(H.emit("quit"),H.pause(),p=!1,S={},f))e();if(t.global){for(let e in H)delete n[e];delete n.ENGINE}}};for(let e of"PI,sin,cos,atan2,hypot,tan,abs,ceil,floor,trunc,min,max,pow,sqrt,sign,exp".split(","))H[e]=i[e];function M(){E||(k=0,y=o.now(),E=s(N))}function N(){E=s(N);let e=o.now(),t=0,a=e-y;for(y=e,k+=a<100?a:b;k>=b;){t++,k-=b;let e=b/1e3*x;H.emit("update",e,t),H.def("T",H.T+e)}t&&(H.emit("draw",w),t>1&&(k=0))}function W(){let e=t.width>0?t.width:innerWidth,a=t.width>0?t.height||t.width:innerHeight;if(H.def("W",e),H.def("H",a),m.width=e,m.height=a,t.autoscale){let l=+t.autoscale;m.style.display||(m.style.display="block",m.style.margin="auto"),g=i.min(innerWidth/e,innerHeight/a),g=l>1&&g>l?l:g,m.style.width=e*g+"px",m.style.height=a*g+"px"}w.imageSmoothingEnabled=!1,H.textalign("start","top"),H.emit("resized",g)}function q(e,t,a,l,n){if(S[e])for(let i of S[e])i(t,a,l,n)}function B(e){return L[~~(D[e]??e)%L.length]}if(t.global){if(n.ENGINE)throw Error("only one global litecanvas is allowed");Object.assign(n,H),n.ENGINE=H}if(l=document,w=(m=(m="string"==typeof t.canvas?l.querySelector(t.canvas):t.canvas)||l.createElement("canvas")).getContext("2d"),c(m,"click",()=>focus()),W(),m.parentNode||l.body.appendChild(m),m.style.imageRendering="pixelated",m.oncontextmenu=()=>!1,u)for(let e in u)u[e]&&H.listen(e,u[e]);return s(function(){if(t.autoscale&&c(n,"resize",W),t.tapEvents){let e=e=>[(e.pageX-m.offsetLeft)/g,(e.pageY-m.offsetTop)/g],t=new Map,a=(e,a,l)=>{let n={x:a,y:l,xi:a,yi:l,t:o.now()};return t.set(e,n),n},l=(e,l,n)=>{let i=t.get(e)||a(e);i.x=l,i.y=n},i=e=>e&&o.now()-e.t<=300,r=!1;c(m,"mousedown",t=>{if(0===t.button){t.preventDefault();let[l,n]=e(t);H.emit("tap",l,n,0),a(0,l,n),r=!0}}),c(m,"mouseup",a=>{if(0===a.button){a.preventDefault();let l=t.get(0),[n,o]=e(a);i(l)&&H.emit("tapped",l.xi,l.yi,0),H.emit("untap",n,o,0),t.delete(0),r=!1}}),c(n,"mousemove",t=>{t.preventDefault();let[a,n]=e(t);H.def("MX",a),H.def("MY",n),r&&(H.emit("tapping",a,n,0),l(0,a,n))}),c(m,"touchstart",t=>{for(let l of(t.preventDefault(),t.changedTouches)){let[t,n]=e(l);H.emit("tap",t,n,l.identifier+1),a(l.identifier+1,t,n)}}),c(m,"touchmove",t=>{for(let a of(t.preventDefault(),t.changedTouches)){let[t,n]=e(a);H.emit("tapping",t,n,a.identifier+1),l(a.identifier+1,t,n)}});let s=e=>{e.preventDefault();let a=[];if(e.targetTouches.length>0)for(let t of e.targetTouches)a.push(t.identifier+1);for(let[e,l]of t)a.includes(e)||(i(l)&&H.emit("tapped",l.xi,l.yi,e),H.emit("untap",l.x,l.y,e),t.delete(e))};c(m,"touchend",s),c(m,"touchcancel",s),c(n,"blur",()=>{for(let[e,a]of(r=!1,t))H.emit("untap",a.x,a.y,e),t.delete(e)})}if(t.keyboardEvents){let e=new Set,t=new Set,a=(e,t="")=>(t=t.toLowerCase())?e.has("space"===t?" ":t):e.size>0,l="";c(n,"keydown",a=>{let n=a.key.toLowerCase();e.has(n)||(e.add(n),t.add(n),l=" "===n?"space":n)}),c(n,"keyup",t=>{e.delete(t.key.toLowerCase())}),c(n,"blur",()=>e.clear()),H.listen("after:update",()=>t.clear()),H.def("iskeydown",t=>a(e,t)),H.def("iskeypressed",e=>a(t,e)),H.def("lastkey",()=>l)}p=!0,H.emit("init",H),h||M()}),H}})();
package/package.json CHANGED
@@ -1,11 +1,11 @@
1
1
  {
2
2
  "name": "litecanvas",
3
- "version": "0.205.0",
3
+ "version": "0.206.1",
4
4
  "description": "Lightweight HTML5 canvas 2D game engine suitable for small projects and creative coding. Inspired by PICO-8 and p5.js/Processing.",
5
5
  "license": "MIT",
6
6
  "author": "Luiz Bills <luizbills@pm.me>",
7
7
  "contributors": [],
8
- "homepage": "https://litecanvas.github.io",
8
+ "homepage": "https://litecanvas.js.org",
9
9
  "repository": {
10
10
  "type": "git",
11
11
  "url": "git+https://github.com/litecanvas/game-engine.git"
@@ -34,9 +34,9 @@
34
34
  "devDependencies": {
35
35
  "@happy-dom/global-registrator": "^20.9.0",
36
36
  "@size-limit/preset-small-lib": "^12.1.0",
37
- "@swc/core": "^1.15.30",
37
+ "@swc/core": "^1.15.33",
38
38
  "ava": "^7.0.0",
39
- "esbuild": "^0.27.7",
39
+ "esbuild": "^0.28.0",
40
40
  "genversion": "^3.2.0",
41
41
  "gzip-size": "^7.0.0",
42
42
  "prettier": "^3.8.3",
package/src/index.js CHANGED
@@ -11,8 +11,7 @@ import { version } from './version.js'
11
11
  * @returns {LitecanvasInstance}
12
12
  */
13
13
  export default function litecanvas(settings = {}) {
14
- const /** @type {Window} */
15
- root = window,
14
+ const root = window,
16
15
  math = Math,
17
16
  perf = performance,
18
17
  TWO_PI = math.PI * 2,
@@ -48,10 +47,11 @@ export default function litecanvas(settings = {}) {
48
47
  // setup the settings default values
49
48
  settings = Object.assign(defaults, settings)
50
49
 
51
- let /** @type {boolean} */
50
+ let _loop = settings.loop,
51
+ /** @type {boolean} */
52
52
  _initialized = false,
53
53
  /** @type {boolean} */
54
- _paused = true,
54
+ _paused,
55
55
  /** @type {HTMLCanvasElement} _canvas */
56
56
  _canvas,
57
57
  /** @type {number} */
@@ -68,8 +68,8 @@ export default function litecanvas(settings = {}) {
68
68
  _fpsInterval = 1000 / 60,
69
69
  /** @type {number} */
70
70
  _accumulated,
71
- /** @type {number?} */
72
- _rafid,
71
+ /** @type {number} */
72
+ _rafid = 0,
73
73
  /** @type {number} */
74
74
  _defaultTextColor = 3,
75
75
  /** @type {string} */
@@ -86,9 +86,6 @@ export default function litecanvas(settings = {}) {
86
86
  _colorPaletteState = [],
87
87
  /** @type {number[]} */
88
88
  _defaultSound = [0.5, 0, 1750, , , 0.3, 1, , , , 600, 0.1],
89
- /** @type {string} list of functions copied from `Math` module */
90
- _mathFunctions =
91
- 'PI,sin,cos,atan2,hypot,tan,abs,ceil,floor,trunc,min,max,pow,sqrt,sign,exp',
92
89
  /**
93
90
  * @type {Object<string,Set<Function>>} game event listeners
94
91
  */
@@ -1008,13 +1005,19 @@ export default function litecanvas(settings = {}) {
1008
1005
  *
1009
1006
  * @see https://github.com/KilledByAPixel/ZzFX
1010
1007
  */
1011
- sfx(zzfxParams, pitchSlide = 0, volumeFactor = 1) {
1008
+ sfx(zzfxParams, pitchSlide, volumeFactor) {
1012
1009
  DEV: assert(
1013
1010
  null == zzfxParams || Array.isArray(zzfxParams),
1014
1011
  loggerPrefix + 'sfx() 1st param must be an array'
1015
1012
  )
1016
- DEV: assert(isNumber(pitchSlide), loggerPrefix + 'sfx() 2nd param must be a number')
1017
- DEV: assert(isNumber(volumeFactor), loggerPrefix + 'sfx() 3rd param must be a number')
1013
+ DEV: assert(
1014
+ null == pitchSlide || isNumber(pitchSlide),
1015
+ loggerPrefix + 'sfx() 2nd param must be a number'
1016
+ )
1017
+ DEV: assert(
1018
+ null == volumeFactor || isNumber(volumeFactor),
1019
+ loggerPrefix + 'sfx() 3rd param must be a number'
1020
+ )
1018
1021
 
1019
1022
  if (
1020
1023
  !root.zzfxV ||
@@ -1023,12 +1026,12 @@ export default function litecanvas(settings = {}) {
1023
1026
  return false
1024
1027
  }
1025
1028
 
1026
- zzfxParams = zzfxParams || _defaultSound
1029
+ zzfxParams ||= _defaultSound
1027
1030
 
1028
1031
  // if has other arguments, copy the sound to not change the original
1029
- if (pitchSlide !== 0 || volumeFactor !== 1) {
1032
+ if (pitchSlide || volumeFactor) {
1030
1033
  zzfxParams = zzfxParams.slice()
1031
- zzfxParams[0] = volumeFactor * (zzfxParams[0] || 1)
1034
+ zzfxParams[0] = (volumeFactor || 1) * (zzfxParams[0] || 1)
1032
1035
  zzfxParams[10] = ~~zzfxParams[10] + pitchSlide
1033
1036
  }
1034
1037
 
@@ -1153,7 +1156,7 @@ export default function litecanvas(settings = {}) {
1153
1156
  // calls a global function with the same name as the event,
1154
1157
  // as long as it's not a global litecanvas function (to avoid infinite loops)
1155
1158
  if (
1156
- !settings.loop &&
1159
+ !_loop &&
1157
1160
  root[eventName] !== instance[eventName] &&
1158
1161
  'function' === typeof root[eventName] /* if is a function */
1159
1162
  ) {
@@ -1343,7 +1346,7 @@ export default function litecanvas(settings = {}) {
1343
1346
  pause() {
1344
1347
  if (!_paused) {
1345
1348
  _paused = true
1346
- cancelAnimationFrame(_rafid)
1349
+ _rafid = ~~cancelAnimationFrame(_rafid)
1347
1350
  instance.emit('paused')
1348
1351
  }
1349
1352
  },
@@ -1358,10 +1361,8 @@ export default function litecanvas(settings = {}) {
1358
1361
  'resume() cannot be called before the "init" event and neither after the quit() function'
1359
1362
  )
1360
1363
  if (_initialized && _paused) {
1364
+ startGameLoop()
1361
1365
  _paused = false
1362
- _accumulated = _fpsInterval
1363
- _lastFrameTime = perf.now()
1364
- _rafid = raf(drawFrame)
1365
1366
  instance.emit('resumed')
1366
1367
  }
1367
1368
  },
@@ -1409,11 +1410,20 @@ export default function litecanvas(settings = {}) {
1409
1410
  }
1410
1411
 
1411
1412
  // prettier-ignore
1412
- for (const k of _mathFunctions.split(',')) {
1413
+ const mathProps = 'PI,sin,cos,atan2,hypot,tan,abs,ceil,floor,trunc,min,max,pow,sqrt,sign,exp'
1414
+ for (const k of mathProps.split(',')) {
1413
1415
  // import native Math functions
1414
1416
  instance[k] = math[k]
1415
1417
  }
1416
1418
 
1419
+ function startGameLoop() {
1420
+ if (!_rafid) {
1421
+ _accumulated = 0
1422
+ _lastFrameTime = perf.now()
1423
+ _rafid = raf(drawFrame)
1424
+ }
1425
+ }
1426
+
1417
1427
  function init() {
1418
1428
  // listen window resize event when "autoscale" is enabled
1419
1429
  if (settings.autoscale) {
@@ -1600,6 +1610,7 @@ export default function litecanvas(settings = {}) {
1600
1610
  })
1601
1611
  }
1602
1612
 
1613
+ // default keyboard handler
1603
1614
  if (settings.keyboardEvents) {
1604
1615
  /** @type {Set<string>} */
1605
1616
  const _keysDown = new Set()
@@ -1677,8 +1688,10 @@ export default function litecanvas(settings = {}) {
1677
1688
 
1678
1689
  // start the engine
1679
1690
  _initialized = true
1680
- instance.resume()
1681
1691
  instance.emit('init', instance)
1692
+ if (!_paused) {
1693
+ startGameLoop()
1694
+ }
1682
1695
  }
1683
1696
 
1684
1697
  function drawFrame() {
@@ -1703,22 +1716,24 @@ export default function litecanvas(settings = {}) {
1703
1716
  }
1704
1717
 
1705
1718
  if (updated) {
1719
+ // draws only when an update happens.
1706
1720
  instance.emit('draw', _ctx)
1721
+
1722
+ // sometimes the FPS locks at a value below 60
1723
+ // and does not go back up, even with a very simple logic.
1724
+ // One solution I found was to reset the variable that
1725
+ // accumulates time between frames, when multiple updates occur.
1707
1726
  if (updated > 1) {
1708
1727
  _accumulated = 0
1709
- DEV: console.warn(
1710
- loggerPrefix +
1711
- 'the last frame updated ' +
1712
- updated +
1713
- ' times. This can drop the FPS if it keeps happening.'
1714
- )
1715
1728
  }
1716
1729
  }
1717
1730
  }
1718
1731
 
1719
1732
  function setupCanvas() {
1733
+ const d = document
1734
+
1720
1735
  if ('string' === typeof settings.canvas) {
1721
- _canvas = document.querySelector(settings.canvas)
1736
+ _canvas = d.querySelector(settings.canvas)
1722
1737
  DEV: assert(
1723
1738
  null != _canvas,
1724
1739
  loggerPrefix + 'litecanvas() option "canvas" is an invalid CSS selector'
@@ -1727,7 +1742,7 @@ export default function litecanvas(settings = {}) {
1727
1742
  _canvas = settings.canvas
1728
1743
  }
1729
1744
 
1730
- _canvas = _canvas || document.createElement('canvas')
1745
+ _canvas = _canvas || d.createElement('canvas')
1731
1746
 
1732
1747
  DEV: assert(
1733
1748
  _canvas instanceof HTMLElement && 'CANVAS' === _canvas.tagName,
@@ -1742,7 +1757,7 @@ export default function litecanvas(settings = {}) {
1742
1757
  resizeCanvas()
1743
1758
 
1744
1759
  if (!_canvas.parentNode) {
1745
- document.body.appendChild(_canvas)
1760
+ d.body.appendChild(_canvas)
1746
1761
  }
1747
1762
 
1748
1763
  _canvas.style.imageRendering = 'pixelated'
@@ -1856,14 +1871,14 @@ export default function litecanvas(settings = {}) {
1856
1871
  setupCanvas()
1857
1872
 
1858
1873
  // setup default event listeners
1859
- if (settings.loop) {
1860
- for (const eventName in settings.loop) {
1861
- if (settings.loop[eventName]) instance.listen(eventName, settings.loop[eventName])
1874
+ if (_loop) {
1875
+ for (const eventName in _loop) {
1876
+ if (_loop[eventName]) instance.listen(eventName, _loop[eventName])
1862
1877
  }
1863
1878
  }
1864
1879
 
1865
1880
  // init the engine (async)
1866
- _rafid = raf(init)
1881
+ raf(init)
1867
1882
 
1868
1883
  return instance
1869
1884
  }
package/src/version.js CHANGED
@@ -1,2 +1,2 @@
1
1
  // Generated by genversion.
2
- export const version = '0.205.0'
2
+ export const version = '0.206.1'