litecanvas 0.98.3 → 0.99.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 +93 -0
- package/dist/dist.dev.js +37 -29
- package/dist/dist.js +29 -26
- package/dist/dist.min.js +1 -1
- package/package.json +1 -1
- package/src/index.js +50 -39
- package/src/version.js +1 -1
- package/types/global.d.ts +9 -8
- package/types/types.d.ts +9 -8
package/README.md
CHANGED
|
@@ -151,6 +151,99 @@ function draw() {
|
|
|
151
151
|
}
|
|
152
152
|
```
|
|
153
153
|
|
|
154
|
+
### Drawing sprites
|
|
155
|
+
|
|
156
|
+
```js
|
|
157
|
+
litecanvas({
|
|
158
|
+
width: 128
|
|
159
|
+
})
|
|
160
|
+
|
|
161
|
+
// you can create sprites with strings
|
|
162
|
+
// each visible char is a pixel
|
|
163
|
+
// numbers are colors
|
|
164
|
+
// dots are transparent pixels
|
|
165
|
+
const smile = `
|
|
166
|
+
.555555.
|
|
167
|
+
55555555
|
|
168
|
+
55055055
|
|
169
|
+
55055055
|
|
170
|
+
55555555
|
|
171
|
+
50555505
|
|
172
|
+
55000055
|
|
173
|
+
.555555.`
|
|
174
|
+
|
|
175
|
+
function draw() {
|
|
176
|
+
cls(0)
|
|
177
|
+
|
|
178
|
+
spr(
|
|
179
|
+
0, 0, // position X Y
|
|
180
|
+
8, 8, // sprite Width and Height
|
|
181
|
+
smile // the pixels
|
|
182
|
+
)
|
|
183
|
+
}
|
|
184
|
+
```
|
|
185
|
+
|
|
186
|
+
### Creating and drawing images
|
|
187
|
+
|
|
188
|
+
```js
|
|
189
|
+
litecanvas()
|
|
190
|
+
|
|
191
|
+
// lets create the flag of the Japan
|
|
192
|
+
const japan = paint(
|
|
193
|
+
48, 32, // image width and height
|
|
194
|
+
function () {
|
|
195
|
+
// the result of this drawings
|
|
196
|
+
// goes to an offscreen canvas
|
|
197
|
+
rectfill(0, 0, 48, 32, 3)
|
|
198
|
+
circfill(24, 16, 8, 4)
|
|
199
|
+
}, {
|
|
200
|
+
// you can scale your image
|
|
201
|
+
// by default, scale=1
|
|
202
|
+
scale: 4
|
|
203
|
+
}
|
|
204
|
+
)
|
|
205
|
+
|
|
206
|
+
function draw() {
|
|
207
|
+
cls(0)
|
|
208
|
+
|
|
209
|
+
// now the japan variable holds a image
|
|
210
|
+
image(W/2 - japan.width/2, H/2 - japan.height/2, japan)
|
|
211
|
+
}
|
|
212
|
+
```
|
|
213
|
+
|
|
214
|
+
It's very useful when you need to draw something the same way every time. This way, you create an image of that drawing, working as a kind of cache.
|
|
215
|
+
|
|
216
|
+
You can also use the `image()` function to draw PNG/JPG images, but you'll need to load them first:
|
|
217
|
+
|
|
218
|
+
```js
|
|
219
|
+
litecanvas()
|
|
220
|
+
|
|
221
|
+
let PngImage
|
|
222
|
+
|
|
223
|
+
function init() {
|
|
224
|
+
// load a image from its URL
|
|
225
|
+
const img = new Image()
|
|
226
|
+
img.onload = () => {
|
|
227
|
+
PngImage = img
|
|
228
|
+
}
|
|
229
|
+
img.src = 'https://litecanvas.js.org/icons/icon-128.png'
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
function draw() {
|
|
233
|
+
cls(0)
|
|
234
|
+
|
|
235
|
+
if (!PngImage) {
|
|
236
|
+
// if not loaded, show this message
|
|
237
|
+
text(10, 10, 'Loading image...')
|
|
238
|
+
} else {
|
|
239
|
+
// when loaded, draw the image file
|
|
240
|
+
image(0, 0, PngImage)
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
```
|
|
244
|
+
|
|
245
|
+
To help you load multiple assets (images, fonts, music, etc.), you can I recommend you the [Asset Loader Plugin](https://github.com/litecanvas/plugin-asset-loader).
|
|
246
|
+
|
|
154
247
|
### Keyboard
|
|
155
248
|
|
|
156
249
|
```js
|
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.99.0";
|
|
36
36
|
|
|
37
37
|
// src/index.js
|
|
38
38
|
function litecanvas(settings = {}) {
|
|
@@ -50,7 +50,7 @@
|
|
|
50
50
|
keyboardEvents: true
|
|
51
51
|
};
|
|
52
52
|
settings = Object.assign(defaults, settings);
|
|
53
|
-
let _initialized = false, _canvas, _scale = 1, _ctx, _outline_fix = 0.5, _timeScale = 1, _lastFrameTime, _fpsInterval = 1e3 / 60, _accumulated, _rafid, _fontFamily = "sans-serif", _fontSize = 20, _rngSeed = Date.now(), _colorPalette = defaultPalette, _colorPaletteState = [], _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 = {};
|
|
53
|
+
let _initialized = false, _paused = true, _canvas, _scale = 1, _ctx, _outline_fix = 0.5, _timeScale = 1, _lastFrameTime, _fpsInterval = 1e3 / 60, _accumulated, _rafid, _fontFamily = "sans-serif", _fontSize = 20, _rngSeed = Date.now(), _colorPalette = defaultPalette, _colorPaletteState = [], _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 = {};
|
|
54
54
|
const instance = {
|
|
55
55
|
/** @type {number} */
|
|
56
56
|
W: 0,
|
|
@@ -283,8 +283,8 @@
|
|
|
283
283
|
*/
|
|
284
284
|
rseed(value) {
|
|
285
285
|
DEV: assert(
|
|
286
|
-
|
|
287
|
-
"[litecanvas] rseed() 1st param must be a positive
|
|
286
|
+
isNumber(value) && value >= 0,
|
|
287
|
+
"[litecanvas] rseed() 1st param must be a positive integer or zero"
|
|
288
288
|
);
|
|
289
289
|
_rngSeed = ~~value;
|
|
290
290
|
},
|
|
@@ -995,7 +995,7 @@
|
|
|
995
995
|
_fpsInterval = 1e3 / ~~value;
|
|
996
996
|
},
|
|
997
997
|
/**
|
|
998
|
-
* Returns information about
|
|
998
|
+
* Returns information about the engine instance.
|
|
999
999
|
*
|
|
1000
1000
|
* @param {number|string} index
|
|
1001
1001
|
* @returns {any}
|
|
@@ -1028,43 +1028,32 @@
|
|
|
1028
1028
|
_rngSeed,
|
|
1029
1029
|
// 10
|
|
1030
1030
|
_fontSize,
|
|
1031
|
-
//
|
|
1032
|
-
_fontFamily
|
|
1031
|
+
// 11
|
|
1032
|
+
_fontFamily,
|
|
1033
|
+
// 12
|
|
1034
|
+
_colorPaletteState
|
|
1033
1035
|
];
|
|
1034
1036
|
const data = { index, value: internals[index] };
|
|
1035
1037
|
instance.emit("stat", data);
|
|
1036
1038
|
return data.value;
|
|
1037
1039
|
},
|
|
1038
|
-
/**
|
|
1039
|
-
* Stops the litecanvas instance and remove all event listeners.
|
|
1040
|
-
*/
|
|
1041
|
-
quit() {
|
|
1042
|
-
instance.pause();
|
|
1043
|
-
instance.emit("quit");
|
|
1044
|
-
_eventListeners = {};
|
|
1045
|
-
for (const removeListener of _browserEventListeners) {
|
|
1046
|
-
removeListener();
|
|
1047
|
-
}
|
|
1048
|
-
if (settings.global) {
|
|
1049
|
-
for (const key in instance) {
|
|
1050
|
-
delete root[key];
|
|
1051
|
-
}
|
|
1052
|
-
delete root.ENGINE;
|
|
1053
|
-
}
|
|
1054
|
-
_initialized = false;
|
|
1055
|
-
},
|
|
1056
1040
|
/**
|
|
1057
1041
|
* Pauses the engine loop (update & draw).
|
|
1058
1042
|
*/
|
|
1059
1043
|
pause() {
|
|
1044
|
+
_paused = true;
|
|
1060
1045
|
cancelAnimationFrame(_rafid);
|
|
1061
|
-
_rafid = 0;
|
|
1062
1046
|
},
|
|
1063
1047
|
/**
|
|
1064
1048
|
* Resumes (if paused) the engine loop.
|
|
1065
1049
|
*/
|
|
1066
1050
|
resume() {
|
|
1067
|
-
|
|
1051
|
+
DEV: assert(
|
|
1052
|
+
_initialized,
|
|
1053
|
+
'[litecanvas] resume() cannot be called before the "init" event and neither after the quit() function'
|
|
1054
|
+
);
|
|
1055
|
+
if (_initialized && _paused) {
|
|
1056
|
+
_paused = false;
|
|
1068
1057
|
_accumulated = _fpsInterval;
|
|
1069
1058
|
_lastFrameTime = Date.now();
|
|
1070
1059
|
_rafid = raf(drawFrame);
|
|
@@ -1076,7 +1065,26 @@
|
|
|
1076
1065
|
* @returns {boolean}
|
|
1077
1066
|
*/
|
|
1078
1067
|
paused() {
|
|
1079
|
-
return
|
|
1068
|
+
return _paused;
|
|
1069
|
+
},
|
|
1070
|
+
/**
|
|
1071
|
+
* Shutdown the litecanvas instance and remove all event listeners.
|
|
1072
|
+
*/
|
|
1073
|
+
quit() {
|
|
1074
|
+
instance.emit("quit");
|
|
1075
|
+
instance.pause();
|
|
1076
|
+
_initialized = false;
|
|
1077
|
+
_eventListeners = {};
|
|
1078
|
+
for (const removeListener of _browserEventListeners) {
|
|
1079
|
+
removeListener();
|
|
1080
|
+
}
|
|
1081
|
+
if (settings.global) {
|
|
1082
|
+
for (const key in instance) {
|
|
1083
|
+
delete root[key];
|
|
1084
|
+
}
|
|
1085
|
+
delete root.ENGINE;
|
|
1086
|
+
}
|
|
1087
|
+
DEV: console.warn("[litecanvas] quit() terminated a Litecanvas instance.");
|
|
1080
1088
|
}
|
|
1081
1089
|
};
|
|
1082
1090
|
for (const k of _mathFunctions.split(",")) {
|
|
@@ -1428,7 +1436,7 @@
|
|
|
1428
1436
|
if ("loading" === document.readyState) {
|
|
1429
1437
|
on(root, "DOMContentLoaded", () => raf(init));
|
|
1430
1438
|
} else {
|
|
1431
|
-
raf(init);
|
|
1439
|
+
_rafid = raf(init);
|
|
1432
1440
|
}
|
|
1433
1441
|
return instance;
|
|
1434
1442
|
}
|
package/dist/dist.js
CHANGED
|
@@ -42,7 +42,7 @@
|
|
|
42
42
|
keyboardEvents: true
|
|
43
43
|
};
|
|
44
44
|
settings = Object.assign(defaults, settings);
|
|
45
|
-
let _initialized = false, _canvas, _scale = 1, _ctx, _outline_fix = 0.5, _timeScale = 1, _lastFrameTime, _fpsInterval = 1e3 / 60, _accumulated, _rafid, _fontFamily = "sans-serif", _fontSize = 20, _rngSeed = Date.now(), _colorPalette = defaultPalette, _colorPaletteState = [], _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 = {};
|
|
45
|
+
let _initialized = false, _paused = true, _canvas, _scale = 1, _ctx, _outline_fix = 0.5, _timeScale = 1, _lastFrameTime, _fpsInterval = 1e3 / 60, _accumulated, _rafid, _fontFamily = "sans-serif", _fontSize = 20, _rngSeed = Date.now(), _colorPalette = defaultPalette, _colorPaletteState = [], _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 = {};
|
|
46
46
|
const instance = {
|
|
47
47
|
/** @type {number} */
|
|
48
48
|
W: 0,
|
|
@@ -687,7 +687,7 @@
|
|
|
687
687
|
_fpsInterval = 1e3 / ~~value;
|
|
688
688
|
},
|
|
689
689
|
/**
|
|
690
|
-
* Returns information about
|
|
690
|
+
* Returns information about the engine instance.
|
|
691
691
|
*
|
|
692
692
|
* @param {number|string} index
|
|
693
693
|
* @returns {any}
|
|
@@ -716,43 +716,28 @@
|
|
|
716
716
|
_rngSeed,
|
|
717
717
|
// 10
|
|
718
718
|
_fontSize,
|
|
719
|
-
//
|
|
720
|
-
_fontFamily
|
|
719
|
+
// 11
|
|
720
|
+
_fontFamily,
|
|
721
|
+
// 12
|
|
722
|
+
_colorPaletteState
|
|
721
723
|
];
|
|
722
724
|
const data = { index, value: internals[index] };
|
|
723
725
|
instance.emit("stat", data);
|
|
724
726
|
return data.value;
|
|
725
727
|
},
|
|
726
|
-
/**
|
|
727
|
-
* Stops the litecanvas instance and remove all event listeners.
|
|
728
|
-
*/
|
|
729
|
-
quit() {
|
|
730
|
-
instance.pause();
|
|
731
|
-
instance.emit("quit");
|
|
732
|
-
_eventListeners = {};
|
|
733
|
-
for (const removeListener of _browserEventListeners) {
|
|
734
|
-
removeListener();
|
|
735
|
-
}
|
|
736
|
-
if (settings.global) {
|
|
737
|
-
for (const key in instance) {
|
|
738
|
-
delete root[key];
|
|
739
|
-
}
|
|
740
|
-
delete root.ENGINE;
|
|
741
|
-
}
|
|
742
|
-
_initialized = false;
|
|
743
|
-
},
|
|
744
728
|
/**
|
|
745
729
|
* Pauses the engine loop (update & draw).
|
|
746
730
|
*/
|
|
747
731
|
pause() {
|
|
732
|
+
_paused = true;
|
|
748
733
|
cancelAnimationFrame(_rafid);
|
|
749
|
-
_rafid = 0;
|
|
750
734
|
},
|
|
751
735
|
/**
|
|
752
736
|
* Resumes (if paused) the engine loop.
|
|
753
737
|
*/
|
|
754
738
|
resume() {
|
|
755
|
-
if (_initialized &&
|
|
739
|
+
if (_initialized && _paused) {
|
|
740
|
+
_paused = false;
|
|
756
741
|
_accumulated = _fpsInterval;
|
|
757
742
|
_lastFrameTime = Date.now();
|
|
758
743
|
_rafid = raf(drawFrame);
|
|
@@ -764,7 +749,25 @@
|
|
|
764
749
|
* @returns {boolean}
|
|
765
750
|
*/
|
|
766
751
|
paused() {
|
|
767
|
-
return
|
|
752
|
+
return _paused;
|
|
753
|
+
},
|
|
754
|
+
/**
|
|
755
|
+
* Shutdown the litecanvas instance and remove all event listeners.
|
|
756
|
+
*/
|
|
757
|
+
quit() {
|
|
758
|
+
instance.emit("quit");
|
|
759
|
+
instance.pause();
|
|
760
|
+
_initialized = false;
|
|
761
|
+
_eventListeners = {};
|
|
762
|
+
for (const removeListener of _browserEventListeners) {
|
|
763
|
+
removeListener();
|
|
764
|
+
}
|
|
765
|
+
if (settings.global) {
|
|
766
|
+
for (const key in instance) {
|
|
767
|
+
delete root[key];
|
|
768
|
+
}
|
|
769
|
+
delete root.ENGINE;
|
|
770
|
+
}
|
|
768
771
|
}
|
|
769
772
|
};
|
|
770
773
|
for (const k of _mathFunctions.split(",")) {
|
|
@@ -1076,7 +1079,7 @@
|
|
|
1076
1079
|
if ("loading" === document.readyState) {
|
|
1077
1080
|
on(root, "DOMContentLoaded", () => raf(init));
|
|
1078
1081
|
} else {
|
|
1079
|
-
raf(init);
|
|
1082
|
+
_rafid = raf(init);
|
|
1080
1083
|
}
|
|
1081
1084
|
return instance;
|
|
1082
1085
|
}
|
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,l=Math,n=2*l.PI,i=requestAnimationFrame,o=[],r=(e,t,a)=>{e.addEventListener(t,a,!1),o.push(()=>e.removeEventListener(t,a,!1))},s=e=>e.toLowerCase(),c=e=>e.preventDefault(),f=e=>e.beginPath(),d=(e=>{let t=new AudioContext;return e.zzfxV=1,(a=1,l=.05,n=220,i=0,o=0,r=.1,s=0,c=1,f=0,d=0,u=0,p=0,h=0,m=0,g=0,v=0,w=0,x=1,y=0,b=0,k=0)=>{let E=Math,z=2*E.PI,T=f*=500*z/44100/44100,I=n*=(1-l+2*l*E.random(l=[]))*z/44100,D=0,S=0,A=0,M=1,C=0,L=0,N=0,P=k<0?-1:1,F=z*P*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+P*q)/2/O,G=-(P+q)/O,X=0,Y=0,$=0,j=0;for(i=44100*i+9,y*=44100,o*=44100,r*=44100,w*=44100,d*=500*z/85766121e6,g*=z/44100,u*=z/44100,p*=44100,h=44100*h|0,a*=.3*e.zzfxV,P=i+y+o+r+w|0;A<P;l[A++]=N*a)++L%(100*v|0)||(N=s?1<s?2<s?3<s?B(D*D):E.max(E.min(E.tan(D),1),-1):1-(2*D/z%2+2)%2:1-4*E.abs(E.round(D/z)-D/z):B(D),N=(h?1-b+b*B(z*A/h):1)*(N<0?-1:1)*E.abs(N)**c*(A<i?A/i:A<i+y?1-(A-i)/y*(1-x):A<i+y+o?x:A<P-w?(P-A-w)/r*x:0),N=w?N/2+(w>A?0:(A<P-w?1:(P-A)/w)*l[A-w|0]/2/a):N,k&&(N=j=R*X+G*(X=Y)+R*(Y=N)-W*$-V*($=j))),D+=(F=(n+=f+=d)*E.cos(g*S++))+F*m*B(A**5),M&&++M>p&&(n+=u,I+=u,M=0),!h||++C%h||(n=I,f=T,M=M||1);(a=t.createBuffer(1,P,44100)).getChannelData(0).set(l),(n=t.createBufferSource()).buffer=a,n.connect(t.destination),n.start()}})(a);t=Object.assign({width:null,height:null,autoscale:!0,canvas:null,global:!0,loop:null,tapEvents:!0,keyboardEvents:!0},t);let u=!1,p,h=1,
|
|
1
|
+
(()=>{var e=["#111","#6a7799","#aec2c2","#FFF1E8","#e83b3b","#fabc20","#155fd9","#3cbcfc","#327345","#63c64d","#6c2c1f","#ac7c00"];globalThis.litecanvas=function(t={}){let a=window,l=Math,n=2*l.PI,i=requestAnimationFrame,o=[],r=(e,t,a)=>{e.addEventListener(t,a,!1),o.push(()=>e.removeEventListener(t,a,!1))},s=e=>e.toLowerCase(),c=e=>e.preventDefault(),f=e=>e.beginPath(),d=(e=>{let t=new AudioContext;return e.zzfxV=1,(a=1,l=.05,n=220,i=0,o=0,r=.1,s=0,c=1,f=0,d=0,u=0,p=0,h=0,m=0,g=0,v=0,w=0,x=1,y=0,b=0,k=0)=>{let E=Math,z=2*E.PI,T=f*=500*z/44100/44100,I=n*=(1-l+2*l*E.random(l=[]))*z/44100,D=0,S=0,A=0,M=1,C=0,L=0,N=0,P=k<0?-1:1,F=z*P*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+P*q)/2/O,G=-(P+q)/O,X=0,Y=0,$=0,j=0;for(i=44100*i+9,y*=44100,o*=44100,r*=44100,w*=44100,d*=500*z/85766121e6,g*=z/44100,u*=z/44100,p*=44100,h=44100*h|0,a*=.3*e.zzfxV,P=i+y+o+r+w|0;A<P;l[A++]=N*a)++L%(100*v|0)||(N=s?1<s?2<s?3<s?B(D*D):E.max(E.min(E.tan(D),1),-1):1-(2*D/z%2+2)%2:1-4*E.abs(E.round(D/z)-D/z):B(D),N=(h?1-b+b*B(z*A/h):1)*(N<0?-1:1)*E.abs(N)**c*(A<i?A/i:A<i+y?1-(A-i)/y*(1-x):A<i+y+o?x:A<P-w?(P-A-w)/r*x:0),N=w?N/2+(w>A?0:(A<P-w?1:(P-A)/w)*l[A-w|0]/2/a):N,k&&(N=j=R*X+G*(X=Y)+R*(Y=N)-W*$-V*($=j))),D+=(F=(n+=f+=d)*E.cos(g*S++))+F*m*B(A**5),M&&++M>p&&(n+=u,I+=u,M=0),!h||++C%h||(n=I,f=T,M=M||1);(a=t.createBuffer(1,P,44100)).getChannelData(0).set(l),(n=t.createBufferSource()).buffer=a,n.connect(t.destination),n.start()}})(a);t=Object.assign({width:null,height:null,autoscale:!0,canvas:null,global:!0,loop:null,tapEvents:!0,keyboardEvents:!0},t);let u=!1,p=!0,h,m=1,g,v=.5,w=1,x,y=1e3/60,b,k,E="sans-serif",z=20,T=Date.now(),I=e,D=[],S=[.5,0,1750,,,.3,1,,,,600,.1],A={},M={W:0,H:0,T:0,MX:-1,MY:-1,TWO_PI:n,HALF_PI:n/4,lerp:(e,t,a)=>a*(t-e)+e,deg2rad:e=>l.PI/180*e,rad2deg:e=>180/l.PI*e,round:(e,t=0)=>{if(!t)return l.round(e);let a=10**t;return l.round(e*a)/a},clamp:(e,t,a)=>e<t?t:e>a?a:e,wrap:(e,t,a)=>e-(a-t)*l.floor((e-t)/(a-t)),map(e,t,a,l,n,i){let o=(e-t)/(a-t)*(n-l)+l;return i?M.clamp(o,l,n):o},norm:(e,t,a)=>M.map(e,t,a,0,1),wave:(e,t,a,l=Math.sin)=>e+(l(a)+1)/2*(t-e),rand:(e=0,t=1)=>(T=(1664525*T+0x3c6ef35f)%0x100000000)/0x100000000*(t-e)+e,randi:(e=0,t=1)=>l.floor(M.rand(e,t+1)),rseed(e){T=~~e},cls(e){null==e?g.clearRect(0,0,g.canvas.width,g.canvas.height):M.rectfill(0,0,g.canvas.width,g.canvas.height,e)},rect(e,t,a,l,n,i){f(g),g[i?"roundRect":"rect"](~~e-v,~~t-v,~~a+2*v,~~l+2*v,i),M.stroke(n)},rectfill(e,t,a,l,n,i){f(g),g[i?"roundRect":"rect"](~~e,~~t,~~a,~~l,i),M.fill(n)},circ(e,t,a,l){f(g),g.arc(~~e,~~t,~~a,0,n),M.stroke(l)},circfill(e,t,a,l){f(g),g.arc(~~e,~~t,~~a,0,n),M.fill(l)},oval(e,t,a,l,i){f(g),g.ellipse(~~e,~~t,~~a,~~l,0,0,n),M.stroke(i)},ovalfill(e,t,a,l,i){f(g),g.ellipse(~~e,~~t,~~a,~~l,0,0,n),M.fill(i)},line(e,t,a,l,n){f(g);let i=.5*(0!==v&&~~e==~~a),o=.5*(0!==v&&~~t==~~l);g.moveTo(~~e+i,~~t+o),g.lineTo(~~a+i,~~l+o),M.stroke(n)},linewidth(e){g.lineWidth=~~e,v=.5*(0!=~~e%2)},linedash(e,t=0){g.setLineDash(e),g.lineDashOffset=t},text(e,t,a,l=3,n="normal"){g.font=`${n} ${z}px ${E}`,g.fillStyle=F(l),g.fillText(a,~~e,~~t)},textfont(e){E=e},textsize(e){z=e},textalign(e,t){e&&(g.textAlign=e),t&&(g.textBaseline=t)},image(e,t,a){g.drawImage(a,~~e,~~t)},spr(e,t,a,l,n){let i=n.replace(/\s/g,"");for(let n=0;n<a;n++)for(let o=0;o<l;o++){let l=i[a*o+n]||".";"."!==l&&M.rectfill(e+n,t+o,1,1,parseInt(l,36)||0)}},paint(e,t,a,l={}){let n=l.canvas||new OffscreenCanvas(1,1),i=l.scale||1,o=g;return n.width=e*i,n.height=t*i,(g=n.getContext("2d")).scale(i,i),a(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){g.scale(e,t||e)},rotate(e){g.rotate(e)},alpha(e){g.globalAlpha=M.clamp(e,0,1)},fill(e){g.fillStyle=F(e),g.fill()},stroke(e){g.strokeStyle=F(e),g.stroke()},clip(e){f(g),e(g),g.clip()},sfx:(e,t=0,l=1)=>!!a.zzfxV&&(!navigator.userActivation||!!navigator.userActivation.hasBeenActive)&&(e=e||S,(0!==t||1!==l)&&((e=e.slice())[0]=l*(e[0]||1),e[10]=~~e[10]+t),d.apply(0,e),e),volume(e){a.zzfxV=e},canvas:()=>h,use(e,t={}){var a=e,l=t;let n=a(M,l);for(let e in n)M.def(e,n[e])},listen:(e,t)=>(A[e=s(e)]=A[e]||new Set,A[e].add(t),()=>A&&A[e].delete(t)),emit(e,t,a,l,n){u&&(P("before:"+(e=s(e)),t,a,l,n),P(e,t,a,l,n),P("after:"+e,t,a,l,n))},pal(t=e){I=t,D=[]},palc(e,t){null==e?D=[]:D[e]=t},def(e,l){M[e]=l,t.global&&(a[e]=l)},timescale(e){w=e},framerate(e){y=1e3/~~e},stat(e){let l={index:e,value:[t,u,y/1e3,m,A,I,S,w,a.zzfxV,T,z,E,D][e]};return M.emit("stat",l),l.value},pause(){p=!0,cancelAnimationFrame(k)},resume(){u&&p&&(p=!1,b=y,x=Date.now(),k=i(L))},paused:()=>p,quit(){for(let e of(M.emit("quit"),M.pause(),u=!1,A={},o))e();if(t.global){for(let e in M)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(","))M[e]=l[e];function C(){let e=t.loop?t.loop:a;for(let t of"init,update,draw,tap,untap,tapping,tapped,resized".split(","))e[t]&&M.listen(t,e[t]);if(t.autoscale&&r(a,"resize",N),t.tapEvents){let e=e=>[(e.pageX-h.offsetLeft)/m,(e.pageY-h.offsetTop)/m],t=new Map,l=(e,a,l)=>{let n={x:a,y:l,xi:a,yi:l,t:Date.now()};return t.set(e,n),n},n=(e,a,n)=>{let i=t.get(e)||l(e);i.x=a,i.y=n},i=e=>e&&Date.now()-e.t<=300,o=!1;r(h,"mousedown",t=>{if(0===t.button){c(t);let[a,n]=e(t);M.emit("tap",a,n,0),l(0,a,n),o=!0}}),r(h,"mouseup",a=>{if(0===a.button){c(a);let l=t.get(0),[n,r]=e(a);i(l)&&M.emit("tapped",l.xi,l.yi,0),M.emit("untap",n,r,0),t.delete(0),o=!1}}),r(a,"mousemove",t=>{c(t);let[a,l]=e(t);M.def("MX",a),M.def("MY",l),o&&(M.emit("tapping",a,l,0),n(0,a,l))}),r(h,"touchstart",t=>{for(let a of(c(t),t.changedTouches)){let[t,n]=e(a);M.emit("tap",t,n,a.identifier+1),l(a.identifier+1,t,n)}}),r(h,"touchmove",t=>{for(let a of(c(t),t.changedTouches)){let[t,l]=e(a);M.emit("tapping",t,l,a.identifier+1),n(a.identifier+1,t,l)}});let s=e=>{c(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)&&M.emit("tapped",l.xi,l.yi,e),M.emit("untap",l.x,l.y,e),t.delete(e))};r(h,"touchend",s),r(h,"touchcancel",s),r(a,"blur",()=>{for(let[e,a]of(o=!1,t))M.emit("untap",a.x,a.y,e),t.delete(e)})}if(t.keyboardEvents){let e=new Set,t=new Set,l=(e,t="")=>(t=s(t))?e.has("space"===t?" ":t):e.size>0,n="";r(a,"keydown",a=>{let l=s(a.key);e.has(l)||(e.add(l),t.add(l),n=" "===l?"space":l)}),r(a,"keyup",t=>{e.delete(s(t.key))}),r(a,"blur",()=>e.clear()),M.listen("after:update",()=>t.clear()),M.def("iskeydown",t=>l(e,t)),M.def("iskeypressed",e=>l(t,e)),M.def("lastkey",()=>n)}u=!0,M.emit("init",M),M.resume()}function L(){k=i(L);let e=Date.now(),t=0,a=e-x;for(x=e,b+=a<100?a:y;b>=y;){t++,b-=y;let e=y/1e3*w;M.emit("update",e,t),M.def("T",M.T+e)}t&&(M.emit("draw",g),t>1&&(b=0))}function N(){let e=t.width>0?t.width:innerWidth,a=t.width>0?t.height||t.width:innerHeight;if(M.def("W",e),M.def("H",a),h.width=e,h.height=a,t.autoscale){let n=+t.autoscale;h.style.display||(h.style.display="block",h.style.margin="auto"),m=l.min(innerWidth/e,innerHeight/a),m=n>1&&m>n?n:m,h.style.width=e*m+"px",h.style.height=a*m+"px"}g.imageSmoothingEnabled=!1,M.textalign("start","top"),M.emit("resized",m)}function P(e,t,a,l,n){if(A[e])for(let i of A[e])i(t,a,l,n)}function F(e){return I[~~(D[e]??e)%I.length]}if(t.global){if(a.ENGINE)throw Error("only one global litecanvas is allowed");Object.assign(a,M),a.ENGINE=M}return g=(h=(h="string"==typeof t.canvas?document.querySelector(t.canvas):t.canvas)||document.createElement("canvas")).getContext("2d"),r(h,"click",()=>focus()),N(),h.parentNode||document.body.appendChild(h),h.style.imageRendering="pixelated",h.oncontextmenu=()=>!1,"loading"===document.readyState?r(a,"DOMContentLoaded",()=>i(C)):k=i(C),M}})();
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "litecanvas",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.99.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>",
|
package/src/index.js
CHANGED
|
@@ -48,6 +48,8 @@ export default function litecanvas(settings = {}) {
|
|
|
48
48
|
|
|
49
49
|
let /** @type {boolean} */
|
|
50
50
|
_initialized = false,
|
|
51
|
+
/** @type {boolean} */
|
|
52
|
+
_paused = true,
|
|
51
53
|
/** @type {HTMLCanvasElement} _canvas */
|
|
52
54
|
_canvas,
|
|
53
55
|
/** @type {number} */
|
|
@@ -351,10 +353,9 @@ export default function litecanvas(settings = {}) {
|
|
|
351
353
|
*/
|
|
352
354
|
rseed(value) {
|
|
353
355
|
DEV: assert(
|
|
354
|
-
|
|
355
|
-
'[litecanvas] rseed() 1st param must be a positive
|
|
356
|
+
isNumber(value) && value >= 0,
|
|
357
|
+
'[litecanvas] rseed() 1st param must be a positive integer or zero'
|
|
356
358
|
)
|
|
357
|
-
|
|
358
359
|
_rngSeed = ~~value
|
|
359
360
|
},
|
|
360
361
|
|
|
@@ -1057,6 +1058,7 @@ export default function litecanvas(settings = {}) {
|
|
|
1057
1058
|
'string' === typeof eventName,
|
|
1058
1059
|
'[litecanvas] emit() 1st param must be a string'
|
|
1059
1060
|
)
|
|
1061
|
+
|
|
1060
1062
|
if (_initialized) {
|
|
1061
1063
|
eventName = lowerCase(eventName)
|
|
1062
1064
|
|
|
@@ -1157,7 +1159,7 @@ export default function litecanvas(settings = {}) {
|
|
|
1157
1159
|
},
|
|
1158
1160
|
|
|
1159
1161
|
/**
|
|
1160
|
-
* Returns information about
|
|
1162
|
+
* Returns information about the engine instance.
|
|
1161
1163
|
*
|
|
1162
1164
|
* @param {number|string} index
|
|
1163
1165
|
* @returns {any}
|
|
@@ -1191,8 +1193,10 @@ export default function litecanvas(settings = {}) {
|
|
|
1191
1193
|
_rngSeed,
|
|
1192
1194
|
// 10
|
|
1193
1195
|
_fontSize,
|
|
1194
|
-
//
|
|
1196
|
+
// 11
|
|
1195
1197
|
_fontFamily,
|
|
1198
|
+
// 12
|
|
1199
|
+
_colorPaletteState,
|
|
1196
1200
|
]
|
|
1197
1201
|
|
|
1198
1202
|
const data = { index, value: internals[index] }
|
|
@@ -1203,49 +1207,24 @@ export default function litecanvas(settings = {}) {
|
|
|
1203
1207
|
return data.value
|
|
1204
1208
|
},
|
|
1205
1209
|
|
|
1206
|
-
/**
|
|
1207
|
-
* Stops the litecanvas instance and remove all event listeners.
|
|
1208
|
-
*/
|
|
1209
|
-
quit() {
|
|
1210
|
-
// stop the game loop (update & draw)
|
|
1211
|
-
instance.pause()
|
|
1212
|
-
|
|
1213
|
-
// emit "quit" event to manual clean ups
|
|
1214
|
-
instance.emit('quit')
|
|
1215
|
-
|
|
1216
|
-
// clear all engine event listeners
|
|
1217
|
-
_eventListeners = {}
|
|
1218
|
-
|
|
1219
|
-
// clear all browser event listeners
|
|
1220
|
-
for (const removeListener of _browserEventListeners) {
|
|
1221
|
-
removeListener()
|
|
1222
|
-
}
|
|
1223
|
-
|
|
1224
|
-
// maybe clear global context
|
|
1225
|
-
if (settings.global) {
|
|
1226
|
-
for (const key in instance) {
|
|
1227
|
-
delete root[key]
|
|
1228
|
-
}
|
|
1229
|
-
delete root.ENGINE
|
|
1230
|
-
}
|
|
1231
|
-
|
|
1232
|
-
// unset that flag
|
|
1233
|
-
_initialized = false
|
|
1234
|
-
},
|
|
1235
|
-
|
|
1236
1210
|
/**
|
|
1237
1211
|
* Pauses the engine loop (update & draw).
|
|
1238
1212
|
*/
|
|
1239
1213
|
pause() {
|
|
1214
|
+
_paused = true
|
|
1240
1215
|
cancelAnimationFrame(_rafid)
|
|
1241
|
-
_rafid = 0
|
|
1242
1216
|
},
|
|
1243
1217
|
|
|
1244
1218
|
/**
|
|
1245
1219
|
* Resumes (if paused) the engine loop.
|
|
1246
1220
|
*/
|
|
1247
1221
|
resume() {
|
|
1248
|
-
|
|
1222
|
+
DEV: assert(
|
|
1223
|
+
_initialized,
|
|
1224
|
+
'[litecanvas] resume() cannot be called before the "init" event and neither after the quit() function'
|
|
1225
|
+
)
|
|
1226
|
+
if (_initialized && _paused) {
|
|
1227
|
+
_paused = false
|
|
1249
1228
|
_accumulated = _fpsInterval
|
|
1250
1229
|
_lastFrameTime = Date.now()
|
|
1251
1230
|
_rafid = raf(drawFrame)
|
|
@@ -1258,7 +1237,39 @@ export default function litecanvas(settings = {}) {
|
|
|
1258
1237
|
* @returns {boolean}
|
|
1259
1238
|
*/
|
|
1260
1239
|
paused() {
|
|
1261
|
-
return
|
|
1240
|
+
return _paused
|
|
1241
|
+
},
|
|
1242
|
+
|
|
1243
|
+
/**
|
|
1244
|
+
* Shutdown the litecanvas instance and remove all event listeners.
|
|
1245
|
+
*/
|
|
1246
|
+
quit() {
|
|
1247
|
+
// emit "quit" event to manual clean ups
|
|
1248
|
+
instance.emit('quit')
|
|
1249
|
+
|
|
1250
|
+
// stop the game loop (update & draw)
|
|
1251
|
+
instance.pause()
|
|
1252
|
+
|
|
1253
|
+
// deinitialize the engine
|
|
1254
|
+
_initialized = false
|
|
1255
|
+
|
|
1256
|
+
// clear all engine event listeners
|
|
1257
|
+
_eventListeners = {}
|
|
1258
|
+
|
|
1259
|
+
// clear all browser event listeners
|
|
1260
|
+
for (const removeListener of _browserEventListeners) {
|
|
1261
|
+
removeListener()
|
|
1262
|
+
}
|
|
1263
|
+
|
|
1264
|
+
// maybe clear global context
|
|
1265
|
+
if (settings.global) {
|
|
1266
|
+
for (const key in instance) {
|
|
1267
|
+
delete root[key]
|
|
1268
|
+
}
|
|
1269
|
+
delete root.ENGINE
|
|
1270
|
+
}
|
|
1271
|
+
|
|
1272
|
+
DEV: console.warn('[litecanvas] quit() terminated a Litecanvas instance.')
|
|
1262
1273
|
},
|
|
1263
1274
|
}
|
|
1264
1275
|
|
|
@@ -1714,7 +1725,7 @@ export default function litecanvas(settings = {}) {
|
|
|
1714
1725
|
if ('loading' === document.readyState) {
|
|
1715
1726
|
on(root, 'DOMContentLoaded', () => raf(init))
|
|
1716
1727
|
} else {
|
|
1717
|
-
raf(init)
|
|
1728
|
+
_rafid = raf(init)
|
|
1718
1729
|
}
|
|
1719
1730
|
|
|
1720
1731
|
return instance
|
package/src/version.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
// Generated by genversion.
|
|
2
|
-
export const version = '0.
|
|
2
|
+
export const version = '0.99.0'
|
package/types/global.d.ts
CHANGED
|
@@ -583,9 +583,9 @@ declare global {
|
|
|
583
583
|
*/
|
|
584
584
|
function framerate(fps: number): void
|
|
585
585
|
/**
|
|
586
|
-
* Returns information about
|
|
586
|
+
* Returns information about the engine instance.
|
|
587
587
|
*
|
|
588
|
-
* - n = 0: the settings passed to
|
|
588
|
+
* - n = 0: the settings passed to this instance
|
|
589
589
|
* - n = 1: returns true if the "init" event has already been emitted
|
|
590
590
|
* - n = 2: the current delta time (dt)
|
|
591
591
|
* - n = 3: the current canvas element scale (not the context 2D scale)
|
|
@@ -597,15 +597,12 @@ declare global {
|
|
|
597
597
|
* - n = 9: the current RNG state
|
|
598
598
|
* - n = 10: the current font size
|
|
599
599
|
* - n = 11: the current font family
|
|
600
|
+
* - n = 12: the current state of the color palette
|
|
600
601
|
* - n = *any other value*: probably returns undefined
|
|
601
602
|
*
|
|
602
|
-
* @param
|
|
603
|
+
* @param index
|
|
603
604
|
*/
|
|
604
|
-
function stat(
|
|
605
|
-
/**
|
|
606
|
-
* Shutdown the litecanvas instance and remove all event listeners.
|
|
607
|
-
*/
|
|
608
|
-
function quit(): void
|
|
605
|
+
function stat(index: number | string): any
|
|
609
606
|
/**
|
|
610
607
|
* Pauses the engine loop (update & draw).
|
|
611
608
|
*/
|
|
@@ -618,4 +615,8 @@ declare global {
|
|
|
618
615
|
* Returns `true` if the engine loop is paused.
|
|
619
616
|
*/
|
|
620
617
|
function paused(): boolean
|
|
618
|
+
/**
|
|
619
|
+
* Shutdown the litecanvas instance and remove all event listeners.
|
|
620
|
+
*/
|
|
621
|
+
function quit(): void
|
|
621
622
|
}
|
package/types/types.d.ts
CHANGED
|
@@ -573,9 +573,9 @@ type LitecanvasInstance = {
|
|
|
573
573
|
*/
|
|
574
574
|
framerate(fps: number): void
|
|
575
575
|
/**
|
|
576
|
-
* Returns information about
|
|
576
|
+
* Returns information about the engine instance.
|
|
577
577
|
*
|
|
578
|
-
* - n = 0: the settings passed to
|
|
578
|
+
* - n = 0: the settings passed to this instance
|
|
579
579
|
* - n = 1: returns true if the "init" event has already been emitted
|
|
580
580
|
* - n = 2: the current delta time (dt)
|
|
581
581
|
* - n = 3: the current canvas element scale (not the context 2D scale)
|
|
@@ -587,15 +587,12 @@ type LitecanvasInstance = {
|
|
|
587
587
|
* - n = 9: the current RNG state
|
|
588
588
|
* - n = 10: the current font size
|
|
589
589
|
* - n = 11: the current font family
|
|
590
|
+
* - n = 12: the current state of the color palette
|
|
590
591
|
* - n = *any other value*: probably returns undefined
|
|
591
592
|
*
|
|
592
|
-
* @param
|
|
593
|
+
* @param index
|
|
593
594
|
*/
|
|
594
|
-
stat(
|
|
595
|
-
/**
|
|
596
|
-
* Stops the litecanvas instance and remove all event listeners.
|
|
597
|
-
*/
|
|
598
|
-
quit(): void
|
|
595
|
+
stat(index: number | string): any
|
|
599
596
|
/**
|
|
600
597
|
* Pauses the engine loop (update & draw).
|
|
601
598
|
*/
|
|
@@ -608,6 +605,10 @@ type LitecanvasInstance = {
|
|
|
608
605
|
* Returns `true` if the engine loop is paused.
|
|
609
606
|
*/
|
|
610
607
|
paused(): boolean
|
|
608
|
+
/**
|
|
609
|
+
* Shutdown the litecanvas instance and remove all event listeners.
|
|
610
|
+
*/
|
|
611
|
+
quit(): void
|
|
611
612
|
}
|
|
612
613
|
|
|
613
614
|
type LitecanvasOptions = {
|