litecanvas 0.80.0 → 0.81.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
@@ -1,7 +1,7 @@
1
+ // @ts-check
1
2
  import { zzfx } from './zzfx.js'
2
3
  import { defaultPalette } from './palette.js'
3
4
  import { assert } from './dev.js'
4
- import './types.js'
5
5
 
6
6
  /**
7
7
  * The litecanvas constructor
@@ -10,7 +10,8 @@ import './types.js'
10
10
  * @returns {LitecanvasInstance}
11
11
  */
12
12
  export default function litecanvas(settings = {}) {
13
- const root = globalThis,
13
+ const /** @type {typeof globalThis} */
14
+ root = globalThis,
14
15
  math = Math,
15
16
  TWO_PI = math.PI * 2,
16
17
  raf = requestAnimationFrame,
@@ -45,9 +46,9 @@ export default function litecanvas(settings = {}) {
45
46
 
46
47
  let /** @type {boolean} */
47
48
  _initialized = false,
48
- /** @type {Function[]} */
49
+ /** @type {any[]} */
49
50
  _plugins = [],
50
- /** @type {HTMLCanvasElement|string} _canvas */
51
+ /** @type {HTMLCanvasElement} _canvas */
51
52
  _canvas,
52
53
  /** @type {number} */
53
54
  _scale = 1,
@@ -63,7 +64,7 @@ export default function litecanvas(settings = {}) {
63
64
  _deltaTime = 1 / 60,
64
65
  /** @type {number} */
65
66
  _accumulated = 0,
66
- /** @type {number} */
67
+ /** @type {number|null} */
67
68
  _rafid,
68
69
  /** @type {string} */
69
70
  _fontFamily = 'sans-serif',
@@ -73,60 +74,49 @@ export default function litecanvas(settings = {}) {
73
74
  _rng_seed = Date.now(),
74
75
  /** @type {string[]} */
75
76
  _colors = defaultPalette,
77
+ /** @type {number[]} */
78
+ _default_sound = [0.5, 0, 1750, , , 0.3, 1, , , , 600, 0.1],
76
79
  /**
77
80
  * default game events
81
+ *
78
82
  * @type {Object<string,Set<Function>>}
79
83
  */
80
84
  _events = {
81
- init: false,
82
- update: false,
83
- draw: false,
84
- resized: false,
85
- tap: false,
86
- untap: false,
87
- tapping: false,
88
- tapped: false,
89
- },
90
- /**
91
- * Helpers to be used by plugins
92
- *
93
- * @type {LitecanvasPluginHelpers}
94
- */
95
- _helpers = {
96
- settings: Object.assign({}, settings),
85
+ init: null,
86
+ update: null,
87
+ draw: null,
88
+ resized: null,
89
+ tap: null,
90
+ untap: null,
91
+ tapping: null,
92
+ tapped: null,
97
93
  }
98
94
 
99
- /** @type {LitecanvasInstance} */
95
+ /** @type {Omit<LitecanvasInstance,'PI'|'sin'|'cos'|'atan2'|'hypot'|'tan'|'abs'|'ceil'|'floor'|'trunc'|'min'|'max'|'pow'|'sqrt'|'sign'|'exp'|'iskeydown'|'iskeypressed'>} */
100
96
  const instance = {
101
- /** @type {number} */
102
- WIDTH: 0,
103
-
104
- /** @type {number} */
105
- HEIGHT: 0,
106
-
107
97
  /** @type {HTMLCanvasElement} */
108
- CANVAS: false,
98
+ CANVAS: null,
109
99
 
110
100
  /** @type {number} */
111
- ELAPSED: 0,
101
+ W: 0,
112
102
 
113
103
  /** @type {number} */
114
- CENTERX: 0,
104
+ H: 0,
115
105
 
116
106
  /** @type {number} */
117
- CENTERY: 0,
107
+ T: 0,
118
108
 
119
109
  /** @type {number} */
120
- MOUSEX: -1,
110
+ CX: 0,
121
111
 
122
112
  /** @type {number} */
123
- MOUSEY: -1,
113
+ CY: 0,
124
114
 
125
- /** @type {number[]} */
126
- DEFAULT_SFX: [0.5, 0, 1750, , , 0.3, 1, , , , 600, 0.1],
115
+ /** @type {number} */
116
+ MX: -1,
127
117
 
128
- /** @type {string[]} */
129
- COLORS: _colors,
118
+ /** @type {number} */
119
+ MY: -1,
130
120
 
131
121
  /** MATH API */
132
122
  /**
@@ -298,6 +288,17 @@ export default function litecanvas(settings = {}) {
298
288
  return instance.map(value, start, stop, 0, 1)
299
289
  },
300
290
 
291
+ /**
292
+ * Interpolate between 2 values using a periodic function.
293
+ *
294
+ * @param {number} from - the lower bound
295
+ * @param {number} to - the higher bound
296
+ * @param {number} t - the amount
297
+ * @param {(n: number) => number} fn - the periodic function (which default to `Math.sin`)
298
+ */
299
+ wave: (from, to, t, fn = Math.sin) =>
300
+ from + ((fn(t) + 1) / 2) * (to - from),
301
+
301
302
  /** RNG API */
302
303
  /**
303
304
  * Generates a pseudorandom float between min (inclusive) and max (exclusive)
@@ -343,19 +344,19 @@ export default function litecanvas(settings = {}) {
343
344
  },
344
345
 
345
346
  /**
346
- * If a value is passed, initializes the random number generator with an explicit seed value.
347
- * Otherwise, returns the current seed state.
347
+ * Initializes the random number generator with an explicit seed value.
348
+ *
349
+ * Note: The seed should be a integer number greater than or equal to zero.
348
350
  *
349
351
  * @param {number} value
350
- * @returns {number} the seed state
351
352
  */
352
- seed: (value) => {
353
+ rseed(value) {
353
354
  DEV: assert(
354
355
  null == value || (isNumber(value) && value >= 0),
355
- 'seed: 1st param must be a positive number or zero'
356
+ 'rseed: 1st param must be a positive number or zero'
356
357
  )
357
358
 
358
- return null == value ? _rng_seed : (_rng_seed = ~~value)
359
+ _rng_seed = ~~value
359
360
  },
360
361
 
361
362
  /** BASIC GRAPHICS API */
@@ -606,10 +607,6 @@ export default function litecanvas(settings = {}) {
606
607
  text(x, y, message, color = 3, fontStyle = 'normal') {
607
608
  DEV: assert(isNumber(x), 'text: 1st param must be a number')
608
609
  DEV: assert(isNumber(y), 'text: 2nd param must be a number')
609
- // DEV: assert(
610
- // 'string' === typeof message,
611
- // 'text: 3rd param must be a string'
612
- // )
613
610
  DEV: assert(
614
611
  null == color || (isNumber(color) && color >= 0),
615
612
  'text: 4th param must be a positive number or zero'
@@ -620,7 +617,7 @@ export default function litecanvas(settings = {}) {
620
617
  )
621
618
 
622
619
  _ctx.font = `${fontStyle} ${_fontSize}px ${_fontFamily}`
623
- _ctx.fillStyle = instance.getcolor(color)
620
+ _ctx.fillStyle = _colors[~~color % _colors.length]
624
621
  _ctx.fillText(message, ~~x, ~~y)
625
622
  },
626
623
 
@@ -652,8 +649,8 @@ export default function litecanvas(settings = {}) {
652
649
  /**
653
650
  * Sets the alignment used when drawing texts
654
651
  *
655
- * @param {string} align the horizontal alignment. Possible values: "left", "right", "center", "start" or "end"
656
- * @param {string} baseline the vertical alignment. Possible values: "top", "bottom", "middle", "hanging" or "ideographic"
652
+ * @param {CanvasTextAlign} align the horizontal alignment. Possible values: "left", "right", "center", "start" or "end"
653
+ * @param {CanvasTextBaseline} baseline the vertical alignment. Possible values: "top", "bottom", "middle", "hanging" or "ideographic"
657
654
  * @see https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/textBaseline
658
655
  * @see https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/textAlign
659
656
  */
@@ -661,7 +658,7 @@ export default function litecanvas(settings = {}) {
661
658
  DEV: assert(
662
659
  null == align ||
663
660
  ['left', 'right', 'center', 'start', 'end'].includes(align),
664
- 'textalign: 1st param must be null or one of the following values: center, left, right, start or end.'
661
+ 'textalign: 1st param must be null or one of the following strings: center, left, right, start or end.'
665
662
  )
666
663
  DEV: assert(
667
664
  null == baseline ||
@@ -673,7 +670,7 @@ export default function litecanvas(settings = {}) {
673
670
  'alphabetic',
674
671
  'ideographic',
675
672
  ].includes(baseline),
676
- 'textalign: 2nd param must be null or one of the following values: middle, top, bottom, hanging, alphabetic or ideographic.'
673
+ 'textalign: 2nd param must be null or one of the following strings: middle, top, bottom, hanging, alphabetic or ideographic.'
677
674
  )
678
675
 
679
676
  if (align) _ctx.textAlign = align
@@ -703,7 +700,7 @@ export default function litecanvas(settings = {}) {
703
700
  * @param {string[]|drawCallback} drawing
704
701
  * @param {object} [options]
705
702
  * @param {number} [options.scale=1]
706
- * @param {OffscreenCanvas | HTMLCanvasElement} [options.canvas]
703
+ * @param {OffscreenCanvas} [options.canvas]
707
704
  * @returns {ImageBitmap}
708
705
  * @see https://developer.mozilla.org/en-US/docs/Web/API/OffscreenCanvas
709
706
  */
@@ -731,12 +728,14 @@ export default function litecanvas(settings = {}) {
731
728
  _ctx.scale(scale, scale)
732
729
 
733
730
  // draw pixel art if `draw` is a array
731
+ // @ts-ignore
734
732
  if (drawing.push) {
735
733
  let x = 0,
736
734
  y = 0
737
735
 
738
736
  _ctx.imageSmoothingEnabled = false
739
737
 
738
+ // @ts-ignore
740
739
  for (const str of drawing) {
741
740
  for (const color of str) {
742
741
  if (' ' !== color && '.' !== color) {
@@ -749,6 +748,7 @@ export default function litecanvas(settings = {}) {
749
748
  x = 0
750
749
  }
751
750
  } else {
751
+ // @ts-ignore
752
752
  drawing(_ctx)
753
753
  }
754
754
 
@@ -872,7 +872,7 @@ export default function litecanvas(settings = {}) {
872
872
  'fill: 2nd param must be a Path2D instance'
873
873
  )
874
874
 
875
- _ctx.fillStyle = instance.getcolor(color)
875
+ _ctx.fillStyle = _colors[~~color % _colors.length]
876
876
  if (path) {
877
877
  _ctx.fill(path)
878
878
  } else {
@@ -896,7 +896,7 @@ export default function litecanvas(settings = {}) {
896
896
  'stroke: 2nd param must be a Path2D instance'
897
897
  )
898
898
 
899
- _ctx.strokeStyle = instance.getcolor(color)
899
+ _ctx.strokeStyle = _colors[~~color % _colors.length]
900
900
  if (path) {
901
901
  _ctx.stroke(path)
902
902
  } else {
@@ -950,7 +950,7 @@ export default function litecanvas(settings = {}) {
950
950
  return false
951
951
  }
952
952
 
953
- zzfxParams = zzfxParams || instance.DEFAULT_SFX
953
+ zzfxParams = zzfxParams || _default_sound
954
954
 
955
955
  // if has other arguments, copy the sound to not change the original
956
956
  if (pitchSlide !== 0 || volumeFactor !== 1) {
@@ -1053,36 +1053,23 @@ export default function litecanvas(settings = {}) {
1053
1053
  'pal: 1st param must be a array of strings'
1054
1054
  )
1055
1055
  _colors = colors
1056
- instance.setvar('COLORS', _colors)
1057
1056
  },
1058
1057
 
1059
1058
  /**
1060
- * Get a color by index
1061
- *
1062
- * @param {number} [index=0] The color number
1063
- * @returns {string} the color code
1064
- */
1065
- getcolor: (index) => {
1066
- DEV: assert(
1067
- null == index || (isNumber(index) && index >= 0),
1068
- 'getcolor: 1st param must be a number'
1069
- )
1070
- return _colors[~~index % _colors.length]
1071
- },
1072
-
1073
- /**
1074
- * Create or update a instance variable
1059
+ * Define or update a instance property.
1075
1060
  *
1076
1061
  * @param {string} key
1077
1062
  * @param {*} value
1078
1063
  */
1079
- setvar(key, value) {
1064
+ def(key, value) {
1080
1065
  DEV: assert(
1081
1066
  'string' === typeof key,
1082
- 'setvar: 1st param must be a string'
1067
+ 'def: 1st param must be a string'
1083
1068
  )
1084
- if (null == value) {
1085
- console.warn(`setvar: key "${key}" was defined as ${value}`)
1069
+ DEV: if (null == value) {
1070
+ console.warn(
1071
+ `def: key "${key}" was defined as ${value} but now is null`
1072
+ )
1086
1073
  }
1087
1074
 
1088
1075
  instance[key] = value
@@ -1100,45 +1087,95 @@ export default function litecanvas(settings = {}) {
1100
1087
  */
1101
1088
  timescale(value) {
1102
1089
  DEV: assert(
1103
- isNumber(value),
1104
- 'timescale: 1st param must be a number'
1090
+ isNumber(value) && value >= 0,
1091
+ 'timescale: 1st param must be a positive number or zero'
1105
1092
  )
1106
1093
 
1107
1094
  _timeScale = value
1108
1095
  },
1109
1096
 
1110
1097
  /**
1111
- * Set the target FPS at runtime.
1098
+ * Set the target FPS (frames per second).
1112
1099
  *
1113
1100
  * @param {number} value
1114
1101
  */
1115
- setfps(value) {
1102
+ framerate(value) {
1116
1103
  DEV: assert(
1117
1104
  isNumber(value) && value >= 1,
1118
- 'setfps: 1st param must be a positive number'
1105
+ 'framerate: 1st param must be a positive number'
1119
1106
  )
1120
1107
 
1121
1108
  _deltaTime = 1 / ~~value
1122
1109
  },
1123
1110
 
1111
+ /**
1112
+ * Returns information about that engine instance.
1113
+ *
1114
+ * n = 0: the settings passed to that instance
1115
+ * n = 1: returns true if the "init" event has already been emitted
1116
+ * n = 2: the current ID returned by last requestAnimationFrame
1117
+ * n = 3: the current canvas element scale (not the context 2D scale)
1118
+ * n = 4: the attached event callbacks
1119
+ * n = 5: the current color palette
1120
+ * n = 6: the default sound used by `sfx()`
1121
+ * n = 7: the current time scale
1122
+ * n = 8: the current volume used by ZzFX
1123
+ * n = 9: the current RNG state
1124
+ *
1125
+ * n = any other value: returns undefined
1126
+ *
1127
+ * @param {number} n
1128
+ * @returns {any}
1129
+ */
1130
+ stat(n) {
1131
+ DEV: assert(
1132
+ isNumber(n) && n >= 0,
1133
+ 'stat: 1st param must be a positive number'
1134
+ )
1135
+
1136
+ const list = [
1137
+ // 0
1138
+ settings,
1139
+ // 1
1140
+ _initialized,
1141
+ // 2
1142
+ _rafid,
1143
+ // 3
1144
+ _scale,
1145
+ // 4
1146
+ _events,
1147
+ // 5
1148
+ _colors,
1149
+ // 6
1150
+ _default_sound,
1151
+ // 7
1152
+ _timeScale,
1153
+ // 8
1154
+ root.zzfxV || 1,
1155
+ // 9
1156
+ _rng_seed,
1157
+ ]
1158
+ return list[n]
1159
+ },
1160
+
1124
1161
  /**
1125
1162
  * Stops the litecanvas instance and remove all event listeners.
1126
1163
  */
1127
1164
  quit() {
1128
- // stop the renderer
1165
+ // stop the game loop (update & draw)
1129
1166
  cancelAnimationFrame(_rafid)
1130
1167
 
1131
1168
  // emit "quit" event to manual clean ups
1132
1169
  instance.emit('quit')
1133
1170
 
1134
- // clear all engine events
1135
- _events = []
1136
-
1137
- // clear all browser events
1171
+ // clear all browser event listeners
1138
1172
  for (const removeListener of _browserEventListeners) {
1139
1173
  removeListener()
1140
1174
  }
1141
1175
 
1176
+ // clear all engine event listeners
1177
+ _events = {}
1178
+
1142
1179
  // maybe clear global context
1143
1180
  if (settings.global) {
1144
1181
  for (const key in instance) {
@@ -1156,8 +1193,6 @@ export default function litecanvas(settings = {}) {
1156
1193
  }
1157
1194
 
1158
1195
  function init() {
1159
- _initialized = true
1160
-
1161
1196
  // setup default event listeners
1162
1197
  const source = settings.loop ? settings.loop : root
1163
1198
  for (const event in _events) {
@@ -1171,6 +1206,7 @@ export default function litecanvas(settings = {}) {
1171
1206
 
1172
1207
  // listen window resize event when "autoscale" is enabled
1173
1208
  if (settings.autoscale) {
1209
+ // @ts-ignore
1174
1210
  on(root, 'resize', resizeCanvas)
1175
1211
  }
1176
1212
 
@@ -1204,65 +1240,102 @@ export default function litecanvas(settings = {}) {
1204
1240
 
1205
1241
  let _pressingMouse = false
1206
1242
 
1207
- on(_canvas, 'mousedown', (ev) => {
1208
- if (ev.button === 0) {
1209
- preventDefault(ev)
1210
- const [x, y] = _getXY(ev.pageX, ev.pageY)
1211
- instance.emit('tap', x, y, 0)
1212
- _registerTap(0, x, y)
1213
- _pressingMouse = true
1243
+ on(
1244
+ _canvas,
1245
+ 'mousedown',
1246
+ /**
1247
+ * @param {MouseEvent} ev
1248
+ */
1249
+ (ev) => {
1250
+ if (ev.button === 0) {
1251
+ preventDefault(ev)
1252
+ const [x, y] = _getXY(ev.pageX, ev.pageY)
1253
+ instance.emit('tap', x, y, 0)
1254
+ _registerTap(0, x, y)
1255
+ _pressingMouse = true
1256
+ }
1214
1257
  }
1215
- })
1258
+ )
1216
1259
 
1217
- on(_canvas, 'mouseup', (ev) => {
1218
- if (ev.button === 0) {
1219
- preventDefault(ev)
1220
- const tap = _taps.get(0)
1221
- const [x, y] = _getXY(ev.pageX, ev.pageY)
1222
- if (_checkTapped(tap)) {
1223
- instance.emit('tapped', tap.startX, tap.startY, 0)
1260
+ on(
1261
+ _canvas,
1262
+ 'mouseup',
1263
+ /**
1264
+ * @param {MouseEvent} ev
1265
+ */
1266
+ (ev) => {
1267
+ if (ev.button === 0) {
1268
+ preventDefault(ev)
1269
+ const tap = _taps.get(0)
1270
+ const [x, y] = _getXY(ev.pageX, ev.pageY)
1271
+ if (_checkTapped(tap)) {
1272
+ instance.emit('tapped', tap.startX, tap.startY, 0)
1273
+ }
1274
+ instance.emit('untap', x, y, 0)
1275
+ _taps.delete(0)
1276
+ _pressingMouse = false
1224
1277
  }
1225
- instance.emit('untap', x, y, 0)
1226
- _taps.delete(0)
1227
- _pressingMouse = false
1228
1278
  }
1229
- })
1279
+ )
1230
1280
 
1231
- on(_canvas, 'mousemove', (ev) => {
1232
- preventDefault(ev)
1281
+ on(
1282
+ _canvas,
1283
+ 'mousemove',
1284
+ /**
1285
+ * @param {MouseEvent} ev
1286
+ */
1287
+ (ev) => {
1288
+ preventDefault(ev)
1233
1289
 
1234
- const [x, y] = _getXY(ev.pageX, ev.pageY)
1235
- instance.setvar('MOUSEX', x)
1236
- instance.setvar('MOUSEY', y)
1290
+ const [x, y] = _getXY(ev.pageX, ev.pageY)
1291
+ instance.def('MX', x)
1292
+ instance.def('MY', y)
1237
1293
 
1238
- if (!_pressingMouse) return
1294
+ if (!_pressingMouse) return
1239
1295
 
1240
- instance.emit('tapping', x, y, 0)
1241
- _updateTap(0, x, y)
1242
- })
1296
+ instance.emit('tapping', x, y, 0)
1297
+ _updateTap(0, x, y)
1298
+ }
1299
+ )
1243
1300
 
1244
- on(_canvas, 'touchstart', (ev) => {
1245
- preventDefault(ev)
1246
- /** @type {TouchList} touches */
1247
- const touches = ev.changedTouches
1248
- for (const touch of touches) {
1249
- const [x, y] = _getXY(touch.pageX, touch.pageY)
1250
- instance.emit('tap', x, y, touch.identifier + 1)
1251
- _registerTap(touch.identifier + 1, x, y)
1301
+ on(
1302
+ _canvas,
1303
+ 'touchstart',
1304
+ /**
1305
+ * @param {TouchEvent} ev
1306
+ */
1307
+ (ev) => {
1308
+ preventDefault(ev)
1309
+ /** @type {TouchList} touches */
1310
+ const touches = ev.changedTouches
1311
+ for (const touch of touches) {
1312
+ const [x, y] = _getXY(touch.pageX, touch.pageY)
1313
+ instance.emit('tap', x, y, touch.identifier + 1)
1314
+ _registerTap(touch.identifier + 1, x, y)
1315
+ }
1252
1316
  }
1253
- })
1317
+ )
1254
1318
 
1255
- on(_canvas, 'touchmove', (ev) => {
1256
- preventDefault(ev)
1257
- /** @type {TouchList} touches */
1258
- const touches = ev.changedTouches
1259
- for (const touch of touches) {
1260
- const [x, y] = _getXY(touch.pageX, touch.pageY)
1261
- instance.emit('tapping', x, y, touch.identifier + 1)
1262
- _updateTap(touch.identifier + 1, x, y)
1319
+ on(
1320
+ _canvas,
1321
+ 'touchmove',
1322
+ /**
1323
+ * @param {TouchEvent} ev
1324
+ */
1325
+ (ev) => {
1326
+ preventDefault(ev)
1327
+ const touches = ev.changedTouches
1328
+ for (const touch of touches) {
1329
+ const [x, y] = _getXY(touch.pageX, touch.pageY)
1330
+ instance.emit('tapping', x, y, touch.identifier + 1)
1331
+ _updateTap(touch.identifier + 1, x, y)
1332
+ }
1263
1333
  }
1264
- })
1334
+ )
1265
1335
 
1336
+ /**
1337
+ * @param {TouchEvent} ev
1338
+ */
1266
1339
  const _touchEndHandler = (ev) => {
1267
1340
  preventDefault(ev)
1268
1341
  const existing = []
@@ -1286,6 +1359,7 @@ export default function litecanvas(settings = {}) {
1286
1359
  on(_canvas, 'touchend', _touchEndHandler)
1287
1360
  on(_canvas, 'touchcancel', _touchEndHandler)
1288
1361
 
1362
+ // @ts-ignore
1289
1363
  on(root, 'blur', () => {
1290
1364
  _pressingMouse = false
1291
1365
  for (const [id, tap] of _taps) {
@@ -1296,7 +1370,7 @@ export default function litecanvas(settings = {}) {
1296
1370
  }
1297
1371
 
1298
1372
  if (settings.keyboardEvents) {
1299
- const toLowerCase = (s) => s.toLowerCase()
1373
+ const toLowerCase = (/** @type {string} */ s) => s.toLowerCase()
1300
1374
 
1301
1375
  /** @type {Set<string>} */
1302
1376
  const _keysDown = new Set()
@@ -1317,6 +1391,7 @@ export default function litecanvas(settings = {}) {
1317
1391
  )
1318
1392
  }
1319
1393
 
1394
+ // @ts-ignore
1320
1395
  on(root, 'keydown', (/** @type {KeyboardEvent} */ event) => {
1321
1396
  if (!_keysDown.has(toLowerCase(event.key))) {
1322
1397
  _keysDown.add(toLowerCase(event.key))
@@ -1324,14 +1399,16 @@ export default function litecanvas(settings = {}) {
1324
1399
  }
1325
1400
  })
1326
1401
 
1402
+ // @ts-ignore
1327
1403
  on(root, 'keyup', (/** @type {KeyboardEvent} */ event) => {
1328
1404
  _keysDown.delete(toLowerCase(event.key))
1329
1405
  })
1330
1406
 
1407
+ // @ts-ignore
1331
1408
  on(root, 'blur', () => _keysDown.clear())
1332
1409
  instance.listen('after:draw', () => _keysPress.clear())
1333
1410
 
1334
- instance.setvar(
1411
+ instance.def(
1335
1412
  'iskeydown',
1336
1413
  /**
1337
1414
  * Checks if a which key is pressed (down) on the keyboard.
@@ -1349,7 +1426,7 @@ export default function litecanvas(settings = {}) {
1349
1426
  }
1350
1427
  )
1351
1428
 
1352
- instance.setvar(
1429
+ instance.def(
1353
1430
  'iskeypressed',
1354
1431
  /**
1355
1432
  * Checks if a which key just got pressed on the keyboard.
@@ -1370,10 +1447,13 @@ export default function litecanvas(settings = {}) {
1370
1447
 
1371
1448
  // listen browser focus/blur events and pause the update/draw loop
1372
1449
  if (settings.pauseOnBlur) {
1450
+ // @ts-ignore
1373
1451
  on(root, 'blur', () => {
1452
+ // @ts-ignore
1374
1453
  _rafid = cancelAnimationFrame(_rafid)
1375
1454
  })
1376
1455
 
1456
+ // @ts-ignore
1377
1457
  on(root, 'focus', () => {
1378
1458
  if (!_rafid) {
1379
1459
  _accumulated = 0
@@ -1382,6 +1462,8 @@ export default function litecanvas(settings = {}) {
1382
1462
  })
1383
1463
  }
1384
1464
 
1465
+ _initialized = true
1466
+
1385
1467
  // start the game loop
1386
1468
  instance.emit('init', instance)
1387
1469
 
@@ -1410,10 +1492,7 @@ export default function litecanvas(settings = {}) {
1410
1492
 
1411
1493
  while (_accumulated >= _deltaTime) {
1412
1494
  instance.emit('update', _deltaTime * _timeScale)
1413
- instance.setvar(
1414
- 'ELAPSED',
1415
- instance.ELAPSED + _deltaTime * _timeScale
1416
- )
1495
+ instance.def('T', instance.T + _deltaTime * _timeScale)
1417
1496
  updated++
1418
1497
  _accumulated -= _deltaTime
1419
1498
  }
@@ -1432,29 +1511,30 @@ export default function litecanvas(settings = {}) {
1432
1511
  }
1433
1512
 
1434
1513
  function setupCanvas() {
1435
- _canvas = settings.canvas || document.createElement('canvas')
1436
-
1437
- /** @type {HTMLCanvasElement} */
1438
- _canvas =
1439
- 'string' === typeof _canvas
1440
- ? document.querySelector(_canvas)
1441
- : _canvas
1514
+ if ('string' === typeof settings.canvas) {
1515
+ _canvas = document.querySelector(settings.canvas)
1516
+ } else {
1517
+ _canvas = settings.canvas || document.createElement('canvas')
1518
+ }
1442
1519
 
1443
1520
  DEV: assert(
1444
1521
  _canvas && _canvas.tagName === 'CANVAS',
1445
1522
  'Invalid canvas element'
1446
1523
  )
1447
1524
 
1448
- instance.setvar('CANVAS', _canvas)
1525
+ instance.def('CANVAS', _canvas)
1449
1526
  _ctx = _canvas.getContext('2d')
1450
1527
 
1451
1528
  on(_canvas, 'click', () => root.focus())
1452
1529
 
1530
+ // @ts-ignore
1453
1531
  _canvas.style = ''
1454
1532
 
1455
1533
  resizeCanvas()
1456
1534
 
1457
- if (!_canvas.parentNode) document.body.appendChild(_canvas)
1535
+ if (!_canvas.parentNode) {
1536
+ document.body.appendChild(_canvas)
1537
+ }
1458
1538
  }
1459
1539
 
1460
1540
  function resizeCanvas() {
@@ -1477,11 +1557,11 @@ export default function litecanvas(settings = {}) {
1477
1557
  const width = settings.width || root.innerWidth,
1478
1558
  height = settings.height || settings.width || root.innerHeight
1479
1559
 
1480
- instance.setvar('WIDTH', (_canvas.width = width))
1481
- instance.setvar('HEIGHT', (_canvas.height = height))
1560
+ instance.def('W', (_canvas.width = width))
1561
+ instance.def('H', (_canvas.height = height))
1482
1562
 
1483
- instance.setvar('CENTERX', instance.WIDTH / 2)
1484
- instance.setvar('CENTERY', instance.HEIGHT / 2)
1563
+ instance.def('CX', instance.W / 2)
1564
+ instance.def('CY', instance.H / 2)
1485
1565
 
1486
1566
  if (settings.autoscale) {
1487
1567
  if (!_canvas.style.display) {
@@ -1490,13 +1570,13 @@ export default function litecanvas(settings = {}) {
1490
1570
  }
1491
1571
 
1492
1572
  _scale = math.min(
1493
- root.innerWidth / instance.WIDTH,
1494
- root.innerHeight / instance.HEIGHT
1573
+ root.innerWidth / instance.W,
1574
+ root.innerHeight / instance.H
1495
1575
  )
1496
1576
  _scale = (settings.pixelart ? ~~_scale : _scale) || 1
1497
1577
 
1498
- _canvas.style.width = instance.WIDTH * _scale + 'px'
1499
- _canvas.style.height = instance.HEIGHT * _scale + 'px'
1578
+ _canvas.style.width = instance.W * _scale + 'px'
1579
+ _canvas.style.height = instance.H * _scale + 'px'
1500
1580
  }
1501
1581
 
1502
1582
  // restore canvas image rendering properties
@@ -1508,14 +1588,24 @@ export default function litecanvas(settings = {}) {
1508
1588
  // trigger "resized" event
1509
1589
  instance.emit('resized', _scale)
1510
1590
 
1591
+ instance.cls(0)
1592
+
1511
1593
  // force redraw
1512
1594
  if (!settings.animate) {
1513
1595
  raf(drawFrame)
1514
1596
  }
1515
1597
  }
1516
1598
 
1599
+ /**
1600
+ * @param {string} eventName
1601
+ * @param {*} arg1
1602
+ * @param {*} arg2
1603
+ * @param {*} arg3
1604
+ * @param {*} arg4
1605
+ */
1517
1606
  function triggerEvent(eventName, arg1, arg2, arg3, arg4) {
1518
1607
  if (!_events[eventName]) return
1608
+ // @ts-ignore
1519
1609
  for (const callback of _events[eventName]) {
1520
1610
  callback(arg1, arg2, arg3, arg4)
1521
1611
  }
@@ -1523,9 +1613,11 @@ export default function litecanvas(settings = {}) {
1523
1613
 
1524
1614
  /**
1525
1615
  * @param {pluginCallback} callback
1616
+ * @param {*} config
1526
1617
  */
1527
1618
  function loadPlugin(callback, config) {
1528
- const pluginData = callback(instance, _helpers, config)
1619
+ // @ts-ignore
1620
+ const pluginData = callback(instance, config)
1529
1621
 
1530
1622
  DEV: assert(
1531
1623
  null == pluginData || 'object' === typeof pluginData,
@@ -1533,7 +1625,7 @@ export default function litecanvas(settings = {}) {
1533
1625
  )
1534
1626
 
1535
1627
  for (const key in pluginData) {
1536
- instance.setvar(key, pluginData[key])
1628
+ instance.def(key, pluginData[key])
1537
1629
  }
1538
1630
  }
1539
1631
 
@@ -1548,10 +1640,12 @@ export default function litecanvas(settings = {}) {
1548
1640
  setupCanvas()
1549
1641
 
1550
1642
  if ('loading' === document.readyState) {
1643
+ // @ts-ignore
1551
1644
  on(root, 'DOMContentLoaded', () => raf(init))
1552
1645
  } else {
1553
1646
  raf(init)
1554
1647
  }
1555
1648
 
1649
+ // @ts-ignore
1556
1650
  return instance
1557
1651
  }