litecanvas 0.75.1 → 0.76.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/dist/dist.dev.js +55 -46
- package/dist/dist.js +40 -42
- package/dist/dist.min.js +1 -1
- package/package.json +3 -3
- package/src/index.js +63 -56
- package/src/types.js +0 -2
- package/types/types.d.ts +1 -9
package/README.md
CHANGED
package/dist/dist.dev.js
CHANGED
|
@@ -36,7 +36,6 @@
|
|
|
36
36
|
() => elem.removeEventListener(evt, callback, false)
|
|
37
37
|
);
|
|
38
38
|
}, isFinite = Number.isFinite, defaults = {
|
|
39
|
-
fullscreen: true,
|
|
40
39
|
width: null,
|
|
41
40
|
height: null,
|
|
42
41
|
autoscale: true,
|
|
@@ -51,7 +50,7 @@
|
|
|
51
50
|
animate: true
|
|
52
51
|
};
|
|
53
52
|
settings = Object.assign(defaults, settings);
|
|
54
|
-
let _initialized = false, _plugins = [], _canvas = settings.canvas || document.createElement("canvas"),
|
|
53
|
+
let _initialized = false, _plugins = [], _canvas = settings.canvas || document.createElement("canvas"), _autoscale = settings.autoscale, _animated = settings.animate, _scale = 1, _ctx, _outline_fix = 0.5, _timeScale = 1, _lastFrameTime, _deltaTime, _accumulated = 0, _rafid, _fontFamily = "sans-serif", _fontSize = 32, _rng_seed = Date.now(), _global = settings.global, _events = {
|
|
55
54
|
init: null,
|
|
56
55
|
update: null,
|
|
57
56
|
draw: null,
|
|
@@ -894,9 +893,11 @@
|
|
|
894
893
|
"string" === typeof eventName,
|
|
895
894
|
"emit: 1st param must be a string"
|
|
896
895
|
);
|
|
897
|
-
|
|
898
|
-
|
|
899
|
-
|
|
896
|
+
if (_initialized) {
|
|
897
|
+
triggerEvent("before:" + eventName, arg1, arg2, arg3, arg4);
|
|
898
|
+
triggerEvent(eventName, arg1, arg2, arg3, arg4);
|
|
899
|
+
triggerEvent("after:" + eventName, arg1, arg2, arg3, arg4);
|
|
900
|
+
}
|
|
900
901
|
},
|
|
901
902
|
/**
|
|
902
903
|
* Get a color by index
|
|
@@ -937,11 +938,19 @@
|
|
|
937
938
|
* @param {number} height
|
|
938
939
|
*/
|
|
939
940
|
resize(width, height) {
|
|
940
|
-
DEV: assert(
|
|
941
|
-
|
|
941
|
+
DEV: assert(
|
|
942
|
+
isFinite(width) && width > 0,
|
|
943
|
+
"resize: 1st param must be a number"
|
|
944
|
+
);
|
|
945
|
+
DEV: assert(
|
|
946
|
+
isFinite(height) && height > 0,
|
|
947
|
+
"resize: 2nd param must be a number"
|
|
948
|
+
);
|
|
942
949
|
instance.setvar("WIDTH", _canvas.width = width);
|
|
943
950
|
instance.setvar("HEIGHT", _canvas.height = height);
|
|
944
|
-
|
|
951
|
+
instance.setvar("CENTERX", instance.WIDTH / 2);
|
|
952
|
+
instance.setvar("CENTERY", instance.HEIGHT / 2);
|
|
953
|
+
onResize();
|
|
945
954
|
},
|
|
946
955
|
/**
|
|
947
956
|
* The scale of the game's delta time (dt).
|
|
@@ -999,10 +1008,9 @@
|
|
|
999
1008
|
for (const [callback, config] of _plugins) {
|
|
1000
1009
|
loadPlugin(callback, config);
|
|
1001
1010
|
}
|
|
1002
|
-
if (
|
|
1003
|
-
on(root, "resize",
|
|
1011
|
+
if (_autoscale) {
|
|
1012
|
+
on(root, "resize", onResize);
|
|
1004
1013
|
}
|
|
1005
|
-
pageResized();
|
|
1006
1014
|
if (settings.tapEvents) {
|
|
1007
1015
|
const _getXY = (pageX, pageY) => [
|
|
1008
1016
|
(pageX - _canvas.offsetLeft) / _scale,
|
|
@@ -1139,21 +1147,23 @@
|
|
|
1139
1147
|
}
|
|
1140
1148
|
let updated = 0, frameTime = (now - _lastFrameTime) / 1e3;
|
|
1141
1149
|
_lastFrameTime = now;
|
|
1142
|
-
if (frameTime > _deltaTime * 30)
|
|
1143
|
-
|
|
1144
|
-
|
|
1145
|
-
|
|
1146
|
-
|
|
1147
|
-
|
|
1148
|
-
|
|
1149
|
-
|
|
1150
|
-
|
|
1151
|
-
|
|
1152
|
-
|
|
1153
|
-
|
|
1154
|
-
|
|
1150
|
+
if (frameTime > _deltaTime * 30) {
|
|
1151
|
+
console.log("skipping too long frame");
|
|
1152
|
+
} else {
|
|
1153
|
+
_accumulated += frameTime;
|
|
1154
|
+
if (!_animated) {
|
|
1155
|
+
_accumulated = _deltaTime;
|
|
1156
|
+
}
|
|
1157
|
+
for (; _accumulated >= _deltaTime; _accumulated -= _deltaTime) {
|
|
1158
|
+
instance.emit("update", _deltaTime * _timeScale);
|
|
1159
|
+
instance.setvar(
|
|
1160
|
+
"ELAPSED",
|
|
1161
|
+
instance.ELAPSED + _deltaTime * _timeScale
|
|
1162
|
+
);
|
|
1163
|
+
updated++;
|
|
1164
|
+
}
|
|
1155
1165
|
}
|
|
1156
|
-
if (updated) {
|
|
1166
|
+
if (updated || !_animated) {
|
|
1157
1167
|
instance.textalign("start", "top");
|
|
1158
1168
|
instance.emit("draw");
|
|
1159
1169
|
}
|
|
@@ -1165,44 +1175,43 @@
|
|
|
1165
1175
|
"Invalid canvas element"
|
|
1166
1176
|
);
|
|
1167
1177
|
DEV: assert(
|
|
1168
|
-
null
|
|
1178
|
+
null == instance.WIDTH || instance.WIDTH > 0,
|
|
1169
1179
|
`Litecanvas' "width" option should be null or a positive number`
|
|
1170
1180
|
);
|
|
1171
1181
|
DEV: assert(
|
|
1172
|
-
null
|
|
1182
|
+
null == instance.HEIGHT || instance.HEIGHT > 0,
|
|
1173
1183
|
`Litecanvas' "width" option should be null or a positive number`
|
|
1174
1184
|
);
|
|
1185
|
+
DEV: assert(
|
|
1186
|
+
null == instance.HEIGHT || instance.WIDTH > 0 && instance.HEIGHT > 0,
|
|
1187
|
+
`Litecanvas' "width" is required when "heigth" is passed`
|
|
1188
|
+
);
|
|
1175
1189
|
instance.setvar("CANVAS", _canvas);
|
|
1176
1190
|
_ctx = _canvas.getContext("2d");
|
|
1177
1191
|
on(_canvas, "click", () => root.focus());
|
|
1178
|
-
if (instance.WIDTH > 0) {
|
|
1179
|
-
_fullscreen = false;
|
|
1180
|
-
}
|
|
1181
1192
|
_canvas.style = "";
|
|
1182
|
-
|
|
1183
|
-
|
|
1193
|
+
if (!instance.WIDTH) {
|
|
1194
|
+
instance.WIDTH = root.innerWidth;
|
|
1195
|
+
instance.HEIGHT = root.innerHeight;
|
|
1196
|
+
}
|
|
1197
|
+
instance.resize(instance.WIDTH, instance.HEIGHT, false);
|
|
1184
1198
|
if (!_canvas.parentNode) document.body.appendChild(_canvas);
|
|
1185
1199
|
}
|
|
1186
|
-
function
|
|
1187
|
-
const
|
|
1188
|
-
|
|
1189
|
-
|
|
1190
|
-
|
|
1191
|
-
|
|
1192
|
-
|
|
1193
|
-
instance.setvar("HEIGHT", _canvas.height = pageHeight);
|
|
1194
|
-
} else if (_autoscale) {
|
|
1195
|
-
styles.margin = "auto";
|
|
1200
|
+
function onResize() {
|
|
1201
|
+
const styles = _canvas.style;
|
|
1202
|
+
if (_autoscale) {
|
|
1203
|
+
if (!styles.display) {
|
|
1204
|
+
styles.display = "block";
|
|
1205
|
+
styles.margin = "auto";
|
|
1206
|
+
}
|
|
1196
1207
|
_scale = Math.min(
|
|
1197
|
-
|
|
1198
|
-
|
|
1208
|
+
root.innerWidth / instance.WIDTH,
|
|
1209
|
+
root.innerHeight / instance.HEIGHT
|
|
1199
1210
|
);
|
|
1200
1211
|
_scale = (settings.pixelart ? ~~_scale : _scale) || 1;
|
|
1201
1212
|
styles.width = instance.WIDTH * _scale + "px";
|
|
1202
1213
|
styles.height = instance.HEIGHT * _scale + "px";
|
|
1203
1214
|
}
|
|
1204
|
-
instance.setvar("CENTERX", instance.WIDTH / 2);
|
|
1205
|
-
instance.setvar("CENTERY", instance.HEIGHT / 2);
|
|
1206
1215
|
if (!settings.antialias || settings.pixelart) {
|
|
1207
1216
|
_ctx.imageSmoothingEnabled = false;
|
|
1208
1217
|
styles.imageRendering = "pixelated";
|
package/dist/dist.js
CHANGED
|
@@ -31,7 +31,6 @@
|
|
|
31
31
|
() => elem.removeEventListener(evt, callback, false)
|
|
32
32
|
);
|
|
33
33
|
}, isFinite = Number.isFinite, defaults = {
|
|
34
|
-
fullscreen: true,
|
|
35
34
|
width: null,
|
|
36
35
|
height: null,
|
|
37
36
|
autoscale: true,
|
|
@@ -46,7 +45,7 @@
|
|
|
46
45
|
animate: true
|
|
47
46
|
};
|
|
48
47
|
settings = Object.assign(defaults, settings);
|
|
49
|
-
let _initialized = false, _plugins = [], _canvas = settings.canvas || document.createElement("canvas"),
|
|
48
|
+
let _initialized = false, _plugins = [], _canvas = settings.canvas || document.createElement("canvas"), _autoscale = settings.autoscale, _animated = settings.animate, _scale = 1, _ctx, _outline_fix = 0.5, _timeScale = 1, _lastFrameTime, _deltaTime, _accumulated = 0, _rafid, _fontFamily = "sans-serif", _fontSize = 32, _rng_seed = Date.now(), _global = settings.global, _events = {
|
|
50
49
|
init: null,
|
|
51
50
|
update: null,
|
|
52
51
|
draw: null,
|
|
@@ -637,9 +636,11 @@
|
|
|
637
636
|
* @param {*} [arg4] any data to be passed over the listeners
|
|
638
637
|
*/
|
|
639
638
|
emit(eventName, arg1, arg2, arg3, arg4) {
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
639
|
+
if (_initialized) {
|
|
640
|
+
triggerEvent("before:" + eventName, arg1, arg2, arg3, arg4);
|
|
641
|
+
triggerEvent(eventName, arg1, arg2, arg3, arg4);
|
|
642
|
+
triggerEvent("after:" + eventName, arg1, arg2, arg3, arg4);
|
|
643
|
+
}
|
|
643
644
|
},
|
|
644
645
|
/**
|
|
645
646
|
* Get a color by index
|
|
@@ -673,7 +674,9 @@
|
|
|
673
674
|
resize(width, height) {
|
|
674
675
|
instance.setvar("WIDTH", _canvas.width = width);
|
|
675
676
|
instance.setvar("HEIGHT", _canvas.height = height);
|
|
676
|
-
|
|
677
|
+
instance.setvar("CENTERX", instance.WIDTH / 2);
|
|
678
|
+
instance.setvar("CENTERY", instance.HEIGHT / 2);
|
|
679
|
+
onResize();
|
|
677
680
|
},
|
|
678
681
|
/**
|
|
679
682
|
* The scale of the game's delta time (dt).
|
|
@@ -723,10 +726,9 @@
|
|
|
723
726
|
for (const [callback, config] of _plugins) {
|
|
724
727
|
loadPlugin(callback, config);
|
|
725
728
|
}
|
|
726
|
-
if (
|
|
727
|
-
on(root, "resize",
|
|
729
|
+
if (_autoscale) {
|
|
730
|
+
on(root, "resize", onResize);
|
|
728
731
|
}
|
|
729
|
-
pageResized();
|
|
730
732
|
if (settings.tapEvents) {
|
|
731
733
|
const _getXY = (pageX, pageY) => [
|
|
732
734
|
(pageX - _canvas.offsetLeft) / _scale,
|
|
@@ -859,21 +861,22 @@
|
|
|
859
861
|
}
|
|
860
862
|
let updated = 0, frameTime = (now - _lastFrameTime) / 1e3;
|
|
861
863
|
_lastFrameTime = now;
|
|
862
|
-
if (frameTime > _deltaTime * 30)
|
|
863
|
-
|
|
864
|
-
|
|
865
|
-
|
|
866
|
-
|
|
867
|
-
|
|
868
|
-
|
|
869
|
-
|
|
870
|
-
|
|
871
|
-
|
|
872
|
-
|
|
873
|
-
|
|
874
|
-
|
|
864
|
+
if (frameTime > _deltaTime * 30) {
|
|
865
|
+
} else {
|
|
866
|
+
_accumulated += frameTime;
|
|
867
|
+
if (!_animated) {
|
|
868
|
+
_accumulated = _deltaTime;
|
|
869
|
+
}
|
|
870
|
+
for (; _accumulated >= _deltaTime; _accumulated -= _deltaTime) {
|
|
871
|
+
instance.emit("update", _deltaTime * _timeScale);
|
|
872
|
+
instance.setvar(
|
|
873
|
+
"ELAPSED",
|
|
874
|
+
instance.ELAPSED + _deltaTime * _timeScale
|
|
875
|
+
);
|
|
876
|
+
updated++;
|
|
877
|
+
}
|
|
875
878
|
}
|
|
876
|
-
if (updated) {
|
|
879
|
+
if (updated || !_animated) {
|
|
877
880
|
instance.textalign("start", "top");
|
|
878
881
|
instance.emit("draw");
|
|
879
882
|
}
|
|
@@ -883,34 +886,29 @@
|
|
|
883
886
|
instance.setvar("CANVAS", _canvas);
|
|
884
887
|
_ctx = _canvas.getContext("2d");
|
|
885
888
|
on(_canvas, "click", () => root.focus());
|
|
886
|
-
if (instance.WIDTH > 0) {
|
|
887
|
-
_fullscreen = false;
|
|
888
|
-
}
|
|
889
889
|
_canvas.style = "";
|
|
890
|
-
|
|
891
|
-
|
|
890
|
+
if (!instance.WIDTH) {
|
|
891
|
+
instance.WIDTH = root.innerWidth;
|
|
892
|
+
instance.HEIGHT = root.innerHeight;
|
|
893
|
+
}
|
|
894
|
+
instance.resize(instance.WIDTH, instance.HEIGHT, false);
|
|
892
895
|
if (!_canvas.parentNode) document.body.appendChild(_canvas);
|
|
893
896
|
}
|
|
894
|
-
function
|
|
895
|
-
const
|
|
896
|
-
|
|
897
|
-
|
|
898
|
-
|
|
899
|
-
|
|
900
|
-
|
|
901
|
-
instance.setvar("HEIGHT", _canvas.height = pageHeight);
|
|
902
|
-
} else if (_autoscale) {
|
|
903
|
-
styles.margin = "auto";
|
|
897
|
+
function onResize() {
|
|
898
|
+
const styles = _canvas.style;
|
|
899
|
+
if (_autoscale) {
|
|
900
|
+
if (!styles.display) {
|
|
901
|
+
styles.display = "block";
|
|
902
|
+
styles.margin = "auto";
|
|
903
|
+
}
|
|
904
904
|
_scale = Math.min(
|
|
905
|
-
|
|
906
|
-
|
|
905
|
+
root.innerWidth / instance.WIDTH,
|
|
906
|
+
root.innerHeight / instance.HEIGHT
|
|
907
907
|
);
|
|
908
908
|
_scale = (settings.pixelart ? ~~_scale : _scale) || 1;
|
|
909
909
|
styles.width = instance.WIDTH * _scale + "px";
|
|
910
910
|
styles.height = instance.HEIGHT * _scale + "px";
|
|
911
911
|
}
|
|
912
|
-
instance.setvar("CENTERX", instance.WIDTH / 2);
|
|
913
|
-
instance.setvar("CENTERY", instance.HEIGHT / 2);
|
|
914
912
|
if (!settings.antialias || settings.pixelart) {
|
|
915
913
|
_ctx.imageSmoothingEnabled = false;
|
|
916
914
|
styles.imageRendering = "pixelated";
|
package/dist/dist.min.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
(()=>{var e=new AudioContext,t=(t=1,a=.05,l=220,n=0,i=0,o=.1,r=0,s=1,c=0,f=0,
|
|
1
|
+
(()=>{var e=new AudioContext,t=(t=1,a=.05,l=220,n=0,i=0,o=.1,r=0,s=1,c=0,f=0,d=0,p=0,u=0,h=0,g=0,m=0,v=0,E=1,b=0,x=0,T=0)=>{let w=Math,y=2*w.PI,H=c*=500*y/44100/44100,I=l*=(1-a+2*a*w.random(a=[]))*y/44100,S=0,D=0,A=0,k=1,C=0,L=0,X=0,z=T<0?-1:1,P=y*z*T*2/44100,M=w.cos(P),O=w.sin,Y=O(P)/4,F=1+Y,W=-2*M/F,_=(1-Y)/F,R=(1+z*M)/2/F,G=-(z+M)/F,N=0,B=0,U=0,q=0;for(n=44100*n+9,b*=44100,i*=44100,o*=44100,v*=44100,f*=500*y/85766121e6,g*=y/44100,d*=y/44100,p*=44100,u=44100*u|0,t*=.3*(globalThis.zzfxV||1),z=n+b+i+o+v|0;A<z;a[A++]=X*t)++L%(100*m|0)||(X=r?1<r?2<r?3<r?O(S*S):w.max(w.min(w.tan(S),1),-1):1-(2*S/y%2+2)%2:1-4*w.abs(w.round(S/y)-S/y):O(S),X=(u?1-x+x*O(y*A/u):1)*(X<0?-1:1)*w.abs(X)**s*(A<n?A/n:A<n+b?1-(A-n)/b*(1-E):A<n+b+i?E:A<z-v?(z-A-v)/o*E:0),X=v?X/2+(v>A?0:(A<z-v?1:(z-A)/v)*a[A-v|0]/2/t):X,T&&(X=q=R*N+G*(N=B)+R*(B=X)-_*U-W*(U=q))),S+=(P=(l+=c+=f)*w.cos(g*D++))+P*h*O(A**5),k&&++k>p&&(l+=d,I+=d,k=0),!u||++C%u||(l=I,c=H,k=k||1);(t=e.createBuffer(1,z,44100)).getChannelData(0).set(a),(l=e.createBufferSource()).buffer=t,l.connect(e.destination),l.start()},a=["#111","#6a7799","#aec2c2","#FFF1E8","#e83b3b","#fabc20","#155fd9","#3cbcfc","#327345","#63c64d","#6c2c1f","#ac7c00"];globalThis.litecanvas=function(e={}){let l=globalThis,n=Math.PI,i=2*n,o=requestAnimationFrame,r=[],s=(e,t,a)=>{e.addEventListener(t,a,!1),r.push(()=>e.removeEventListener(t,a,!1))};e=Object.assign({width:null,height:null,autoscale:!0,pixelart:!1,antialias:!1,canvas:null,global:!0,loop:null,pauseOnBlur:!0,tapEvents:!0,keyboardEvents:!0,animate:!0},e);let c=!1,f=[],d=e.canvas||document.createElement("canvas"),p=e.autoscale,u=e.animate,h=1,g,m=.5,v=1,E,b,x=0,T,w="sans-serif",y=32,H=Date.now(),I=e.global,S={init:null,update:null,draw:null,resized:null,tap:null,untap:null,tapping:null,tapped:null},D={settings:Object.assign({},e),colors:a},A={WIDTH:e.width,HEIGHT:e.height||e.width,CANVAS:null,ELAPSED:0,CENTERX:0,CENTERY:0,MOUSEX:-1,MOUSEY:-1,DEFAULT_SFX:[.5,,1675,,.06,.2,1,1.8,,,637,.06],TWO_PI:i,HALF_PI:n/2,lerp:(e,t,a)=>a*(t-e)+e,deg2rad:e=>n/180*e,rad2deg:e=>180/n*e,clamp:(e,t,a)=>e<t?t:e>a?a:e,wrap:(e,t,a)=>e-(a-t)*Math.floor((e-t)/(a-t)),map(e,t,a,l,n,i){let o=(e-t)/(a-t)*(n-l)+l;return i?A.clamp(o,l,n):o},norm:(e,t,a)=>A.map(e,t,a,0,1),rand:(e=0,t=1)=>(H=(1664525*H+0x3c6ef35f)%0x100000000)/0x100000000*(t-e)+e,randi:(e=0,t=1)=>Math.floor(A.rand(e,t+1)),seed:e=>null==e?H:H=~~e,cls(e){null==e?g.clearRect(0,0,g.canvas.width,g.canvas.height):A.rectfill(0,0,g.canvas.width,g.canvas.height,e)},rect(e,t,a,l,n,i=null){g.beginPath(),g[i?"roundRect":"rect"](~~e-m,~~t-m,~~a+2*m,~~l+2*m,i),A.stroke(n)},rectfill(e,t,a,l,n,i=null){g.beginPath(),g[i?"roundRect":"rect"](~~e,~~t,~~a,~~l,i),A.fill(n)},circ(e,t,a,l){g.beginPath(),g.arc(~~e,~~t,~~a,0,i),A.stroke(l)},circfill(e,t,a,l){g.beginPath(),g.arc(~~e,~~t,~~a,0,i),A.fill(l)},line(e,t,a,l,n){g.beginPath();let i=.5*(0!==m&&~~e==~~a),o=.5*(0!==m&&~~t==~~l);g.moveTo(~~e+i,~~t+o),g.lineTo(~~a+i,~~l+o),A.stroke(n)},linewidth(e){g.lineWidth=~~e,m=.5*(~~e%2!=0)},linedash(e,t=0){g.setLineDash(e),g.lineDashOffset=t},text(e,t,a,l=3,n="normal"){g.font=`${n} ${y}px ${w}`,g.fillStyle=A.getcolor(l),g.fillText(a,~~e,~~t)},textfont(e){w=e},textsize(e){y=e},textalign(e,t){e&&(g.textAlign=e),t&&(g.textBaseline=t)},image(e,t,a){g.drawImage(a,~~e,~~t)},paint(e,t,a,l={}){let n=l.canvas||new OffscreenCanvas(1,1),i=l.scale||1,o=g;if(n.width=e*i,n.height=t*i,(g=n.getContext("2d")).scale(i,i),a.push){let e=0,t=0;for(let l of(g.imageSmoothingEnabled=!1,a)){for(let a of l)" "!==a&&"."!==a&&A.rectfill(e,t,1,1,parseInt(a,16)),e++;t++,e=0}}else a(g);return g=o,n},ctx:e=>(e&&(g=e),g),push:()=>g.save(),pop:()=>g.restore(),translate:(e,t)=>g.translate(~~e,~~t),scale:(e,t)=>g.scale(e,t||e),rotate:e=>g.rotate(e),alpha(e){g.globalAlpha=A.clamp(e,0,1)},path:e=>new Path2D(e),fill(e,t){g.fillStyle=A.getcolor(e),t?g.fill(t):g.fill()},stroke(e,t){g.strokeStyle=A.getcolor(e),t?g.stroke(t):g.stroke()},clip(e){g.clip(e)},sfx:(e,a=0,n=1)=>!(l.zzfxV<=0)&&(!navigator.userActivation||!!navigator.userActivation.hasBeenActive)&&(e=e||A.DEFAULT_SFX,(0!==a||1!==n)&&((e=e.slice())[0]=n*(e[0]||1),e[10]=~~e[10]+a),t.apply(0,e),e),volume(e){l.zzfxV=e},colrect:(e,t,a,l,n,i,o,r)=>e<n+o&&e+a>n&&t<i+r&&t+l>i,colcirc:(e,t,a,l,n,i)=>(l-e)*(l-e)+(n-t)*(n-t)<=(a+i)*(a+i),use(e,t={}){c?z(e,t):f.push([e,t])},listen:(e,t)=>(S[e]=S[e]||new Set,S[e].add(t),()=>S[e].delete(t)),emit(e,t,a,l,n){c&&(X("before:"+e,t,a,l,n),X(e,t,a,l,n),X("after:"+e,t,a,l,n))},getcolor:e=>a[~~e%a.length],setvar(e,t){A[e]=t,I&&(l[e]=t)},resize(e,t){A.setvar("WIDTH",d.width=e),A.setvar("HEIGHT",d.height=t),A.setvar("CENTERX",A.WIDTH/2),A.setvar("CENTERY",A.HEIGHT/2),L()},timescale(e){v=e},setfps(e){b=1/~~e},quit(){for(let e of(A.emit("quit"),r))e();if(cancelAnimationFrame(T),S=!1,I){for(let e in A)delete l[e];delete l.__litecanvas}}};for(let e of"PI,sin,cos,atan2,hypot,tan,abs,ceil,round,floor,trunc,min,max,pow,sqrt,sign,exp".split(","))A[e]=Math[e];function k(){c=!0;let t=e.loop?e.loop:l;for(let e in S)t[e]&&A.listen(e,t[e]);for(let[e,t]of f)z(e,t);if(p&&s(l,"resize",L),e.tapEvents){let e=(e,t)=>[(e-d.offsetLeft)/h,(t-d.offsetTop)/h],t=new Map,a=(e,a,l)=>{let n={x:a,y:l,startX:a,startY:l,ts:performance.now()};return t.set(e,n),n},n=(e,l,n)=>{let i=t.get(e)||a(e);i.x=l,i.y=n},i=e=>e&&performance.now()-e.ts<=200,o=e=>e.preventDefault(),r=!1;s(d,"mousedown",t=>{if(0===t.button){o(t);let[l,n]=e(t.pageX,t.pageY);A.emit("tap",l,n,0),a(0,l,n),r=!0}}),s(d,"mouseup",a=>{if(0===a.button){o(a);let l=t.get(0),[n,s]=e(a.pageX,a.pageY);i(l)&&A.emit("tapped",l.startX,l.startY,0),A.emit("untap",n,s,0),t.delete(0),r=!1}}),s(d,"mousemove",t=>{o(t);let[a,l]=e(t.pageX,t.pageY);A.setvar("MOUSEX",a),A.setvar("MOUSEY",l),r&&(A.emit("tapping",a,l,0),n(0,a,l))}),s(d,"touchstart",t=>{for(let l of(o(t),t.changedTouches)){let[t,n]=e(l.pageX,l.pageY);A.emit("tap",t,n,l.identifier+1),a(l.identifier+1,t,n)}}),s(d,"touchmove",t=>{for(let a of(o(t),t.changedTouches)){let[t,l]=e(a.pageX,a.pageY);A.emit("tapping",t,l,a.identifier+1),n(a.identifier+1,t,l)}});let c=e=>{o(e);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)&&A.emit("tapped",l.startX,l.startY,e),A.emit("untap",l.x,l.y,e),t.delete(e))};s(d,"touchend",c),s(d,"touchcancel",c),s(l,"blur",()=>{for(let[e,a]of(r=!1,t))A.emit("untap",a.x,a.y,e),t.delete(e)})}if(e.keyboardEvents){let e=new Set;A.setvar("iskeydown",t=>"any"===t?e.size>0:e.has(t.toLowerCase())),s(l,"keydown",t=>{e.add(t.key.toLowerCase())}),s(l,"keyup",t=>{e.delete(t.key.toLowerCase())}),s(l,"blur",()=>e.clear())}e.pauseOnBlur&&(s(l,"blur",()=>{T=cancelAnimationFrame(T)}),s(l,"focus",()=>{T||(T=o(C))})),A.setfps(60),A.emit("init",A),E=performance.now(),T=o(C)}function C(e){u&&(T=o(C));let t=0,a=(e-E)/1e3;if(E=e,a>30*b);else for(x+=a,u||(x=b);x>=b;x-=b)A.emit("update",b*v),A.setvar("ELAPSED",A.ELAPSED+b*v),t++;(t||!u)&&(A.textalign("start","top"),A.emit("draw"))}function L(){let t=d.style;p&&(t.display||(t.display="block",t.margin="auto"),h=Math.min(l.innerWidth/A.WIDTH,l.innerHeight/A.HEIGHT),h=(e.pixelart?~~h:h)||1,t.width=A.WIDTH*h+"px",t.height=A.HEIGHT*h+"px"),(!e.antialias||e.pixelart)&&(g.imageSmoothingEnabled=!1,t.imageRendering="pixelated"),A.emit("resized",h),u||o(C)}function X(e,t,a,l,n){if(S[e])for(let i of S[e])i(t,a,l,n)}function z(e,t){let a=e(A,D,t);for(let e in a)A.setvar(e,a[e])}if(I){if(l.__litecanvas)throw"global litecanvas already instantiated";Object.assign(l,A),l.__litecanvas=A}return d="string"==typeof d?document.querySelector(d):d,A.setvar("CANVAS",d),g=d.getContext("2d"),s(d,"click",()=>l.focus()),d.style="",A.WIDTH||(A.WIDTH=l.innerWidth,A.HEIGHT=l.innerHeight),A.resize(A.WIDTH,A.HEIGHT,!1),d.parentNode||document.body.appendChild(d),"loading"===document.readyState?s(l,"DOMContentLoaded",()=>o(k)):o(k),A}})();
|
package/package.json
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "litecanvas",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.76.0",
|
|
4
4
|
"description": "Lightweight HTML5 canvas 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>",
|
|
7
7
|
"contributors": [],
|
|
8
8
|
"devDependencies": {
|
|
9
|
-
"@swc/core": "^1.11.
|
|
9
|
+
"@swc/core": "^1.11.8",
|
|
10
10
|
"ava": "^6.2.0",
|
|
11
|
-
"esbuild": "^0.25.
|
|
11
|
+
"esbuild": "^0.25.1",
|
|
12
12
|
"gzip-size": "^7.0.0",
|
|
13
13
|
"prettier": "^3.5.3"
|
|
14
14
|
},
|
package/src/index.js
CHANGED
|
@@ -26,7 +26,6 @@ export default function litecanvas(settings = {}) {
|
|
|
26
26
|
isFinite = Number.isFinite,
|
|
27
27
|
/** @type {LitecanvasOptions} */
|
|
28
28
|
defaults = {
|
|
29
|
-
fullscreen: true,
|
|
30
29
|
width: null,
|
|
31
30
|
height: null,
|
|
32
31
|
autoscale: true,
|
|
@@ -51,8 +50,6 @@ export default function litecanvas(settings = {}) {
|
|
|
51
50
|
/** @type {HTMLCanvasElement|string} _canvas */
|
|
52
51
|
_canvas = settings.canvas || document.createElement('canvas'),
|
|
53
52
|
/** @type {boolean} */
|
|
54
|
-
_fullscreen = settings.fullscreen,
|
|
55
|
-
/** @type {boolean} */
|
|
56
53
|
_autoscale = settings.autoscale,
|
|
57
54
|
/** @type {boolean} */
|
|
58
55
|
_animated = settings.animate,
|
|
@@ -1069,10 +1066,11 @@ export default function litecanvas(settings = {}) {
|
|
|
1069
1066
|
'string' === typeof eventName,
|
|
1070
1067
|
'emit: 1st param must be a string'
|
|
1071
1068
|
)
|
|
1072
|
-
|
|
1073
|
-
|
|
1074
|
-
|
|
1075
|
-
|
|
1069
|
+
if (_initialized) {
|
|
1070
|
+
triggerEvent('before:' + eventName, arg1, arg2, arg3, arg4)
|
|
1071
|
+
triggerEvent(eventName, arg1, arg2, arg3, arg4)
|
|
1072
|
+
triggerEvent('after:' + eventName, arg1, arg2, arg3, arg4)
|
|
1073
|
+
}
|
|
1076
1074
|
},
|
|
1077
1075
|
|
|
1078
1076
|
/**
|
|
@@ -1118,12 +1116,22 @@ export default function litecanvas(settings = {}) {
|
|
|
1118
1116
|
* @param {number} height
|
|
1119
1117
|
*/
|
|
1120
1118
|
resize(width, height) {
|
|
1121
|
-
DEV: assert(
|
|
1122
|
-
|
|
1119
|
+
DEV: assert(
|
|
1120
|
+
isFinite(width) && width > 0,
|
|
1121
|
+
'resize: 1st param must be a number'
|
|
1122
|
+
)
|
|
1123
|
+
DEV: assert(
|
|
1124
|
+
isFinite(height) && height > 0,
|
|
1125
|
+
'resize: 2nd param must be a number'
|
|
1126
|
+
)
|
|
1123
1127
|
|
|
1124
1128
|
instance.setvar('WIDTH', (_canvas.width = width))
|
|
1125
1129
|
instance.setvar('HEIGHT', (_canvas.height = height))
|
|
1126
|
-
|
|
1130
|
+
|
|
1131
|
+
instance.setvar('CENTERX', instance.WIDTH / 2)
|
|
1132
|
+
instance.setvar('CENTERY', instance.HEIGHT / 2)
|
|
1133
|
+
|
|
1134
|
+
onResize()
|
|
1127
1135
|
},
|
|
1128
1136
|
|
|
1129
1137
|
/**
|
|
@@ -1184,7 +1192,7 @@ export default function litecanvas(settings = {}) {
|
|
|
1184
1192
|
function init() {
|
|
1185
1193
|
_initialized = true
|
|
1186
1194
|
|
|
1187
|
-
//
|
|
1195
|
+
// setup default event listeners
|
|
1188
1196
|
const source = settings.loop ? settings.loop : root
|
|
1189
1197
|
for (const event in _events) {
|
|
1190
1198
|
if (source[event]) instance.listen(event, source[event])
|
|
@@ -1195,13 +1203,11 @@ export default function litecanvas(settings = {}) {
|
|
|
1195
1203
|
loadPlugin(callback, config)
|
|
1196
1204
|
}
|
|
1197
1205
|
|
|
1198
|
-
// listen window resize event
|
|
1199
|
-
if (
|
|
1200
|
-
on(root, 'resize',
|
|
1206
|
+
// listen window resize event when "autoscale" is enabled
|
|
1207
|
+
if (_autoscale) {
|
|
1208
|
+
on(root, 'resize', onResize)
|
|
1201
1209
|
}
|
|
1202
1210
|
|
|
1203
|
-
pageResized()
|
|
1204
|
-
|
|
1205
1211
|
// default mouse/touch handlers
|
|
1206
1212
|
if (settings.tapEvents) {
|
|
1207
1213
|
const _getXY = (pageX, pageY) => [
|
|
@@ -1395,25 +1401,26 @@ export default function litecanvas(settings = {}) {
|
|
|
1395
1401
|
|
|
1396
1402
|
_lastFrameTime = now
|
|
1397
1403
|
|
|
1398
|
-
if (frameTime > _deltaTime * 30)
|
|
1399
|
-
|
|
1400
|
-
|
|
1401
|
-
|
|
1404
|
+
if (frameTime > _deltaTime * 30) {
|
|
1405
|
+
console.log('skipping too long frame')
|
|
1406
|
+
} else {
|
|
1407
|
+
_accumulated += frameTime
|
|
1402
1408
|
|
|
1403
|
-
|
|
1404
|
-
|
|
1405
|
-
|
|
1409
|
+
if (!_animated) {
|
|
1410
|
+
_accumulated = _deltaTime
|
|
1411
|
+
}
|
|
1406
1412
|
|
|
1407
|
-
|
|
1408
|
-
|
|
1409
|
-
|
|
1410
|
-
|
|
1411
|
-
|
|
1412
|
-
|
|
1413
|
-
|
|
1413
|
+
for (; _accumulated >= _deltaTime; _accumulated -= _deltaTime) {
|
|
1414
|
+
instance.emit('update', _deltaTime * _timeScale)
|
|
1415
|
+
instance.setvar(
|
|
1416
|
+
'ELAPSED',
|
|
1417
|
+
instance.ELAPSED + _deltaTime * _timeScale
|
|
1418
|
+
)
|
|
1419
|
+
updated++
|
|
1420
|
+
}
|
|
1414
1421
|
}
|
|
1415
1422
|
|
|
1416
|
-
if (updated) {
|
|
1423
|
+
if (updated || !_animated) {
|
|
1417
1424
|
instance.textalign('start', 'top') // default values for textAlign & textBaseline
|
|
1418
1425
|
instance.emit('draw')
|
|
1419
1426
|
}
|
|
@@ -1431,57 +1438,56 @@ export default function litecanvas(settings = {}) {
|
|
|
1431
1438
|
'Invalid canvas element'
|
|
1432
1439
|
)
|
|
1433
1440
|
DEV: assert(
|
|
1434
|
-
null
|
|
1441
|
+
null == instance.WIDTH || instance.WIDTH > 0,
|
|
1435
1442
|
'Litecanvas\' "width" option should be null or a positive number'
|
|
1436
1443
|
)
|
|
1437
1444
|
DEV: assert(
|
|
1438
|
-
null
|
|
1445
|
+
null == instance.HEIGHT || instance.HEIGHT > 0,
|
|
1439
1446
|
'Litecanvas\' "width" option should be null or a positive number'
|
|
1440
1447
|
)
|
|
1448
|
+
DEV: assert(
|
|
1449
|
+
null == instance.HEIGHT ||
|
|
1450
|
+
(instance.WIDTH > 0 && instance.HEIGHT > 0),
|
|
1451
|
+
'Litecanvas\' "width" is required when "heigth" is passed'
|
|
1452
|
+
)
|
|
1441
1453
|
|
|
1442
1454
|
instance.setvar('CANVAS', _canvas)
|
|
1443
1455
|
_ctx = _canvas.getContext('2d')
|
|
1444
1456
|
|
|
1445
1457
|
on(_canvas, 'click', () => root.focus())
|
|
1446
1458
|
|
|
1447
|
-
|
|
1448
|
-
|
|
1449
|
-
|
|
1459
|
+
_canvas.style = ''
|
|
1460
|
+
|
|
1461
|
+
// If width is not set, the canvas will have the size of the page width.
|
|
1462
|
+
if (!instance.WIDTH) {
|
|
1463
|
+
instance.WIDTH = root.innerWidth
|
|
1464
|
+
instance.HEIGHT = root.innerHeight
|
|
1450
1465
|
}
|
|
1451
1466
|
|
|
1452
|
-
|
|
1453
|
-
_canvas.width = instance.WIDTH
|
|
1454
|
-
_canvas.height = instance.HEIGHT || instance.WIDTH
|
|
1467
|
+
instance.resize(instance.WIDTH, instance.HEIGHT, false)
|
|
1455
1468
|
|
|
1456
1469
|
if (!_canvas.parentNode) document.body.appendChild(_canvas)
|
|
1457
1470
|
}
|
|
1458
1471
|
|
|
1459
|
-
function
|
|
1460
|
-
const
|
|
1461
|
-
pageHeight = root.innerHeight,
|
|
1462
|
-
styles = _canvas.style
|
|
1472
|
+
function onResize() {
|
|
1473
|
+
const styles = _canvas.style
|
|
1463
1474
|
|
|
1464
|
-
|
|
1475
|
+
if (_autoscale) {
|
|
1476
|
+
if (!styles.display) {
|
|
1477
|
+
styles.display = 'block'
|
|
1478
|
+
styles.margin = 'auto'
|
|
1479
|
+
}
|
|
1465
1480
|
|
|
1466
|
-
if (_fullscreen) {
|
|
1467
|
-
styles.position = 'absolute'
|
|
1468
|
-
styles.inset = 0
|
|
1469
|
-
instance.setvar('WIDTH', (_canvas.width = pageWidth))
|
|
1470
|
-
instance.setvar('HEIGHT', (_canvas.height = pageHeight))
|
|
1471
|
-
} else if (_autoscale) {
|
|
1472
|
-
styles.margin = 'auto'
|
|
1473
1481
|
_scale = Math.min(
|
|
1474
|
-
|
|
1475
|
-
|
|
1482
|
+
root.innerWidth / instance.WIDTH,
|
|
1483
|
+
root.innerHeight / instance.HEIGHT
|
|
1476
1484
|
)
|
|
1477
1485
|
_scale = (settings.pixelart ? ~~_scale : _scale) || 1
|
|
1486
|
+
|
|
1478
1487
|
styles.width = instance.WIDTH * _scale + 'px'
|
|
1479
1488
|
styles.height = instance.HEIGHT * _scale + 'px'
|
|
1480
1489
|
}
|
|
1481
1490
|
|
|
1482
|
-
instance.setvar('CENTERX', instance.WIDTH / 2)
|
|
1483
|
-
instance.setvar('CENTERY', instance.HEIGHT / 2)
|
|
1484
|
-
|
|
1485
1491
|
// restore canvas image rendering properties
|
|
1486
1492
|
if (!settings.antialias || settings.pixelart) {
|
|
1487
1493
|
_ctx.imageSmoothingEnabled = false
|
|
@@ -1490,6 +1496,7 @@ export default function litecanvas(settings = {}) {
|
|
|
1490
1496
|
|
|
1491
1497
|
instance.emit('resized', _scale)
|
|
1492
1498
|
|
|
1499
|
+
// force redraw
|
|
1493
1500
|
if (!_animated) {
|
|
1494
1501
|
raf(drawFrame)
|
|
1495
1502
|
}
|
package/src/types.js
CHANGED
package/types/types.d.ts
CHANGED
|
@@ -579,15 +579,7 @@ type LitecanvasInstance = {
|
|
|
579
579
|
|
|
580
580
|
type LitecanvasOptions = {
|
|
581
581
|
/**
|
|
582
|
-
*
|
|
583
|
-
*/
|
|
584
|
-
fps?: number
|
|
585
|
-
/**
|
|
586
|
-
* Makes the canvas fills the entire page. By default is `true`.
|
|
587
|
-
*/
|
|
588
|
-
fullscreen?: boolean
|
|
589
|
-
/**
|
|
590
|
-
* The game screen width. If specified, disables fullscreen.
|
|
582
|
+
* The game screen width. If not set, the canvas will have the size of the webpage.
|
|
591
583
|
*/
|
|
592
584
|
width?: number
|
|
593
585
|
/**
|