litecanvas 0.204.0 → 0.206.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 +30 -23
- package/dist/dist.js +29 -16
- package/dist/dist.min.js +1 -1
- package/package.json +3 -3
- package/src/index.js +44 -25
- package/src/version.js +1 -1
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.
|
|
118
|
+
var version = "0.206.0";
|
|
119
119
|
function litecanvas(settings = {}) {
|
|
120
120
|
const root = window,
|
|
121
121
|
math = Math,
|
|
@@ -147,7 +147,7 @@
|
|
|
147
147
|
};
|
|
148
148
|
settings = Object.assign(defaults, settings);
|
|
149
149
|
let _initialized = false,
|
|
150
|
-
_paused
|
|
150
|
+
_paused,
|
|
151
151
|
_canvas,
|
|
152
152
|
_canvasScale = 1,
|
|
153
153
|
_ctx,
|
|
@@ -156,7 +156,7 @@
|
|
|
156
156
|
_lastFrameTime,
|
|
157
157
|
_fpsInterval = 1e3 / 60,
|
|
158
158
|
_accumulated,
|
|
159
|
-
_rafid,
|
|
159
|
+
_rafid = 0,
|
|
160
160
|
_defaultTextColor = 3,
|
|
161
161
|
_fontFamily = "sans-serif",
|
|
162
162
|
_fontSize = 20,
|
|
@@ -165,8 +165,6 @@
|
|
|
165
165
|
_colorPalette = defaultPalette,
|
|
166
166
|
_colorPaletteState = [],
|
|
167
167
|
_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
168
|
_eventListeners = {};
|
|
171
169
|
const instance = {
|
|
172
170
|
W: 0,
|
|
@@ -929,7 +927,11 @@
|
|
|
929
927
|
if (_initialized) {
|
|
930
928
|
eventName = lowerCase(eventName);
|
|
931
929
|
triggerEvent("before:" + eventName, arg1, arg2, arg3, arg4);
|
|
932
|
-
if (
|
|
930
|
+
if (
|
|
931
|
+
!settings.loop &&
|
|
932
|
+
root[eventName] !== instance[eventName] &&
|
|
933
|
+
"function" === typeof root[eventName]
|
|
934
|
+
) {
|
|
933
935
|
root[eventName](arg1, arg2, arg3, arg4);
|
|
934
936
|
}
|
|
935
937
|
triggerEvent(eventName, arg1, arg2, arg3, arg4);
|
|
@@ -949,6 +951,7 @@
|
|
|
949
951
|
_colorPalette = colors || defaultPalette;
|
|
950
952
|
_colorPaletteState = [];
|
|
951
953
|
_defaultTextColor = textColor;
|
|
954
|
+
instance.emit("pal", _colorPalette, _defaultTextColor);
|
|
952
955
|
},
|
|
953
956
|
palc(a, b) {
|
|
954
957
|
DEV: assert(
|
|
@@ -1028,7 +1031,7 @@
|
|
|
1028
1031
|
pause() {
|
|
1029
1032
|
if (!_paused) {
|
|
1030
1033
|
_paused = true;
|
|
1031
|
-
cancelAnimationFrame(_rafid);
|
|
1034
|
+
_rafid = ~~cancelAnimationFrame(_rafid);
|
|
1032
1035
|
instance.emit("paused");
|
|
1033
1036
|
}
|
|
1034
1037
|
},
|
|
@@ -1039,10 +1042,8 @@
|
|
|
1039
1042
|
'resume() cannot be called before the "init" event and neither after the quit() function',
|
|
1040
1043
|
);
|
|
1041
1044
|
if (_initialized && _paused) {
|
|
1045
|
+
startGameLoop();
|
|
1042
1046
|
_paused = false;
|
|
1043
|
-
_accumulated = _fpsInterval;
|
|
1044
|
-
_lastFrameTime = perf.now();
|
|
1045
|
-
_rafid = raf(drawFrame);
|
|
1046
1047
|
instance.emit("resumed");
|
|
1047
1048
|
}
|
|
1048
1049
|
},
|
|
@@ -1050,7 +1051,7 @@
|
|
|
1050
1051
|
return _paused;
|
|
1051
1052
|
},
|
|
1052
1053
|
quit() {
|
|
1053
|
-
instance.emit("
|
|
1054
|
+
instance.emit("quit");
|
|
1054
1055
|
instance.pause();
|
|
1055
1056
|
_initialized = false;
|
|
1056
1057
|
_eventListeners = {};
|
|
@@ -1068,9 +1069,18 @@
|
|
|
1068
1069
|
);
|
|
1069
1070
|
},
|
|
1070
1071
|
};
|
|
1071
|
-
|
|
1072
|
+
const mathProps =
|
|
1073
|
+
"PI,sin,cos,atan2,hypot,tan,abs,ceil,floor,trunc,min,max,pow,sqrt,sign,exp";
|
|
1074
|
+
for (const k of mathProps.split(",")) {
|
|
1072
1075
|
instance[k] = math[k];
|
|
1073
1076
|
}
|
|
1077
|
+
function startGameLoop() {
|
|
1078
|
+
if (!_rafid) {
|
|
1079
|
+
_accumulated = 0;
|
|
1080
|
+
_lastFrameTime = perf.now();
|
|
1081
|
+
_rafid = raf(drawFrame);
|
|
1082
|
+
}
|
|
1083
|
+
}
|
|
1074
1084
|
function init() {
|
|
1075
1085
|
if (settings.autoscale) {
|
|
1076
1086
|
on(root, "resize", resizeCanvas);
|
|
@@ -1211,8 +1221,10 @@
|
|
|
1211
1221
|
instance.def("lastkey", () => _lastKey);
|
|
1212
1222
|
}
|
|
1213
1223
|
_initialized = true;
|
|
1214
|
-
instance.resume();
|
|
1215
1224
|
instance.emit("init", instance);
|
|
1225
|
+
if (!_paused) {
|
|
1226
|
+
startGameLoop();
|
|
1227
|
+
}
|
|
1216
1228
|
}
|
|
1217
1229
|
function drawFrame() {
|
|
1218
1230
|
_rafid = raf(drawFrame);
|
|
@@ -1232,18 +1244,13 @@
|
|
|
1232
1244
|
instance.emit("draw", _ctx);
|
|
1233
1245
|
if (updated > 1) {
|
|
1234
1246
|
_accumulated = 0;
|
|
1235
|
-
DEV: console.warn(
|
|
1236
|
-
loggerPrefix +
|
|
1237
|
-
"the last frame updated " +
|
|
1238
|
-
updated +
|
|
1239
|
-
" times. This can drop the FPS if it keeps happening.",
|
|
1240
|
-
);
|
|
1241
1247
|
}
|
|
1242
1248
|
}
|
|
1243
1249
|
}
|
|
1244
1250
|
function setupCanvas() {
|
|
1251
|
+
const d = document;
|
|
1245
1252
|
if ("string" === typeof settings.canvas) {
|
|
1246
|
-
_canvas =
|
|
1253
|
+
_canvas = d.querySelector(settings.canvas);
|
|
1247
1254
|
DEV: assert(
|
|
1248
1255
|
null != _canvas,
|
|
1249
1256
|
loggerPrefix +
|
|
@@ -1252,7 +1259,7 @@
|
|
|
1252
1259
|
} else {
|
|
1253
1260
|
_canvas = settings.canvas;
|
|
1254
1261
|
}
|
|
1255
|
-
_canvas = _canvas ||
|
|
1262
|
+
_canvas = _canvas || d.createElement("canvas");
|
|
1256
1263
|
DEV: assert(
|
|
1257
1264
|
_canvas instanceof HTMLElement && "CANVAS" === _canvas.tagName,
|
|
1258
1265
|
loggerPrefix +
|
|
@@ -1262,7 +1269,7 @@
|
|
|
1262
1269
|
on(_canvas, "click", () => focus());
|
|
1263
1270
|
resizeCanvas();
|
|
1264
1271
|
if (!_canvas.parentNode) {
|
|
1265
|
-
|
|
1272
|
+
d.body.appendChild(_canvas);
|
|
1266
1273
|
}
|
|
1267
1274
|
_canvas.style.imageRendering = "pixelated";
|
|
1268
1275
|
_canvas.oncontextmenu = () => false;
|
|
@@ -1346,7 +1353,7 @@
|
|
|
1346
1353
|
instance.listen(eventName, settings.loop[eventName]);
|
|
1347
1354
|
}
|
|
1348
1355
|
}
|
|
1349
|
-
|
|
1356
|
+
raf(init);
|
|
1350
1357
|
return instance;
|
|
1351
1358
|
}
|
|
1352
1359
|
window.litecanvas = litecanvas;
|
package/dist/dist.js
CHANGED
|
@@ -143,7 +143,7 @@
|
|
|
143
143
|
};
|
|
144
144
|
settings = Object.assign(defaults, settings);
|
|
145
145
|
let _initialized = false,
|
|
146
|
-
_paused
|
|
146
|
+
_paused,
|
|
147
147
|
_canvas,
|
|
148
148
|
_canvasScale = 1,
|
|
149
149
|
_ctx,
|
|
@@ -152,7 +152,7 @@
|
|
|
152
152
|
_lastFrameTime,
|
|
153
153
|
_fpsInterval = 1e3 / 60,
|
|
154
154
|
_accumulated,
|
|
155
|
-
_rafid,
|
|
155
|
+
_rafid = 0,
|
|
156
156
|
_defaultTextColor = 3,
|
|
157
157
|
_fontFamily = "sans-serif",
|
|
158
158
|
_fontSize = 20,
|
|
@@ -161,8 +161,6 @@
|
|
|
161
161
|
_colorPalette = defaultPalette,
|
|
162
162
|
_colorPaletteState = [],
|
|
163
163
|
_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
164
|
_eventListeners = {};
|
|
167
165
|
const instance = {
|
|
168
166
|
W: 0,
|
|
@@ -423,7 +421,11 @@
|
|
|
423
421
|
if (_initialized) {
|
|
424
422
|
eventName = lowerCase(eventName);
|
|
425
423
|
triggerEvent("before:" + eventName, arg1, arg2, arg3, arg4);
|
|
426
|
-
if (
|
|
424
|
+
if (
|
|
425
|
+
!settings.loop &&
|
|
426
|
+
root[eventName] !== instance[eventName] &&
|
|
427
|
+
"function" === typeof root[eventName]
|
|
428
|
+
) {
|
|
427
429
|
root[eventName](arg1, arg2, arg3, arg4);
|
|
428
430
|
}
|
|
429
431
|
triggerEvent(eventName, arg1, arg2, arg3, arg4);
|
|
@@ -435,6 +437,7 @@
|
|
|
435
437
|
_colorPalette = colors || defaultPalette;
|
|
436
438
|
_colorPaletteState = [];
|
|
437
439
|
_defaultTextColor = textColor;
|
|
440
|
+
instance.emit("pal", _colorPalette, _defaultTextColor);
|
|
438
441
|
},
|
|
439
442
|
palc(a, b) {
|
|
440
443
|
if (a == null) {
|
|
@@ -477,16 +480,14 @@
|
|
|
477
480
|
pause() {
|
|
478
481
|
if (!_paused) {
|
|
479
482
|
_paused = true;
|
|
480
|
-
cancelAnimationFrame(_rafid);
|
|
483
|
+
_rafid = ~~cancelAnimationFrame(_rafid);
|
|
481
484
|
instance.emit("paused");
|
|
482
485
|
}
|
|
483
486
|
},
|
|
484
487
|
resume() {
|
|
485
488
|
if (_initialized && _paused) {
|
|
489
|
+
startGameLoop();
|
|
486
490
|
_paused = false;
|
|
487
|
-
_accumulated = _fpsInterval;
|
|
488
|
-
_lastFrameTime = perf.now();
|
|
489
|
-
_rafid = raf(drawFrame);
|
|
490
491
|
instance.emit("resumed");
|
|
491
492
|
}
|
|
492
493
|
},
|
|
@@ -494,7 +495,7 @@
|
|
|
494
495
|
return _paused;
|
|
495
496
|
},
|
|
496
497
|
quit() {
|
|
497
|
-
instance.emit("
|
|
498
|
+
instance.emit("quit");
|
|
498
499
|
instance.pause();
|
|
499
500
|
_initialized = false;
|
|
500
501
|
_eventListeners = {};
|
|
@@ -509,9 +510,18 @@
|
|
|
509
510
|
}
|
|
510
511
|
},
|
|
511
512
|
};
|
|
512
|
-
|
|
513
|
+
const mathProps =
|
|
514
|
+
"PI,sin,cos,atan2,hypot,tan,abs,ceil,floor,trunc,min,max,pow,sqrt,sign,exp";
|
|
515
|
+
for (const k of mathProps.split(",")) {
|
|
513
516
|
instance[k] = math[k];
|
|
514
517
|
}
|
|
518
|
+
function startGameLoop() {
|
|
519
|
+
if (!_rafid) {
|
|
520
|
+
_accumulated = 0;
|
|
521
|
+
_lastFrameTime = perf.now();
|
|
522
|
+
_rafid = raf(drawFrame);
|
|
523
|
+
}
|
|
524
|
+
}
|
|
515
525
|
function init() {
|
|
516
526
|
if (settings.autoscale) {
|
|
517
527
|
on(root, "resize", resizeCanvas);
|
|
@@ -642,8 +652,10 @@
|
|
|
642
652
|
instance.def("lastkey", () => _lastKey);
|
|
643
653
|
}
|
|
644
654
|
_initialized = true;
|
|
645
|
-
instance.resume();
|
|
646
655
|
instance.emit("init", instance);
|
|
656
|
+
if (!_paused) {
|
|
657
|
+
startGameLoop();
|
|
658
|
+
}
|
|
647
659
|
}
|
|
648
660
|
function drawFrame() {
|
|
649
661
|
_rafid = raf(drawFrame);
|
|
@@ -667,17 +679,18 @@
|
|
|
667
679
|
}
|
|
668
680
|
}
|
|
669
681
|
function setupCanvas() {
|
|
682
|
+
const d = document;
|
|
670
683
|
if ("string" === typeof settings.canvas) {
|
|
671
|
-
_canvas =
|
|
684
|
+
_canvas = d.querySelector(settings.canvas);
|
|
672
685
|
} else {
|
|
673
686
|
_canvas = settings.canvas;
|
|
674
687
|
}
|
|
675
|
-
_canvas = _canvas ||
|
|
688
|
+
_canvas = _canvas || d.createElement("canvas");
|
|
676
689
|
_ctx = _canvas.getContext("2d");
|
|
677
690
|
on(_canvas, "click", () => focus());
|
|
678
691
|
resizeCanvas();
|
|
679
692
|
if (!_canvas.parentNode) {
|
|
680
|
-
|
|
693
|
+
d.body.appendChild(_canvas);
|
|
681
694
|
}
|
|
682
695
|
_canvas.style.imageRendering = "pixelated";
|
|
683
696
|
_canvas.oncontextmenu = () => false;
|
|
@@ -737,7 +750,7 @@
|
|
|
737
750
|
instance.listen(eventName, settings.loop[eventName]);
|
|
738
751
|
}
|
|
739
752
|
}
|
|
740
|
-
|
|
753
|
+
raf(init);
|
|
741
754
|
return instance;
|
|
742
755
|
}
|
|
743
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,
|
|
1
|
+
(()=>{var e=["#211e20","#555568","#a0a08b","#e9efec"];window.litecanvas=function(t={}){let l,a,n=window,i=Math,o=performance,r=2*i.PI,s=requestAnimationFrame,f=[],c=(e,t,l)=>{e.addEventListener(t,l,!1),f.push(()=>e.removeEventListener(t,l,!1))},d=(l=new AudioContext,n.zzfxV=1,(e=1,t=.05,a=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=a*=(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*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=(a+=c+=d)*E.cos(g*I++))+N*m*q(L**5),D&&++D>u&&(a+=p,z+=p,D=0),!h||++A%h||(a=z,c=T,D=D||1);(e=l.createBuffer(1,M,44100)).getChannelData(0).set(t),(a=l.createBufferSource()).buffer=e,a.connect(l.destination),a.start()});t=Object.assign({width:null,height:null,autoscale:!0,canvas:null,global:!0,loop:null,tapEvents:!0,keyboardEvents:!0},t);let p=!1,u,h,m=1,g,w=.5,v=1,x,y=1e3/60,b,k=0,E=3,P="sans-serif",T=20,z=1.2,C=Date.now(),I=e,L=[],D=[.5,0,1750,,,.3,1,,,,600,.1],A={},S={W:0,H:0,T:0,MX:-1,MY:-1,TWO_PI:r,HALF_PI:r/4,lerp:(e,t,l)=>e+l*(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 l=10**t;return i.round(e*l)/l},clamp:(e,t,l)=>e<t?t:e>l?l:e,dist:(e,t,l,a)=>i.hypot(l-e,a-t),wrap:(e,t,l)=>e-(l-t)*i.floor((e-t)/(l-t)),map(e,t,l,a,n,i){let o=(e-t)/(l-t)*(n-a)+a;return i?S.clamp(o,a,n):o},norm:(e,t,l)=>S.map(e,t,l,0,1),rand:(e=0,t=1)=>(C=(1664525*C+0x3c6ef35f)%0x100000000)/0x100000000*(t-e)+e,randi:(e=0,t=1)=>~~S.rand(e,t+1),rseed(e){C=~~e},cls(e){null==e?g.clearRect(0,0,S.W,S.H):S.rectfill(0,0,S.W,S.H,e)},rect(e,t,l,a,n,i){g.beginPath(),g[i?"roundRect":"rect"](~~e-w,~~t-w,~~l+2*w,~~a+2*w,i),S.stroke(n)},rectfill(e,t,l,a,n,i){g.beginPath(),g[i?"roundRect":"rect"](~~e,~~t,~~l,~~a,i),S.fill(n)},circ(e,t,l,a){g.beginPath(),g.arc(~~e,~~t,~~l,0,r),S.stroke(a)},circfill(e,t,l,a){g.beginPath(),g.arc(~~e,~~t,~~l,0,r),S.fill(a)},oval(e,t,l,a,n){g.beginPath(),g.ellipse(~~e,~~t,~~l,~~a,0,0,r),S.stroke(n)},ovalfill(e,t,l,a,n){g.beginPath(),g.ellipse(~~e,~~t,~~l,~~a,0,0,r),S.fill(n)},shape(e){g.beginPath();for(let t=0;t<e.length;t+=2)0===t?g.moveTo(~~e[t],~~e[t+1]):g.lineTo(~~e[t],~~e[t+1]);g.lineTo(~~e[0],~~e[1])},line(e,t,l,a,n){g.beginPath();let i=.5*(0!==w&&~~e==~~l),o=.5*(0!==w&&~~t==~~a);g.moveTo(~~e+i,~~t+o),g.lineTo(~~l+i,~~a+o),S.stroke(n)},linewidth(e){g.lineWidth=~~e,w=.5*(0!=~~e%2)},linedash(e,t=0){g.setLineDash(e),g.lineDashOffset=t},text(e,t,l,a=E,n="normal"){g.font=`${n} ${T}px ${P}`,g.fillStyle=q(a);let i=(""+l).split("\n");for(let l=0;l<i.length;l++)g.fillText(i[l],~~e,~~t+T*z*l)},textgap(e){z=e},textfont(e){P=e},textsize(e){T=e},textalign(e,t){e&&(g.textAlign=e),t&&(g.textBaseline=t)},image(e,t,l){g.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&&S.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=g;return n.width=e*i,n.height=t*i,(g=n.getContext("2d")).scale(i,i),l(g),g=o,n.transferToImageBitmap()},ctx:e=>(e&&(g=e),g),push(){g.save()},pop(){g.restore()},translate(e,t){g.translate(~~e,~~t)},scale(e,t=e){g.scale(e,t)},rotate(e){g.rotate(e)},alpha(e){g.globalAlpha=S.clamp(e,0,1)},fill(e){g.fillStyle=q(e),g.fill()},stroke(e){g.strokeStyle=q(e),g.stroke()},clip(e){g.beginPath(),e(g),g.clip()},sfx:(e,t=0,l=1)=>!!n.zzfxV&&(!navigator.userActivation||!!navigator.userActivation.hasBeenActive)&&(e=e||D,(0!==t||1!==l)&&((e=e.slice())[0]=l*(e[0]||1),e[10]=~~e[10]+t),d.apply(0,e),e),volume(e){n.zzfxV=e},canvas:()=>h,use(e,t={}){var l=e,a=t;let n=l(S,a);for(let e in n)S.def(e,n[e])},listen:(e,t)=>{A[e=e.toLowerCase()]=A[e]||new Set,A[e].add(t)},unlisten:(e,t)=>{A[e=e.toLowerCase()]&&A[e].delete(t)},emit:(e,l,a,i,o)=>(p&&(W("before:"+(e=e.toLowerCase()),l,a,i,o),t.loop||n[e]===S[e]||"function"!=typeof n[e]||n[e](l,a,i,o),W(e,l,a,i,o),W("after:"+e,l,a,i,o)),l),pal(t,l=3){I=t||e,L=[],E=l,S.emit("pal",I,E)},palc(e,t){null==e?L=[]:L[e]=t},def(e,l){S[e]=l,t.global&&(n[e]=l)},timescale(e){v=e},framerate(e){y=1e3/~~e},stat:e=>[t,p,y/1e3,m,A,I,D,v,n.zzfxV,C,T,P,L,z][e],pause(){u||(u=!0,k=~~cancelAnimationFrame(k),S.emit("paused"))},resume(){p&&u&&(H(),u=!1,S.emit("resumed"))},ispaused:()=>u,quit(){for(let e of(S.emit("quit"),S.pause(),p=!1,A={},f))e();if(t.global){for(let e in S)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(","))S[e]=i[e];function H(){k||(b=0,x=o.now(),k=s(M))}function M(){k=s(M);let e=o.now(),t=0,l=e-x;for(x=e,b+=l<100?l:y;b>=y;){t++,b-=y;let e=y/1e3*v;S.emit("update",e,t),S.def("T",S.T+e)}t&&(S.emit("draw",g),t>1&&(b=0))}function N(){let e=t.width>0?t.width:innerWidth,l=t.width>0?t.height||t.width:innerHeight;if(S.def("W",e),S.def("H",l),h.width=e,h.height=l,t.autoscale){let a=+t.autoscale;h.style.display||(h.style.display="block",h.style.margin="auto"),m=i.min(innerWidth/e,innerHeight/l),m=a>1&&m>a?a:m,h.style.width=e*m+"px",h.style.height=l*m+"px"}g.imageSmoothingEnabled=!1,S.textalign("start","top"),S.emit("resized",m)}function W(e,t,l,a,n){if(A[e])for(let i of A[e])i(t,l,a,n)}function q(e){return I[~~(L[e]??e)%I.length]}if(t.global){if(n.ENGINE)throw Error("only one global litecanvas is allowed");Object.assign(n,S),n.ENGINE=S}if(a=document,g=(h=(h="string"==typeof t.canvas?a.querySelector(t.canvas):t.canvas)||a.createElement("canvas")).getContext("2d"),c(h,"click",()=>focus()),N(),h.parentNode||a.body.appendChild(h),h.style.imageRendering="pixelated",h.oncontextmenu=()=>!1,t.loop)for(let e in t.loop)t.loop[e]&&S.listen(e,t.loop[e]);return s(function(){if(t.autoscale&&c(n,"resize",N),t.tapEvents){let e=e=>[(e.pageX-h.offsetLeft)/m,(e.pageY-h.offsetTop)/m],t=new Map,l=(e,l,a)=>{let n={x:l,y:a,xi:l,yi:a,t:o.now()};return t.set(e,n),n},a=(e,a,n)=>{let i=t.get(e)||l(e);i.x=a,i.y=n},i=e=>e&&o.now()-e.t<=300,r=!1;c(h,"mousedown",t=>{if(0===t.button){t.preventDefault();let[a,n]=e(t);S.emit("tap",a,n,0),l(0,a,n),r=!0}}),c(h,"mouseup",l=>{if(0===l.button){l.preventDefault();let a=t.get(0),[n,o]=e(l);i(a)&&S.emit("tapped",a.xi,a.yi,0),S.emit("untap",n,o,0),t.delete(0),r=!1}}),c(n,"mousemove",t=>{t.preventDefault();let[l,n]=e(t);S.def("MX",l),S.def("MY",n),r&&(S.emit("tapping",l,n,0),a(0,l,n))}),c(h,"touchstart",t=>{for(let a of(t.preventDefault(),t.changedTouches)){let[t,n]=e(a);S.emit("tap",t,n,a.identifier+1),l(a.identifier+1,t,n)}}),c(h,"touchmove",t=>{for(let l of(t.preventDefault(),t.changedTouches)){let[t,n]=e(l);S.emit("tapping",t,n,l.identifier+1),a(l.identifier+1,t,n)}});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)||(i(a)&&S.emit("tapped",a.xi,a.yi,e),S.emit("untap",a.x,a.y,e),t.delete(e))};c(h,"touchend",s),c(h,"touchcancel",s),c(n,"blur",()=>{for(let[e,l]of(r=!1,t))S.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,a="";c(n,"keydown",l=>{let n=l.key.toLowerCase();e.has(n)||(e.add(n),t.add(n),a=" "===n?"space":n)}),c(n,"keyup",t=>{e.delete(t.key.toLowerCase())}),c(n,"blur",()=>e.clear()),S.listen("after:update",()=>t.clear()),S.def("iskeydown",t=>l(e,t)),S.def("iskeypressed",e=>l(t,e)),S.def("lastkey",()=>a)}p=!0,S.emit("init",S),u||H()}),S}})();
|
package/package.json
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "litecanvas",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.206.0",
|
|
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.
|
|
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,7 +34,7 @@
|
|
|
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.
|
|
37
|
+
"@swc/core": "^1.15.32",
|
|
38
38
|
"ava": "^7.0.0",
|
|
39
39
|
"esbuild": "^0.27.7",
|
|
40
40
|
"genversion": "^3.2.0",
|
package/src/index.js
CHANGED
|
@@ -51,7 +51,7 @@ export default function litecanvas(settings = {}) {
|
|
|
51
51
|
let /** @type {boolean} */
|
|
52
52
|
_initialized = false,
|
|
53
53
|
/** @type {boolean} */
|
|
54
|
-
_paused
|
|
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
|
*/
|
|
@@ -1149,9 +1146,17 @@ export default function litecanvas(settings = {}) {
|
|
|
1149
1146
|
|
|
1150
1147
|
triggerEvent('before:' + eventName, arg1, arg2, arg3, arg4)
|
|
1151
1148
|
|
|
1152
|
-
if
|
|
1149
|
+
// if the "loop" option not exists,
|
|
1150
|
+
// calls a global function with the same name as the event,
|
|
1151
|
+
// as long as it's not a global litecanvas function (to avoid infinite loops)
|
|
1152
|
+
if (
|
|
1153
|
+
!settings.loop &&
|
|
1154
|
+
root[eventName] !== instance[eventName] &&
|
|
1155
|
+
'function' === typeof root[eventName] /* if is a function */
|
|
1156
|
+
) {
|
|
1153
1157
|
root[eventName](arg1, arg2, arg3, arg4)
|
|
1154
1158
|
}
|
|
1159
|
+
|
|
1155
1160
|
triggerEvent(eventName, arg1, arg2, arg3, arg4)
|
|
1156
1161
|
|
|
1157
1162
|
triggerEvent('after:' + eventName, arg1, arg2, arg3, arg4)
|
|
@@ -1179,6 +1184,8 @@ export default function litecanvas(settings = {}) {
|
|
|
1179
1184
|
_colorPalette = colors || defaultPalette
|
|
1180
1185
|
_colorPaletteState = []
|
|
1181
1186
|
_defaultTextColor = textColor
|
|
1187
|
+
|
|
1188
|
+
instance.emit('pal', _colorPalette, _defaultTextColor)
|
|
1182
1189
|
},
|
|
1183
1190
|
|
|
1184
1191
|
/**
|
|
@@ -1333,7 +1340,7 @@ export default function litecanvas(settings = {}) {
|
|
|
1333
1340
|
pause() {
|
|
1334
1341
|
if (!_paused) {
|
|
1335
1342
|
_paused = true
|
|
1336
|
-
cancelAnimationFrame(_rafid)
|
|
1343
|
+
_rafid = ~~cancelAnimationFrame(_rafid)
|
|
1337
1344
|
instance.emit('paused')
|
|
1338
1345
|
}
|
|
1339
1346
|
},
|
|
@@ -1348,10 +1355,8 @@ export default function litecanvas(settings = {}) {
|
|
|
1348
1355
|
'resume() cannot be called before the "init" event and neither after the quit() function'
|
|
1349
1356
|
)
|
|
1350
1357
|
if (_initialized && _paused) {
|
|
1358
|
+
startGameLoop()
|
|
1351
1359
|
_paused = false
|
|
1352
|
-
_accumulated = _fpsInterval
|
|
1353
|
-
_lastFrameTime = perf.now()
|
|
1354
|
-
_rafid = raf(drawFrame)
|
|
1355
1360
|
instance.emit('resumed')
|
|
1356
1361
|
}
|
|
1357
1362
|
},
|
|
@@ -1369,8 +1374,8 @@ export default function litecanvas(settings = {}) {
|
|
|
1369
1374
|
* Shutdown the litecanvas instance and remove all event listeners.
|
|
1370
1375
|
*/
|
|
1371
1376
|
quit() {
|
|
1372
|
-
// emit "
|
|
1373
|
-
instance.emit('
|
|
1377
|
+
// emit "quit" event to manual clean ups
|
|
1378
|
+
instance.emit('quit')
|
|
1374
1379
|
|
|
1375
1380
|
// stop the game loop (update & draw)
|
|
1376
1381
|
instance.pause()
|
|
@@ -1399,11 +1404,20 @@ export default function litecanvas(settings = {}) {
|
|
|
1399
1404
|
}
|
|
1400
1405
|
|
|
1401
1406
|
// prettier-ignore
|
|
1402
|
-
|
|
1407
|
+
const mathProps = 'PI,sin,cos,atan2,hypot,tan,abs,ceil,floor,trunc,min,max,pow,sqrt,sign,exp'
|
|
1408
|
+
for (const k of mathProps.split(',')) {
|
|
1403
1409
|
// import native Math functions
|
|
1404
1410
|
instance[k] = math[k]
|
|
1405
1411
|
}
|
|
1406
1412
|
|
|
1413
|
+
function startGameLoop() {
|
|
1414
|
+
if (!_rafid) {
|
|
1415
|
+
_accumulated = 0
|
|
1416
|
+
_lastFrameTime = perf.now()
|
|
1417
|
+
_rafid = raf(drawFrame)
|
|
1418
|
+
}
|
|
1419
|
+
}
|
|
1420
|
+
|
|
1407
1421
|
function init() {
|
|
1408
1422
|
// listen window resize event when "autoscale" is enabled
|
|
1409
1423
|
if (settings.autoscale) {
|
|
@@ -1590,6 +1604,7 @@ export default function litecanvas(settings = {}) {
|
|
|
1590
1604
|
})
|
|
1591
1605
|
}
|
|
1592
1606
|
|
|
1607
|
+
// default keyboard handler
|
|
1593
1608
|
if (settings.keyboardEvents) {
|
|
1594
1609
|
/** @type {Set<string>} */
|
|
1595
1610
|
const _keysDown = new Set()
|
|
@@ -1667,8 +1682,10 @@ export default function litecanvas(settings = {}) {
|
|
|
1667
1682
|
|
|
1668
1683
|
// start the engine
|
|
1669
1684
|
_initialized = true
|
|
1670
|
-
instance.resume()
|
|
1671
1685
|
instance.emit('init', instance)
|
|
1686
|
+
if (!_paused) {
|
|
1687
|
+
startGameLoop()
|
|
1688
|
+
}
|
|
1672
1689
|
}
|
|
1673
1690
|
|
|
1674
1691
|
function drawFrame() {
|
|
@@ -1693,22 +1710,24 @@ export default function litecanvas(settings = {}) {
|
|
|
1693
1710
|
}
|
|
1694
1711
|
|
|
1695
1712
|
if (updated) {
|
|
1713
|
+
// draws only when an update happens.
|
|
1696
1714
|
instance.emit('draw', _ctx)
|
|
1715
|
+
|
|
1716
|
+
// sometimes the FPS locks at a value below 60
|
|
1717
|
+
// and does not go back up, even with a very simple logic.
|
|
1718
|
+
// One solution I found was to reset the variable that
|
|
1719
|
+
// accumulates time between frames, when multiple updates occur.
|
|
1697
1720
|
if (updated > 1) {
|
|
1698
1721
|
_accumulated = 0
|
|
1699
|
-
DEV: console.warn(
|
|
1700
|
-
loggerPrefix +
|
|
1701
|
-
'the last frame updated ' +
|
|
1702
|
-
updated +
|
|
1703
|
-
' times. This can drop the FPS if it keeps happening.'
|
|
1704
|
-
)
|
|
1705
1722
|
}
|
|
1706
1723
|
}
|
|
1707
1724
|
}
|
|
1708
1725
|
|
|
1709
1726
|
function setupCanvas() {
|
|
1727
|
+
const d = document
|
|
1728
|
+
|
|
1710
1729
|
if ('string' === typeof settings.canvas) {
|
|
1711
|
-
_canvas =
|
|
1730
|
+
_canvas = d.querySelector(settings.canvas)
|
|
1712
1731
|
DEV: assert(
|
|
1713
1732
|
null != _canvas,
|
|
1714
1733
|
loggerPrefix + 'litecanvas() option "canvas" is an invalid CSS selector'
|
|
@@ -1717,7 +1736,7 @@ export default function litecanvas(settings = {}) {
|
|
|
1717
1736
|
_canvas = settings.canvas
|
|
1718
1737
|
}
|
|
1719
1738
|
|
|
1720
|
-
_canvas = _canvas ||
|
|
1739
|
+
_canvas = _canvas || d.createElement('canvas')
|
|
1721
1740
|
|
|
1722
1741
|
DEV: assert(
|
|
1723
1742
|
_canvas instanceof HTMLElement && 'CANVAS' === _canvas.tagName,
|
|
@@ -1732,7 +1751,7 @@ export default function litecanvas(settings = {}) {
|
|
|
1732
1751
|
resizeCanvas()
|
|
1733
1752
|
|
|
1734
1753
|
if (!_canvas.parentNode) {
|
|
1735
|
-
|
|
1754
|
+
d.body.appendChild(_canvas)
|
|
1736
1755
|
}
|
|
1737
1756
|
|
|
1738
1757
|
_canvas.style.imageRendering = 'pixelated'
|
|
@@ -1853,7 +1872,7 @@ export default function litecanvas(settings = {}) {
|
|
|
1853
1872
|
}
|
|
1854
1873
|
|
|
1855
1874
|
// init the engine (async)
|
|
1856
|
-
|
|
1875
|
+
raf(init)
|
|
1857
1876
|
|
|
1858
1877
|
return instance
|
|
1859
1878
|
}
|
package/src/version.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
// Generated by genversion.
|
|
2
|
-
export const version = '0.
|
|
2
|
+
export const version = '0.206.0'
|