litecanvas 0.92.3 → 0.93.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 +21 -15
- package/dist/dist.js +15 -13
- package/dist/dist.min.js +1 -1
- package/package.json +12 -11
- package/src/index.js +32 -22
- package/src/version.js +1 -1
- package/types/types.d.ts +4 -5
package/dist/dist.dev.js
CHANGED
|
@@ -32,7 +32,7 @@
|
|
|
32
32
|
};
|
|
33
33
|
|
|
34
34
|
// src/version.js
|
|
35
|
-
var version = "0.
|
|
35
|
+
var version = "0.93.1";
|
|
36
36
|
|
|
37
37
|
// src/index.js
|
|
38
38
|
function litecanvas(settings = {}) {
|
|
@@ -44,7 +44,6 @@
|
|
|
44
44
|
height: null,
|
|
45
45
|
autoscale: true,
|
|
46
46
|
pixelart: false,
|
|
47
|
-
antialias: false,
|
|
48
47
|
canvas: null,
|
|
49
48
|
global: true,
|
|
50
49
|
loop: null,
|
|
@@ -53,7 +52,7 @@
|
|
|
53
52
|
animate: true
|
|
54
53
|
};
|
|
55
54
|
settings = Object.assign(defaults, settings);
|
|
56
|
-
let _initialized = false, _plugins = [], _canvas, _scale = 1, _ctx, _outline_fix = 0.5, _timeScale = 1, _lastFrameTime, _deltaTime = 1 / 60, _accumulated
|
|
55
|
+
let _initialized = false, _plugins = [], _canvas, _scale = 1, _ctx, _outline_fix = 0.5, _timeScale = 1, _lastFrameTime, _deltaTime = 1 / 60, _accumulated, _rafid, _fontFamily = "sans-serif", _fontSize = 20, _rngSeed = Date.now(), _colors = defaultPalette, _defaultSound = [0.5, 0, 1750, , , 0.3, 1, , , , 600, 0.1], _coreEvents = "init,update,draw,tap,untap,tapping,tapped,resized", _mathFunctions = "PI,sin,cos,atan2,hypot,tan,abs,ceil,floor,trunc,min,max,pow,sqrt,sign,exp", _eventListeners = {};
|
|
57
56
|
const instance = {
|
|
58
57
|
/** @type {number} */
|
|
59
58
|
W: 0,
|
|
@@ -811,7 +810,7 @@
|
|
|
811
810
|
);
|
|
812
811
|
DEV: assert(isNumber(pitchSlide), "[litecanvas] sfx() 2nd param must be a number");
|
|
813
812
|
DEV: assert(isNumber(volumeFactor), "[litecanvas] sfx() 3rd param must be a number");
|
|
814
|
-
if (root.zzfxV
|
|
813
|
+
if (!root.zzfxV || navigator.userActivation && !navigator.userActivation.hasBeenActive) {
|
|
815
814
|
return false;
|
|
816
815
|
}
|
|
817
816
|
zzfxParams = zzfxParams || _defaultSound;
|
|
@@ -830,7 +829,10 @@
|
|
|
830
829
|
* @param {number} value
|
|
831
830
|
*/
|
|
832
831
|
volume(value) {
|
|
833
|
-
DEV: assert(
|
|
832
|
+
DEV: assert(
|
|
833
|
+
isNumber(value) && value >= 0,
|
|
834
|
+
"[litecanvas] volume() 1st param must be a positive number or zero"
|
|
835
|
+
);
|
|
834
836
|
root.zzfxV = value;
|
|
835
837
|
},
|
|
836
838
|
/** PLUGINS API */
|
|
@@ -1025,7 +1027,9 @@
|
|
|
1025
1027
|
* Resumes (if paused) the engine loop.
|
|
1026
1028
|
*/
|
|
1027
1029
|
resume() {
|
|
1028
|
-
if (
|
|
1030
|
+
if (_initialized && !_rafid) {
|
|
1031
|
+
_accumulated = 0;
|
|
1032
|
+
_lastFrameTime = performance.now();
|
|
1029
1033
|
_rafid = raf(drawFrame);
|
|
1030
1034
|
}
|
|
1031
1035
|
},
|
|
@@ -1274,14 +1278,20 @@
|
|
|
1274
1278
|
}
|
|
1275
1279
|
);
|
|
1276
1280
|
}
|
|
1281
|
+
on(root, "focus", () => {
|
|
1282
|
+
DEV: console.warn('[litecanvas] engine loop restarted on "focus" event');
|
|
1283
|
+
instance.pause();
|
|
1284
|
+
instance.resume();
|
|
1285
|
+
});
|
|
1277
1286
|
_initialized = true;
|
|
1278
1287
|
instance.emit("init", instance);
|
|
1279
|
-
_lastFrameTime = performance.now();
|
|
1280
1288
|
instance.resume();
|
|
1281
1289
|
}
|
|
1282
1290
|
function drawFrame(now) {
|
|
1283
1291
|
if (!settings.animate) {
|
|
1284
1292
|
return instance.emit("draw");
|
|
1293
|
+
} else if (_rafid) {
|
|
1294
|
+
_rafid = raf(drawFrame);
|
|
1285
1295
|
}
|
|
1286
1296
|
let updated = 0;
|
|
1287
1297
|
let frameTime = (now - _lastFrameTime) / 1e3;
|
|
@@ -1298,9 +1308,6 @@
|
|
|
1298
1308
|
if (updated) {
|
|
1299
1309
|
instance.emit("draw");
|
|
1300
1310
|
}
|
|
1301
|
-
if (_rafid) {
|
|
1302
|
-
_rafid = raf(drawFrame);
|
|
1303
|
-
}
|
|
1304
1311
|
}
|
|
1305
1312
|
function setupCanvas() {
|
|
1306
1313
|
if ("string" === typeof settings.canvas) {
|
|
@@ -1318,7 +1325,7 @@
|
|
|
1318
1325
|
'[litecanvas] litecanvas() option "canvas" should be a canvas element or string (CSS selector)'
|
|
1319
1326
|
);
|
|
1320
1327
|
_ctx = _canvas.getContext("2d");
|
|
1321
|
-
on(_canvas, "click", () =>
|
|
1328
|
+
on(_canvas, "click", () => focus());
|
|
1322
1329
|
_canvas.style = "";
|
|
1323
1330
|
resizeCanvas();
|
|
1324
1331
|
if (!_canvas.parentNode) {
|
|
@@ -1339,7 +1346,7 @@
|
|
|
1339
1346
|
null == settings.height || settings.width > 0 && settings.height > 0,
|
|
1340
1347
|
'[litecanvas] litecanvas() option "width" is required when the option "height" is defined'
|
|
1341
1348
|
);
|
|
1342
|
-
const width = settings.width
|
|
1349
|
+
const width = settings.width > 0 ? settings.width : innerWidth, height = settings.width > 0 ? settings.height || settings.width : innerHeight;
|
|
1343
1350
|
instance.def("W", width);
|
|
1344
1351
|
instance.def("H", height);
|
|
1345
1352
|
_canvas.width = width;
|
|
@@ -1350,13 +1357,12 @@
|
|
|
1350
1357
|
_canvas.style.display = "block";
|
|
1351
1358
|
_canvas.style.margin = "auto";
|
|
1352
1359
|
}
|
|
1353
|
-
_scale = math.min(
|
|
1360
|
+
_scale = math.min(innerWidth / width, innerHeight / height);
|
|
1354
1361
|
_scale = maxScale > 1 && _scale > maxScale ? maxScale : _scale;
|
|
1355
|
-
_scale = (settings.pixelart ? ~~_scale : _scale) || 1;
|
|
1356
1362
|
_canvas.style.width = width * _scale + "px";
|
|
1357
1363
|
_canvas.style.height = height * _scale + "px";
|
|
1358
1364
|
}
|
|
1359
|
-
if (
|
|
1365
|
+
if (settings.pixelart) {
|
|
1360
1366
|
_ctx.imageSmoothingEnabled = false;
|
|
1361
1367
|
_canvas.style.imageRendering = "pixelated";
|
|
1362
1368
|
}
|
package/dist/dist.js
CHANGED
|
@@ -36,7 +36,6 @@
|
|
|
36
36
|
height: null,
|
|
37
37
|
autoscale: true,
|
|
38
38
|
pixelart: false,
|
|
39
|
-
antialias: false,
|
|
40
39
|
canvas: null,
|
|
41
40
|
global: true,
|
|
42
41
|
loop: null,
|
|
@@ -45,7 +44,7 @@
|
|
|
45
44
|
animate: true
|
|
46
45
|
};
|
|
47
46
|
settings = Object.assign(defaults, settings);
|
|
48
|
-
let _initialized = false, _plugins = [], _canvas, _scale = 1, _ctx, _outline_fix = 0.5, _timeScale = 1, _lastFrameTime, _deltaTime = 1 / 60, _accumulated
|
|
47
|
+
let _initialized = false, _plugins = [], _canvas, _scale = 1, _ctx, _outline_fix = 0.5, _timeScale = 1, _lastFrameTime, _deltaTime = 1 / 60, _accumulated, _rafid, _fontFamily = "sans-serif", _fontSize = 20, _rngSeed = Date.now(), _colors = defaultPalette, _defaultSound = [0.5, 0, 1750, , , 0.3, 1, , , , 600, 0.1], _coreEvents = "init,update,draw,tap,untap,tapping,tapped,resized", _mathFunctions = "PI,sin,cos,atan2,hypot,tan,abs,ceil,floor,trunc,min,max,pow,sqrt,sign,exp", _eventListeners = {};
|
|
49
48
|
const instance = {
|
|
50
49
|
/** @type {number} */
|
|
51
50
|
W: 0,
|
|
@@ -558,7 +557,7 @@
|
|
|
558
557
|
* @see https://github.com/KilledByAPixel/ZzFX
|
|
559
558
|
*/
|
|
560
559
|
sfx(zzfxParams, pitchSlide = 0, volumeFactor = 1) {
|
|
561
|
-
if (root.zzfxV
|
|
560
|
+
if (!root.zzfxV || navigator.userActivation && !navigator.userActivation.hasBeenActive) {
|
|
562
561
|
return false;
|
|
563
562
|
}
|
|
564
563
|
zzfxParams = zzfxParams || _defaultSound;
|
|
@@ -732,7 +731,9 @@
|
|
|
732
731
|
* Resumes (if paused) the engine loop.
|
|
733
732
|
*/
|
|
734
733
|
resume() {
|
|
735
|
-
if (
|
|
734
|
+
if (_initialized && !_rafid) {
|
|
735
|
+
_accumulated = 0;
|
|
736
|
+
_lastFrameTime = performance.now();
|
|
736
737
|
_rafid = raf(drawFrame);
|
|
737
738
|
}
|
|
738
739
|
},
|
|
@@ -970,14 +971,19 @@
|
|
|
970
971
|
}
|
|
971
972
|
);
|
|
972
973
|
}
|
|
974
|
+
on(root, "focus", () => {
|
|
975
|
+
instance.pause();
|
|
976
|
+
instance.resume();
|
|
977
|
+
});
|
|
973
978
|
_initialized = true;
|
|
974
979
|
instance.emit("init", instance);
|
|
975
|
-
_lastFrameTime = performance.now();
|
|
976
980
|
instance.resume();
|
|
977
981
|
}
|
|
978
982
|
function drawFrame(now) {
|
|
979
983
|
if (!settings.animate) {
|
|
980
984
|
return instance.emit("draw");
|
|
985
|
+
} else if (_rafid) {
|
|
986
|
+
_rafid = raf(drawFrame);
|
|
981
987
|
}
|
|
982
988
|
let updated = 0;
|
|
983
989
|
let frameTime = (now - _lastFrameTime) / 1e3;
|
|
@@ -994,9 +1000,6 @@
|
|
|
994
1000
|
if (updated) {
|
|
995
1001
|
instance.emit("draw");
|
|
996
1002
|
}
|
|
997
|
-
if (_rafid) {
|
|
998
|
-
_rafid = raf(drawFrame);
|
|
999
|
-
}
|
|
1000
1003
|
}
|
|
1001
1004
|
function setupCanvas() {
|
|
1002
1005
|
if ("string" === typeof settings.canvas) {
|
|
@@ -1006,7 +1009,7 @@
|
|
|
1006
1009
|
}
|
|
1007
1010
|
_canvas = _canvas || document.createElement("canvas");
|
|
1008
1011
|
_ctx = _canvas.getContext("2d");
|
|
1009
|
-
on(_canvas, "click", () =>
|
|
1012
|
+
on(_canvas, "click", () => focus());
|
|
1010
1013
|
_canvas.style = "";
|
|
1011
1014
|
resizeCanvas();
|
|
1012
1015
|
if (!_canvas.parentNode) {
|
|
@@ -1015,7 +1018,7 @@
|
|
|
1015
1018
|
_canvas.oncontextmenu = () => false;
|
|
1016
1019
|
}
|
|
1017
1020
|
function resizeCanvas() {
|
|
1018
|
-
const width = settings.width
|
|
1021
|
+
const width = settings.width > 0 ? settings.width : innerWidth, height = settings.width > 0 ? settings.height || settings.width : innerHeight;
|
|
1019
1022
|
instance.def("W", width);
|
|
1020
1023
|
instance.def("H", height);
|
|
1021
1024
|
_canvas.width = width;
|
|
@@ -1026,13 +1029,12 @@
|
|
|
1026
1029
|
_canvas.style.display = "block";
|
|
1027
1030
|
_canvas.style.margin = "auto";
|
|
1028
1031
|
}
|
|
1029
|
-
_scale = math.min(
|
|
1032
|
+
_scale = math.min(innerWidth / width, innerHeight / height);
|
|
1030
1033
|
_scale = maxScale > 1 && _scale > maxScale ? maxScale : _scale;
|
|
1031
|
-
_scale = (settings.pixelart ? ~~_scale : _scale) || 1;
|
|
1032
1034
|
_canvas.style.width = width * _scale + "px";
|
|
1033
1035
|
_canvas.style.height = height * _scale + "px";
|
|
1034
1036
|
}
|
|
1035
|
-
if (
|
|
1037
|
+
if (settings.pixelart) {
|
|
1036
1038
|
_ctx.imageSmoothingEnabled = false;
|
|
1037
1039
|
_canvas.style.imageRendering = "pixelated";
|
|
1038
1040
|
}
|
package/dist/dist.min.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
(()=>{var e=["#111","#6a7799","#aec2c2","#FFF1E8","#e83b3b","#fabc20","#155fd9","#3cbcfc","#327345","#63c64d","#6c2c1f","#ac7c00"];globalThis.litecanvas=function(t={}){let a=window,i=Math,l=2*i.PI,n=requestAnimationFrame,o=[],r=(e,t,a)=>{e.addEventListener(t,a,!1),o.push(()=>e.removeEventListener(t,a,!1))},s=e=>e.beginPath(),f=(e=>{let t=new AudioContext;return e.zzfxV=1,(a=1,i=.05,l=220,n=0,o=0,r=.1,s=0,f=1,c=0,d=0,u=0,p=0,m=0,h=0,g=0,
|
|
1
|
+
(()=>{var e=["#111","#6a7799","#aec2c2","#FFF1E8","#e83b3b","#fabc20","#155fd9","#3cbcfc","#327345","#63c64d","#6c2c1f","#ac7c00"];globalThis.litecanvas=function(t={}){let a=window,i=Math,l=2*i.PI,n=requestAnimationFrame,o=[],r=(e,t,a)=>{e.addEventListener(t,a,!1),o.push(()=>e.removeEventListener(t,a,!1))},s=e=>e.beginPath(),f=(e=>{let t=new AudioContext;return e.zzfxV=1,(a=1,i=.05,l=220,n=0,o=0,r=.1,s=0,f=1,c=0,d=0,u=0,p=0,m=0,h=0,g=0,w=0,v=0,x=1,y=0,b=0,k=0)=>{let E=Math,z=2*E.PI,T=c*=500*z/44100/44100,C=l*=(1-i+2*i*E.random(i=[]))*z/44100,I=0,A=0,L=0,S=1,M=0,N=0,P=0,D=k<0?-1:1,F=z*D*k*2/44100,q=E.cos(F),B=E.sin,H=B(F)/4,O=1+H,V=-2*q/O,W=(1-H)/O,R=(1+D*q)/2/O,G=-(D+q)/O,X=0,Y=0,$=0,j=0;for(n=44100*n+9,y*=44100,o*=44100,r*=44100,v*=44100,d*=500*z/85766121e6,g*=z/44100,u*=z/44100,p*=44100,m=44100*m|0,a*=.3*e.zzfxV,D=n+y+o+r+v|0;L<D;i[L++]=P*a)++N%(100*w|0)||(P=s?1<s?2<s?3<s?B(I*I):E.max(E.min(E.tan(I),1),-1):1-(2*I/z%2+2)%2:1-4*E.abs(E.round(I/z)-I/z):B(I),P=(m?1-b+b*B(z*L/m):1)*(P<0?-1:1)*E.abs(P)**f*(L<n?L/n:L<n+y?1-(L-n)/y*(1-x):L<n+y+o?x:L<D-v?(D-L-v)/r*x:0),P=v?P/2+(v>L?0:(L<D-v?1:(D-L)/v)*i[L-v|0]/2/a):P,k&&(P=j=R*X+G*(X=Y)+R*(Y=P)-W*$-V*($=j))),I+=(F=(l+=c+=d)*E.cos(g*A++))+F*h*B(L**5),S&&++S>p&&(l+=u,C+=u,S=0),!m||++M%m||(l=C,c=T,S=S||1);(a=t.createBuffer(1,D,44100)).getChannelData(0).set(i),(l=t.createBufferSource()).buffer=a,l.connect(t.destination),l.start()}})(a);t=Object.assign({width:null,height:null,autoscale:!0,pixelart:!1,canvas:null,global:!0,loop:null,tapEvents:!0,keyboardEvents:!0,animate:!0},t);let c=!1,d=[],u,p=1,m,h=.5,g=1,w,v=1/60,x,y,b="sans-serif",k=20,E=Date.now(),z=e,T=[.5,0,1750,,,.3,1,,,,600,.1],C={},I={W:0,H:0,T:0,MX:-1,MY:-1,TWO_PI:l,HALF_PI:l/4,lerp:(e,t,a)=>a*(t-e)+e,deg2rad:e=>i.PI/180*e,rad2deg:e=>180/i.PI*e,round:(e,t=0)=>{if(!t)return i.round(e);let a=10**t;return i.round(e*a)/a},clamp:(e,t,a)=>e<t?t:e>a?a:e,wrap:(e,t,a)=>e-(a-t)*i.floor((e-t)/(a-t)),map(e,t,a,i,l,n){let o=(e-t)/(a-t)*(l-i)+i;return n?I.clamp(o,i,l):o},norm:(e,t,a)=>I.map(e,t,a,0,1),wave:(e,t,a,i=Math.sin)=>e+(i(a)+1)/2*(t-e),rand:(e=0,t=1)=>(E=(1664525*E+0x3c6ef35f)%0x100000000)/0x100000000*(t-e)+e,randi:(e=0,t=1)=>i.floor(I.rand(e,t+1)),rseed(e){E=~~e},cls(e){null==e?m.clearRect(0,0,m.canvas.width,m.canvas.height):I.rectfill(0,0,m.canvas.width,m.canvas.height,e)},rect(e,t,a,i,l,n){s(m),m[n?"roundRect":"rect"](~~e-h,~~t-h,~~a+2*h,~~i+2*h,n),I.stroke(l)},rectfill(e,t,a,i,l,n){s(m),m[n?"roundRect":"rect"](~~e,~~t,~~a,~~i,n),I.fill(l)},circ(e,t,a,i){s(m),m.arc(~~e,~~t,~~a,0,l),I.stroke(i)},circfill(e,t,a,i){s(m),m.arc(~~e,~~t,~~a,0,l),I.fill(i)},oval(e,t,a,i,n){s(m),m.ellipse(~~e,~~t,~~a,~~i,0,0,l),I.stroke(n)},ovalfill(e,t,a,i,n){s(m),m.ellipse(~~e,~~t,~~a,~~i,0,0,l),I.fill(n)},line(e,t,a,i,l){s(m);let n=.5*(0!==h&&~~e==~~a),o=.5*(0!==h&&~~t==~~i);m.moveTo(~~e+n,~~t+o),m.lineTo(~~a+n,~~i+o),I.stroke(l)},linewidth(e){m.lineWidth=~~e,h=.5*(0!=~~e%2)},linedash(e,t=0){m.setLineDash(e),m.lineDashOffset=t},text(e,t,a,i=3,l="normal"){m.font=`${l} ${k}px ${b}`,m.fillStyle=z[~~i%z.length],m.fillText(a,~~e,~~t)},textfont(e){b=e},textsize(e){k=e},textalign(e,t){e&&(m.textAlign=e),t&&(m.textBaseline=t)},image(e,t,a){m.drawImage(a,~~e,~~t)},paint(e,t,a,i={}){let l=i.canvas||new OffscreenCanvas(1,1),n=i.scale||1,o=m;if(l.width=e*n,l.height=t*n,(m=l.getContext("2d")).scale(n,n),Array.isArray(a)){let e=0,t=0;for(let i of(m.imageSmoothingEnabled=!1,a)){for(let a of i)" "!==a&&"."!==a&&I.rectfill(e,t,1,1,parseInt(a,16)),e++;t++,e=0}}else a(m);return m=o,l.transferToImageBitmap()},ctx:e=>(e&&(m=e),m),push:()=>m.save(),pop:()=>m.restore(),translate:(e,t)=>m.translate(~~e,~~t),scale:(e,t)=>m.scale(e,t||e),rotate:e=>m.rotate(e),alpha(e){m.globalAlpha=I.clamp(e,0,1)},fill(e){m.fillStyle=z[~~e%z.length],m.fill()},stroke(e){m.strokeStyle=z[~~e%z.length],m.stroke()},clip(e){s(m),e(m),m.clip()},sfx:(e,t=0,i=1)=>!!a.zzfxV&&(!navigator.userActivation||!!navigator.userActivation.hasBeenActive)&&(e=e||T,(0!==t||1!==i)&&((e=e.slice())[0]=i*(e[0]||1),e[10]=~~e[10]+t),f.apply(0,e),e),volume(e){a.zzfxV=e},canvas:()=>u,use(e,t={}){c?N(e,t):d.push([e,t])},listen:(e,t)=>(C[e=e.toLowerCase()]=C[e]||new Set,C[e].add(t),()=>C&&C[e].delete(t)),emit(e,t,a,i,l){c&&(M("before:"+(e=e.toLowerCase()),t,a,i,l),M(e,t,a,i,l),M("after:"+e,t,a,i,l))},pal(t=e){z=t},def(e,i){I[e]=i,t.global&&(a[e]=i)},timescale(e){g=e},framerate(e){v=1/~~e},stat(e){let i={index:e,value:[t,c,v,p,C,z,T,g,a.zzfxV,E,k,b][e]};return I.emit("stat",i),i.value},quit(){for(let e of(I.pause(),I.emit("quit"),C={},o))e();if(t.global){for(let e in I)delete a[e];delete a.ENGINE}c=!1},pause(){cancelAnimationFrame(y),y=0},resume(){c&&!y&&(x=0,w=performance.now(),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))}r(a,"focus",()=>{I.pause(),I.resume()}),c=!0,I.emit("init",I),I.resume()}function L(e){if(!t.animate)return I.emit("draw");y&&(y=n(L));let a=0,i=(e-w)/1e3;if(w=e,i<.1)for(x+=i;x>=v;)a++,I.emit("update",v*g,a),I.def("T",I.T+v*g),x-=v;a&&I.emit("draw")}function S(){let e=t.width>0?t.width:innerWidth,a=t.width>0?t.height||t.width:innerHeight;if(I.def("W",e),I.def("H",a),u.width=e,u.height=a,t.autoscale){let l=+t.autoscale;u.style.display||(u.style.display="block",u.style.margin="auto"),p=i.min(innerWidth/e,innerHeight/a),p=l>1&&p>l?l:p,u.style.width=e*p+"px",u.style.height=a*p+"px"}t.pixelart&&(m.imageSmoothingEnabled=!1,u.style.imageRendering="pixelated"),I.textalign("start","top"),I.emit("resized",p),I.cls(0),t.animate||n(L)}function M(e,t,a,i,l){if(C[e])for(let n of C[e])n(t,a,i,l)}function N(e,t){let a=e(I,t);for(let e in a)I.def(e,a[e])}if(t.global){if(a.ENGINE)throw Error("only one global litecanvas is allowed");Object.assign(a,I),a.ENGINE=I}return m=(u=(u="string"==typeof t.canvas?document.querySelector(t.canvas):t.canvas)||document.createElement("canvas")).getContext("2d"),r(u,"click",()=>focus()),u.style="",S(),u.parentNode||document.body.appendChild(u),u.oncontextmenu=()=>!1,"loading"===document.readyState?r(a,"DOMContentLoaded",()=>n(A)):n(A),I}})();
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "litecanvas",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.93.1",
|
|
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>",
|
|
@@ -19,23 +19,24 @@
|
|
|
19
19
|
"types": "./types/index.d.ts",
|
|
20
20
|
"unpkg": "./dist/dist.dev.js",
|
|
21
21
|
"keywords": [
|
|
22
|
-
"
|
|
23
|
-
"
|
|
24
|
-
"
|
|
22
|
+
"tiny",
|
|
23
|
+
"micro",
|
|
24
|
+
"javascript",
|
|
25
|
+
"html5",
|
|
25
26
|
"canvas",
|
|
27
|
+
"2d",
|
|
28
|
+
"game",
|
|
26
29
|
"gamedev",
|
|
27
30
|
"js13k",
|
|
28
|
-
"creative
|
|
29
|
-
"pico-8",
|
|
30
|
-
"p5"
|
|
31
|
+
"creative coding"
|
|
31
32
|
],
|
|
32
33
|
"devDependencies": {
|
|
33
|
-
"@litecanvas/jsdom-extras": "^2.0.
|
|
34
|
+
"@litecanvas/jsdom-extras": "^2.0.1",
|
|
34
35
|
"@size-limit/preset-small-lib": "^11.2.0",
|
|
35
|
-
"@swc/core": "^1.
|
|
36
|
+
"@swc/core": "^1.13.1",
|
|
36
37
|
"@types/jsdom": "^21.1.7",
|
|
37
38
|
"ava": "^6.4.1",
|
|
38
|
-
"esbuild": "^0.25.
|
|
39
|
+
"esbuild": "^0.25.8",
|
|
39
40
|
"genversion": "^3.2.0",
|
|
40
41
|
"gzip-size": "^7.0.0",
|
|
41
42
|
"jsdom": "^26.1.0",
|
|
@@ -52,7 +53,7 @@
|
|
|
52
53
|
"prepublishOnly": "npm test",
|
|
53
54
|
"test": "ava --timeout=1s --fast-fail --tap | tap-min",
|
|
54
55
|
"test:watch": "ava --watch",
|
|
55
|
-
"dev": "esbuild src/web.js --bundle --watch --outfile=
|
|
56
|
+
"dev": "esbuild src/web.js --bundle --watch --outfile=samples/dist.js --servedir=samples",
|
|
56
57
|
"build": "npm run genversion && node script/build.js && size-limit",
|
|
57
58
|
"format": "prettier -w src/* samples/* types/* script/* types/*",
|
|
58
59
|
"check-types": "npx ts types/*",
|
package/src/index.js
CHANGED
|
@@ -33,7 +33,6 @@ export default function litecanvas(settings = {}) {
|
|
|
33
33
|
height: null,
|
|
34
34
|
autoscale: true,
|
|
35
35
|
pixelart: false,
|
|
36
|
-
antialias: false,
|
|
37
36
|
canvas: null,
|
|
38
37
|
global: true,
|
|
39
38
|
loop: null,
|
|
@@ -64,7 +63,7 @@ export default function litecanvas(settings = {}) {
|
|
|
64
63
|
/** @type {number} duration of a frame at 60 FPS (default) */
|
|
65
64
|
_deltaTime = 1 / 60,
|
|
66
65
|
/** @type {number} */
|
|
67
|
-
_accumulated
|
|
66
|
+
_accumulated,
|
|
68
67
|
/** @type {number?} */
|
|
69
68
|
_rafid,
|
|
70
69
|
/** @type {string} */
|
|
@@ -945,7 +944,7 @@ export default function litecanvas(settings = {}) {
|
|
|
945
944
|
DEV: assert(isNumber(volumeFactor), '[litecanvas] sfx() 3rd param must be a number')
|
|
946
945
|
|
|
947
946
|
if (
|
|
948
|
-
root.zzfxV
|
|
947
|
+
!root.zzfxV ||
|
|
949
948
|
(navigator.userActivation && !navigator.userActivation.hasBeenActive)
|
|
950
949
|
) {
|
|
951
950
|
return false
|
|
@@ -972,7 +971,10 @@ export default function litecanvas(settings = {}) {
|
|
|
972
971
|
* @param {number} value
|
|
973
972
|
*/
|
|
974
973
|
volume(value) {
|
|
975
|
-
DEV: assert(
|
|
974
|
+
DEV: assert(
|
|
975
|
+
isNumber(value) && value >= 0,
|
|
976
|
+
'[litecanvas] volume() 1st param must be a positive number or zero'
|
|
977
|
+
)
|
|
976
978
|
|
|
977
979
|
root.zzfxV = value
|
|
978
980
|
},
|
|
@@ -1207,7 +1209,9 @@ export default function litecanvas(settings = {}) {
|
|
|
1207
1209
|
* Resumes (if paused) the engine loop.
|
|
1208
1210
|
*/
|
|
1209
1211
|
resume() {
|
|
1210
|
-
if (
|
|
1212
|
+
if (_initialized && !_rafid) {
|
|
1213
|
+
_accumulated = 0
|
|
1214
|
+
_lastFrameTime = performance.now()
|
|
1211
1215
|
_rafid = raf(drawFrame)
|
|
1212
1216
|
}
|
|
1213
1217
|
},
|
|
@@ -1502,11 +1506,17 @@ export default function litecanvas(settings = {}) {
|
|
|
1502
1506
|
)
|
|
1503
1507
|
}
|
|
1504
1508
|
|
|
1509
|
+
// this seems to solve a strange bug that drop the FPS
|
|
1510
|
+
// when switching tabs in the browser
|
|
1511
|
+
on(root, 'focus', () => {
|
|
1512
|
+
DEV: console.warn('[litecanvas] engine loop restarted on "focus" event')
|
|
1513
|
+
instance.pause()
|
|
1514
|
+
instance.resume()
|
|
1515
|
+
})
|
|
1516
|
+
|
|
1505
1517
|
// start the engine
|
|
1506
1518
|
_initialized = true
|
|
1507
1519
|
instance.emit('init', instance)
|
|
1508
|
-
|
|
1509
|
-
_lastFrameTime = performance.now()
|
|
1510
1520
|
instance.resume()
|
|
1511
1521
|
}
|
|
1512
1522
|
|
|
@@ -1517,6 +1527,11 @@ export default function litecanvas(settings = {}) {
|
|
|
1517
1527
|
if (!settings.animate) {
|
|
1518
1528
|
return instance.emit('draw')
|
|
1519
1529
|
}
|
|
1530
|
+
// request the next frame
|
|
1531
|
+
// only when the engine loop are not paused (_rafid >= 1)
|
|
1532
|
+
else if (_rafid) {
|
|
1533
|
+
_rafid = raf(drawFrame)
|
|
1534
|
+
}
|
|
1520
1535
|
|
|
1521
1536
|
let updated = 0
|
|
1522
1537
|
let frameTime = (now - _lastFrameTime) / 1000
|
|
@@ -1536,12 +1551,6 @@ export default function litecanvas(settings = {}) {
|
|
|
1536
1551
|
if (updated) {
|
|
1537
1552
|
instance.emit('draw')
|
|
1538
1553
|
}
|
|
1539
|
-
|
|
1540
|
-
// request the next frame
|
|
1541
|
-
// only when the engine loop are not paused (_rafid >= 1)
|
|
1542
|
-
if (_rafid) {
|
|
1543
|
-
_rafid = raf(drawFrame)
|
|
1544
|
-
}
|
|
1545
1554
|
}
|
|
1546
1555
|
|
|
1547
1556
|
function setupCanvas() {
|
|
@@ -1564,7 +1573,7 @@ export default function litecanvas(settings = {}) {
|
|
|
1564
1573
|
|
|
1565
1574
|
_ctx = _canvas.getContext('2d')
|
|
1566
1575
|
|
|
1567
|
-
on(_canvas, 'click', () =>
|
|
1576
|
+
on(_canvas, 'click', () => focus())
|
|
1568
1577
|
|
|
1569
1578
|
/** @ts-ignore */
|
|
1570
1579
|
_canvas.style = ''
|
|
@@ -1592,8 +1601,8 @@ export default function litecanvas(settings = {}) {
|
|
|
1592
1601
|
'[litecanvas] litecanvas() option "width" is required when the option "height" is defined'
|
|
1593
1602
|
)
|
|
1594
1603
|
|
|
1595
|
-
const width = settings.width
|
|
1596
|
-
height = settings.height || settings.width
|
|
1604
|
+
const width = settings.width > 0 ? settings.width : innerWidth,
|
|
1605
|
+
height = settings.width > 0 ? settings.height || settings.width : innerHeight
|
|
1597
1606
|
|
|
1598
1607
|
instance.def('W', width)
|
|
1599
1608
|
instance.def('H', height)
|
|
@@ -1608,29 +1617,30 @@ export default function litecanvas(settings = {}) {
|
|
|
1608
1617
|
_canvas.style.margin = 'auto'
|
|
1609
1618
|
}
|
|
1610
1619
|
|
|
1611
|
-
_scale = math.min(
|
|
1620
|
+
_scale = math.min(innerWidth / width, innerHeight / height)
|
|
1612
1621
|
_scale = maxScale > 1 && _scale > maxScale ? maxScale : _scale
|
|
1613
|
-
_scale = (settings.pixelart ? ~~_scale : _scale) || 1
|
|
1614
1622
|
|
|
1615
1623
|
_canvas.style.width = width * _scale + 'px'
|
|
1616
1624
|
_canvas.style.height = height * _scale + 'px'
|
|
1617
1625
|
}
|
|
1618
1626
|
|
|
1619
|
-
//
|
|
1620
|
-
if (
|
|
1627
|
+
// set canvas image rendering properties
|
|
1628
|
+
if (settings.pixelart) {
|
|
1621
1629
|
_ctx.imageSmoothingEnabled = false
|
|
1622
1630
|
_canvas.style.imageRendering = 'pixelated'
|
|
1623
1631
|
}
|
|
1624
1632
|
|
|
1625
|
-
//
|
|
1633
|
+
// set the default text align and baseline
|
|
1626
1634
|
instance.textalign('start', 'top')
|
|
1627
1635
|
|
|
1628
1636
|
// trigger "resized" event
|
|
1637
|
+
// note: not triggered before the "init" event
|
|
1629
1638
|
instance.emit('resized', _scale)
|
|
1630
1639
|
|
|
1640
|
+
// paint a temporary background
|
|
1631
1641
|
instance.cls(0)
|
|
1632
1642
|
|
|
1633
|
-
// force redraw
|
|
1643
|
+
// force redraw when the canvas is not animated
|
|
1634
1644
|
if (!settings.animate) {
|
|
1635
1645
|
raf(drawFrame)
|
|
1636
1646
|
}
|
package/src/version.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
// Generated by genversion.
|
|
2
|
-
export const version = '0.
|
|
2
|
+
export const version = '0.93.1'
|
package/types/types.d.ts
CHANGED
|
@@ -594,19 +594,18 @@ type LitecanvasOptions = {
|
|
|
594
594
|
canvas?: HTMLCanvasElement | string
|
|
595
595
|
/**
|
|
596
596
|
* If `true` (default) scales the canvas to fill the screen, but preserving the aspect ratio.
|
|
597
|
-
* Instead of `true`, you can pass a number to
|
|
597
|
+
* Instead of `true`, you can pass a number to determine the maximum scale.
|
|
598
598
|
*
|
|
599
599
|
* Note: Only works if the option "width" was specified.
|
|
600
600
|
*/
|
|
601
601
|
autoscale?: boolean | number
|
|
602
602
|
/**
|
|
603
603
|
* If `true`, the pixel art images won't look blurry.
|
|
604
|
+
* Also, disables canvas built-in antialias.
|
|
605
|
+
*
|
|
606
|
+
* Default: `false`
|
|
604
607
|
*/
|
|
605
608
|
pixelart?: boolean
|
|
606
|
-
/**
|
|
607
|
-
* If `false` (default), disable the canvas antialias.
|
|
608
|
-
*/
|
|
609
|
-
antialias?: boolean
|
|
610
609
|
/**
|
|
611
610
|
* If `true` (default), all methods and properties of the engine will be exposed to the global scope (window).
|
|
612
611
|
*/
|