kaplay 3001.0.0-alpha.1

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