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/README.md +2 -2
- package/dist/dist.dev.js +204 -127
- package/dist/dist.js +189 -116
- package/dist/dist.min.js +1 -1
- package/package.json +3 -3
- package/src/index.js +255 -161
- package/types/index.d.ts +68 -29
- package/types/types.d.ts +67 -46
- package/src/types.js +0 -55
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
|
|
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 {
|
|
49
|
+
/** @type {any[]} */
|
|
49
50
|
_plugins = [],
|
|
50
|
-
/** @type {HTMLCanvasElement
|
|
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:
|
|
82
|
-
update:
|
|
83
|
-
draw:
|
|
84
|
-
resized:
|
|
85
|
-
tap:
|
|
86
|
-
untap:
|
|
87
|
-
tapping:
|
|
88
|
-
tapped:
|
|
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:
|
|
98
|
+
CANVAS: null,
|
|
109
99
|
|
|
110
100
|
/** @type {number} */
|
|
111
|
-
|
|
101
|
+
W: 0,
|
|
112
102
|
|
|
113
103
|
/** @type {number} */
|
|
114
|
-
|
|
104
|
+
H: 0,
|
|
115
105
|
|
|
116
106
|
/** @type {number} */
|
|
117
|
-
|
|
107
|
+
T: 0,
|
|
118
108
|
|
|
119
109
|
/** @type {number} */
|
|
120
|
-
|
|
110
|
+
CX: 0,
|
|
121
111
|
|
|
122
112
|
/** @type {number} */
|
|
123
|
-
|
|
113
|
+
CY: 0,
|
|
124
114
|
|
|
125
|
-
/** @type {number
|
|
126
|
-
|
|
115
|
+
/** @type {number} */
|
|
116
|
+
MX: -1,
|
|
127
117
|
|
|
128
|
-
/** @type {
|
|
129
|
-
|
|
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
|
-
*
|
|
347
|
-
*
|
|
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
|
-
|
|
353
|
+
rseed(value) {
|
|
353
354
|
DEV: assert(
|
|
354
355
|
null == value || (isNumber(value) && value >= 0),
|
|
355
|
-
'
|
|
356
|
+
'rseed: 1st param must be a positive number or zero'
|
|
356
357
|
)
|
|
357
358
|
|
|
358
|
-
|
|
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 =
|
|
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 {
|
|
656
|
-
* @param {
|
|
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
|
|
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
|
|
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
|
|
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 =
|
|
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 =
|
|
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 ||
|
|
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
|
-
*
|
|
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
|
-
|
|
1064
|
+
def(key, value) {
|
|
1080
1065
|
DEV: assert(
|
|
1081
1066
|
'string' === typeof key,
|
|
1082
|
-
'
|
|
1067
|
+
'def: 1st param must be a string'
|
|
1083
1068
|
)
|
|
1084
|
-
if (null == value) {
|
|
1085
|
-
console.warn(
|
|
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
|
|
1098
|
+
* Set the target FPS (frames per second).
|
|
1112
1099
|
*
|
|
1113
1100
|
* @param {number} value
|
|
1114
1101
|
*/
|
|
1115
|
-
|
|
1102
|
+
framerate(value) {
|
|
1116
1103
|
DEV: assert(
|
|
1117
1104
|
isNumber(value) && value >= 1,
|
|
1118
|
-
'
|
|
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
|
|
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
|
|
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(
|
|
1208
|
-
|
|
1209
|
-
|
|
1210
|
-
|
|
1211
|
-
|
|
1212
|
-
|
|
1213
|
-
|
|
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(
|
|
1218
|
-
|
|
1219
|
-
|
|
1220
|
-
|
|
1221
|
-
|
|
1222
|
-
|
|
1223
|
-
|
|
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(
|
|
1232
|
-
|
|
1281
|
+
on(
|
|
1282
|
+
_canvas,
|
|
1283
|
+
'mousemove',
|
|
1284
|
+
/**
|
|
1285
|
+
* @param {MouseEvent} ev
|
|
1286
|
+
*/
|
|
1287
|
+
(ev) => {
|
|
1288
|
+
preventDefault(ev)
|
|
1233
1289
|
|
|
1234
|
-
|
|
1235
|
-
|
|
1236
|
-
|
|
1290
|
+
const [x, y] = _getXY(ev.pageX, ev.pageY)
|
|
1291
|
+
instance.def('MX', x)
|
|
1292
|
+
instance.def('MY', y)
|
|
1237
1293
|
|
|
1238
|
-
|
|
1294
|
+
if (!_pressingMouse) return
|
|
1239
1295
|
|
|
1240
|
-
|
|
1241
|
-
|
|
1242
|
-
|
|
1296
|
+
instance.emit('tapping', x, y, 0)
|
|
1297
|
+
_updateTap(0, x, y)
|
|
1298
|
+
}
|
|
1299
|
+
)
|
|
1243
1300
|
|
|
1244
|
-
on(
|
|
1245
|
-
|
|
1246
|
-
|
|
1247
|
-
|
|
1248
|
-
|
|
1249
|
-
|
|
1250
|
-
|
|
1251
|
-
|
|
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(
|
|
1256
|
-
|
|
1257
|
-
|
|
1258
|
-
|
|
1259
|
-
|
|
1260
|
-
|
|
1261
|
-
|
|
1262
|
-
|
|
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.
|
|
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.
|
|
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.
|
|
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
|
-
|
|
1436
|
-
|
|
1437
|
-
|
|
1438
|
-
|
|
1439
|
-
|
|
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.
|
|
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)
|
|
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.
|
|
1481
|
-
instance.
|
|
1560
|
+
instance.def('W', (_canvas.width = width))
|
|
1561
|
+
instance.def('H', (_canvas.height = height))
|
|
1482
1562
|
|
|
1483
|
-
instance.
|
|
1484
|
-
instance.
|
|
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.
|
|
1494
|
-
root.innerHeight / instance.
|
|
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.
|
|
1499
|
-
_canvas.style.height = instance.
|
|
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
|
-
|
|
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.
|
|
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
|
}
|