litecanvas 0.98.1 → 0.98.3

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 CHANGED
@@ -28,74 +28,210 @@ Litecanvas is a lightweight HTML5 canvas 2D engine suitable for small web games,
28
28
  - **Extensible**: Use or create [plugins](https://www.npmjs.com/search?q=keywords:litecanvas) to add functionalities or change the engine.
29
29
  - **Playground**: Access or install the [playground](https://litecanvas.js.org/) webapp to code and share games (even offline).
30
30
 
31
- [Learn more in the cheatsheet...](https://litecanvas.js.org/about.html)
32
-
33
31
  ## Getting Started
34
32
 
35
- You can try our [online playground](https://litecanvas.github.io) or install the NPM package:
33
+ ### Installation
34
+
35
+ You can get started using our [online playground](https://litecanvas.github.io).
36
+
37
+ Or installing our package via NPM:
36
38
 
37
39
  ```sh
38
40
  npm i litecanvas
39
41
  ```
40
42
 
41
- or just use add a `<script>` tag with our CDN link:
43
+ Or just create a HTML file and add a `<script>` tag with our CDN link:
42
44
 
43
45
  ```html
44
46
  <script src="https://unpkg.com/litecanvas"></script>
45
47
  ```
46
48
 
47
- ### Show me the code!
49
+ ### Basic game structure
48
50
 
49
51
  ```js
50
- // import the package if you installed via NPM
51
- import litecanvas from 'litecanvas'
52
-
53
- // Start and setup the engine
54
- // learn more: https://litecanvas.js.org/about.html#settings
55
52
  litecanvas({
56
- loop: { init, update, draw, tapped },
53
+ // This is required only in ESM format.
54
+ // Note: the next examples will assume that you are
55
+ // testing through the playground or the CDN
56
+ loop: { init, update, draw },
57
57
  })
58
58
 
59
- // this function runs once at the beginning
60
59
  function init() {
61
- bg = 0 // the color #0 (black)
62
- color = 3 // the color #3 (white)
63
- radius = W / 10 // the canvas Width/10
64
- posx = W / 2 // center X (or canvas Width/2)
65
- posy = H / 2 // center Y (or canvas Height/2)
60
+ // this functions is called one time only
61
+ // before the game starts
62
+ }
63
+
64
+ function update(dt) {
65
+ // this functions is called 60 times per second
66
+ // your game logic goes here
66
67
  }
67
68
 
68
- // this function detect clicks/touches
69
- function tapped(x, y) {
70
- // changes the circle position
71
- // based on the position of the tap
72
- posx = x
73
- posy = y
69
+ function draw() {
70
+ // this functions is called 60 times per second
71
+ // your game rendering goes here
74
72
  }
73
+ ```
75
74
 
76
- // put the game logic in this function
77
- function update(dt) {
78
- // make the circle falls 200 pixels per second
79
- posy += 200 * dt
75
+ > **Note**: if you installed via NPM you need to import the package first: <br/>
76
+ > `import litecanvas from "litecanvas"`
77
+
78
+ ### Set the width and height of the game screen
79
+
80
+ ```js
81
+ // example: a game screen size equal to 480x360
82
+ litecanvas({
83
+ width: 480,
84
+ height: 360,
85
+ })
86
+ ```
87
+
88
+ ### Colors
89
+
90
+ Litecanvas has a default palette with 12 colors:
91
+
92
+ | # | Color | # | Color |
93
+ | --- | ---------- | --- | ----------- |
94
+ | 0 | Black | 6 | Dark blue |
95
+ | 1 | Dark grey | 7 | Light blue |
96
+ | 2 | Light grey | 8 | Dark green |
97
+ | 3 | White | 9 | Light green |
98
+ | 4 | Red | 10 | Brown |
99
+ | 5 | Yellow | 11 | Beige |
100
+
101
+ ![The litecanvas color palette](.github/_assets/palette.png)
102
+
103
+ Each time a Litecanvas' function ask for a color, you should use an of theses colors by its index.
104
+
105
+ ```js
106
+ // example: draw a white rectangle
107
+ color = 3
108
+ rectfill(0, 0, 32, 32, color)
109
+ ```
110
+
111
+ ### Printing messages
112
+
113
+ ```js
114
+ litecanvas()
115
+
116
+ function draw() {
117
+ // clear and fill the game screen with color #0 (black)
118
+ cls(0)
119
+
120
+ // print a red "Hello" text at x=0, y=0
121
+ text(0, 0, 'Hello', 4)
122
+ }
123
+ ```
124
+
125
+ ### Drawing shapes
126
+
127
+ You can use the following functions to draw shapes:
128
+
129
+ - `rect(x, y, width, height, color)` draw a rectangle outline
130
+ - `rectfill(x, y, width, height, color)` draw a color-filled rectangle
131
+ - `circ(x, y, radius, color)` draw a circle outline
132
+ - `circfill(x, y, radius, color)` draw a color-filled circle
133
+ - `oval(x, y, rx, ry, color)` draw a ellipse outline
134
+ - `ovalfill(x, y, rx, ry, color)` draw a color-filled ellipse
135
+
136
+ ```js
137
+ litecanvas()
138
+
139
+ function draw() {
140
+ cls(0)
141
+
142
+ // draw a color filled rectangle at x=0 and y=0
143
+ // with width=32 and height=32
144
+ // and color=3 (white)
145
+ rectfill(0, 0, 32, 32, 3)
146
+
147
+ // draw a circle outline at x=64 and y=32
148
+ // with radius=40
149
+ // and color=5 (yellow)
150
+ circ(64, 32, 40, 5)
80
151
  }
152
+ ```
153
+
154
+ ### Keyboard
155
+
156
+ ```js
157
+ litecanvas()
158
+
159
+ function update() {
160
+ if (iskeydown('space')) {
161
+ // checks if the spacebar key is down
162
+ }
163
+
164
+ if (iskeypressed('a')) {
165
+ // checks if the "a" key was pressed
166
+ }
167
+
168
+ // Returns the last key pressed in your keyboard.
169
+ const key = lastkey()
170
+
171
+ console.log(key)
172
+ }
173
+ ```
174
+
175
+ > Note: you can call `iskeydown()` or `iskeypressed()` (without arguments) to check for any key.
176
+
177
+ ### Clicks and Touches
178
+
179
+ ```js
180
+ litecanvas()
181
+
182
+ let x, y
183
+
184
+ function tapped(tapX, tapY) {
185
+ // this function is called when a click or a touch happens
186
+ // tapX and tapY is where the tap happened
187
+ x = tapX
188
+ y = tapY
189
+ }
190
+
191
+ function draw() {
192
+ cls(0)
193
+
194
+ if (x != null) {
195
+ // Draw a red circle wherever you tap
196
+ circfill(x, y, 32, 4)
197
+ }
198
+ }
199
+ ```
200
+
201
+ ### Mouse cursor
202
+
203
+ Use `MX` and `MY` variables (automatically declared by Litecanvas) to track the position of the mouse cursor.
204
+
205
+ ```js
206
+ litecanvas()
81
207
 
82
- // put the game rendering in this function
83
208
  function draw() {
84
- cls(bg) // clear the screen
85
- circfill(posx, posy, radius, color) // draw a circle
86
- text(10, 10, 'Tap anywhere') // draw a text
209
+ cls(0)
210
+
211
+ // draw a red circle in the mouse cursor's position
212
+ circfill(MX, MY, 32, 4)
87
213
  }
88
214
  ```
89
215
 
90
- [Play with this code in the playground](https://litecanvas.js.org?c=eJx9U8tu2zAQvOsrBsghcitYtnMz4HvvLdD2SJFriTVNEuSqthH430tSduQEQQUI0GNmdnZ22bb4ziIwhFWIxKMHDwSyvbZUtS0MiWBxdIG2GJh93Lat0UxS2L8iLv%2FEpQt9Kzo38nLgo3lKIqxtH6sZVb9WSJdxzm%2FxCm01Nxi9EkwNVBCnBiy8J4VrU10XVa7Lg47Yj1aydhZhtBHOSoLgYrCjZNCmOtUbJsvWC0y1uh47rFCECNIZF%2FC0Qt0ZIQ%2BLApk%2B7vDyAfWC%2BjQk7xMqCKXHmGA%2F0WI9K5bGcNKKh3a9KlDv4vkG3GScJMsU8At1kn1H2CzuhEsifPtA%2BP0p4fpJLIpSxAxptDzElt0oB4pzIlOo9bnB5Z5LrjII21Oc2tBBGspGdGbcIZ2IaRhZYZh%2Fwu3Le1J9bPf82MrlZtOP05h6caQ0917LNJ735meb0ybUih9MHsWBHh3uhTEx5b%2BC12dKjz4FFUk6q%2Bb6X3fYJMQXKP7MRyCrKKSd%2BY%2BXvI1vSyRNrLt%2BUULL56BIRRmIpqSyt702ps5RNMVDc1uYZtqmws2aELdOCpHpzPV61SDfzz%2BET8fvchoo0PMjI8Oq6z8yIyTy)
216
+ ### Litecanvas' variables
217
+
218
+ Like `MX` and `MY`, Litecanvas also declares these other variables:
219
+
220
+ - `W`: the width of the game canvas
221
+ - `H`: the height of the game canvas
222
+ - `T`: the amount of seconds since the game started
223
+ - `PI`: approximately 3.14 radians (or 180 degrees)
224
+ - `TWO_PI`: approximately 6.28 radians (or 360 degrees)
225
+ - `HALF_PI`: approximately 1.57 radians (or 90 degrees)
91
226
 
92
- https://github.com/user-attachments/assets/854ac6bd-724f-4da8-bb3c-bc04dba5d8c8
227
+ ### And much more!
228
+
229
+ You can find a complete list of everything litecanvas has to offer on our [cheatsheet](https://litecanvas.js.org/about.html).
93
230
 
94
231
  ## Demos
95
232
 
96
233
  Try some demos in the playground:
97
234
 
98
- - [Pong](https://litecanvas.js.org?c=eJy1VV1y00gQftcpmidJWJYl2U5IIKFMyiEPgKk4YMLW1paQxvYUiqSSxiT8hCtwgn3bQ3AeLsAV6J7RzyjEKV42rozdPT39%2B803CROQh%2FECDsAPPMcA%2FEP5hORxI74h0Wu3z1EeDSs5ZqUgA7JTmndhkmg%2Fz9ufc%2F6Jaa5JNUlXCelqb7yQ0RrpvJXKnLEYxaBOpYyyQjub8CUrURwqUbArQQErWxEWQh5fhknJDCPhgkVh%2BiEsrc%2FS4pLHYr0Pw7oPa8ZXa7EPoweouLYNYzCAo00psgt4%2B%2Bn4DZTZJo1LWGYFiDUvYRVeMLLJCyYEZ0Wfr1LMz4iytBTwZPbqxdEUw%2F%2FlgAM%2BG9KX6w1pCVDhQEAaB%2FZGXrVRf1zccXeU%2Fc7fD7fHmJ9NTs8ohOeOHewKjLFT8tgIl6EeZbzrVZHlUgXyRne5fzJ59uyf2fHx%2FOh0On1BcXx36MtyxhjAcz2KSnFw2ZXRpNTfc%2Fdw3aGVPp7r%2B%2FWvQJ6T60iuPlVoLDdpJHiWAk%2B5sGz43AIL4y4GQYsulE8GAfThBAYw6kyeTFHpB8a15lKEec5i68qBj7VjvgTrXoWQWtcFjSg2rFUvryzZa7tRYcM2RSrF6861%2BPrVusLk5CUbQGB3UtnkcSiYFYvbE1FOAQciuMBbUkYFY%2BnjxrIC%2FAHeAN2YgAjZB1Y8NqQpqi5QRJQyyiNOmH6xE1bklry8Kmc1SLs5GmepKdBKaOdRDCuHKqcmJen0EeVTuffkFsMr1%2B73VDsOYdGYLaoeGY0nNdxeyxuHcKLPpgaDv%2BN1dASI3VZVk4L67oPfmWIX0nY1v7p0NR7pFfKs5DQzDYi9A0VX9ytmug%2Bx0HCpts%2B724qosJnvkD0inY%2BqmEqvYiJCbrS3Cqw3ZQFfvlQJPWr0eqNUjgfQb0tvgze4vm5npNLf6kwy8p2ummKiNYveq1qiLEl4SaC%2F5GKt45BC4m7BIqHqc6pno0lA%2F6WQSo%2BQXBdIM%2FYtCWrFqleiR0%2FYH2QtG6B2bQURSdzdexsX4WXDSlFSWp59J48QIYUJkqllRiwVrDAdMC84tcC0O1YlFmnV%2FNXdspD2HOI6PHs2eQlnM0X46Gto35yhgvshXcQ2DWrxkieJ9XsT6dFv%2FMiqeBFJ220jqSliS%2Ba31S47Q6Wvw3TF09WN2i0f3yT6N3%2F8%2B9%2FP79%2FAdAuWs1CoamwHRrf7ZWl8h1eiltqzZZp4eyQibBdrnlNGFr6tnn2zi%2F%2FX9DCbAN9J8%2Bnk%2BRRmr6enZqfvv7lB3vDcB%2BNt3nqqY%2FOj2el0n4r7oxIRzb8ATsCfrQ%3D%3D)
99
235
  - [Bouncing Ball](https://litecanvas.js.org?c=eJxtkkFugzAQRfecYpaGOMFJW6lVQhddcQPWlm0iSy4gY0hRkrt3ADc4SRdI9nzm%2FzcMRjlo6lY7XVeQQa8E2TJG8YlpBHg3tdBuGM9Hy3t%2FtFzqrsX3X9%2BjyGinBK963pI4isquEpOZrrQjMZwDFx9QJDuap7t4v5h6hdEcq9fApWskd4pINzv9oW5%2BYJXdfPGWgHShPtzpw6wHKLOBT1%2F6g45AXtrTFL5qZFNQlyUoeVQtVnUJZCFb%2Ba%2FzCQVcLgHy2gsHYPM0dzhJBuvt%2Fp8q23y8TeVg%2BAyE4d9NkEr9UigUPifGpusjHc4FN778CWOYMJ4TxwXl3neyDXckLT%2F5TQvTEjYtVmgrSm1MiLjYUQ%2F78rDu8SfAUYbZzSrX2QrOYwUjfwF7%2FdPj)
100
236
  - [Scroller](https://litecanvas.js.org?c=eJxVUM1SgzAQvvMU68FpAhFDLVpH%2BxbOcOj0ECGUzATSIYsyOn13NwXRHpJNvv1%2BkrUGdam6D%2BUZj6J66Eo0rgPTGQTG4TsCaLX36qhhB6tC29K1GtCBXYQ3KyKN1C6onpSl034jcvEonsRWPItMiiw7ROd%2F9sOpUqiBVThFePMV%2FIv7OSu1ujtiQ52G4FxeAu528CAlxFDhHNiqkY0C1pJfuVe9%2Bvx9fGk9ozZA7XpgViMYEsoXKq9wnUZYkkwqgMBEYr4lTKZZbPiC0kLdh%2FRZ7Yd3jz0zArI%2FVumsCySax762zvUM4%2FyWbnMYP1yoqEcMn2dh4wvExsTEAYpluhXQJGuZeNORx4bHjZjfIKaUIDvTAH4AEIGEgw%3D%3D)
101
237
  - [3D projection](https://litecanvas.js.org?c=eJyNVcuS2jAQvPsrJofUykE8wykJySlVyRckuy4fZGwWgZEpWQSWFP%2BeGUlgizVLqgyyprul1mgkl9IUc6H%2BiJrFUbTYqbmRlQKppGEx%2FI0AanksYAa%2F4Cv8gG%2F4G8IUPmEfW4S3uloVTjSDBAMAyZjDCJ%2BUuy6%2Bj8MuRWw3pREqqUzdqPs0I4d2k3IYDiE5cHjhcEwdr4vWRjqA%2Fj2kRQgHuwm8jvc7gbTJVZHTYikg1HNJyR1Fp1byd9tcmILlxm2AI%2FWQNRiNIwwsKg2sLAxIkn7G5otP4qAs1LNZYqjXc2KAeaVqgzhl2LImG2G0PLDBYOBUiUxjS6UxdWWEc4i0za5kNoC2fjNrJOY0luPf5D5euJ5yh%2F%2FUzb%2FkCx02oqbiAvopyGGuxd4X8Lys2SimxG139ZIRt5Sq2MvcLNmEukYLVZeUc6rqCbdFbpGuVE%2Bv06vQDZMcmIQejGN4D1PeeI9DGlIQZS1u7EK3BBxkB%2BFkD84WV9Ne9VkkOGTc14QzSitmfrtFmozoOTMoMA4C2TUjuzA%2BhjP6PaEJfbZtuYl5VVLBCdT4omwwXe0tdg1kXpR1iDIvys4AInIBzE30bjZzjBjMElvA7YXvWleaPfzEy62UObiqL%2BoHWwpuVF3U56PYtdPWabDbKHC1mLhL6KJaOdUKVXYZ%2BNqo3Mmqdxt71F3kolw75Zrmc8p1WwlW16NUyjRZp%2FAB87NOk1XqCSffOmsYx%2FFQEp2xEy1XF2anFXGC3WvOtha5xEPg5vXsm7f5vKovAns1qla3TQyRUDby12KXn8e3%2FFwNE85y45tz7TE084aTp%2F93cisP95Pw6qPYdhLc2f4LGJpJDngukxf6O6Yk%2FgdWEko3)
@@ -103,6 +239,19 @@ Try some demos in the playground:
103
239
 
104
240
  > _See other demos in [samples](/samples) folder_
105
241
 
242
+ ## Contributing
243
+
244
+ 1. Fork this repository and clone it.
245
+ 1. Install the dependencies: `npm i`
246
+ 1. Create a new branch and make your changes.
247
+ 1. Format the code: `npm run format`
248
+ 1. Create new tests in `tests` directory, if necessary.
249
+ 1. Test with `npm run test`
250
+ 1. Create your pull request.
251
+ 1. Done!
252
+
253
+ > Note: You'll need Node.JS installed in your machine.
254
+
106
255
  ## Inspirations
107
256
 
108
257
  - [floppy](https://github.com/lpagg/floppy): a micro game engine for beginners.
package/dist/dist.dev.js CHANGED
@@ -32,7 +32,7 @@
32
32
  };
33
33
 
34
34
  // src/version.js
35
- var version = "0.98.1";
35
+ var version = "0.98.3";
36
36
 
37
37
  // src/index.js
38
38
  function litecanvas(settings = {}) {
@@ -642,9 +642,9 @@
642
642
  const chars = pixels.replace(/\s/g, "");
643
643
  for (let gridx = 0; gridx < width; gridx++) {
644
644
  for (let gridy = 0; gridy < height; gridy++) {
645
- const char = chars[height * gridy + gridx] || ".";
645
+ const char = chars[width * gridy + gridx] || ".";
646
646
  if (char !== ".") {
647
- instance.rectfill(x + gridx, y + gridy, 1, 1, parseInt(char, 16) || 0);
647
+ instance.rectfill(x + gridx, y + gridy, 1, 1, parseInt(char, 36) || 0);
648
648
  }
649
649
  }
650
650
  }
package/dist/dist.js CHANGED
@@ -428,9 +428,9 @@
428
428
  const chars = pixels.replace(/\s/g, "");
429
429
  for (let gridx = 0; gridx < width; gridx++) {
430
430
  for (let gridy = 0; gridy < height; gridy++) {
431
- const char = chars[height * gridy + gridx] || ".";
431
+ const char = chars[width * gridy + gridx] || ".";
432
432
  if (char !== ".") {
433
- instance.rectfill(x + gridx, y + gridy, 1, 1, parseInt(char, 16) || 0);
433
+ instance.rectfill(x + gridx, y + gridy, 1, 1, parseInt(char, 36) || 0);
434
434
  }
435
435
  }
436
436
  }
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,m,g=.5,v=1,w,x=1e3/60,y,b,k="sans-serif",E=20,z=Date.now(),T=e,I=[],D=[.5,0,1750,,,.3,1,,,,600,.1],S={},A={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?A.clamp(o,l,n):o},norm:(e,t,a)=>A.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)=>(z=(1664525*z+0x3c6ef35f)%0x100000000)/0x100000000*(t-e)+e,randi:(e=0,t=1)=>l.floor(A.rand(e,t+1)),rseed(e){z=~~e},cls(e){null==e?m.clearRect(0,0,m.canvas.width,m.canvas.height):A.rectfill(0,0,m.canvas.width,m.canvas.height,e)},rect(e,t,a,l,n,i){f(m),m[i?"roundRect":"rect"](~~e-g,~~t-g,~~a+2*g,~~l+2*g,i),A.stroke(n)},rectfill(e,t,a,l,n,i){f(m),m[i?"roundRect":"rect"](~~e,~~t,~~a,~~l,i),A.fill(n)},circ(e,t,a,l){f(m),m.arc(~~e,~~t,~~a,0,n),A.stroke(l)},circfill(e,t,a,l){f(m),m.arc(~~e,~~t,~~a,0,n),A.fill(l)},oval(e,t,a,l,i){f(m),m.ellipse(~~e,~~t,~~a,~~l,0,0,n),A.stroke(i)},ovalfill(e,t,a,l,i){f(m),m.ellipse(~~e,~~t,~~a,~~l,0,0,n),A.fill(i)},line(e,t,a,l,n){f(m);let i=.5*(0!==g&&~~e==~~a),o=.5*(0!==g&&~~t==~~l);m.moveTo(~~e+i,~~t+o),m.lineTo(~~a+i,~~l+o),A.stroke(n)},linewidth(e){m.lineWidth=~~e,g=.5*(0!=~~e%2)},linedash(e,t=0){m.setLineDash(e),m.lineDashOffset=t},text(e,t,a,l=3,n="normal"){m.font=`${n} ${E}px ${k}`,m.fillStyle=P(l),m.fillText(a,~~e,~~t)},textfont(e){k=e},textsize(e){E=e},textalign(e,t){e&&(m.textAlign=e),t&&(m.textBaseline=t)},image(e,t,a){m.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 a=0;a<l;a++){let o=i[l*a+n]||".";"."!==o&&A.rectfill(e+n,t+a,1,1,parseInt(o,16)||0)}},paint(e,t,a,l={}){let n=l.canvas||new OffscreenCanvas(1,1),i=l.scale||1,o=m;return n.width=e*i,n.height=t*i,(m=n.getContext("2d")).scale(i,i),a(m),m=o,n.transferToImageBitmap()},ctx:e=>(e&&(m=e),m),push(){m.save()},pop(){m.restore()},translate(e,t){m.translate(~~e,~~t)},scale(e,t){m.scale(e,t||e)},rotate(e){m.rotate(e)},alpha(e){m.globalAlpha=A.clamp(e,0,1)},fill(e){m.fillStyle=P(e),m.fill()},stroke(e){m.strokeStyle=P(e),m.stroke()},clip(e){f(m),e(m),m.clip()},sfx:(e,t=0,l=1)=>!!a.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){a.zzfxV=e},canvas:()=>p,use(e,t={}){var a=e,l=t;let n=a(A,l);for(let e in n)A.def(e,n[e])},listen:(e,t)=>(S[e=s(e)]=S[e]||new Set,S[e].add(t),()=>S&&S[e].delete(t)),emit(e,t,a,l,n){u&&(N("before:"+(e=s(e)),t,a,l,n),N(e,t,a,l,n),N("after:"+e,t,a,l,n))},pal(t=e){T=t,I=[]},palc(e,t){null==e?I=[]:I[e]=t},def(e,l){A[e]=l,t.global&&(a[e]=l)},timescale(e){v=e},framerate(e){x=1e3/~~e},stat(e){let l={index:e,value:[t,u,x/1e3,h,S,T,D,v,a.zzfxV,z,E,k][e]};return A.emit("stat",l),l.value},quit(){for(let e of(A.pause(),A.emit("quit"),S={},o))e();if(t.global){for(let e in A)delete a[e];delete a.ENGINE}u=!1},pause(){cancelAnimationFrame(b),b=0},resume(){u&&!b&&(y=x,w=Date.now(),b=i(C))},paused:()=>!b};for(let e of"PI,sin,cos,atan2,hypot,tan,abs,ceil,floor,trunc,min,max,pow,sqrt,sign,exp".split(","))A[e]=l[e];function M(){let e=t.loop?t.loop:a;for(let t of"init,update,draw,tap,untap,tapping,tapped,resized".split(","))e[t]&&A.listen(t,e[t]);if(t.autoscale&&r(a,"resize",L),t.tapEvents){let e=e=>[(e.pageX-p.offsetLeft)/h,(e.pageY-p.offsetTop)/h],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(p,"mousedown",t=>{if(0===t.button){c(t);let[a,n]=e(t);A.emit("tap",a,n,0),l(0,a,n),o=!0}}),r(p,"mouseup",a=>{if(0===a.button){c(a);let l=t.get(0),[n,r]=e(a);i(l)&&A.emit("tapped",l.xi,l.yi,0),A.emit("untap",n,r,0),t.delete(0),o=!1}}),r(a,"mousemove",t=>{c(t);let[a,l]=e(t);A.def("MX",a),A.def("MY",l),o&&(A.emit("tapping",a,l,0),n(0,a,l))}),r(p,"touchstart",t=>{for(let a of(c(t),t.changedTouches)){let[t,n]=e(a);A.emit("tap",t,n,a.identifier+1),l(a.identifier+1,t,n)}}),r(p,"touchmove",t=>{for(let a of(c(t),t.changedTouches)){let[t,l]=e(a);A.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)&&A.emit("tapped",l.xi,l.yi,e),A.emit("untap",l.x,l.y,e),t.delete(e))};r(p,"touchend",s),r(p,"touchcancel",s),r(a,"blur",()=>{for(let[e,a]of(o=!1,t))A.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()),A.listen("after:update",()=>t.clear()),A.def("iskeydown",t=>l(e,t)),A.def("iskeypressed",e=>l(t,e)),A.def("lastkey",()=>n)}u=!0,A.emit("init",A),A.resume()}function C(){b=i(C);let e=Date.now(),t=0,a=e-w;for(w=e,y+=a<100?a:x;y>=x;){t++,y-=x;let e=x/1e3*v;A.emit("update",e,t),A.def("T",A.T+e)}t&&(A.emit("draw",m),t>1&&(y=0))}function L(){let e=t.width>0?t.width:innerWidth,a=t.width>0?t.height||t.width:innerHeight;if(A.def("W",e),A.def("H",a),p.width=e,p.height=a,t.autoscale){let n=+t.autoscale;p.style.display||(p.style.display="block",p.style.margin="auto"),h=l.min(innerWidth/e,innerHeight/a),h=n>1&&h>n?n:h,p.style.width=e*h+"px",p.style.height=a*h+"px"}m.imageSmoothingEnabled=!1,A.textalign("start","top"),A.emit("resized",h)}function N(e,t,a,l,n){if(S[e])for(let i of S[e])i(t,a,l,n)}function P(e){return T[~~(I[e]??e)%T.length]}if(t.global){if(a.ENGINE)throw Error("only one global litecanvas is allowed");Object.assign(a,A),a.ENGINE=A}return m=(p=(p="string"==typeof t.canvas?document.querySelector(t.canvas):t.canvas)||document.createElement("canvas")).getContext("2d"),r(p,"click",()=>focus()),L(),p.parentNode||document.body.appendChild(p),p.style.imageRendering="pixelated",p.oncontextmenu=()=>!1,"loading"===document.readyState?r(a,"DOMContentLoaded",()=>i(M)):i(M),A}})();
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,m,g=.5,v=1,w,x=1e3/60,y,b,k="sans-serif",E=20,z=Date.now(),T=e,I=[],D=[.5,0,1750,,,.3,1,,,,600,.1],S={},A={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?A.clamp(o,l,n):o},norm:(e,t,a)=>A.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)=>(z=(1664525*z+0x3c6ef35f)%0x100000000)/0x100000000*(t-e)+e,randi:(e=0,t=1)=>l.floor(A.rand(e,t+1)),rseed(e){z=~~e},cls(e){null==e?m.clearRect(0,0,m.canvas.width,m.canvas.height):A.rectfill(0,0,m.canvas.width,m.canvas.height,e)},rect(e,t,a,l,n,i){f(m),m[i?"roundRect":"rect"](~~e-g,~~t-g,~~a+2*g,~~l+2*g,i),A.stroke(n)},rectfill(e,t,a,l,n,i){f(m),m[i?"roundRect":"rect"](~~e,~~t,~~a,~~l,i),A.fill(n)},circ(e,t,a,l){f(m),m.arc(~~e,~~t,~~a,0,n),A.stroke(l)},circfill(e,t,a,l){f(m),m.arc(~~e,~~t,~~a,0,n),A.fill(l)},oval(e,t,a,l,i){f(m),m.ellipse(~~e,~~t,~~a,~~l,0,0,n),A.stroke(i)},ovalfill(e,t,a,l,i){f(m),m.ellipse(~~e,~~t,~~a,~~l,0,0,n),A.fill(i)},line(e,t,a,l,n){f(m);let i=.5*(0!==g&&~~e==~~a),o=.5*(0!==g&&~~t==~~l);m.moveTo(~~e+i,~~t+o),m.lineTo(~~a+i,~~l+o),A.stroke(n)},linewidth(e){m.lineWidth=~~e,g=.5*(0!=~~e%2)},linedash(e,t=0){m.setLineDash(e),m.lineDashOffset=t},text(e,t,a,l=3,n="normal"){m.font=`${n} ${E}px ${k}`,m.fillStyle=P(l),m.fillText(a,~~e,~~t)},textfont(e){k=e},textsize(e){E=e},textalign(e,t){e&&(m.textAlign=e),t&&(m.textBaseline=t)},image(e,t,a){m.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&&A.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=m;return n.width=e*i,n.height=t*i,(m=n.getContext("2d")).scale(i,i),a(m),m=o,n.transferToImageBitmap()},ctx:e=>(e&&(m=e),m),push(){m.save()},pop(){m.restore()},translate(e,t){m.translate(~~e,~~t)},scale(e,t){m.scale(e,t||e)},rotate(e){m.rotate(e)},alpha(e){m.globalAlpha=A.clamp(e,0,1)},fill(e){m.fillStyle=P(e),m.fill()},stroke(e){m.strokeStyle=P(e),m.stroke()},clip(e){f(m),e(m),m.clip()},sfx:(e,t=0,l=1)=>!!a.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){a.zzfxV=e},canvas:()=>p,use(e,t={}){var a=e,l=t;let n=a(A,l);for(let e in n)A.def(e,n[e])},listen:(e,t)=>(S[e=s(e)]=S[e]||new Set,S[e].add(t),()=>S&&S[e].delete(t)),emit(e,t,a,l,n){u&&(N("before:"+(e=s(e)),t,a,l,n),N(e,t,a,l,n),N("after:"+e,t,a,l,n))},pal(t=e){T=t,I=[]},palc(e,t){null==e?I=[]:I[e]=t},def(e,l){A[e]=l,t.global&&(a[e]=l)},timescale(e){v=e},framerate(e){x=1e3/~~e},stat(e){let l={index:e,value:[t,u,x/1e3,h,S,T,D,v,a.zzfxV,z,E,k][e]};return A.emit("stat",l),l.value},quit(){for(let e of(A.pause(),A.emit("quit"),S={},o))e();if(t.global){for(let e in A)delete a[e];delete a.ENGINE}u=!1},pause(){cancelAnimationFrame(b),b=0},resume(){u&&!b&&(y=x,w=Date.now(),b=i(C))},paused:()=>!b};for(let e of"PI,sin,cos,atan2,hypot,tan,abs,ceil,floor,trunc,min,max,pow,sqrt,sign,exp".split(","))A[e]=l[e];function M(){let e=t.loop?t.loop:a;for(let t of"init,update,draw,tap,untap,tapping,tapped,resized".split(","))e[t]&&A.listen(t,e[t]);if(t.autoscale&&r(a,"resize",L),t.tapEvents){let e=e=>[(e.pageX-p.offsetLeft)/h,(e.pageY-p.offsetTop)/h],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(p,"mousedown",t=>{if(0===t.button){c(t);let[a,n]=e(t);A.emit("tap",a,n,0),l(0,a,n),o=!0}}),r(p,"mouseup",a=>{if(0===a.button){c(a);let l=t.get(0),[n,r]=e(a);i(l)&&A.emit("tapped",l.xi,l.yi,0),A.emit("untap",n,r,0),t.delete(0),o=!1}}),r(a,"mousemove",t=>{c(t);let[a,l]=e(t);A.def("MX",a),A.def("MY",l),o&&(A.emit("tapping",a,l,0),n(0,a,l))}),r(p,"touchstart",t=>{for(let a of(c(t),t.changedTouches)){let[t,n]=e(a);A.emit("tap",t,n,a.identifier+1),l(a.identifier+1,t,n)}}),r(p,"touchmove",t=>{for(let a of(c(t),t.changedTouches)){let[t,l]=e(a);A.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)&&A.emit("tapped",l.xi,l.yi,e),A.emit("untap",l.x,l.y,e),t.delete(e))};r(p,"touchend",s),r(p,"touchcancel",s),r(a,"blur",()=>{for(let[e,a]of(o=!1,t))A.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()),A.listen("after:update",()=>t.clear()),A.def("iskeydown",t=>l(e,t)),A.def("iskeypressed",e=>l(t,e)),A.def("lastkey",()=>n)}u=!0,A.emit("init",A),A.resume()}function C(){b=i(C);let e=Date.now(),t=0,a=e-w;for(w=e,y+=a<100?a:x;y>=x;){t++,y-=x;let e=x/1e3*v;A.emit("update",e,t),A.def("T",A.T+e)}t&&(A.emit("draw",m),t>1&&(y=0))}function L(){let e=t.width>0?t.width:innerWidth,a=t.width>0?t.height||t.width:innerHeight;if(A.def("W",e),A.def("H",a),p.width=e,p.height=a,t.autoscale){let n=+t.autoscale;p.style.display||(p.style.display="block",p.style.margin="auto"),h=l.min(innerWidth/e,innerHeight/a),h=n>1&&h>n?n:h,p.style.width=e*h+"px",p.style.height=a*h+"px"}m.imageSmoothingEnabled=!1,A.textalign("start","top"),A.emit("resized",h)}function N(e,t,a,l,n){if(S[e])for(let i of S[e])i(t,a,l,n)}function P(e){return T[~~(I[e]??e)%T.length]}if(t.global){if(a.ENGINE)throw Error("only one global litecanvas is allowed");Object.assign(a,A),a.ENGINE=A}return m=(p=(p="string"==typeof t.canvas?document.querySelector(t.canvas):t.canvas)||document.createElement("canvas")).getContext("2d"),r(p,"click",()=>focus()),L(),p.parentNode||document.body.appendChild(p),p.style.imageRendering="pixelated",p.oncontextmenu=()=>!1,"loading"===document.readyState?r(a,"DOMContentLoaded",()=>i(M)):i(M),A}})();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "litecanvas",
3
- "version": "0.98.1",
3
+ "version": "0.98.3",
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
@@ -747,9 +747,9 @@ export default function litecanvas(settings = {}) {
747
747
  const chars = pixels.replace(/\s/g, '')
748
748
  for (let gridx = 0; gridx < width; gridx++) {
749
749
  for (let gridy = 0; gridy < height; gridy++) {
750
- const char = chars[height * gridy + gridx] || '.'
750
+ const char = chars[width * gridy + gridx] || '.'
751
751
  if (char !== '.') {
752
- instance.rectfill(x + gridx, y + gridy, 1, 1, parseInt(char, 16) || 0)
752
+ instance.rectfill(x + gridx, y + gridy, 1, 1, parseInt(char, 36) || 0)
753
753
  }
754
754
  }
755
755
  }
package/src/version.js CHANGED
@@ -1,2 +1,2 @@
1
1
  // Generated by genversion.
2
- export const version = '0.98.1'
2
+ export const version = '0.98.3'