kaplay 3000.1.17

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/CHANGELOG.md ADDED
@@ -0,0 +1,1050 @@
1
+ ### v3000.1.17
2
+ - exposed `vel` property on `BodyComp`
3
+
4
+ ### v3000.1.16
5
+ - fixed error not being logged
6
+ - fixed error screen scaling error in letterbox mode
7
+
8
+ ### v3000.1.15
9
+ - fixed `loadRoot()` not working sometimes
10
+ - fixed audio being resumed when the tab is switched on but `debug.paused` is true
11
+
12
+ ### v3000.1.12
13
+ - fixed `color()` and `rgb()` not working
14
+
15
+ ### v3000.1.11
16
+ - added option `kaboom({ focus: false })` to disable focus on start
17
+ - fixed `rand()` typing for numbers
18
+ - fixed mouse position in fullscreen
19
+ - added `Color#toHSL()`
20
+
21
+ ### v3000.1.10
22
+ - fixed test code accidentally getting shipped (where a screenshot will be downloaded every time you press space)
23
+
24
+ ### v3000.1.9
25
+ - added `fill` option to `rect()`, `circle()` and `sprite()`
26
+ - fixed view getting cut off in letterbox mode
27
+
28
+ ### v3000.1.8
29
+ - fixed `scale` option acting weird when width and height are defined (by @hirnsalat)
30
+
31
+ ### v3000.1.7
32
+ - fixed `debug.paused` not pausing audio
33
+ - added `mask()` component
34
+ - added support for colored font outline
35
+ ```js
36
+ loadFont("apl386", "/examples/fonts/apl386.ttf", {
37
+ outline: {
38
+ width: 8,
39
+ color: rgb(0, 0, 255),
40
+ },
41
+ })
42
+ ```
43
+ - fixed `wave()` not starting at `0` when time is `0`
44
+ - kaboom now only displays error screen for kaboom's own error, instead of catching all errors in current window
45
+ - added `KaboomError` class for errors related to current kaboom instance
46
+ - setting `obj.text` with `text()` component now immediately updates `width` and `height` property
47
+ ```js
48
+ const obj = add([
49
+ text("oh hi"),
50
+ pos(100, 200),
51
+ ])
52
+
53
+ // before
54
+ obj.text = "bye"
55
+ console.log(obj.width) // still the width of "oh hi" until next render
56
+
57
+ // before
58
+ obj.text = "bye"
59
+ console.log(obj.width) // will be updated to the width of "bye"
60
+ ```
61
+
62
+ ### v3000.1.6
63
+ - fixed `loadSound` typing to accept `ArrayBuffer`
64
+
65
+ ### v3000.1.5
66
+ - added `Event#clear()` method
67
+ - fixed `add()` without argument
68
+
69
+ ### v3000.1.4
70
+ - added `audio.stop()` method
71
+ ```js
72
+ const music = play("music")
73
+ music.stop()
74
+ ```
75
+
76
+ ### v3000.1.3
77
+
78
+ - fixed `onCollideUpdate()` still runs when object is paused
79
+ - allow `add()` and `make()` without arguments
80
+ - added `debug.numObjects()`
81
+ - added `width` and `height` properties to `SpriteData`
82
+ ```js
83
+ // get sprite size
84
+ getSprite("bean").then((spr) => {
85
+ console.log(spr.width, spr.height)
86
+ })
87
+ ```
88
+
89
+ ### v3000.1.2
90
+
91
+ - fixed audio not pausing when tab hidden and `backgroundAudio` not set
92
+ - fixed `debug.timeScale` not working
93
+ - fixed `debug.paused` not able to resume
94
+ - fixed `quad` option not working in `sprite()` component
95
+ - added `onHide()` and `onShow()` for tab visibility event
96
+
97
+ ### v3000.1.1
98
+
99
+ - fixed some indirect `fixed` related issues
100
+
101
+ ## v3000.1
102
+
103
+ - added game object level input handling
104
+
105
+ ```js
106
+ // add a scene game object
107
+ const scene = add([])
108
+
109
+ const bean = scene.add([
110
+ sprite("bean"),
111
+ pos(100, 200),
112
+ area(),
113
+ body(),
114
+ ])
115
+
116
+ scene.onKeyPress("space", () => {
117
+ bean.jump()
118
+ })
119
+
120
+ scene.onMousePress(() => {
121
+ bean.jump()
122
+ })
123
+
124
+ // setting scene.paused will pause all the input events
125
+ scene.paused = true
126
+
127
+ // destroying scene will cancel all its input events
128
+ scene.destroy()
129
+
130
+ const ui = add([])
131
+
132
+ ui.add(makeButton())
133
+
134
+ // these will only work if ui game object is active
135
+ ui.onMousePress(() => {
136
+ // ...
137
+ })
138
+
139
+ // before you'll have to manually clean up events on obj.onDestroy()
140
+ const scene = add([])
141
+ const evs = []
142
+ scene.onDestroy(() => {
143
+ evs.forEach((ev) => ev.cancel())
144
+ })
145
+ evs.push(k.onKeyPress("space", () => {
146
+ doSomeSceneSpecificStuff()
147
+ }))
148
+ ```
149
+
150
+ - added `make()` to create game object without adding to the scene
151
+ ```js
152
+ const obj = make([
153
+ sprite("bean"),
154
+ pos(120, 60),
155
+ ])
156
+
157
+ add(obj)
158
+ ```
159
+
160
+ - fixed children not inheriting `fixed()` from parent
161
+ ```js
162
+ // before
163
+ const ui = add([
164
+ fixed(),
165
+ ])
166
+
167
+ ui.add([
168
+ rect(),
169
+ // have to also give all children game objects fixed()
170
+ fixed(),
171
+ ])
172
+
173
+ // now
174
+ const ui = add([
175
+ fixed(),
176
+ ])
177
+
178
+ // you don't have to add fixed() to children
179
+ ui.add([
180
+ rect(100, 100),
181
+ ])
182
+ ```
183
+
184
+ - fixed `AreaComp#onClick()` event not getting cleaned up when game object is destroyed
185
+ - fixed typo `isTouchScreen()` -> `isTouchscreen()`
186
+ - fixed inspect mode doesn't show the properties box of indirect children game objects
187
+ - fixed some problem causing kaboom to not work with vite
188
+ - fixed "destroy" event not run on children game objects
189
+ - calling `shake()` when another shake is happening adds to the shake instead of reset it?
190
+ - fixed incorrect touch position when canvas is not at top left of page
191
+
192
+ # v3000
193
+
194
+ ## Game Objects
195
+
196
+ - added scene graph, game objects are now stored in a tree-like structure and can have children with `obj.add()`
197
+ ```js
198
+ const bean = add([
199
+ sprite("bean"),
200
+ pos(160, 120),
201
+ ])
202
+
203
+ const sword = bean.add([
204
+ sprite("sword"),
205
+ // transforms will be relative to parent bean object
206
+ pos(20, 20),
207
+ rotate(20),
208
+ ])
209
+
210
+ const hat = bean.add([
211
+ sprite("hat"),
212
+ // transforms will be relative to parent bean object
213
+ pos(0, -10),
214
+ ])
215
+
216
+ // children will be moved alongside the parent
217
+ bean.moveBy(100, 200)
218
+
219
+ // children will be destroyed alongside the parent
220
+ bean.destroy()
221
+ ```
222
+ - added `recursive` and `liveUpdate` options to `get()`
223
+ ```js
224
+ const enemies = get("enemy", {
225
+ // get from all children and descendants, instead of only direct children
226
+ recursive: true,
227
+ // live update the returned list to listen to onAdd and onDestroy events
228
+ liveUpdate: true,
229
+ })
230
+
231
+ console.log(enemies.length) // 3
232
+
233
+ add([
234
+ sprite("bigbird"),
235
+ "enemy",
236
+ ])
237
+
238
+ console.log(enemies.length) // 4
239
+ ```
240
+ - changed object update order from reversed to not reversed
241
+ - (**BREAK**) removed `GameObj#every()` and `GameObj#revery()` in favor of `obj.get("*").forEach()`
242
+ - (**BREAK**) renamed `GameObj#_id` to `GameObj#id`
243
+ - `addLevel()` now returns a `GameObj` which has all individual grid objects as its children game objects, with `LevelComp` containing its previous methods
244
+ - added `onAdd()` and `onDestroy()` events to listen to added / destroyed game objects
245
+
246
+ ## Components
247
+
248
+ - added support for getter and setters in component properties
249
+
250
+ #### Area
251
+
252
+ - added collision support for rotate shapes and polygons
253
+ - added option `collisionIgnore` to `area()` component, which accepts a list of tags to ignore when checking collision
254
+ ```js
255
+ const bean = add([
256
+ sprite("bean"),
257
+ pos(100, 80),
258
+ area({
259
+ collisionIgnore: [ "cloud", "particle" ],
260
+ }),
261
+ ])
262
+ ```
263
+ - added `Area#getCollisions` to get a list of all current collisions happening
264
+ ```js
265
+ for (const col of player.getCollisions()) {
266
+ const c = col.target
267
+ if (c.is("chest")) {
268
+ c.open()
269
+ }
270
+ }
271
+ ```
272
+ - added `Area#onCollideUpdate()` and `onCollideUpdate()` to register an event that runs every frame when 2 object is colising
273
+ - added `Area#onCollideEnd()` and `onCollideEnd()` to register an event that runs once when 2 objects stopped colliding
274
+ - added `Area#onHover()` and `onHover()` to register an event that runs once when an object(s) is hovered
275
+ - added `Area#onHoverEnd()` and `onHoverEnd()` to register an event that runs once when an object(s) stopped being hovered
276
+ - (**BREAK**) renamed `onHover()` to `onHoverUpdate()` (it registers an event that runs every frame when an object is hovered)
277
+ - (**BREAK**) renamed `pushOut()` to `resolveCollision()`
278
+
279
+ #### Body
280
+
281
+ - added `Body#onFall()` which fires when object starts falling
282
+ - added `Body#onPhysicsResolve()` and `Body#onBeforePhysicsResolve()` to register events relating to collision resolution
283
+ ```js
284
+ // make semi-solid platforms that doesn't block player when player is jumping over it
285
+ player.onBeforePhysicsResolve((collision) => {
286
+ if (collision.target.is(["platform", "soft"]) && player.isJumping()) {
287
+ collision.preventResolution()
288
+ }
289
+ })
290
+ ```
291
+ - (**BREAK**) removed `solid()` in favor of `body({ isStatic: true })`
292
+ - added option `body({ mass: 3 })` to define how hard a non-static body is to be pushed by another non-static body
293
+ - added option `body({ stickToPlatform: false })` to turn off object moving with platform
294
+ - (**BREAK**) removed `Body#doubleJump()` in favor of `doubleJump()` component
295
+ - (**BREAK**) renamed `Body#weight` to `Body#gravityScale`
296
+ - (**BREAK**) renamed `Body#onFall()` to `Body#onFallOff()` which triggers when object fall off a platform
297
+ - (**BREAK**) defining `setGravity()` is now required for enabling gravity, `body()` by default will only prevent objects from going through each other
298
+
299
+ #### Others
300
+
301
+ - (**BREAK**) renamed `origin()` to `anchor()`, so it won't mess up typescript in global mode
302
+ - (**BREAK**) `anchor` (previously `origin`) no longer controls text alignment, use `text({ align: "left" })` option instead
303
+ - added `doubleJump()` component to enable double jump (or any number of jumps)
304
+ - (**BREAK**) renamed `outview()` to `offscreen()`, and uses a much faster check (but less accurate) for if object is offscreen
305
+ - removed `offset` option in favor of a simpler `distance` option
306
+ - renamed `onExitView()` and `onEnterView()` to `onExitScreen()` and `onEnterScreen()`
307
+ - (**BREAK**) removed `cleanup()` component in favor of `offscreen({ destroy: true })`
308
+ - added `OpacityComp#fadeOut()`
309
+ - added `fadeIn()` component
310
+ - `stay()` now accepts a list of scenes to stay for, like `stay(["gameover", "menu"])`
311
+ - (**BREAK**) changed `SpriteComp#flipX` and `SpriteComp#flipY` to properties instead of functions
312
+ - (**BEARK**) `sprite.onAnimStart()` and `sprite.onAnimEnd()` now triggers on any animation
313
+ ```js
314
+ // before
315
+ obj.onAnimEnd("walk", () => {
316
+ // do something
317
+ })
318
+
319
+ // v3000
320
+ obj.onAnimEnd((anim) => {
321
+ if (anim === "walk") {
322
+ // do something
323
+ }
324
+ })
325
+ ```
326
+ - (**BREAK**) `ScaleComp#scale` will always be a `Vec2` not `number`
327
+ - `shader()` comp `uniform` parameter now supports a callback that returns the uniform every frame
328
+ ```js
329
+ const player = add([
330
+ sprite("bean"),
331
+ // will calculate and send u_time every frame
332
+ shader("flashy", () => ({
333
+ "u_time": time(),
334
+ })),
335
+ ])
336
+ ```
337
+
338
+ ## Assets
339
+
340
+ - added `loadProgress()` that returns a `0.0 - 1.0` that indicates current asset loading progress
341
+ - added option `loadingScreen` to `kaboom()` where you can turn off the default loading screen
342
+ - added `onLoadUpdate()` to register a custom loading screen (see "loader" example)
343
+ ```js
344
+ // custom loading screen
345
+ onLoadUpdate((progress) => {
346
+ drawCircle({
347
+ pos: center(),
348
+ radius: 32,
349
+ end: map(progress, 0, 1, 0, 360),
350
+ })
351
+ })
352
+ ```
353
+ - added support for multiple sprite sources as frames in `loadSprite()`
354
+ ```js
355
+ loadSprite("player", [
356
+ "sprites/player_idle.png",
357
+ "sprites/player_run.png",
358
+ "sprites/player_jump.png",
359
+ ])
360
+ ```
361
+ - (**BREAK**) added `loadShaderURL()`, `loadShader()` now only load shader code not files
362
+
363
+ ## Text
364
+
365
+ - added `loadFont()` to load `.ttf`, `.otf`, `.woff2` or any font supported by browser `FontFace`
366
+ ```js
367
+ // Load a custom font from a .ttf file
368
+ loadFont("FlowerSketches", "/examples/fonts/FlowerSketches.ttf")
369
+
370
+ // Load a custom font with options
371
+ loadFont("apl386", "/examples/fonts/apl386.ttf", { outline: 4, filter: "linear" })
372
+ ```
373
+ - (**BREAK**) renamed previous `loadFont()` to `loadBitmapFont()`
374
+ - (**BREAK**) removed built-in `apl386`, `apl386o`, `sink`, `sinko` (still available under `examples/fonts`)
375
+ - changed default font size to `36`
376
+ - (**BREAK**) changed to bbcode syntax for styled text
377
+ ```js
378
+ // before
379
+ "[oh hi].green here's some [styled].wavy text"
380
+ // v3000
381
+ "[green]oh hi[/green] here's some [wavy]styled[/wavy] text"
382
+ ```
383
+
384
+ ## Graphics
385
+
386
+ - fixed visual artifacts on text rendering
387
+ - added `colors` option to `drawPolygon()` that controls the color of each corner
388
+ - added `gradient` option to `drawRect()` that specifies the start and end color
389
+ - added `drawMasked()` and `drawSubtracted()`
390
+ - added `pushRotateX()`, `pushRotateY()` and `pushRotateZ()`
391
+ - added `pixelDensity` option to `kaboom()`
392
+ - (**BREAK**) changed position vertex format from `vec3` to `vec2` (which is passed in as the first argument of custom `frag` and `vert` shader functions)
393
+ - added `usePostEffect()` to add post process shader
394
+ ```js
395
+ loadShader("invert", null, `
396
+ vec4 frag(vec2 pos, vec2 uv, vec4 color, sampler2D tex) {
397
+ vec4 c = def_frag();
398
+ return vec4(1.0 - c.r, 1.0 - c.g, 1.0 - c.b, c.a);
399
+ }
400
+ `)
401
+
402
+ usePostEffect("invert")
403
+ ```
404
+ - shader error logs now yields the correct line number
405
+ - added `slice9` option to `loadSprite()` to enable [9 slice scaling](https://en.wikipedia.org/wiki/9-slice_scaling)
406
+ ```js
407
+ loadSprite("grass", "/sprites/grass.png", {
408
+ slice9: {
409
+ left: 8,
410
+ right: 8,
411
+ top: 8,
412
+ bottom: 8,
413
+ },
414
+ })
415
+
416
+ const g = add([
417
+ sprite("grass"),
418
+ ])
419
+
420
+ onMouseMove(() => {
421
+ const mpos = mousePos()
422
+ // updating width / height will scale the image but not the sliced frame
423
+ g.width = mpos.x
424
+ g.height = mpos.y
425
+ })
426
+ ```
427
+
428
+ ## Audio
429
+
430
+ - added option `kaboom({ backgroundAudio: false })` to not pause audio when tab not active
431
+ - changed `speed`, `detune`, `volume`, `loop` in `AudioPlay` from functions to properties
432
+ - added `onEnd()` event for `const pb = play("sound")`
433
+ ```js
434
+ // before
435
+ const music = play("song")
436
+ music.speed(2)
437
+ music.volume(0.5)
438
+ music.loop(true)
439
+
440
+ // v3000
441
+ const music = play("song")
442
+ music.speed = 2
443
+ music.volume = 0.5
444
+ music.loop = true
445
+ ```
446
+
447
+ ## Input
448
+
449
+ - added `onScroll(action: (delta: Vec2) => void)` to listen mouse wheel scroll
450
+ - fixed touches not treated as mouse
451
+ - (**BREAK**) changed `onTouchStart()`, `onTouchMove()` and `onTouchEnd()` callback signature to `(pos: Vec2, touch: Touch) => void` (exposes the native `Touch` object)
452
+ - added `onGamepadButtonPress()`, `onGamepadButtonDown()`, `onGamepadButtonRelease()`
453
+ - added `isGamepadButtonPressed()`, `isGamepadButtonDown()`, `isGamepadButtonReleased()`
454
+ - added `onGamepadStick()` to handle gamepad axes info for left and right sticks
455
+ - added `getConnectedGamepads()`
456
+ - added `onGamepadConnect()` and `onGamepadDisconnect()`
457
+ - added `gamepads` option to `kaboom()` to define custom gamepads
458
+
459
+
460
+ ## Level
461
+
462
+ - (**BREAK**) changed `addLevel()` options API
463
+ - renamed `width` and `height` to `tileWidth` and `tileHeight`
464
+ - renamed `any` to `wildcardTile`
465
+ - now all tile symbols are defined in the `tiles` object
466
+
467
+ ```js
468
+ // before
469
+ addLevel([
470
+ "@ ^ $$",
471
+ "=======",
472
+ ], {
473
+ width: 32,
474
+ height: 32,
475
+ "=": () => [
476
+ sprite("grass"),
477
+ area(),
478
+ body({ isStatic: true }),
479
+ ],
480
+ "$": () => [
481
+ sprite("coin"),
482
+ area(),
483
+ "coin",
484
+ ],
485
+ any: (symbol) => {
486
+ if (symbol === "@") {
487
+ return [ /* ... */ ]
488
+ }
489
+ },
490
+ })
491
+
492
+ // v3000
493
+ addLevel([
494
+ "@ ^ $$",
495
+ "=======",
496
+ ], {
497
+ tileWidth: 32,
498
+ tileHeight: 32,
499
+ tiles: {
500
+ "=": () => [
501
+ sprite("grass"),
502
+ area(),
503
+ body({ isStatic: true }),
504
+ ],
505
+ "$": () => [
506
+ sprite("coin"),
507
+ area(),
508
+ "coin",
509
+ ],
510
+ },
511
+ wildcardTile: (symbol) => {
512
+ if (symbol === "@") {
513
+ return [ /* ... */ ]
514
+ }
515
+ },
516
+ })
517
+ ```
518
+
519
+ ## Misc
520
+
521
+ - sprites are now automatically packed, improving performance
522
+ - (**BREAK**) renamed `gravity()` into `getGravity()` and `setGravity()`
523
+ - (**BREAK**) removed all deprecated functions in v2000.2
524
+ - (**BREAK**) raised esbuild target to `esnext`
525
+ - added `setBackground()` and `getBackground()` in addition to `background` option in `kaboom()`
526
+ - moved type defs for global functions to `import "kaboom/global"`
527
+
528
+ ```js
529
+ // if use global functions
530
+ import "kaboom"
531
+ import "kaboom/global" // required to load global types
532
+
533
+ kaboom()
534
+
535
+ // will have definition
536
+ add()
537
+ ```
538
+ ```js
539
+ // if don't use global function
540
+ import "kaboom"
541
+
542
+ kaboom({ global: false })
543
+
544
+ // type error, won't pollute global namespace if not manually import "kaboom/global"
545
+ add()
546
+ ```
547
+
548
+ - added `tween()` for tweening, and a set of built-in easing functions in `easings`
549
+
550
+ ```js
551
+ onMousePress(() => {
552
+ tween(bean.pos.x, mousePos().x, 1, (val) => bean.pos.x = val, easings.easeOutBounce)
553
+ tween(bean.pos.y, mousePos().y, 1, (val) => bean.pos.y = val, easings.easeOutBounce)
554
+ })
555
+ ```
556
+
557
+ - (**BREAK**) changed all event handlers to return a `EventController` object instead of a function to cancel event
558
+
559
+ ```js
560
+ // before
561
+ const cancel = onUpdate(() => { /* ... */ })
562
+ cancel()
563
+
564
+ // v3000
565
+ const ev = onUpdate(() => { /* ... */ })
566
+ ev.paused = true
567
+ ev.cancel()
568
+ ```
569
+
570
+ - timers can now be paused
571
+
572
+ ```js
573
+ const timer = wait(4, () => { /* ... */ })
574
+ timer.paused = true
575
+ timer.resume()
576
+
577
+ const timer = loop(1, () => { /* ... */ })
578
+ timer.paused = true
579
+ timer.resume()
580
+ ```
581
+
582
+ - `kaboom()` now automatically focuses the canvas
583
+ - added `quit()` to end everything
584
+ - added `download()`, `downloadText()`, `downloadJSON()`, `downloadBlob()`
585
+ - added `Recording#stop()` to stop the recording and returns the video data as mp4 Blob
586
+ - added `debug.numFrames()` to get the total number of frames elapsed
587
+ - added `onError()` to handle error or even custom error screen
588
+ - added `onResize()` to register an event that runs when canvas resizes
589
+ - added `setCursorLocked()` and `isCursorLocked()`
590
+ - (**BREAK**) renamed `cursor()` to `setCursor()`
591
+ - (**BREAK**) renamed `fullscreen()` to `setFullscreen()`
592
+ - (**BREAK**) renamed `isTouch()` to `isTouchscreen()`
593
+ - (**BREAK**) removed `layers()` in favor of parent game objects (see "layers" example)
594
+ - (**BREAK**) removed `load()` event for components, use `onLoad()` in `add()` event
595
+ - (**BREAK**) removed `debug.objCount()` in favor of `getAll().length`
596
+ - added `debug.numFrames()` to get the current frame count
597
+
598
+ ### v2000.2.6
599
+
600
+ - fixed text always being wrapped if updated
601
+ - fixed text comp properties `letterSpacing`, `charSpacing`, `transform`, `styles` not being exposed
602
+
603
+ ### v2000.2.5
604
+
605
+ - fixed updating `font` property on gameobj not updating the text font
606
+
607
+ ### v2000.2.4
608
+
609
+ - fixed `focus()` not properly exported
610
+ - deprecated `focus()` in favor of `canvas.focus()` due to name collision
611
+
612
+ ### v2000.2.3
613
+
614
+ - fixed `kaboom.d.ts` completely messed up
615
+
616
+ ### v2000.2.2
617
+
618
+ - fixed doc for `TextCompOpt#styles` and `DrawTextOpt#styles`
619
+
620
+ ### v2000.2.1
621
+
622
+ - fixed updates not running at all when `kaboom({ debug: false })`
623
+
624
+ ## v2000.2 "Fancy Text Mode"
625
+
626
+ - added `formatText()` and `drawFormattedText()`
627
+ - added `charSpacing` and `lineSpacing` in `TextCompOpt` and `DrawTextOpt`
628
+ - added optional `transitions` argument in `state()` to define allowed transitions
629
+ - added `StateComp#onStateTransition` to register event for specific transitions
630
+ - added syntax to style a piece of text `"this is a [styled].wavy text"` and `style` option in `TextCompOpt` and `DrawTextOpt` to define the styles with `CharTransformFunc`
631
+ - deprecated `dir()` in favor of `Vec2.fromAngle()`
632
+ - fixed `onTouchEnd()` fired on `touchmove`
633
+ - added `outview()` component to control behavior when object leaves visible area
634
+ - deprecated `cleanup(delay?: number)` in favor of `cleanup(opt?: CleanupOpt)`
635
+ - deprecated `mouseWorldPos()` in favor of `toWorld(mousePos())`
636
+ - deprecated `rng()` in favor of `new RNG()`
637
+ - added classes `Vec2`, `Color`, `Mat4`, `Timer`, `Quad`, `RNG`, `Line`, `Rect`, `Circle`
638
+ - added deprecation warning
639
+ - fixed letterbox view mode
640
+ - allow non-stretch letterbox
641
+ - fixed mouse position malfunction in fullscreen, stretch and letterbox mode
642
+
643
+ ### v2000.1.8
644
+
645
+ - fixed `Color#eq()` not giving correct result
646
+
647
+ ### v2000.1.7
648
+
649
+ - fixed not having export if installed from github repo with npm
650
+ - fixed event canceller returned by raw `onUpdate()` and `onDraw()` crashing
651
+
652
+ ### v2000.1.6
653
+
654
+ - fixed debug widget scale
655
+
656
+ ### v2000.1.5
657
+
658
+ - fixed `enterState()` not passing args to `onStateEnter()` callback
659
+
660
+ ### v2000.1.4
661
+
662
+ - fixed `state()` to not require registering `onStateUpdate()` before using any state
663
+
664
+ ### v2000.1.2
665
+
666
+ - fixed `onKeyRelease()` wrongfully check for key press instead of release
667
+
668
+ ### v2000.1.1
669
+
670
+ - fixed `StateComp#enterState()` not accepting any state
671
+
672
+ ## v2000.1 "Record Mode"
673
+
674
+ - added `hsl2rgb()` for converting HSL color to kaboom RGB
675
+ - added `record()` to start a screen recording
676
+ - added F5 to screenshot and F6 to toggle record mode in debug mode
677
+ - added `DrawTextOpt#transform()` and `TextCompOpt#transform()` for defining style and transformation for each character
678
+ - added `state()` component for finite state machine
679
+ - added support for multiple tags in `get()` and `every()`
680
+ - added UI indicator for `debug.paused` and `debug.timeScale`
681
+ - changed inspect mode UI style
682
+ - added color constants `WHITE`, `BLACK`, `BLUE`, `GREEN`, `RED`, `MAGENTA`, `CYAN`, `YELLOW`
683
+ - added new API style (`on` prefix for all event handler function, `is` prefix for all boolean state getters)
684
+ - `onLoad()`
685
+ - `onUpdate()`
686
+ - `onDraw()`
687
+ - `onKeyPress()`
688
+ - `onKeyPressRepeat()`
689
+ - `onKeyDown()`
690
+ - `onKeyRelease()`
691
+ - `onMousePress()`
692
+ - `onMouseDown()`
693
+ - `onMouseRelease()`
694
+ - `onMoueMove()`
695
+ - `onTouchStart()`
696
+ - `onTouchMove()`
697
+ - `onTouchEnd()`
698
+ - `onCollide()`
699
+ - `onClick()`
700
+ - `onHover()`
701
+ - `isFocused()`
702
+ - `isKeyDown()`
703
+ - `isKeyPressed()`
704
+ - `isKeyPressedRepeat()`
705
+ - `isKeyDown()`
706
+ - `isMouseDown()`
707
+ - `isMousePressed()`
708
+ - `isMouseReleased()`
709
+ - `isMouseMoved()`
710
+ - `isMouseMoved()`
711
+ - `GameObj#onUpdate()`
712
+ - `GameObj#onDraw()`
713
+ - `AreaComp#onCollide()`
714
+ - `AreaComp#onHover()`
715
+ - `AreaComp#onClick()`
716
+ - `BodyComp#onGround()`
717
+ - `BodyComp#onFall()`
718
+ - `BodyComp#onHeadbutt()`
719
+ - `BodyComp#onDoubleJump()`
720
+ - `BodyComp#isGrounded()`
721
+ - `BodyComp#isFalling()`
722
+ - `SpriteComp#onAnimEnd()`
723
+ - `SpriteComp#onAnimStart()`
724
+ - `HealthComp#onDeath()`
725
+ - `HealthComp#onHurt()`
726
+ - `HealthComp#onHeal()`
727
+ - `AudioPlay#isStopped()`
728
+ - `AudioPlay#isPaused()`
729
+
730
+ # v2000 "Burp Mode"
731
+ - version jumped to v2000.0.0 (still semver, just big)
732
+ - added `burp()` for easy burping
733
+ - added decent typescript / autocomplete support and jsdocs
734
+ - introducing new character "bean"
735
+ ![bean](assets/sprites/bean.png)
736
+ - added `loadBean()` to load `"bean"` as a default sprite
737
+ - changed default font to [APL386](https://abrudz.github.io/APL386/), as `"apl386o"` (default outlined version) and `"apl386"`
738
+ - included font [kitchen sink](https://polyducks.itch.io/kitchen-sink-textmode-font) as `"sinko"` (outlined version) and `"sink"` (standard version with extended characters for text-mode games)
739
+ - added `font` field in `KaboomOpt` to set the default font
740
+ - added `loadSpriteAtlas(src, entries)` to load sprite atlas
741
+ - inspect mode now displays every comp's state
742
+ - **BREAK** added continuous collision resolution which checks collision in `move()` if 2 objects are both "solid" (objects now won't pass through other solid object at high speed or low framerate)
743
+
744
+ ```js
745
+ // before
746
+ add([
747
+ sprite("player"),
748
+ area(),
749
+ ]);
750
+
751
+ add([
752
+ sprite("rock"),
753
+ solid(),
754
+ ]);
755
+
756
+ keyDown("left", () => {
757
+ player.move(-120, 0);
758
+ });
759
+
760
+ player.action(() => {
761
+ player.resolve(); // or pushOutAll() in beta versions
762
+ });
763
+
764
+ // after
765
+ const player = add([
766
+ sprite("player"),
767
+ area(),
768
+ solid(),
769
+ ]);
770
+
771
+ // both should be solid
772
+ add([
773
+ sprite("rock"),
774
+ area(),
775
+ solid(),
776
+ ]);
777
+
778
+ keyDown("left", () => {
779
+ // this will handle collision resolution for you, if the other obj is also "solid"
780
+ player.move(-120, 0);
781
+ });
782
+ ```
783
+ - added comp `opacity()` to set opacity
784
+ - added comp `health()` to manage health related logic
785
+ - added comp `move()` to manage projectile-like behavior
786
+ - added comp `cleanup()` to auto destroy obj when it leaves screen
787
+ - added comp `outline()` to draw a lil outline
788
+ - added comp `timer()` to attach timers to a game obj
789
+ - added comp `fixed()` to make a game obj unaffected by camera
790
+ - added comp `stay()` to make a game obj stay after scene switch
791
+ - added comp `lifespan()` to destroy game obj after certain amount of time
792
+ - added comp `z()` to define draw order for objs on the same layer
793
+ - added `weight` to `BodyComp` and `BodyCompOpt` to control the gravity multiplier
794
+ - added `djump()` to `BodyComp` for double jump
795
+ - added `dir()` to calculate directional vector from angle
796
+ - added constants `LEFT`, `RIGHT`, `UP`, `DOWN` for unit directional vector
797
+ - added `fullscreen()` to enable real fullscreen mode
798
+ - **BREAK** separated color and opacity, removed `rgba()` in favor of `rgb`, use component `opacity()` to define opacity
799
+ - **BREAK** changed color from 0-1 range to 0-255, angles from radians to degrees
800
+
801
+ ```js
802
+ // before
803
+ add([
804
+ rotate(Math.PI / 2),
805
+ color(0, 0.5, 1.0, 0.5),
806
+ ]);
807
+
808
+ // after
809
+ add([
810
+ rotate(90),
811
+ color(0, 127, 255),
812
+ opacity(0.5)
813
+ ]);
814
+ ```
815
+ - `global` and `debug` flag now are enabled by default, need to turn off manually if you don't want
816
+ - added input events `touchStart(id, pos)`, `touchMove(id, pos)`, `touchEnd(id, pos)`, `mouseMove(pos)`
817
+ - added `mouseDeltaPos()`
818
+ - added `touchToMouse` to control if touch events should be translated to mouse events
819
+ - added `mousePos()` now gets the screen mouse pos, use `mouseWorldPos()` to get the mouse position affected by camera
820
+ - added `anim` field in `SpriteCompOpt` to play an anim on start
821
+ - beter type support for components
822
+ - `scene()` and `start()` (also removed in favor of `go()`) are optional now, if you don't need multiple scenes yet you can just go directly
823
+ ```js
824
+ kaboom();
825
+ // no mandatory scene() to start kabooming
826
+ add(...);
827
+ keyPress(...);
828
+ ```
829
+ - **BREAK** `area()` is now explicit and not automatically added by `sprite()`, `rect()`, and `text()`, removed each `noArea` or `area` config field
830
+ - **BREAK** `area()` now takes an `AreaCompOpt`, where you can define the area size, scale, and hover cursor
831
+
832
+ ```js
833
+ add([
834
+ sprite("bean"),
835
+ area(), // empty area will derive from sprite size
836
+ area({ scale: 0.5, }), // 0.5x the sprite size
837
+ area({ offset: vec2(0, 12), width: 4, height: 12, }), // more control over the collider region
838
+ ]);
839
+ ```
840
+ - **BREAK** renamed `isCollided()` to `isColliding()`, `isHovered()` to `isHovering()`
841
+ - **BREAK** removed `overlaps()` and `isOverlapped()` and replaced with `isColliding()` and `collides()` only checks doesn't return true when 2 objects are just touching each other, use `isTouching()` to check if they're not colliding but just touching each other
842
+ - added `isTouching()` to check if 2 objects are collided or just touching other
843
+ - audio is now paused when you leave the tab
844
+ - audio is now paused on `debug.paused = true`
845
+ - added local storage helper `getData(key, default?)` and `setData(key, data)`
846
+ - added `loadShader(id, vert, frag, isUrl)`
847
+ - added `shader()` comp for attaching custom shader to an obj
848
+ - different layers do not prevent collisions now
849
+ - **BREAK** changed last argument of `loadFont()` to `FontLoadOpt`
850
+ - all event handlers like `keyPress()`, `mouseClick()`, `action()`, `collides()` now returns a function to cancel that listener
851
+ - added `require` on component definitions, making it possible to declare dependencies for components, e.g.
852
+ ```js
853
+ function alwaysRight() {
854
+ return {
855
+ // the id of this component
856
+ id: "alwaysRight",
857
+ // list of component ids that this requires
858
+ require: [ "pos", ],
859
+ update() {
860
+ // so you can use `move()` from pos() component with no worry
861
+ this.move(100, 0);
862
+ },
863
+ };
864
+ }
865
+ ```
866
+ - **BREAK** overlapping component fields are not allowed, e.g. you can't have a custom comp that has a `collides` field if it already have a `area` component, since it already has that
867
+ - **BREAK** changed `text(txt, size, conf)` to `text(txt, conf)` with `size` as a field
868
+ - added `obj.c(id)` for getting a specific comp's state (by default all comps' states are mounted to the obj by `Object.defineProperty`)
869
+ ```js
870
+ // both works
871
+ obj.play("anim");
872
+ obj.c("sprite").play("anim");
873
+ ```
874
+ - pedit, aseprite plugins are now included by default
875
+ - added `addKaboom()` for quick kaboom explosion
876
+ - `load*()` now accepts `null` as name and not load into assets manager, instead just return the resource data handle
877
+ - **BREAK** renamed event `headbump` to `headbutt`
878
+ - **BREAK** renamed event `grounded` to `ground`
879
+ - added `width`, `height`, and `tiled` attrib to `SpriteCompOpt`, for better control over sprite size and tiled sprite support
880
+ - **BREAK** renamed `resolve()` to `pushOutAll()` on `area` comp
881
+ - added `pushOut()` for pushing a single object out from another with `area` comp
882
+ - fixed `"add"` event getting called twice for tagged objs
883
+ - added `moveTo(dest: Vec2, speed?: number)` to `pos()` comp
884
+ - added `keyPress()` (and all other key events) with no arg to check for any key
885
+ - **BREAK** renamed `camShake()` to `shake()`
886
+ - added `flipX` and `flipY` on `sprite()` comp configuration, and `flipX()` `flipY()` methods
887
+ - **BREAK** remove `flipX()` and `flipY()` on `scale()` comp
888
+ - **BREAK** removed `start()` in favor of `go()`
889
+ - **BREAK** removed `changeSprite()` in favor of `use(sprite("newsprite"))`
890
+ - tags and components are converged, tags are just empty components now
891
+ - added `unuse()` to remove a component or tag
892
+ - **BREAK** removed `rmTag()` in favor of `unuse()`
893
+ - **BREAK** removed `camIgnore()` in favor of `fixed()`
894
+ - **BREAK** renamed `makeRng()` to `rng()`
895
+ - sprite animation now supports defining properties like loop and speed in load step and play step
896
+
897
+ ```js
898
+ loadSprite("hero", "hero.png", {
899
+ sliceX: 9,
900
+ anims: {
901
+ idle: { from: 0, to: 3, speed: 3, loop: true },
902
+ run: { from: 4, to: 7, speed: 10, loop: true },
903
+ hit: 8,
904
+ },
905
+ });
906
+ ```
907
+ - **BREAK** changed `.play(anim, ifLoop)` under `sprite()` to accept a dict of properties `.play(anim, { loop: true, speed: 60, pingpong: true })`
908
+ - **BREAK** now every symbol definition in `addLevel()` should be a function returning the component list, to ensure there's no weird shared states
909
+
910
+ ```js
911
+ addLevel([
912
+ "* *",
913
+ "* *",
914
+ "======",
915
+ ], {
916
+ "*": () => [
917
+ sprite("wall"),
918
+ area(),
919
+ solid(),
920
+ ],
921
+ "=": () => [
922
+ sprite("floor"),
923
+ area(),
924
+ solid(),
925
+ ],
926
+ })
927
+ ```
928
+ - **BREAK** renamed `clearColor` to `background`
929
+ - added collision detection functions `testLineLine()`, `testRectRect()`, `testRectLine()` etc.
930
+ - added drawing functions `drawSprite()`, `drawRect()`, `drawCircle()`, `drawPolygon()`, `drawEllipse()`, `drawLine()`, `drawLines()`
931
+ - added transformation functions `pushTransform()`, `popTransform()`, `pushTranslate()`, `pushRotate()`, `pushScale()`
932
+ - **BREAK** removed `areaWidth()` and `areaHeight()` since they won't make sense if the area shape is not rectangle, use `worldArea()` if you need area data
933
+ ```js
934
+ const area = player.worldArea();
935
+ if (area.shape === "rect") {
936
+ const width = area.p2.x - area.p1.x;
937
+ const height = area.p2.y - area.p1.y;
938
+ }
939
+ ```
940
+
941
+ ### v0.5.1
942
+ - added plugins npm package support e.g. `import asepritePlugin from "kaboom/plugins/aseprite"`
943
+
944
+ # v0.5 "Sticky Type"
945
+ - platforms are now sticky
946
+ - moved to TypeScript
947
+ - improved graphics performance
948
+ - improved inspect drawing performance
949
+ - added on-screen log that catches all kinds of errors
950
+ - added `cursor()`
951
+ - added `curPlatform()` by `body()`
952
+ - added `falling()` by `body()`
953
+ - added `changeSprite()` by `sprite()`
954
+ - added `duration()` and `time()` for the handle returned by `play()`
955
+ - added optional `seek` field to the audio play conf `play([conf])`
956
+ - added `LoopHandle` returned by `loop()` that has a `stop()`
957
+ - added a default background (can be dismissed by setting `clearColor`)
958
+ - fixed `sound.pause()` to work on firefox
959
+ - fixed collisions not treating explicit default layer the same as implicit default layer
960
+ - fixed unable to play another anim in `onAnimEnd()`
961
+ - fixed scene switches happen in the middle of a frame
962
+ - fixed `scale(0)` not working
963
+ - fixed `mosuePos()` not returning the camera affected pos with no layers
964
+ - **BREAK** changed `dbg()` to plain `debug` object
965
+ - **BREAK** moved `fps()`, `objCount()`, `stepFrame()`, `log()`, `error()` under `debug`
966
+ - **BREAK** removed `debug.logTime`
967
+ - **BREAK** changed component `debugInfo()` hook to `inspect()`
968
+ - **BREAK** removed `timer()` component
969
+ - **BREAK** renamed `removeTag()` to `rmTag()`
970
+ - **BREAK** changed `SpriteAnim` from `[ from, to ]` to `{ from: number, to: number }`
971
+ - **BREAK** removed `onAnimPlay()` and `onAnimEnd()` in favor of generic event `on("animEnd", (anim: string) => {})`
972
+ - **BREAK** removed `obj.addTag()` in favor of `obj.use()`
973
+ - **BREAK** merged `debug.hoverInfo` and `debug.showArea` into `debug.inspect`
974
+ - **BREAK** removed `sound.resume()` in favor of `sound.play()`
975
+
976
+ ### v0.4.1
977
+ - fixed `on("destroy")` handler getting called twice
978
+ - fixed sprite `play()` not playing
979
+
980
+ # v0.4 "Multiboom"
981
+ - **BREAK** removed `init()` and `kaboom.global()`, in favor of `kaboom()`, also allows multiple kaboom games on one page
982
+ ```js
983
+ // replaces init(), and added a 'global' flag for previous kaboom.global()
984
+ kaboom({
985
+ global: true,
986
+ width: 480,
987
+ height: 480,
988
+ });
989
+ ```
990
+ or not global
991
+ ```js
992
+ const k = kaboom();
993
+ k.scene();
994
+ k.start();
995
+ k.vec2();
996
+ ```
997
+ - **BREAK** changed `clearColor` on `kaboom(conf)` to accept a 4 number array instead of `rgba()`
998
+ - added a plugin system, see the `multiboom` example and `src/plugins`
999
+ - **BREAK** removed support for `.kbmsprite`, supports newer version of `.pedit` through pedit plugin
1000
+ - **BREAK** `loadAseprite()` and made it an external plugin under `plugins/aseprite.js`
1001
+ - added `sceneData()` for custom scene data kv store
1002
+ - fixed `mouseClick` doesn't work on mobile
1003
+ - disabled context menu on canvas
1004
+ - prevented default behavior for 'tab' and function keys
1005
+ - added `numFrames()` by `sprite()`
1006
+ - added `screenshot()` that returns of a png base64 data url for a screenshot
1007
+
1008
+ # v0.3 "King Dedede...Bug!"
1009
+ - **BREAK** removed `pause()` and `paused()` in favor to `kaboom.debug.paused`
1010
+ - **BREAK** removed `velY`, `curPlatform` and `maxVel` fields by `body()`
1011
+ - **BREAK** changed `curAnim` by `sprite()` to method `curAnim()`
1012
+ - fixed `dt()` surge on page visibility change (#20)
1013
+ - pause audio when page is not visible
1014
+ - added built in debug control with `init({ debug: true, })`
1015
+ - `` ` ``: toggle `showLog` (default on with `debug: true`)
1016
+ - `f1`: toggle `showArea`
1017
+ - `f2`: toggle `hoverInfo`
1018
+ - `f8`: toggle `paused`
1019
+ - `f7`: decrease `timeScale`
1020
+ - `f9`: increase `timeScale`
1021
+ - `f10`: `stepFrame()`
1022
+ - added on screen logging with `log()` and `error()`
1023
+ - fixed `loadRoot()` sometimes doesn't work in async tasks
1024
+
1025
+ # v0.2 "Hear the Tremble"
1026
+ - **BREAK** removed `aseSpriteSheet` conf field from `loadSprite(name, src, conf)`
1027
+ - added `pause()`, `resume()`, `stop()`, `loop()`, `unloop()`, `volume()`, `detune()`, `speed()` methods to the handle returned by `play()`
1028
+ - added `camShake()` for built in camera shake
1029
+ - added `loadAseprite(name, imgSrc, jsonSrc)`
1030
+ - added area component generation for `text()`
1031
+ - added `noArea` to conf field of `sprite()`, `rect()` and `text()`, allowing to disable auto area component generation
1032
+ - added a `quad` field to sprite comp creation config `sprite(id, { quad: quad(0, 0, 0.5, 0.5) })`
1033
+ - fixed `resolve()` not working if the obj also has `solid`, so it does not check for itself (#8)
1034
+ - `mousePos()` accepts a layer argument, which returns the mouse position affected by camera transform if that layer is not `camIgnore()`-ed
1035
+ - fixed camera position getting calculated before completing every object's update (#14)
1036
+ - fixed some cases `on("grounded", f)` called multiple times when moving on a smooth platform
1037
+ - added `revery()` to iterate objects in reverse order
1038
+ - added `readd()` to re-add an object to the scene without triggering events
1039
+ - added `level.spawn()`
1040
+
1041
+ # v0.1 "Oh Hi Mark"
1042
+ - **BREAK** changed default origin point to `"topleft"`, so if you want object origin point to be at center you'll need to manual `origin("center")`
1043
+ - **BREAK** integrated `kit/physics` and `kit/level` to main lib
1044
+ - **BREAK** makes `collides()` only run on first collision, not run every frame during the same collision
1045
+ - **BREAK** `camPos()` by default focuses to center, so `camPos(player.pos)` puts player in the center of the screen
1046
+ - **BREAK** renamed `kaboom.import()` to `kaboom.global()`
1047
+ - added an arg field to `start(scene, ...)` to forward args to start scene
1048
+ - added `camScale()`, `camRot()` and `camIgnore()`
1049
+ - added `obj.overlaps()` by `area()`, and `overlaps()`
1050
+ - added 3 ext fonts under `ext/fonts`