litecanvas 0.100.1 → 0.101.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 CHANGED
@@ -129,7 +129,6 @@ function draw() {
129
129
 
130
130
  [Live Demo](https://litecanvas.js.org?c=eJxVzEsKwkAMBuB9T%2FEXF52CYEG37j1EN3EadTBmZCb1gXh3pyqIIYs8PwnGnvRC2bVVtRvVW4iKIdHVtXhUKLFYwAtTAumAXRCBHRh7OjGyT8yKa7ADfJSYMOvgtkL%2B2L5%2FvWTXFfnrnFNQAyHxAONbKQ23dTfHfd29b6ahK33JZsMisa7rZo7Vjxgzo1dYxDYxHT%2BMBOX8Bywn4TSKhV6nba%2FTpmmr5wtwJEcj)
131
131
 
132
-
133
132
  ### Drawing shapes
134
133
 
135
134
  You can use the following functions to draw shapes:
@@ -165,7 +164,7 @@ function draw() {
165
164
 
166
165
  ```js
167
166
  litecanvas({
168
- width: 128
167
+ width: 128,
169
168
  })
170
169
 
171
170
  // you can create sprites with strings
@@ -186,8 +185,8 @@ function draw() {
186
185
  cls(0)
187
186
 
188
187
  spr(
189
- 0, 0, // position X Y
190
- 8, 8, // the sprite Width and Height
188
+ 0,
189
+ 0, // the sprite Position X Y
191
190
  smile8x8 // the sprite Pixels
192
191
  )
193
192
  }
@@ -202,14 +201,16 @@ litecanvas()
202
201
 
203
202
  // lets create flag of Japan
204
203
  let japanFlag = paint(
205
- 48, 32, // the image width and height
204
+ 48,
205
+ 32, // the image width and height
206
206
  function () {
207
207
  cls(3) // white background
208
208
  circfill(24, 16, 8, 4) // red circle
209
- }, {
209
+ },
210
+ {
210
211
  // you can scale your image
211
212
  // by default, scale=1
212
- scale: 4
213
+ scale: 4,
213
214
  }
214
215
  )
215
216
 
@@ -218,9 +219,9 @@ function draw() {
218
219
 
219
220
  // draw the japanFlag image
220
221
  image(
221
- W/2 - japanFlag.width/2, // game screen center X
222
- H/2 - japanFlag.height/2, // game screen center Y
223
- japanFlag // the image
222
+ W / 2 - japanFlag.width / 2, // game screen center X
223
+ H / 2 - japanFlag.height / 2, // game screen center Y
224
+ japanFlag // the image
224
225
  )
225
226
  }
226
227
  ```
package/dist/dist.dev.js CHANGED
@@ -11,20 +11,7 @@
11
11
  };
12
12
 
13
13
  // src/palette.js
14
- var defaultPalette = [
15
- "#111",
16
- "#6a7799",
17
- "#aec2c2",
18
- "#FFF1E8",
19
- "#e83b3b",
20
- "#fabc20",
21
- "#155fd9",
22
- "#3cbcfc",
23
- "#327345",
24
- "#63c64d",
25
- "#6c2c1f",
26
- "#ac7c00"
27
- ];
14
+ var defaultPalette = ["#211e20", "#555568", "#a0a08b", "#e9efec"];
28
15
 
29
16
  // src/dev.js
30
17
  var assert = (condition, message = "Assertion failed") => {
@@ -32,7 +19,7 @@
32
19
  };
33
20
 
34
21
  // src/version.js
35
- var version = "0.100.1";
22
+ var version = "0.101.0";
36
23
 
37
24
  // src/index.js
38
25
  function litecanvas(settings = {}) {
@@ -50,7 +37,7 @@
50
37
  keyboardEvents: true
51
38
  };
52
39
  settings = Object.assign(defaults, settings);
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, _fontLineHeight = 1.2, _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 = {};
40
+ let _initialized = false, _paused = true, _canvas, _scale = 1, _ctx, _outline_fix = 0.5, _timeScale = 1, _lastFrameTime, _fpsInterval = 1e3 / 60, _accumulated, _rafid, _defaultTextColor = 3, _fontFamily = "sans-serif", _fontSize = 20, _fontLineHeight = 1.2, _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
41
  const instance = {
55
42
  /** @type {number} */
56
43
  W: 0,
@@ -550,10 +537,10 @@
550
537
  * @param {number} x
551
538
  * @param {number} y
552
539
  * @param {string} message the text message
553
- * @param {number} [color=3] the color index
540
+ * @param {number} [color] the color index
554
541
  * @param {string} [fontStyle] can be "normal" (default), "italic" and/or "bold".
555
542
  */
556
- text(x, y, message, color = 3, fontStyle = "normal") {
543
+ text(x, y, message, color = _defaultTextColor, fontStyle = "normal") {
557
544
  DEV: assert(isNumber(x), "[litecanvas] text() 1st param must be a number");
558
545
  DEV: assert(isNumber(y), "[litecanvas] text() 2nd param must be a number");
559
546
  DEV: assert(
@@ -638,26 +625,23 @@
638
625
  _ctx.drawImage(source2, ~~x, ~~y);
639
626
  },
640
627
  /**
641
- * Draw a sprite pxiel by pixel represented by a string. Each pixel must be a base 36 number (0-9 or a-z) or a dot.
628
+ * Draw a sprite pixel by pixel represented by a string. Each pixel must be a base 36 number (0-9 or a-z) or a dot.
642
629
  *
643
630
  * @param {number} x
644
631
  * @param {number} y
645
- * @param {number} width
646
- * @param {number} height
647
632
  * @param {string} pixels
648
633
  */
649
- spr(x, y, width, height, pixels) {
634
+ spr(x, y, pixels) {
650
635
  DEV: assert(isNumber(x), "[litecanvas] spr() 1st param must be a number");
651
636
  DEV: assert(isNumber(y), "[litecanvas] spr() 2nd param must be a number");
652
- DEV: assert(isNumber(width), "[litecanvas] spr() 3rd param must be a number");
653
- DEV: assert(isNumber(height), "[litecanvas] spr() 4th param must be a number");
654
- DEV: assert("string" === typeof pixels, "[litecanvas] spr() 5th param must be a string");
655
- const chars = pixels.replace(/\s/g, "");
656
- for (let gridx = 0; gridx < width; gridx++) {
657
- for (let gridy = 0; gridy < height; gridy++) {
658
- const char = chars[width * gridy + gridx] || ".";
659
- if (char !== ".") {
660
- instance.rectfill(x + gridx, y + gridy, 1, 1, parseInt(char, 36) || 0);
637
+ DEV: assert("string" === typeof pixels, "[litecanvas] spr() 3rd param must be a string");
638
+ const rows = pixels.trim().split("\n");
639
+ for (let row = 0; row < rows.length; row++) {
640
+ const chars = rows[row].trim();
641
+ for (let col = 0; col < chars.length; col++) {
642
+ const char = chars[col];
643
+ if (char !== "." && char !== " ") {
644
+ instance.rectfill(x + col, y + row, 1, 1, parseInt(char, 36) || 0);
661
645
  }
662
646
  }
663
647
  }
@@ -928,15 +912,21 @@
928
912
  /**
929
913
  * Set new palette colors or restore the default palette.
930
914
  *
931
- * @param {string[]} [colors]
915
+ * @param {string[]} [colors] an array of colors
916
+ * @param {number} [textColor] the default text color this palette
932
917
  */
933
- pal(colors = defaultPalette) {
918
+ pal(colors, textColor = 3) {
934
919
  DEV: assert(
935
920
  Array.isArray(colors) && colors.length > 0,
936
- "[litecanvas] pal() 1st param must be a array of strings"
921
+ "[litecanvas] pal() 1st param must be a array of color strings"
922
+ );
923
+ DEV: assert(
924
+ isNumber(textColor) && textColor >= 0,
925
+ "[litecanvas] pal() 2nd param must be a positive number or zero"
937
926
  );
938
- _colorPalette = colors;
927
+ _colorPalette = colors || defaultPalette;
939
928
  _colorPaletteState = [];
929
+ _defaultTextColor = textColor;
940
930
  },
941
931
  /**
942
932
  * Replace the color "a" with color "b".
@@ -1457,5 +1447,5 @@
1457
1447
  }
1458
1448
 
1459
1449
  // src/web.js
1460
- globalThis.litecanvas = litecanvas;
1450
+ window.litecanvas = litecanvas;
1461
1451
  })();
package/dist/dist.js CHANGED
@@ -11,20 +11,7 @@
11
11
  };
12
12
 
13
13
  // src/palette.js
14
- var defaultPalette = [
15
- "#111",
16
- "#6a7799",
17
- "#aec2c2",
18
- "#FFF1E8",
19
- "#e83b3b",
20
- "#fabc20",
21
- "#155fd9",
22
- "#3cbcfc",
23
- "#327345",
24
- "#63c64d",
25
- "#6c2c1f",
26
- "#ac7c00"
27
- ];
14
+ var defaultPalette = ["#211e20", "#555568", "#a0a08b", "#e9efec"];
28
15
 
29
16
  // src/index.js
30
17
  function litecanvas(settings = {}) {
@@ -42,7 +29,7 @@
42
29
  keyboardEvents: true
43
30
  };
44
31
  settings = Object.assign(defaults, settings);
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, _fontLineHeight = 1.2, _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 = {};
32
+ let _initialized = false, _paused = true, _canvas, _scale = 1, _ctx, _outline_fix = 0.5, _timeScale = 1, _lastFrameTime, _fpsInterval = 1e3 / 60, _accumulated, _rafid, _defaultTextColor = 3, _fontFamily = "sans-serif", _fontSize = 20, _fontLineHeight = 1.2, _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
33
  const instance = {
47
34
  /** @type {number} */
48
35
  W: 0,
@@ -368,10 +355,10 @@
368
355
  * @param {number} x
369
356
  * @param {number} y
370
357
  * @param {string} message the text message
371
- * @param {number} [color=3] the color index
358
+ * @param {number} [color] the color index
372
359
  * @param {string} [fontStyle] can be "normal" (default), "italic" and/or "bold".
373
360
  */
374
- text(x, y, message, color = 3, fontStyle = "normal") {
361
+ text(x, y, message, color = _defaultTextColor, fontStyle = "normal") {
375
362
  _ctx.font = `${fontStyle} ${_fontSize}px ${_fontFamily}`;
376
363
  _ctx.fillStyle = getColor(color);
377
364
  const messages = ("" + message).split("\n");
@@ -429,21 +416,20 @@
429
416
  _ctx.drawImage(source2, ~~x, ~~y);
430
417
  },
431
418
  /**
432
- * Draw a sprite pxiel by pixel represented by a string. Each pixel must be a base 36 number (0-9 or a-z) or a dot.
419
+ * Draw a sprite pixel by pixel represented by a string. Each pixel must be a base 36 number (0-9 or a-z) or a dot.
433
420
  *
434
421
  * @param {number} x
435
422
  * @param {number} y
436
- * @param {number} width
437
- * @param {number} height
438
423
  * @param {string} pixels
439
424
  */
440
- spr(x, y, width, height, pixels) {
441
- const chars = pixels.replace(/\s/g, "");
442
- for (let gridx = 0; gridx < width; gridx++) {
443
- for (let gridy = 0; gridy < height; gridy++) {
444
- const char = chars[width * gridy + gridx] || ".";
445
- if (char !== ".") {
446
- instance.rectfill(x + gridx, y + gridy, 1, 1, parseInt(char, 36) || 0);
425
+ spr(x, y, pixels) {
426
+ const rows = pixels.trim().split("\n");
427
+ for (let row = 0; row < rows.length; row++) {
428
+ const chars = rows[row].trim();
429
+ for (let col = 0; col < chars.length; col++) {
430
+ const char = chars[col];
431
+ if (char !== "." && char !== " ") {
432
+ instance.rectfill(x + col, y + row, 1, 1, parseInt(char, 36) || 0);
447
433
  }
448
434
  }
449
435
  }
@@ -646,11 +632,13 @@
646
632
  /**
647
633
  * Set new palette colors or restore the default palette.
648
634
  *
649
- * @param {string[]} [colors]
635
+ * @param {string[]} [colors] an array of colors
636
+ * @param {number} [textColor] the default text color this palette
650
637
  */
651
- pal(colors = defaultPalette) {
652
- _colorPalette = colors;
638
+ pal(colors, textColor = 3) {
639
+ _colorPalette = colors || defaultPalette;
653
640
  _colorPaletteState = [];
641
+ _defaultTextColor = textColor;
654
642
  },
655
643
  /**
656
644
  * Replace the color "a" with color "b".
@@ -1100,5 +1088,5 @@
1100
1088
  }
1101
1089
 
1102
1090
  // src/web.js
1103
- globalThis.litecanvas = litecanvas;
1091
+ window.litecanvas = litecanvas;
1104
1092
  })();
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,l=window,n=Math,i=2*n.PI,o=requestAnimationFrame,r=[],s=(e,t,a)=>{e.addEventListener(t,a,!1),r.push(()=>e.removeEventListener(t,a,!1))},f=(a=new AudioContext,l.zzfxV=1,(e=1,t=.05,n=220,i=0,o=0,r=.1,s=0,f=1,c=0,d=0,u=0,p=0,h=0,g=0,m=0,v=0,w=0,x=1,b=0,y=0,k=0)=>{let E=Math,z=2*E.PI,D=c*=500*z/44100/44100,P=n*=(1-t+2*t*E.random(t=[]))*z/44100,T=0,C=0,I=0,L=1,S=0,A=0,M=0,N=k<0?-1:1,F=z*N*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+N*q)/2/O,G=-(N+q)/O,X=0,Y=0,$=0,j=0;for(i=44100*i+9,b*=44100,o*=44100,r*=44100,w*=44100,d*=500*z/85766121e6,m*=z/44100,u*=z/44100,p*=44100,h=44100*h|0,e*=.3*l.zzfxV,N=i+b+o+r+w|0;I<N;t[I++]=M*e)++A%(100*v|0)||(M=s?1<s?2<s?3<s?B(T*T):E.max(E.min(E.tan(T),1),-1):1-(2*T/z%2+2)%2:1-4*E.abs(E.round(T/z)-T/z):B(T),M=(h?1-y+y*B(z*I/h):1)*(M<0?-1:1)*E.abs(M)**f*(I<i?I/i:I<i+b?1-(I-i)/b*(1-x):I<i+b+o?x:I<N-w?(N-I-w)/r*x:0),M=w?M/2+(w>I?0:(I<N-w?1:(N-I)/w)*t[I-w|0]/2/e):M,k&&(M=j=R*X+G*(X=Y)+R*(Y=M)-W*$-V*($=j))),T+=(F=(n+=c+=d)*E.cos(m*C++))+F*g*B(I**5),L&&++L>p&&(n+=u,P+=u,L=0),!h||++S%h||(n=P,c=D,L=L||1);(e=a.createBuffer(1,N,44100)).getChannelData(0).set(t),(n=a.createBufferSource()).buffer=e,n.connect(a.destination),n.start()});t=Object.assign({width:null,height:null,autoscale:!0,canvas:null,global:!0,loop:null,tapEvents:!0,keyboardEvents:!0},t);let c=!1,d=!0,u,p=1,h,g=.5,m=1,v,w=1e3/60,x,b,y="sans-serif",k=20,E=1.2,z=Date.now(),D=e,P=[],T=[.5,0,1750,,,.3,1,,,,600,.1],C={},I={W:0,H:0,T:0,MX:-1,MY:-1,TWO_PI:i,HALF_PI:i/4,lerp:(e,t,a)=>a*(t-e)+e,deg2rad:e=>n.PI/180*e,rad2deg:e=>180/n.PI*e,round:(e,t=0)=>{if(!t)return n.round(e);let a=10**t;return n.round(e*a)/a},clamp:(e,t,a)=>e<t?t:e>a?a:e,wrap:(e,t,a)=>e-(a-t)*n.floor((e-t)/(a-t)),map(e,t,a,l,n,i){let o=(e-t)/(a-t)*(n-l)+l;return i?I.clamp(o,l,n):o},norm:(e,t,a)=>I.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)=>n.floor(I.rand(e,t+1)),rseed(e){z=~~e},cls(e){null==e?h.clearRect(0,0,h.canvas.width,h.canvas.height):I.rectfill(0,0,h.canvas.width,h.canvas.height,e)},rect(e,t,a,l,n,i){h.beginPath(),h[i?"roundRect":"rect"](~~e-g,~~t-g,~~a+2*g,~~l+2*g,i),I.stroke(n)},rectfill(e,t,a,l,n,i){h.beginPath(),h[i?"roundRect":"rect"](~~e,~~t,~~a,~~l,i),I.fill(n)},circ(e,t,a,l){h.beginPath(),h.arc(~~e,~~t,~~a,0,i),I.stroke(l)},circfill(e,t,a,l){h.beginPath(),h.arc(~~e,~~t,~~a,0,i),I.fill(l)},oval(e,t,a,l,n){h.beginPath(),h.ellipse(~~e,~~t,~~a,~~l,0,0,i),I.stroke(n)},ovalfill(e,t,a,l,n){h.beginPath(),h.ellipse(~~e,~~t,~~a,~~l,0,0,i),I.fill(n)},line(e,t,a,l,n){h.beginPath();let i=.5*(0!==g&&~~e==~~a),o=.5*(0!==g&&~~t==~~l);h.moveTo(~~e+i,~~t+o),h.lineTo(~~a+i,~~l+o),I.stroke(n)},linewidth(e){h.lineWidth=~~e,g=.5*(0!=~~e%2)},linedash(e,t=0){h.setLineDash(e),h.lineDashOffset=t},text(e,t,a,l=3,n="normal"){h.font=`${n} ${k}px ${y}`,h.fillStyle=N(l);let i=(""+a).split("\n");for(let a=0;a<i.length;a++)h.fillText(i[a],~~e,~~t+k*E*a)},textgap(e){E=e},textfont(e){y=e},textsize(e){k=e},textalign(e,t){e&&(h.textAlign=e),t&&(h.textBaseline=t)},image(e,t,a){h.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&&I.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=h;return n.width=e*i,n.height=t*i,(h=n.getContext("2d")).scale(i,i),a(h),h=o,n.transferToImageBitmap()},ctx:e=>(e&&(h=e),h),push(){h.save()},pop(){h.restore()},translate(e,t){h.translate(~~e,~~t)},scale(e,t){h.scale(e,t||e)},rotate(e){h.rotate(e)},alpha(e){h.globalAlpha=I.clamp(e,0,1)},fill(e){h.fillStyle=N(e),h.fill()},stroke(e){h.strokeStyle=N(e),h.stroke()},clip(e){h.beginPath(),e(h),h.clip()},sfx:(e,t=0,a=1)=>!!l.zzfxV&&(!navigator.userActivation||!!navigator.userActivation.hasBeenActive)&&(e=e||T,(0!==t||1!==a)&&((e=e.slice())[0]=a*(e[0]||1),e[10]=~~e[10]+t),f.apply(0,e),e),volume(e){l.zzfxV=e},canvas:()=>u,use(e,t={}){var a=e,l=t;let n=a(I,l);for(let e in n)I.def(e,n[e])},listen:(e,t)=>(C[e=e.toLowerCase()]=C[e]||new Set,C[e].add(t),()=>C&&C[e].delete(t)),emit(e,t,a,l,n){c&&(M("before:"+(e=e.toLowerCase()),t,a,l,n),M(e,t,a,l,n),M("after:"+e,t,a,l,n))},pal(t=e){D=t,P=[]},palc(e,t){null==e?P=[]:P[e]=t},def(e,a){I[e]=a,t.global&&(l[e]=a)},timescale(e){m=e},framerate(e){w=1e3/~~e},stat(e){let a={index:e,value:[t,c,w/1e3,p,C,D,T,m,l.zzfxV,z,k,y,P,E][e]};return I.emit("stat",a),a.value},pause(){d=!0,cancelAnimationFrame(b)},resume(){c&&d&&(d=!1,x=w,v=Date.now(),b=o(S))},paused:()=>d,quit(){for(let e of(I.emit("quit"),I.pause(),c=!1,C={},r))e();if(t.global){for(let e in I)delete l[e];delete l.ENGINE}}};for(let e of"PI,sin,cos,atan2,hypot,tan,abs,ceil,floor,trunc,min,max,pow,sqrt,sign,exp".split(","))I[e]=n[e];function L(){if(t.autoscale&&s(l,"resize",A),t.tapEvents){let e=e=>[(e.pageX-u.offsetLeft)/p,(e.pageY-u.offsetTop)/p],t=new Map,a=(e,a,l)=>{let n={x:a,y:l,xi:a,yi:l,t:Date.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&&Date.now()-e.t<=300,o=!1;s(u,"mousedown",t=>{if(0===t.button){t.preventDefault();let[l,n]=e(t);I.emit("tap",l,n,0),a(0,l,n),o=!0}}),s(u,"mouseup",a=>{if(0===a.button){a.preventDefault();let l=t.get(0),[n,r]=e(a);i(l)&&I.emit("tapped",l.xi,l.yi,0),I.emit("untap",n,r,0),t.delete(0),o=!1}}),s(l,"mousemove",t=>{t.preventDefault();let[a,l]=e(t);I.def("MX",a),I.def("MY",l),o&&(I.emit("tapping",a,l,0),n(0,a,l))}),s(u,"touchstart",t=>{for(let l of(t.preventDefault(),t.changedTouches)){let[t,n]=e(l);I.emit("tap",t,n,l.identifier+1),a(l.identifier+1,t,n)}}),s(u,"touchmove",t=>{for(let a of(t.preventDefault(),t.changedTouches)){let[t,l]=e(a);I.emit("tapping",t,l,a.identifier+1),n(a.identifier+1,t,l)}});let r=e=>{e.preventDefault();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)&&I.emit("tapped",l.xi,l.yi,e),I.emit("untap",l.x,l.y,e),t.delete(e))};s(u,"touchend",r),s(u,"touchcancel",r),s(l,"blur",()=>{for(let[e,a]of(o=!1,t))I.emit("untap",a.x,a.y,e),t.delete(e)})}if(t.keyboardEvents){let e=new Set,t=new Set,a=(e,t="")=>(t=t.toLowerCase())?e.has("space"===t?" ":t):e.size>0,n="";s(l,"keydown",a=>{let l=a.key.toLowerCase();e.has(l)||(e.add(l),t.add(l),n=" "===l?"space":l)}),s(l,"keyup",t=>{e.delete(t.key.toLowerCase())}),s(l,"blur",()=>e.clear()),I.listen("after:update",()=>t.clear()),I.def("iskeydown",t=>a(e,t)),I.def("iskeypressed",e=>a(t,e)),I.def("lastkey",()=>n)}c=!0,I.emit("init",I),I.resume()}function S(){b=o(S);let e=Date.now(),t=0,a=e-v;for(v=e,x+=a<100?a:w;x>=w;){t++,x-=w;let e=w/1e3*m;I.emit("update",e,t),I.def("T",I.T+e)}t&&(I.emit("draw",h),t>1&&(x=0))}function A(){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=n.min(innerWidth/e,innerHeight/a),p=l>1&&p>l?l:p,u.style.width=e*p+"px",u.style.height=a*p+"px"}h.imageSmoothingEnabled=!1,I.textalign("start","top"),I.emit("resized",p)}function M(e,t,a,l,n){if(C[e])for(let i of C[e])i(t,a,l,n)}function N(e){return D[~~(P[e]??e)%D.length]}if(t.global){if(l.ENGINE)throw Error("only one global litecanvas is allowed");Object.assign(l,I),l.ENGINE=I}h=(u=(u="string"==typeof t.canvas?document.querySelector(t.canvas):t.canvas)||document.createElement("canvas")).getContext("2d"),s(u,"click",()=>focus()),A(),u.parentNode||document.body.appendChild(u),u.style.imageRendering="pixelated",u.oncontextmenu=()=>!1;let F=t.loop?t.loop:l;for(let e of"init,update,draw,tap,untap,tapping,tapped,resized".split(","))F[e]&&I.listen(e,F[e]);return"loading"===document.readyState?s(l,"DOMContentLoaded",()=>o(L)):b=o(L),I}})();
1
+ (()=>{var e=["#211e20","#555568","#a0a08b","#e9efec"];window.litecanvas=function(t={}){let a,l=window,n=Math,i=2*n.PI,o=requestAnimationFrame,r=[],s=(e,t,a)=>{e.addEventListener(t,a,!1),r.push(()=>e.removeEventListener(t,a,!1))},f=(a=new AudioContext,l.zzfxV=1,(e=1,t=.05,n=220,i=0,o=0,r=.1,s=0,f=1,d=0,c=0,u=0,p=0,h=0,g=0,m=0,v=0,w=0,x=1,y=0,b=0,k=0)=>{let z=Math,D=2*z.PI,E=d*=500*D/44100/44100,P=n*=(1-t+2*t*z.random(t=[]))*D/44100,C=0,I=0,T=0,L=1,S=0,A=0,M=0,N=k<0?-1:1,q=D*N*k*2/44100,B=z.cos(q),H=z.sin,O=H(q)/4,V=1+O,W=-2*B/V,R=(1-O)/V,F=(1+N*B)/2/V,G=-(N+B)/V,X=0,Y=0,$=0,j=0;for(i=44100*i+9,y*=44100,o*=44100,r*=44100,w*=44100,c*=500*D/85766121e6,m*=D/44100,u*=D/44100,p*=44100,h=44100*h|0,e*=.3*l.zzfxV,N=i+y+o+r+w|0;T<N;t[T++]=M*e)++A%(100*v|0)||(M=s?1<s?2<s?3<s?H(C*C):z.max(z.min(z.tan(C),1),-1):1-(2*C/D%2+2)%2:1-4*z.abs(z.round(C/D)-C/D):H(C),M=(h?1-b+b*H(D*T/h):1)*(M<0?-1:1)*z.abs(M)**f*(T<i?T/i:T<i+y?1-(T-i)/y*(1-x):T<i+y+o?x:T<N-w?(N-T-w)/r*x:0),M=w?M/2+(w>T?0:(T<N-w?1:(N-T)/w)*t[T-w|0]/2/e):M,k&&(M=j=F*X+G*(X=Y)+F*(Y=M)-R*$-W*($=j))),C+=(q=(n+=d+=c)*z.cos(m*I++))+q*g*H(T**5),L&&++L>p&&(n+=u,P+=u,L=0),!h||++S%h||(n=P,d=E,L=L||1);(e=a.createBuffer(1,N,44100)).getChannelData(0).set(t),(n=a.createBufferSource()).buffer=e,n.connect(a.destination),n.start()});t=Object.assign({width:null,height:null,autoscale:!0,canvas:null,global:!0,loop:null,tapEvents:!0,keyboardEvents:!0},t);let d=!1,c=!0,u,p=1,h,g=.5,m=1,v,w=1e3/60,x,y,b=3,k="sans-serif",z=20,D=1.2,E=Date.now(),P=e,C=[],I=[.5,0,1750,,,.3,1,,,,600,.1],T={},L={W:0,H:0,T:0,MX:-1,MY:-1,TWO_PI:i,HALF_PI:i/4,lerp:(e,t,a)=>a*(t-e)+e,deg2rad:e=>n.PI/180*e,rad2deg:e=>180/n.PI*e,round:(e,t=0)=>{if(!t)return n.round(e);let a=10**t;return n.round(e*a)/a},clamp:(e,t,a)=>e<t?t:e>a?a:e,wrap:(e,t,a)=>e-(a-t)*n.floor((e-t)/(a-t)),map(e,t,a,l,n,i){let o=(e-t)/(a-t)*(n-l)+l;return i?L.clamp(o,l,n):o},norm:(e,t,a)=>L.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)=>(E=(1664525*E+0x3c6ef35f)%0x100000000)/0x100000000*(t-e)+e,randi:(e=0,t=1)=>n.floor(L.rand(e,t+1)),rseed(e){E=~~e},cls(e){null==e?h.clearRect(0,0,h.canvas.width,h.canvas.height):L.rectfill(0,0,h.canvas.width,h.canvas.height,e)},rect(e,t,a,l,n,i){h.beginPath(),h[i?"roundRect":"rect"](~~e-g,~~t-g,~~a+2*g,~~l+2*g,i),L.stroke(n)},rectfill(e,t,a,l,n,i){h.beginPath(),h[i?"roundRect":"rect"](~~e,~~t,~~a,~~l,i),L.fill(n)},circ(e,t,a,l){h.beginPath(),h.arc(~~e,~~t,~~a,0,i),L.stroke(l)},circfill(e,t,a,l){h.beginPath(),h.arc(~~e,~~t,~~a,0,i),L.fill(l)},oval(e,t,a,l,n){h.beginPath(),h.ellipse(~~e,~~t,~~a,~~l,0,0,i),L.stroke(n)},ovalfill(e,t,a,l,n){h.beginPath(),h.ellipse(~~e,~~t,~~a,~~l,0,0,i),L.fill(n)},line(e,t,a,l,n){h.beginPath();let i=.5*(0!==g&&~~e==~~a),o=.5*(0!==g&&~~t==~~l);h.moveTo(~~e+i,~~t+o),h.lineTo(~~a+i,~~l+o),L.stroke(n)},linewidth(e){h.lineWidth=~~e,g=.5*(0!=~~e%2)},linedash(e,t=0){h.setLineDash(e),h.lineDashOffset=t},text(e,t,a,l=b,n="normal"){h.font=`${n} ${z}px ${k}`,h.fillStyle=q(l);let i=(""+a).split("\n");for(let a=0;a<i.length;a++)h.fillText(i[a],~~e,~~t+z*D*a)},textgap(e){D=e},textfont(e){k=e},textsize(e){z=e},textalign(e,t){e&&(h.textAlign=e),t&&(h.textBaseline=t)},image(e,t,a){h.drawImage(a,~~e,~~t)},spr(e,t,a){let l=a.trim().split("\n");for(let a=0;a<l.length;a++){let n=l[a].trim();for(let l=0;l<n.length;l++){let i=n[l];"."!==i&&" "!==i&&L.rectfill(e+l,t+a,1,1,parseInt(i,36)||0)}}},paint(e,t,a,l={}){let n=l.canvas||new OffscreenCanvas(1,1),i=l.scale||1,o=h;return n.width=e*i,n.height=t*i,(h=n.getContext("2d")).scale(i,i),a(h),h=o,n.transferToImageBitmap()},ctx:e=>(e&&(h=e),h),push(){h.save()},pop(){h.restore()},translate(e,t){h.translate(~~e,~~t)},scale(e,t){h.scale(e,t||e)},rotate(e){h.rotate(e)},alpha(e){h.globalAlpha=L.clamp(e,0,1)},fill(e){h.fillStyle=q(e),h.fill()},stroke(e){h.strokeStyle=q(e),h.stroke()},clip(e){h.beginPath(),e(h),h.clip()},sfx:(e,t=0,a=1)=>!!l.zzfxV&&(!navigator.userActivation||!!navigator.userActivation.hasBeenActive)&&(e=e||I,(0!==t||1!==a)&&((e=e.slice())[0]=a*(e[0]||1),e[10]=~~e[10]+t),f.apply(0,e),e),volume(e){l.zzfxV=e},canvas:()=>u,use(e,t={}){var a=e,l=t;let n=a(L,l);for(let e in n)L.def(e,n[e])},listen:(e,t)=>(T[e=e.toLowerCase()]=T[e]||new Set,T[e].add(t),()=>T&&T[e].delete(t)),emit(e,t,a,l,n){d&&(N("before:"+(e=e.toLowerCase()),t,a,l,n),N(e,t,a,l,n),N("after:"+e,t,a,l,n))},pal(t,a=3){P=t||e,C=[],b=a},palc(e,t){null==e?C=[]:C[e]=t},def(e,a){L[e]=a,t.global&&(l[e]=a)},timescale(e){m=e},framerate(e){w=1e3/~~e},stat(e){let a={index:e,value:[t,d,w/1e3,p,T,P,I,m,l.zzfxV,E,z,k,C,D][e]};return L.emit("stat",a),a.value},pause(){c=!0,cancelAnimationFrame(y)},resume(){d&&c&&(c=!1,x=w,v=Date.now(),y=o(A))},paused:()=>c,quit(){for(let e of(L.emit("quit"),L.pause(),d=!1,T={},r))e();if(t.global){for(let e in L)delete l[e];delete l.ENGINE}}};for(let e of"PI,sin,cos,atan2,hypot,tan,abs,ceil,floor,trunc,min,max,pow,sqrt,sign,exp".split(","))L[e]=n[e];function S(){if(t.autoscale&&s(l,"resize",M),t.tapEvents){let e=e=>[(e.pageX-u.offsetLeft)/p,(e.pageY-u.offsetTop)/p],t=new Map,a=(e,a,l)=>{let n={x:a,y:l,xi:a,yi:l,t:Date.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&&Date.now()-e.t<=300,o=!1;s(u,"mousedown",t=>{if(0===t.button){t.preventDefault();let[l,n]=e(t);L.emit("tap",l,n,0),a(0,l,n),o=!0}}),s(u,"mouseup",a=>{if(0===a.button){a.preventDefault();let l=t.get(0),[n,r]=e(a);i(l)&&L.emit("tapped",l.xi,l.yi,0),L.emit("untap",n,r,0),t.delete(0),o=!1}}),s(l,"mousemove",t=>{t.preventDefault();let[a,l]=e(t);L.def("MX",a),L.def("MY",l),o&&(L.emit("tapping",a,l,0),n(0,a,l))}),s(u,"touchstart",t=>{for(let l of(t.preventDefault(),t.changedTouches)){let[t,n]=e(l);L.emit("tap",t,n,l.identifier+1),a(l.identifier+1,t,n)}}),s(u,"touchmove",t=>{for(let a of(t.preventDefault(),t.changedTouches)){let[t,l]=e(a);L.emit("tapping",t,l,a.identifier+1),n(a.identifier+1,t,l)}});let r=e=>{e.preventDefault();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)&&L.emit("tapped",l.xi,l.yi,e),L.emit("untap",l.x,l.y,e),t.delete(e))};s(u,"touchend",r),s(u,"touchcancel",r),s(l,"blur",()=>{for(let[e,a]of(o=!1,t))L.emit("untap",a.x,a.y,e),t.delete(e)})}if(t.keyboardEvents){let e=new Set,t=new Set,a=(e,t="")=>(t=t.toLowerCase())?e.has("space"===t?" ":t):e.size>0,n="";s(l,"keydown",a=>{let l=a.key.toLowerCase();e.has(l)||(e.add(l),t.add(l),n=" "===l?"space":l)}),s(l,"keyup",t=>{e.delete(t.key.toLowerCase())}),s(l,"blur",()=>e.clear()),L.listen("after:update",()=>t.clear()),L.def("iskeydown",t=>a(e,t)),L.def("iskeypressed",e=>a(t,e)),L.def("lastkey",()=>n)}d=!0,L.emit("init",L),L.resume()}function A(){y=o(A);let e=Date.now(),t=0,a=e-v;for(v=e,x+=a<100?a:w;x>=w;){t++,x-=w;let e=w/1e3*m;L.emit("update",e,t),L.def("T",L.T+e)}t&&(L.emit("draw",h),t>1&&(x=0))}function M(){let e=t.width>0?t.width:innerWidth,a=t.width>0?t.height||t.width:innerHeight;if(L.def("W",e),L.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=n.min(innerWidth/e,innerHeight/a),p=l>1&&p>l?l:p,u.style.width=e*p+"px",u.style.height=a*p+"px"}h.imageSmoothingEnabled=!1,L.textalign("start","top"),L.emit("resized",p)}function N(e,t,a,l,n){if(T[e])for(let i of T[e])i(t,a,l,n)}function q(e){return P[~~(C[e]??e)%P.length]}if(t.global){if(l.ENGINE)throw Error("only one global litecanvas is allowed");Object.assign(l,L),l.ENGINE=L}h=(u=(u="string"==typeof t.canvas?document.querySelector(t.canvas):t.canvas)||document.createElement("canvas")).getContext("2d"),s(u,"click",()=>focus()),M(),u.parentNode||document.body.appendChild(u),u.style.imageRendering="pixelated",u.oncontextmenu=()=>!1;let B=t.loop?t.loop:l;for(let e of"init,update,draw,tap,untap,tapping,tapped,resized".split(","))B[e]&&L.listen(e,B[e]);return"loading"===document.readyState?s(l,"DOMContentLoaded",()=>o(S)):y=o(S),L}})();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "litecanvas",
3
- "version": "0.100.1",
3
+ "version": "0.101.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>",
@@ -33,7 +33,7 @@
33
33
  "devDependencies": {
34
34
  "@happy-dom/global-registrator": "^18.0.1",
35
35
  "@size-limit/preset-small-lib": "^11.2.0",
36
- "@swc/core": "^1.15.0",
36
+ "@swc/core": "^1.15.2",
37
37
  "ava": "^6.4.1",
38
38
  "esbuild": "^0.25.12",
39
39
  "genversion": "^3.2.0",
package/src/index.js CHANGED
@@ -68,6 +68,8 @@ export default function litecanvas(settings = {}) {
68
68
  _accumulated,
69
69
  /** @type {number?} */
70
70
  _rafid,
71
+ /** @type {number} */
72
+ _defaultTextColor = 3,
71
73
  /** @type {string} */
72
74
  _fontFamily = 'sans-serif',
73
75
  /** @type {number} */
@@ -646,10 +648,10 @@ export default function litecanvas(settings = {}) {
646
648
  * @param {number} x
647
649
  * @param {number} y
648
650
  * @param {string} message the text message
649
- * @param {number} [color=3] the color index
651
+ * @param {number} [color] the color index
650
652
  * @param {string} [fontStyle] can be "normal" (default), "italic" and/or "bold".
651
653
  */
652
- text(x, y, message, color = 3, fontStyle = 'normal') {
654
+ text(x, y, message, color = _defaultTextColor, fontStyle = 'normal') {
653
655
  DEV: assert(isNumber(x), '[litecanvas] text() 1st param must be a number')
654
656
  DEV: assert(isNumber(y), '[litecanvas] text() 2nd param must be a number')
655
657
  DEV: assert(
@@ -747,27 +749,25 @@ export default function litecanvas(settings = {}) {
747
749
  },
748
750
 
749
751
  /**
750
- * Draw a sprite pxiel by pixel represented by a string. Each pixel must be a base 36 number (0-9 or a-z) or a dot.
752
+ * Draw a sprite pixel by pixel represented by a string. Each pixel must be a base 36 number (0-9 or a-z) or a dot.
751
753
  *
752
754
  * @param {number} x
753
755
  * @param {number} y
754
- * @param {number} width
755
- * @param {number} height
756
756
  * @param {string} pixels
757
757
  */
758
- spr(x, y, width, height, pixels) {
758
+ spr(x, y, pixels) {
759
759
  DEV: assert(isNumber(x), '[litecanvas] spr() 1st param must be a number')
760
760
  DEV: assert(isNumber(y), '[litecanvas] spr() 2nd param must be a number')
761
- DEV: assert(isNumber(width), '[litecanvas] spr() 3rd param must be a number')
762
- DEV: assert(isNumber(height), '[litecanvas] spr() 4th param must be a number')
763
- DEV: assert('string' === typeof pixels, '[litecanvas] spr() 5th param must be a string')
764
-
765
- const chars = pixels.replace(/\s/g, '')
766
- for (let gridx = 0; gridx < width; gridx++) {
767
- for (let gridy = 0; gridy < height; gridy++) {
768
- const char = chars[width * gridy + gridx] || '.'
769
- if (char !== '.') {
770
- instance.rectfill(x + gridx, y + gridy, 1, 1, parseInt(char, 36) || 0)
761
+ DEV: assert('string' === typeof pixels, '[litecanvas] spr() 3rd param must be a string')
762
+
763
+ const rows = pixels.trim().split('\n')
764
+
765
+ for (let row = 0; row < rows.length; row++) {
766
+ const chars = rows[row].trim()
767
+ for (let col = 0; col < chars.length; col++) {
768
+ const char = chars[col]
769
+ if (char !== '.' && char !== ' ') {
770
+ instance.rectfill(x + col, y + row, 1, 1, parseInt(char, 36) || 0)
771
771
  }
772
772
  }
773
773
  }
@@ -1088,15 +1088,22 @@ export default function litecanvas(settings = {}) {
1088
1088
  /**
1089
1089
  * Set new palette colors or restore the default palette.
1090
1090
  *
1091
- * @param {string[]} [colors]
1091
+ * @param {string[]} [colors] an array of colors
1092
+ * @param {number} [textColor] the default text color this palette
1092
1093
  */
1093
- pal(colors = defaultPalette) {
1094
+ pal(colors, textColor = 3) {
1094
1095
  DEV: assert(
1095
1096
  Array.isArray(colors) && colors.length > 0,
1096
- '[litecanvas] pal() 1st param must be a array of strings'
1097
+ '[litecanvas] pal() 1st param must be a array of color strings'
1097
1098
  )
1098
- _colorPalette = colors
1099
+ DEV: assert(
1100
+ isNumber(textColor) && textColor >= 0,
1101
+ '[litecanvas] pal() 2nd param must be a positive number or zero'
1102
+ )
1103
+
1104
+ _colorPalette = colors || defaultPalette
1099
1105
  _colorPaletteState = []
1106
+ _defaultTextColor = textColor
1100
1107
  },
1101
1108
 
1102
1109
  /**
@@ -1118,6 +1125,7 @@ export default function litecanvas(settings = {}) {
1118
1125
  isNumber(a) ? isNumber(b) && b >= 0 : null == b,
1119
1126
  '[litecanvas] palc() 2nd param must be a positive number'
1120
1127
  )
1128
+
1121
1129
  if (a == null) {
1122
1130
  _colorPaletteState = []
1123
1131
  } else {
package/src/palette.js CHANGED
@@ -1,16 +1,2 @@
1
- export const defaultPalette = [
2
- '#111',
3
- '#6a7799',
4
- '#aec2c2',
5
- '#FFF1E8',
6
-
7
- '#e83b3b',
8
- '#fabc20',
9
- '#155fd9',
10
- '#3cbcfc',
11
-
12
- '#327345',
13
- '#63c64d',
14
- '#6c2c1f',
15
- '#ac7c00',
16
- ]
1
+ /** colors based on https://lospec.com/palette-list/2bit-demichrome */
2
+ export const defaultPalette = ['#211e20', '#555568', '#a0a08b', '#e9efec']
package/src/version.js CHANGED
@@ -1,2 +1,2 @@
1
1
  // Generated by genversion.
2
- export const version = '0.100.1'
2
+ export const version = '0.101.0'
package/src/web.js CHANGED
@@ -1,3 +1,3 @@
1
1
  import litecanvas from './index.js'
2
2
 
3
- globalThis.litecanvas = litecanvas
3
+ window.litecanvas = litecanvas
package/types/global.d.ts CHANGED
@@ -374,19 +374,17 @@ declare global {
374
374
  */
375
375
  function image(x: number, y: number, source: CanvasImageSource): void
376
376
  /**
377
- * Draw a sprite pxiel by pixel represented by a string. Each pixel must be a base 36 number or a dot:
377
+ * Draw a sprite pixel by pixel represented by a string. Each pixel must be a base 36 number or a dot:
378
378
  *
379
379
  * - A base 36 number (`0-9` or `a-z`) represent a pixel color (supporting color palettes with max 36 colors).
380
380
  * - A dot (`.`) represent a transparent pixel.
381
- * - Spaces and lines breaks are ignored and can be used to improve the visualization.
381
+ * - Spaces are ignored and can be used to improve the visualization.
382
382
  *
383
383
  * @param x the position X of the first pixel
384
384
  * @param y the position Y of the first pixel
385
- * @param width the width of the sprite
386
- * @param height the height of the sprite
387
385
  * @param pixels
388
386
  */
389
- function spr(x: number, y: number, width: number, height: number, pixels: string): void
387
+ function spr(x: number, y: number, pixels: string): void
390
388
  /**
391
389
  * Draw in an OffscreenCanvas and returns its image.
392
390
  *
@@ -555,9 +553,10 @@ declare global {
555
553
  /**
556
554
  * Set new palette colors or restore the default palette.
557
555
  *
558
- * @param [colors]
556
+ * @param colors an array of colors
557
+ * @param textColor the new default text color (default: 3)
559
558
  */
560
- function pal(colors?: string[]): void
559
+ function pal(colors?: string[], textColor?: number): void
561
560
  /**
562
561
  * Replace the color "a" with color "b".
563
562
  *
package/types/types.d.ts CHANGED
@@ -368,19 +368,17 @@ type LitecanvasInstance = {
368
368
  */
369
369
  image(x: number, y: number, source: CanvasImageSource): void
370
370
  /**
371
- * Draw a sprite pxiel by pixel represented by a string. Each pixel must be a base 36 number or a dot:
371
+ * Draw a sprite pixel by pixel represented by a string. Each pixel must be a base 36 number or a dot:
372
372
  *
373
373
  * - A base 36 number (`0-9` or `a-z`) represent a pixel color (supporting color palettes with max 36 colors).
374
374
  * - A dot (`.`) represent a transparent pixel.
375
- * - Spaces and lines breaks are ignored and can be used to improve the visualization.
375
+ * - Spaces are ignored and can be used to improve the visualization.
376
376
  *
377
377
  * @param x the position X of the first pixel
378
378
  * @param y the position Y of the first pixel
379
- * @param width the width of the sprite
380
- * @param height the height of the sprite
381
379
  * @param pixels
382
380
  */
383
- spr(x: number, y: number, width: number, height: number, pixels: string): void
381
+ spr(x: number, y: number, pixels: string): void
384
382
  /**
385
383
  * Draw in an OffscreenCanvas and returns its image.
386
384
  *
@@ -552,9 +550,10 @@ type LitecanvasInstance = {
552
550
  /**
553
551
  * Set new palette colors or restore the default palette.
554
552
  *
555
- * @param [colors]
553
+ * @param colors an array of colors
554
+ * @param textColor the new default text color (default: 3)
556
555
  */
557
- pal(colors?: string[]): void
556
+ pal(colors?: string[], textColor?: number): void
558
557
  /**
559
558
  * Replace the color "a" with color "b".
560
559
  *