litecanvas 0.95.1 → 0.97.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/src/index.js CHANGED
@@ -23,6 +23,8 @@ export default function litecanvas(settings = {}) {
23
23
  elem.addEventListener(evt, callback, false)
24
24
  _browserEventListeners.push(() => elem.removeEventListener(evt, callback, false))
25
25
  },
26
+ /** @type {(str: string) => string} */
27
+ lowerCase = (str) => str.toLowerCase(),
26
28
  /** @type {(ev: Event) => void} */
27
29
  preventDefault = (ev) => ev.preventDefault(),
28
30
  /** @type {(c: CanvasRenderingContext2D | OffscreenCanvasRenderingContext2D) => void} */
@@ -34,13 +36,11 @@ export default function litecanvas(settings = {}) {
34
36
  width: null,
35
37
  height: null,
36
38
  autoscale: true,
37
- pixelart: true,
38
39
  canvas: null,
39
40
  global: true,
40
41
  loop: null,
41
42
  tapEvents: true,
42
43
  keyboardEvents: true,
43
- animate: true,
44
44
  }
45
45
 
46
46
  // setup the settings default values
@@ -75,7 +75,9 @@ export default function litecanvas(settings = {}) {
75
75
  /** @type {number} */
76
76
  _rngSeed = Date.now(),
77
77
  /** @type {string[]} */
78
- _colors = defaultPalette,
78
+ _currentPalette,
79
+ /** @type {string[]} */
80
+ _colors,
79
81
  /** @type {number[]} */
80
82
  _defaultSound = [0.5, 0, 1750, , , 0.3, 1, , , , 600, 0.1],
81
83
  /** @type {string} */
@@ -178,7 +180,7 @@ export default function litecanvas(settings = {}) {
178
180
  round: (n, precision = 0) => {
179
181
  DEV: assert(isNumber(n), '[litecanvas] round() 1st param must be a number')
180
182
  DEV: assert(
181
- null == precision || (isNumber(precision) && precision >= 0),
183
+ isNumber(precision) && precision >= 0,
182
184
  '[litecanvas] round() 2nd param must be a positive number or zero'
183
185
  )
184
186
  if (!precision) {
@@ -602,15 +604,15 @@ export default function litecanvas(settings = {}) {
602
604
  },
603
605
 
604
606
  /**
605
- * Sets the thickness of lines
607
+ * Sets the thickness of the lines
606
608
  *
607
609
  * @param {number} value
608
610
  * @see https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/lineWidth
609
611
  */
610
612
  linewidth(value) {
611
613
  DEV: assert(
612
- isNumber(value) && ~~value > 0,
613
- '[litecanvas] linewidth() 1st param must be a positive number'
614
+ isNumber(value) && value >= 0,
615
+ '[litecanvas] linewidth() 1st param must be a positive number or zero'
614
616
  )
615
617
 
616
618
  _ctx.lineWidth = ~~value
@@ -728,19 +730,46 @@ export default function litecanvas(settings = {}) {
728
730
  _ctx.drawImage(source, ~~x, ~~y)
729
731
  },
730
732
 
733
+ /**
734
+ * 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.
735
+ *
736
+ * @param {number} x
737
+ * @param {number} y
738
+ * @param {number} width
739
+ * @param {number} height
740
+ * @param {string} pixels
741
+ */
742
+ spr(x, y, width, height, pixels) {
743
+ DEV: assert(isNumber(x), '[litecanvas] spr() 1st param must be a number')
744
+ DEV: assert(isNumber(y), '[litecanvas] spr() 2nd param must be a number')
745
+ DEV: assert(isNumber(width), '[litecanvas] spr() 3rd param must be a number')
746
+ DEV: assert(isNumber(height), '[litecanvas] spr() 4th param must be a number')
747
+ DEV: assert('string' === typeof pixels, '[litecanvas] spr() 5th param must be a string')
748
+
749
+ const chars = pixels.replace(/\s/g, '')
750
+ for (let gridx = 0; gridx < width; gridx++) {
751
+ for (let gridy = 0; gridy < height; gridy++) {
752
+ const char = chars[height * gridy + gridx] || '.'
753
+ if (char !== '.') {
754
+ instance.rectfill(x + gridx, y + gridy, 1, 1, parseInt(char, 16) || 0)
755
+ }
756
+ }
757
+ }
758
+ },
759
+
731
760
  /**
732
761
  * Draw in an OffscreenCanvas and returns its image.
733
762
  *
734
763
  * @param {number} width
735
764
  * @param {number} height
736
- * @param {string[]|drawCallback} drawing
765
+ * @param {drawCallback} callback
737
766
  * @param {object} [options]
738
767
  * @param {number} [options.scale=1]
739
768
  * @param {OffscreenCanvas} [options.canvas]
740
769
  * @returns {ImageBitmap}
741
770
  * @see https://developer.mozilla.org/en-US/docs/Web/API/OffscreenCanvas
742
771
  */
743
- paint(width, height, drawing, options = {}) {
772
+ paint(width, height, callback, options = {}) {
744
773
  DEV: assert(
745
774
  isNumber(width) && width >= 1,
746
775
  '[litecanvas] paint() 1st param must be a positive number'
@@ -750,7 +779,7 @@ export default function litecanvas(settings = {}) {
750
779
  '[litecanvas] paint() 2nd param must be a positive number'
751
780
  )
752
781
  DEV: assert(
753
- 'function' === typeof drawing || Array.isArray(drawing),
782
+ 'function' === typeof callback,
754
783
  '[litecanvas] paint() 3rd param must be a function or array'
755
784
  )
756
785
  DEV: assert(
@@ -765,37 +794,16 @@ export default function litecanvas(settings = {}) {
765
794
  const /** @type {OffscreenCanvas} */
766
795
  canvas = options.canvas || new OffscreenCanvas(1, 1),
767
796
  scale = options.scale || 1,
768
- contextOriginal = _ctx
797
+ currentContext = _ctx // context backup
769
798
 
770
799
  canvas.width = width * scale
771
800
  canvas.height = height * scale
772
801
 
773
802
  _ctx = canvas.getContext('2d')
774
803
  _ctx.scale(scale, scale)
804
+ callback(_ctx)
775
805
 
776
- // draw pixel art if `draw` is a array
777
- if (Array.isArray(drawing)) {
778
- let x = 0,
779
- y = 0
780
-
781
- _ctx.imageSmoothingEnabled = false
782
-
783
- for (const str of drawing) {
784
- for (const color of str) {
785
- if (' ' !== color && '.' !== color) {
786
- // support for 16-color palette using hex (from 0 to f)
787
- instance.rectfill(x, y, 1, 1, parseInt(color, 16))
788
- }
789
- x++
790
- }
791
- y++
792
- x = 0
793
- }
794
- } else {
795
- drawing(_ctx)
796
- }
797
-
798
- _ctx = contextOriginal // restore the context
806
+ _ctx = currentContext // restore the context
799
807
 
800
808
  return canvas.transferToImageBitmap()
801
809
  },
@@ -820,14 +828,18 @@ export default function litecanvas(settings = {}) {
820
828
  *
821
829
  * @see https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/save
822
830
  */
823
- push: () => _ctx.save(),
831
+ push() {
832
+ _ctx.save()
833
+ },
824
834
 
825
835
  /**
826
836
  * restores the drawing style settings and transformations
827
837
  *
828
838
  * @see https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/restore
829
839
  */
830
- pop: () => _ctx.restore(),
840
+ pop() {
841
+ _ctx.restore()
842
+ },
831
843
 
832
844
  /**
833
845
  * Adds a translation to the transformation matrix.
@@ -835,11 +847,11 @@ export default function litecanvas(settings = {}) {
835
847
  * @param {number} x
836
848
  * @param {number} y
837
849
  */
838
- translate: (x, y) => {
850
+ translate(x, y) {
839
851
  DEV: assert(isNumber(x), '[litecanvas] translate() 1st param must be a number')
840
852
  DEV: assert(isNumber(y), '[litecanvas] translate() 2nd param must be a number')
841
853
 
842
- return _ctx.translate(~~x, ~~y)
854
+ _ctx.translate(~~x, ~~y)
843
855
  },
844
856
 
845
857
  /**
@@ -848,11 +860,11 @@ export default function litecanvas(settings = {}) {
848
860
  * @param {number} x
849
861
  * @param {number} [y]
850
862
  */
851
- scale: (x, y) => {
863
+ scale(x, y) {
852
864
  DEV: assert(isNumber(x), '[litecanvas] scale() 1st param must be a number')
853
865
  DEV: assert(null == y || isNumber(y), '[litecanvas] scale() 2nd param must be a number')
854
866
 
855
- return _ctx.scale(x, y || x)
867
+ _ctx.scale(x, y || x)
856
868
  },
857
869
 
858
870
  /**
@@ -860,10 +872,10 @@ export default function litecanvas(settings = {}) {
860
872
  *
861
873
  * @param {number} radians
862
874
  */
863
- rotate: (radians) => {
875
+ rotate(radians) {
864
876
  DEV: assert(isNumber(radians), '[litecanvas] rotate() 1st param must be a number')
865
877
 
866
- return _ctx.rotate(radians)
878
+ _ctx.rotate(radians)
867
879
  },
868
880
 
869
881
  /**
@@ -1030,7 +1042,7 @@ export default function litecanvas(settings = {}) {
1030
1042
  '[litecanvas] listen() 2nd param must be a function'
1031
1043
  )
1032
1044
 
1033
- eventName = eventName.toLowerCase()
1045
+ eventName = lowerCase(eventName)
1034
1046
 
1035
1047
  _eventListeners[eventName] = _eventListeners[eventName] || new Set()
1036
1048
  _eventListeners[eventName].add(callback)
@@ -1054,7 +1066,7 @@ export default function litecanvas(settings = {}) {
1054
1066
  '[litecanvas] emit() 1st param must be a string'
1055
1067
  )
1056
1068
  if (_initialized) {
1057
- eventName = eventName.toLowerCase()
1069
+ eventName = lowerCase(eventName)
1058
1070
 
1059
1071
  triggerEvent('before:' + eventName, arg1, arg2, arg3, arg4)
1060
1072
  triggerEvent(eventName, arg1, arg2, arg3, arg4)
@@ -1063,7 +1075,7 @@ export default function litecanvas(settings = {}) {
1063
1075
  },
1064
1076
 
1065
1077
  /**
1066
- * Set or reset the color palette
1078
+ * Set or reset the color palette.
1067
1079
  *
1068
1080
  * @param {string[]} [colors]
1069
1081
  */
@@ -1073,6 +1085,31 @@ export default function litecanvas(settings = {}) {
1073
1085
  '[litecanvas] pal() 1st param must be a array of strings'
1074
1086
  )
1075
1087
  _colors = colors
1088
+ _currentPalette = [...colors]
1089
+ },
1090
+
1091
+ /**
1092
+ * Swap two colors of the current palette.
1093
+ *
1094
+ * If called without arguments, reset the current palette.
1095
+ *
1096
+ * @param {number?} a
1097
+ * @param {number?} b
1098
+ */
1099
+ palc(a, b) {
1100
+ DEV: assert(
1101
+ null == a || (isNumber(a) && a >= 0),
1102
+ '[litecanvas] palc() 1st param must be a positive number'
1103
+ )
1104
+ DEV: assert(
1105
+ isNumber(a) ? isNumber(b) && b >= 0 : null == b,
1106
+ '[litecanvas] palc() 2nd param must be a positive number'
1107
+ )
1108
+ if (a == null) {
1109
+ _colors = [..._currentPalette]
1110
+ } else {
1111
+ ;[_colors[a], _colors[b]] = [_colors[b], _colors[a]]
1112
+ }
1076
1113
  },
1077
1114
 
1078
1115
  /**
@@ -1128,13 +1165,16 @@ export default function litecanvas(settings = {}) {
1128
1165
  /**
1129
1166
  * Returns information about that engine instance.
1130
1167
  *
1131
- * @param {number} n
1168
+ * @param {number|string} index
1132
1169
  * @returns {any}
1133
1170
  */
1134
- stat(n) {
1135
- DEV: assert(isNumber(n) && n >= 0, '[litecanvas] stat() 1st param must be a number')
1171
+ stat(index) {
1172
+ DEV: assert(
1173
+ isNumber(index) || 'string' === typeof index,
1174
+ '[litecanvas] stat() 1st param must be a number or string'
1175
+ )
1136
1176
 
1137
- const list = [
1177
+ const internals = [
1138
1178
  // 0
1139
1179
  settings,
1140
1180
  // 1
@@ -1161,9 +1201,9 @@ export default function litecanvas(settings = {}) {
1161
1201
  _fontFamily,
1162
1202
  ]
1163
1203
 
1164
- const data = { index: n, value: list[n] }
1204
+ const data = { index, value: internals[index] }
1165
1205
 
1166
- // plugins can modify or create stat values
1206
+ // plugins can modify or create new stats
1167
1207
  instance.emit('stat', data)
1168
1208
 
1169
1209
  return data.value
@@ -1447,7 +1487,7 @@ export default function litecanvas(settings = {}) {
1447
1487
  * @returns {boolean}
1448
1488
  */
1449
1489
  const keyCheck = (keySet, key = '') => {
1450
- key = key.toLowerCase()
1490
+ key = lowerCase(key)
1451
1491
  return !key ? keySet.size > 0 : keySet.has('space' === key ? ' ' : key)
1452
1492
  }
1453
1493
 
@@ -1455,7 +1495,7 @@ export default function litecanvas(settings = {}) {
1455
1495
  let _lastKey = ''
1456
1496
 
1457
1497
  on(root, 'keydown', (/** @type {KeyboardEvent} */ event) => {
1458
- const key = event.key.toLowerCase()
1498
+ const key = lowerCase(event.key)
1459
1499
  if (!_keysDown.has(key)) {
1460
1500
  _keysDown.add(key)
1461
1501
  _keysPress.add(key)
@@ -1464,7 +1504,7 @@ export default function litecanvas(settings = {}) {
1464
1504
  })
1465
1505
 
1466
1506
  on(root, 'keyup', (/** @type {KeyboardEvent} */ event) => {
1467
- _keysDown.delete(event.key.toLowerCase())
1507
+ _keysDown.delete(lowerCase(event.key))
1468
1508
  })
1469
1509
 
1470
1510
  on(root, 'blur', () => _keysDown.clear())
@@ -1516,9 +1556,8 @@ export default function litecanvas(settings = {}) {
1516
1556
  }
1517
1557
 
1518
1558
  function drawFrame() {
1519
- if (!settings.animate) {
1520
- return instance.emit('draw', _ctx)
1521
- }
1559
+ // request the next frame
1560
+ _rafid = raf(drawFrame)
1522
1561
 
1523
1562
  let now = Date.now()
1524
1563
  let updated = 0
@@ -1548,9 +1587,6 @@ export default function litecanvas(settings = {}) {
1548
1587
  )
1549
1588
  }
1550
1589
  }
1551
-
1552
- // request the next frame
1553
- _rafid = raf(drawFrame)
1554
1590
  }
1555
1591
 
1556
1592
  function setupCanvas() {
@@ -1575,15 +1611,13 @@ export default function litecanvas(settings = {}) {
1575
1611
 
1576
1612
  on(_canvas, 'click', () => focus())
1577
1613
 
1578
- /** @ts-ignore */
1579
- _canvas.style = ''
1580
-
1581
1614
  resizeCanvas()
1582
1615
 
1583
1616
  if (!_canvas.parentNode) {
1584
1617
  document.body.appendChild(_canvas)
1585
1618
  }
1586
1619
 
1620
+ _canvas.style.imageRendering = 'pixelated'
1587
1621
  _canvas.oncontextmenu = () => false
1588
1622
  }
1589
1623
 
@@ -1625,10 +1659,7 @@ export default function litecanvas(settings = {}) {
1625
1659
  }
1626
1660
 
1627
1661
  // set canvas image rendering properties
1628
- if (settings.pixelart) {
1629
- _ctx.imageSmoothingEnabled = false
1630
- _canvas.style.imageRendering = 'pixelated'
1631
- }
1662
+ _ctx.imageSmoothingEnabled = false
1632
1663
 
1633
1664
  // set the default text align and baseline
1634
1665
  instance.textalign('start', 'top')
@@ -1636,11 +1667,6 @@ export default function litecanvas(settings = {}) {
1636
1667
  // trigger "resized" event
1637
1668
  // note: not triggered before the "init" event
1638
1669
  instance.emit('resized', _scale)
1639
-
1640
- // force redraw when the canvas is not animated
1641
- if (!settings.animate) {
1642
- raf(drawFrame)
1643
- }
1644
1670
  }
1645
1671
 
1646
1672
  /**
@@ -1687,6 +1713,9 @@ export default function litecanvas(settings = {}) {
1687
1713
 
1688
1714
  setupCanvas()
1689
1715
 
1716
+ // init the color palette
1717
+ instance.pal()
1718
+
1690
1719
  if ('loading' === document.readyState) {
1691
1720
  on(root, 'DOMContentLoaded', () => raf(init))
1692
1721
  } else {
package/src/version.js CHANGED
@@ -1,2 +1,2 @@
1
1
  // Generated by genversion.
2
- export const version = '0.95.1'
2
+ export const version = '0.97.0'
package/types/global.d.ts CHANGED
@@ -356,7 +356,7 @@ declare global {
356
356
  */
357
357
  function textalign(align: CanvasTextAlign, baseline: CanvasTextBaseline): void
358
358
 
359
- /** IMAGE GRAPHICS API */
359
+ /** BASIC GRAPHICS API */
360
360
  /**
361
361
  * Draw an image
362
362
  *
@@ -365,19 +365,33 @@ declare global {
365
365
  * @param source
366
366
  */
367
367
  function image(x: number, y: number, source: CanvasImageSource): void
368
+ /**
369
+ * Draw a sprite pxiel by pixel represented by a string. Each pixel must be a base 36 number or a dot:
370
+ *
371
+ * - A base 36 number (`0-9` or `a-z`) represent a pixel color (supporting color palettes with max 36 colors).
372
+ * - A dot (`.`) represent a transparent pixel.
373
+ * - Spaces and lines breaks are ignored and can be used to improve the visualization.
374
+ *
375
+ * @param x the position X of the first pixel
376
+ * @param y the position Y of the first pixel
377
+ * @param width the width of the sprite
378
+ * @param height the height of the sprite
379
+ * @param pixels
380
+ */
381
+ function spr(x: number, y: number, width: number, height: number, pixels: string): void
368
382
  /**
369
383
  * Draw in an OffscreenCanvas and returns its image.
370
384
  *
371
385
  * @param width
372
386
  * @param height
373
- * @param drawing
387
+ * @param callback
374
388
  * @param [options]
375
389
  * @see https://developer.mozilla.org/en-US/docs/Web/API/OffscreenCanvas
376
390
  */
377
391
  function paint(
378
392
  width: number,
379
393
  height: number,
380
- drawing: string[] | drawCallback,
394
+ callback: drawCallback,
381
395
  options?: {
382
396
  scale?: number
383
397
  canvas?: OffscreenCanvas
@@ -531,11 +545,22 @@ declare global {
531
545
  */
532
546
  function emit(event: string, arg1?: any, arg2?: any, arg3?: any, arg4?: any): void
533
547
  /**
534
- * Set or reset the color palette
548
+ * Set or reset the color palette.
535
549
  *
536
550
  * @param [colors]
537
551
  */
538
552
  function pal(colors?: string[]): void
553
+ /**
554
+ * Swap two colors of the current palette.
555
+ *
556
+ * If called without arguments, reset the current palette.
557
+ *
558
+ * Note: `palc()` don't affect drawings made with `image()`.
559
+ *
560
+ * @param a
561
+ * @param b
562
+ */
563
+ function palc(a?: number, b?: number): void
539
564
  /**
540
565
  * Define or update a instance property
541
566
  *
package/types/types.d.ts CHANGED
@@ -350,7 +350,7 @@ type LitecanvasInstance = {
350
350
  */
351
351
  textalign(align: CanvasTextAlign, baseline: CanvasTextBaseline): void
352
352
 
353
- /** IMAGE GRAPHICS API */
353
+ /** BASIC GRAPHICS API */
354
354
  /**
355
355
  * Draw an image
356
356
  *
@@ -359,19 +359,33 @@ type LitecanvasInstance = {
359
359
  * @param source
360
360
  */
361
361
  image(x: number, y: number, source: CanvasImageSource): void
362
+ /**
363
+ * Draw a sprite pxiel by pixel represented by a string. Each pixel must be a base 36 number or a dot:
364
+ *
365
+ * - A base 36 number (`0-9` or `a-z`) represent a pixel color (supporting color palettes with max 36 colors).
366
+ * - A dot (`.`) represent a transparent pixel.
367
+ * - Spaces and lines breaks are ignored and can be used to improve the visualization.
368
+ *
369
+ * @param x the position X of the first pixel
370
+ * @param y the position Y of the first pixel
371
+ * @param width the width of the sprite
372
+ * @param height the height of the sprite
373
+ * @param pixels
374
+ */
375
+ spr(x: number, y: number, width: number, height: number, pixels: string): void
362
376
  /**
363
377
  * Draw in an OffscreenCanvas and returns its image.
364
378
  *
365
379
  * @param width
366
380
  * @param height
367
- * @param drawing
381
+ * @param callback
368
382
  * @param [options]
369
383
  * @see https://developer.mozilla.org/en-US/docs/Web/API/OffscreenCanvas
370
384
  */
371
385
  paint(
372
386
  width: number,
373
387
  height: number,
374
- drawing: string[] | drawCallback,
388
+ callback: drawCallback,
375
389
  options?: {
376
390
  scale?: number
377
391
  canvas?: OffscreenCanvas
@@ -528,11 +542,22 @@ type LitecanvasInstance = {
528
542
  */
529
543
  def(key: string, value: any): void
530
544
  /**
531
- * Set or reset the color palette
545
+ * Set or reset the color palette.
532
546
  *
533
547
  * @param [colors]
534
548
  */
535
549
  pal(colors?: string[]): void
550
+ /**
551
+ * Swap two colors of the current palette.
552
+ *
553
+ * If called without arguments, reset the current palette.
554
+ *
555
+ * Note: `palc()` don't affect drawings made with `image()`.
556
+ *
557
+ * @param a
558
+ * @param b
559
+ */
560
+ palc(a?: number, b?: number): void
536
561
  /**
537
562
  * The scale of the game's delta time (dt).
538
563
  * Values higher than 1 increase the speed of time, while values smaller than 1 decrease it.
@@ -605,13 +630,6 @@ type LitecanvasOptions = {
605
630
  * Note: Only works if the option "width" was specified.
606
631
  */
607
632
  autoscale?: boolean | number
608
- /**
609
- * If `true`, the pixel art images won't look blurry.
610
- * Also, disables canvas built-in antialias.
611
- *
612
- * Default: `true`
613
- */
614
- pixelart?: boolean
615
633
  /**
616
634
  * If `true` (default), all methods and properties of the engine will be exposed to the global scope (window).
617
635
  */
@@ -646,12 +664,6 @@ type LitecanvasOptions = {
646
664
  * Useful when you want to implement your keyboard handler.
647
665
  */
648
666
  keyboardEvents?: boolean
649
- /**
650
- * default: `true`
651
- *
652
- * if `false` stops the code in `update()` and `draw()` from running repeatedly. By default, tries to run these functions 60 times per second.
653
- */
654
- animate?: boolean
655
667
  }
656
668
 
657
669
  type LitecanvasGameLoop = {