- added
loadMusic()to load streaming audio (doesn't block in loading screen) - added support for arrays in uniforms
- added support for texture larger than 2048x2048
- added
chooseMultiple()andshuffle()helper functions
- exposed
velproperty onBodyComp
- fixed error not being logged
- fixed error screen scaling error in letterbox mode
- fixed
loadRoot()not working sometimes - fixed audio being resumed when the tab is switched on but
debug.pausedis true
- fixed
color()andrgb()not working
- added option
kaboom({ focus: false })to disable focus on start - fixed
rand()typing for numbers - fixed mouse position in fullscreen
- added
Color#toHSL()
- fixed test code accidentally getting shipped (where a screenshot will be downloaded every time you press space)
- added
filloption torect(),circle()andsprite() - fixed view getting cut off in letterbox mode
- fixed
scaleoption acting weird when width and height are defined (by @hirnsalat)
- fixed
debug.pausednot pausing audio - added
mask()component - added support for colored font outline
loadFont("apl386", "/examples/fonts/apl386.ttf", {
outline: {
width: 8,
color: rgb(0, 0, 255),
},
})- fixed
wave()not starting at0when time is0 - kaboom now only displays error screen for kaboom's own error, instead of catching all errors in current window
- added
KaboomErrorclass for errors related to current kaboom instance - setting
obj.textwithtext()component now immediately updateswidthandheightproperty
const obj = add([
text("oh hi"),
pos(100, 200),
])
// before
obj.text = "bye"
console.log(obj.width) // still the width of "oh hi" until next render
// before
obj.text = "bye"
console.log(obj.width) // will be updated to the width of "bye"- fixed
loadSoundtyping to acceptArrayBuffer
- added
Event#clear()method - fixed
add()without argument
- added
audio.stop()method
const music = play("music")
music.stop()- fixed
onCollideUpdate()still runs when object is paused - allow
add()andmake()without arguments - added
debug.numObjects() - added
widthandheightproperties toSpriteData
// get sprite size
getSprite("bean").then((spr) => {
console.log(spr.width, spr.height)
})- fixed audio not pausing when tab hidden and
backgroundAudionot set - fixed
debug.timeScalenot working - fixed
debug.pausednot able to resume - fixed
quadoption not working insprite()component - added
onHide()andonShow()for tab visibility event
- fixed some indirect
fixedrelated issues
- added game object level input handling
// add a scene game object
const scene = add([])
const bean = scene.add([
sprite("bean"),
pos(100, 200),
area(),
body(),
])
scene.onKeyPress("space", () => {
bean.jump()
})
scene.onMousePress(() => {
bean.jump()
})
// setting scene.paused will pause all the input events
scene.paused = true
// destroying scene will cancel all its input events
scene.destroy()
const ui = add([])
ui.add(makeButton())
// these will only work if ui game object is active
ui.onMousePress(() => {
// ...
})
// before you'll have to manually clean up events on obj.onDestroy()
const scene = add([])
const evs = []
scene.onDestroy(() => {
evs.forEach((ev) => ev.cancel())
})
evs.push(k.onKeyPress("space", () => {
doSomeSceneSpecificStuff()
}))- added
make()to create game object without adding to the scene
const obj = make([
sprite("bean"),
pos(120, 60),
])
add(obj)- fixed children not inheriting
fixed()from parent
// before
const ui = add([
fixed(),
])
ui.add([
rect(),
// have to also give all children game objects fixed()
fixed(),
])
// now
const ui = add([
fixed(),
])
// you don't have to add fixed() to children
ui.add([
rect(100, 100),
])- fixed
AreaComp#onClick()event not getting cleaned up when game object is destroyed - fixed typo
isTouchScreen()->isTouchscreen() - fixed inspect mode doesn't show the properties box of indirect children game objects
- fixed some problem causing kaboom to not work with vite
- fixed "destroy" event not run on children game objects
- calling
shake()when another shake is happening adds to the shake instead of reset it? - fixed incorrect touch position when canvas is not at top left of page
- added scene graph, game objects are now stored in a tree-like structure and can have children with
obj.add()
const bean = add([
sprite("bean"),
pos(160, 120),
])
const sword = bean.add([
sprite("sword"),
// transforms will be relative to parent bean object
pos(20, 20),
rotate(20),
])
const hat = bean.add([
sprite("hat"),
// transforms will be relative to parent bean object
pos(0, -10),
])
// children will be moved alongside the parent
bean.moveBy(100, 200)
// children will be destroyed alongside the parent
bean.destroy()- added
recursiveandliveUpdateoptions toget()
const enemies = get("enemy", {
// get from all children and descendants, instead of only direct children
recursive: true,
// live update the returned list to listen to onAdd and onDestroy events
liveUpdate: true,
})
console.log(enemies.length) // 3
add([
sprite("bigbird"),
"enemy",
])
console.log(enemies.length) // 4- changed object update order from reversed to not reversed
- (BREAK) removed
GameObj#every()andGameObj#revery()in favor ofobj.get("*").forEach() - (BREAK) renamed
GameObj#_idtoGameObj#id addLevel()now returns aGameObjwhich has all individual grid objects as its children game objects, withLevelCompcontaining its previous methods- added
onAdd()andonDestroy()events to listen to added / destroyed game objects
- added support for getter and setters in component properties
- added collision support for rotate shapes and polygons
- added option
collisionIgnoretoarea()component, which accepts a list of tags to ignore when checking collision
const bean = add([
sprite("bean"),
pos(100, 80),
area({
collisionIgnore: [ "cloud", "particle" ],
}),
])- added
Area#getCollisionsto get a list of all current collisions happening
for (const col of player.getCollisions()) {
const c = col.target
if (c.is("chest")) {
c.open()
}
}- added
Area#onCollideUpdate()andonCollideUpdate()to register an event that runs every frame when 2 object is colising - added
Area#onCollideEnd()andonCollideEnd()to register an event that runs once when 2 objects stopped colliding - added
Area#onHover()andonHover()to register an event that runs once when an object(s) is hovered - added
Area#onHoverEnd()andonHoverEnd()to register an event that runs once when an object(s) stopped being hovered - (BREAK) renamed
onHover()toonHoverUpdate()(it registers an event that runs every frame when an object is hovered) - (BREAK) renamed
pushOut()toresolveCollision()
- added
Body#onFall()which fires when object starts falling - added
Body#onPhysicsResolve()andBody#onBeforePhysicsResolve()to register events relating to collision resolution
// make semi-solid platforms that doesn't block player when player is jumping over it
player.onBeforePhysicsResolve((collision) => {
if (collision.target.is(["platform", "soft"]) && player.isJumping()) {
collision.preventResolution()
}
})- (BREAK) removed
solid()in favor ofbody({ isStatic: true }) - added option
body({ mass: 3 })to define how hard a non-static body is to be pushed by another non-static body - added option
body({ stickToPlatform: false })to turn off object moving with platform - (BREAK) removed
Body#doubleJump()in favor ofdoubleJump()component - (BREAK) renamed
Body#weighttoBody#gravityScale - (BREAK) renamed
Body#onFall()toBody#onFallOff()which triggers when object fall off a platform - (BREAK) defining
setGravity()is now required for enabling gravity,body()by default will only prevent objects from going through each other
- (BREAK) renamed
origin()toanchor(), so it won't mess up typescript in global mode - (BREAK)
anchor(previouslyorigin) no longer controls text alignment, usetext({ align: "left" })option instead - added
doubleJump()component to enable double jump (or any number of jumps) - (BREAK) renamed
outview()tooffscreen(), and uses a much faster check (but less accurate) for if object is offscreen- removed
offsetoption in favor of a simplerdistanceoption - renamed
onExitView()andonEnterView()toonExitScreen()andonEnterScreen()
- removed
- (BREAK) removed
cleanup()component in favor ofoffscreen({ destroy: true }) - added
OpacityComp#fadeOut() - added
fadeIn()component stay()now accepts a list of scenes to stay for, likestay(["gameover", "menu"])- (BREAK) changed
SpriteComp#flipXandSpriteComp#flipYto properties instead of functions - (BEARK)
sprite.onAnimStart()andsprite.onAnimEnd()now triggers on any animation
// before
obj.onAnimEnd("walk", () => {
// do something
})
// v3000
obj.onAnimEnd((anim) => {
if (anim === "walk") {
// do something
}
})- (BREAK)
ScaleComp#scalewill always be aVec2notnumber shader()compuniformparameter now supports a callback that returns the uniform every frame
const player = add([
sprite("bean"),
// will calculate and send u_time every frame
shader("flashy", () => ({
"u_time": time(),
})),
])- added
loadProgress()that returns a0.0 - 1.0that indicates current asset loading progress - added option
loadingScreentokaboom()where you can turn off the default loading screen - added
onLoadUpdate()to register a custom loading screen (see "loader" example)
// custom loading screen
onLoadUpdate((progress) => {
drawCircle({
pos: center(),
radius: 32,
end: map(progress, 0, 1, 0, 360),
})
})- added support for multiple sprite sources as frames in
loadSprite()
loadSprite("player", [
"sprites/player_idle.png",
"sprites/player_run.png",
"sprites/player_jump.png",
])- (BREAK) added
loadShaderURL(),loadShader()now only load shader code not files
- added
loadFont()to load.ttf,.otf,.woff2or any font supported by browserFontFace
// Load a custom font from a .ttf file
loadFont("FlowerSketches", "/examples/fonts/FlowerSketches.ttf")
// Load a custom font with options
loadFont("apl386", "/examples/fonts/apl386.ttf", { outline: 4, filter: "linear" })- (BREAK) renamed previous
loadFont()toloadBitmapFont() - (BREAK) removed built-in
apl386,apl386o,sink,sinko(still available underexamples/fonts) - changed default font size to
36 - (BREAK) changed to bbcode syntax for styled text
// before
"[oh hi].green here's some [styled].wavy text"
// v3000
"[green]oh hi[/green] here's some [wavy]styled[/wavy] text"- fixed visual artifacts on text rendering
- added
colorsoption todrawPolygon()that controls the color of each corner - added
gradientoption todrawRect()that specifies the start and end color - added
drawMasked()anddrawSubtracted() - added
pushRotateX(),pushRotateY()andpushRotateZ() - added
pixelDensityoption tokaboom() - (BREAK) changed position vertex format from
vec3tovec2(which is passed in as the first argument of customfragandvertshader functions) - added
usePostEffect()to add post process shader
loadShader("invert", null, `
vec4 frag(vec2 pos, vec2 uv, vec4 color, sampler2D tex) {
vec4 c = def_frag();
return vec4(1.0 - c.r, 1.0 - c.g, 1.0 - c.b, c.a);
}
`)
usePostEffect("invert")- shader error logs now yields the correct line number
- added
slice9option toloadSprite()to enable 9 slice scaling
loadSprite("grass", "/sprites/grass.png", {
slice9: {
left: 8,
right: 8,
top: 8,
bottom: 8,
},
})
const g = add([
sprite("grass"),
])
onMouseMove(() => {
const mpos = mousePos()
// updating width / height will scale the image but not the sliced frame
g.width = mpos.x
g.height = mpos.y
})- added option
kaboom({ backgroundAudio: false })to not pause audio when tab not active - changed
speed,detune,volume,loopinAudioPlayfrom functions to properties - added
onEnd()event forconst pb = play("sound")
// before
const music = play("song")
music.speed(2)
music.volume(0.5)
music.loop(true)
// v3000
const music = play("song")
music.speed = 2
music.volume = 0.5
music.loop = true- added
onScroll(action: (delta: Vec2) => void)to listen mouse wheel scroll - fixed touches not treated as mouse
- (BREAK) changed
onTouchStart(),onTouchMove()andonTouchEnd()callback signature to(pos: Vec2, touch: Touch) => void(exposes the nativeTouchobject) - added
onGamepadButtonPress(),onGamepadButtonDown(),onGamepadButtonRelease() - added
isGamepadButtonPressed(),isGamepadButtonDown(),isGamepadButtonReleased() - added
onGamepadStick()to handle gamepad axes info for left and right sticks - added
getConnectedGamepads() - added
onGamepadConnect()andonGamepadDisconnect() - added
gamepadsoption tokaboom()to define custom gamepads
- (BREAK) changed
addLevel()options API- renamed
widthandheighttotileWidthandtileHeight - renamed
anytowildcardTile - now all tile symbols are defined in the
tilesobject
- renamed
// before
addLevel([
"@ ^ $$",
"=======",
], {
width: 32,
height: 32,
"=": () => [
sprite("grass"),
area(),
body({ isStatic: true }),
],
"$": () => [
sprite("coin"),
area(),
"coin",
],
any: (symbol) => {
if (symbol === "@") {
return [ /* ... */ ]
}
},
})
// v3000
addLevel([
"@ ^ $$",
"=======",
], {
tileWidth: 32,
tileHeight: 32,
tiles: {
"=": () => [
sprite("grass"),
area(),
body({ isStatic: true }),
],
"$": () => [
sprite("coin"),
area(),
"coin",
],
},
wildcardTile: (symbol) => {
if (symbol === "@") {
return [ /* ... */ ]
}
},
})- sprites are now automatically packed, improving performance
- (BREAK) renamed
gravity()intogetGravity()andsetGravity() - (BREAK) removed all deprecated functions in v2000.2
- (BREAK) raised esbuild target to
esnext - added
setBackground()andgetBackground()in addition tobackgroundoption inkaboom() - moved type defs for global functions to
import "kaboom/global"
// if use global functions
import "kaboom"
import "kaboom/global" // required to load global types
kaboom()
// will have definition
add()// if don't use global function
import "kaboom"
kaboom({ global: false })
// type error, won't pollute global namespace if not manually import "kaboom/global"
add()- added
tween()for tweening, and a set of built-in easing functions ineasings
onMousePress(() => {
tween(bean.pos.x, mousePos().x, 1, (val) => bean.pos.x = val, easings.easeOutBounce)
tween(bean.pos.y, mousePos().y, 1, (val) => bean.pos.y = val, easings.easeOutBounce)
})- (BREAK) changed all event handlers to return a
EventControllerobject instead of a function to cancel event
// before
const cancel = onUpdate(() => { /* ... */ })
cancel()
// v3000
const ev = onUpdate(() => { /* ... */ })
ev.paused = true
ev.cancel()- timers can now be paused
const timer = wait(4, () => { /* ... */ })
timer.paused = true
timer.resume()
const timer = loop(1, () => { /* ... */ })
timer.paused = true
timer.resume()kaboom()now automatically focuses the canvas- added
quit()to end everything - added
download(),downloadText(),downloadJSON(),downloadBlob() - added
Recording#stop()to stop the recording and returns the video data as mp4 Blob - added
debug.numFrames()to get the total number of frames elapsed - added
onError()to handle error or even custom error screen - added
onResize()to register an event that runs when canvas resizes - added
setCursorLocked()andisCursorLocked() - (BREAK) renamed
cursor()tosetCursor() - (BREAK) renamed
fullscreen()tosetFullscreen() - (BREAK) renamed
isTouch()toisTouchscreen() - (BREAK) removed
layers()in favor of parent game objects (see "layers" example) - (BREAK) removed
load()event for components, useonLoad()inadd()event - (BREAK) removed
debug.objCount()in favor ofgetAll().length - added
debug.numFrames()to get the current frame count
- fixed text always being wrapped if updated
- fixed text comp properties
letterSpacing,charSpacing,transform,stylesnot being exposed
- fixed updating
fontproperty on gameobj not updating the text font
- fixed
focus()not properly exported - deprecated
focus()in favor ofcanvas.focus()due to name collision
- fixed
kaboom.d.tscompletely messed up
- fixed doc for
TextCompOpt#stylesandDrawTextOpt#styles
- fixed updates not running at all when
kaboom({ debug: false })
- added
formatText()anddrawFormattedText() - added
charSpacingandlineSpacinginTextCompOptandDrawTextOpt - added optional
transitionsargument instate()to define allowed transitions - added
StateComp#onStateTransitionto register event for specific transitions - added syntax to style a piece of text
"this is a [styled].wavy text"andstyleoption inTextCompOptandDrawTextOptto define the styles withCharTransformFunc - deprecated
dir()in favor ofVec2.fromAngle() - fixed
onTouchEnd()fired ontouchmove - added
outview()component to control behavior when object leaves visible area - deprecated
cleanup(delay?: number)in favor ofcleanup(opt?: CleanupOpt) - deprecated
mouseWorldPos()in favor oftoWorld(mousePos()) - deprecated
rng()in favor ofnew RNG() - added classes
Vec2,Color,Mat4,Timer,Quad,RNG,Line,Rect,Circle - added deprecation warning
- fixed letterbox view mode
- allow non-stretch letterbox
- fixed mouse position malfunction in fullscreen, stretch and letterbox mode
- fixed
Color#eq()not giving correct result
- fixed not having export if installed from github repo with npm
- fixed event canceller returned by raw
onUpdate()andonDraw()crashing
- fixed debug widget scale
- fixed
enterState()not passing args toonStateEnter()callback
- fixed
state()to not require registeringonStateUpdate()before using any state
- fixed
onKeyRelease()wrongfully check for key press instead of release
- fixed
StateComp#enterState()not accepting any state
- added
hsl2rgb()for converting HSL color to kaboom RGB - added
record()to start a screen recording - added F5 to screenshot and F6 to toggle record mode in debug mode
- added
DrawTextOpt#transform()andTextCompOpt#transform()for defining style and transformation for each character - added
state()component for finite state machine - added support for multiple tags in
get()andevery() - added UI indicator for
debug.pausedanddebug.timeScale - changed inspect mode UI style
- added color constants
WHITE,BLACK,BLUE,GREEN,RED,MAGENTA,CYAN,YELLOW - added new API style (
onprefix for all event handler function,isprefix for all boolean state getters)onLoad()onUpdate()onDraw()onKeyPress()onKeyPressRepeat()onKeyDown()onKeyRelease()onMousePress()onMouseDown()onMouseRelease()onMoueMove()onTouchStart()onTouchMove()onTouchEnd()onCollide()onClick()onHover()isFocused()isKeyDown()isKeyPressed()isKeyPressedRepeat()isKeyDown()isMouseDown()isMousePressed()isMouseReleased()isMouseMoved()isMouseMoved()GameObj#onUpdate()GameObj#onDraw()AreaComp#onCollide()AreaComp#onHover()AreaComp#onClick()BodyComp#onGround()BodyComp#onFall()BodyComp#onHeadbutt()BodyComp#onDoubleJump()BodyComp#isGrounded()BodyComp#isFalling()SpriteComp#onAnimEnd()SpriteComp#onAnimStart()HealthComp#onDeath()HealthComp#onHurt()HealthComp#onHeal()AudioPlay#isStopped()AudioPlay#isPaused()
- version jumped to v2000.0.0 (still semver, just big)
- added
burp()for easy burping - added decent typescript / autocomplete support and jsdocs
- introducing new character "bean"

- added
loadBean()to load"bean"as a default sprite - changed default font to APL386, as
"apl386o"(default outlined version) and"apl386" - included font kitchen sink as
"sinko"(outlined version) and"sink"(standard version with extended characters for text-mode games) - added
fontfield inKaboomOptto set the default font - added
loadSpriteAtlas(src, entries)to load sprite atlas - inspect mode now displays every comp's state
- 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)
// before
add([
sprite("player"),
area(),
]);
add([
sprite("rock"),
solid(),
]);
keyDown("left", () => {
player.move(-120, 0);
});
player.action(() => {
player.resolve(); // or pushOutAll() in beta versions
});
// after
const player = add([
sprite("player"),
area(),
solid(),
]);
// both should be solid
add([
sprite("rock"),
area(),
solid(),
]);
keyDown("left", () => {
// this will handle collision resolution for you, if the other obj is also "solid"
player.move(-120, 0);
});- added comp
opacity()to set opacity - added comp
health()to manage health related logic - added comp
move()to manage projectile-like behavior - added comp
cleanup()to auto destroy obj when it leaves screen - added comp
outline()to draw a lil outline - added comp
timer()to attach timers to a game obj - added comp
fixed()to make a game obj unaffected by camera - added comp
stay()to make a game obj stay after scene switch - added comp
lifespan()to destroy game obj after certain amount of time - added comp
z()to define draw order for objs on the same layer - added
weighttoBodyCompandBodyCompOptto control the gravity multiplier - added
djump()toBodyCompfor double jump - added
dir()to calculate directional vector from angle - added constants
LEFT,RIGHT,UP,DOWNfor unit directional vector - added
fullscreen()to enable real fullscreen mode - BREAK separated color and opacity, removed
rgba()in favor ofrgb, use componentopacity()to define opacity - BREAK changed color from 0-1 range to 0-255, angles from radians to degrees
// before
add([
rotate(Math.PI / 2),
color(0, 0.5, 1.0, 0.5),
]);
// after
add([
rotate(90),
color(0, 127, 255),
opacity(0.5)
]);globalanddebugflag now are enabled by default, need to turn off manually if you don't want- added input events
touchStart(id, pos),touchMove(id, pos),touchEnd(id, pos),mouseMove(pos) - added
mouseDeltaPos() - added
touchToMouseto control if touch events should be translated to mouse events - added
mousePos()now gets the screen mouse pos, usemouseWorldPos()to get the mouse position affected by camera - added
animfield inSpriteCompOptto play an anim on start - beter type support for components
scene()andstart()(also removed in favor ofgo()) are optional now, if you don't need multiple scenes yet you can just go directly
kaboom();
// no mandatory scene() to start kabooming
add(...);
keyPress(...);- BREAK
area()is now explicit and not automatically added bysprite(),rect(), andtext(), removed eachnoAreaorareaconfig field - BREAK
area()now takes anAreaCompOpt, where you can define the area size, scale, and hover cursor
add([
sprite("bean"),
area(), // empty area will derive from sprite size
area({ scale: 0.5, }), // 0.5x the sprite size
area({ offset: vec2(0, 12), width: 4, height: 12, }), // more control over the collider region
]);- BREAK renamed
isCollided()toisColliding(),isHovered()toisHovering() - BREAK removed
overlaps()andisOverlapped()and replaced withisColliding()andcollides()only checks doesn't return true when 2 objects are just touching each other, useisTouching()to check if they're not colliding but just touching each other - added
isTouching()to check if 2 objects are collided or just touching other - audio is now paused when you leave the tab
- audio is now paused on
debug.paused = true - added local storage helper
getData(key, default?)andsetData(key, data) - added
loadShader(id, vert, frag, isUrl) - added
shader()comp for attaching custom shader to an obj - different layers do not prevent collisions now
- BREAK changed last argument of
loadFont()toFontLoadOpt - all event handlers like
keyPress(),mouseClick(),action(),collides()now returns a function to cancel that listener - added
requireon component definitions, making it possible to declare dependencies for components, e.g.
function alwaysRight() {
return {
// the id of this component
id: "alwaysRight",
// list of component ids that this requires
require: [ "pos", ],
update() {
// so you can use `move()` from pos() component with no worry
this.move(100, 0);
},
};
}- BREAK overlapping component fields are not allowed, e.g. you can't have a custom comp that has a
collidesfield if it already have aareacomponent, since it already has that - BREAK changed
text(txt, size, conf)totext(txt, conf)withsizeas a field - added
obj.c(id)for getting a specific comp's state (by default all comps' states are mounted to the obj byObject.defineProperty)
// both works
obj.play("anim");
obj.c("sprite").play("anim");- pedit, aseprite plugins are now included by default
- added
addKaboom()for quick kaboom explosion load*()now acceptsnullas name and not load into assets manager, instead just return the resource data handle- BREAK renamed event
headbumptoheadbutt - BREAK renamed event
groundedtoground - added
width,height, andtiledattrib toSpriteCompOpt, for better control over sprite size and tiled sprite support - BREAK renamed
resolve()topushOutAll()onareacomp - added
pushOut()for pushing a single object out from another withareacomp - fixed
"add"event getting called twice for tagged objs - added
moveTo(dest: Vec2, speed?: number)topos()comp - added
keyPress()(and all other key events) with no arg to check for any key - BREAK renamed
camShake()toshake() - added
flipXandflipYonsprite()comp configuration, andflipX()flipY()methods - BREAK remove
flipX()andflipY()onscale()comp - BREAK removed
start()in favor ofgo() - BREAK removed
changeSprite()in favor ofuse(sprite("newsprite")) - tags and components are converged, tags are just empty components now
- added
unuse()to remove a component or tag - BREAK removed
rmTag()in favor ofunuse() - BREAK removed
camIgnore()in favor offixed() - BREAK renamed
makeRng()torng() - sprite animation now supports defining properties like loop and speed in load step and play step
loadSprite("hero", "hero.png", {
sliceX: 9,
anims: {
idle: { from: 0, to: 3, speed: 3, loop: true },
run: { from: 4, to: 7, speed: 10, loop: true },
hit: 8,
},
});- BREAK changed
.play(anim, ifLoop)undersprite()to accept a dict of properties.play(anim, { loop: true, speed: 60, pingpong: true }) - BREAK now every symbol definition in
addLevel()should be a function returning the component list, to ensure there's no weird shared states
addLevel([
"* *",
"* *",
"======",
], {
"*": () => [
sprite("wall"),
area(),
solid(),
],
"=": () => [
sprite("floor"),
area(),
solid(),
],
})- BREAK renamed
clearColortobackground - added collision detection functions
testLineLine(),testRectRect(),testRectLine()etc. - added drawing functions
drawSprite(),drawRect(),drawCircle(),drawPolygon(),drawEllipse(),drawLine(),drawLines() - added transformation functions
pushTransform(),popTransform(),pushTranslate(),pushRotate(),pushScale() - BREAK removed
areaWidth()andareaHeight()since they won't make sense if the area shape is not rectangle, useworldArea()if you need area data
const area = player.worldArea();
if (area.shape === "rect") {
const width = area.p2.x - area.p1.x;
const height = area.p2.y - area.p1.y;
}- added plugins npm package support e.g.
import asepritePlugin from "kaboom/plugins/aseprite"
- platforms are now sticky
- moved to TypeScript
- improved graphics performance
- improved inspect drawing performance
- added on-screen log that catches all kinds of errors
- added
cursor() - added
curPlatform()bybody() - added
falling()bybody() - added
changeSprite()bysprite() - added
duration()andtime()for the handle returned byplay() - added optional
seekfield to the audio play confplay([conf]) - added
LoopHandlereturned byloop()that has astop() - added a default background (can be dismissed by setting
clearColor) - fixed
sound.pause()to work on firefox - fixed collisions not treating explicit default layer the same as implicit default layer
- fixed unable to play another anim in
onAnimEnd() - fixed scene switches happen in the middle of a frame
- fixed
scale(0)not working - fixed
mosuePos()not returning the camera affected pos with no layers - BREAK changed
dbg()to plaindebugobject - BREAK moved
fps(),objCount(),stepFrame(),log(),error()underdebug - BREAK removed
debug.logTime - BREAK changed component
debugInfo()hook toinspect() - BREAK removed
timer()component - BREAK renamed
removeTag()tormTag() - BREAK changed
SpriteAnimfrom[ from, to ]to{ from: number, to: number } - BREAK removed
onAnimPlay()andonAnimEnd()in favor of generic eventon("animEnd", (anim: string) => {}) - BREAK removed
obj.addTag()in favor ofobj.use() - BREAK merged
debug.hoverInfoanddebug.showAreaintodebug.inspect - BREAK removed
sound.resume()in favor ofsound.play()
- fixed
on("destroy")handler getting called twice - fixed sprite
play()not playing
- BREAK removed
init()andkaboom.global(), in favor ofkaboom(), also allows multiple kaboom games on one page
// replaces init(), and added a 'global' flag for previous kaboom.global()
kaboom({
global: true,
width: 480,
height: 480,
});or not global
const k = kaboom();
k.scene();
k.start();
k.vec2();- BREAK changed
clearColoronkaboom(conf)to accept a 4 number array instead ofrgba() - added a plugin system, see the
multiboomexample andsrc/plugins - BREAK removed support for
.kbmsprite, supports newer version of.peditthrough pedit plugin - BREAK
loadAseprite()and made it an external plugin underplugins/aseprite.js - added
sceneData()for custom scene data kv store - fixed
mouseClickdoesn't work on mobile - disabled context menu on canvas
- prevented default behavior for 'tab' and function keys
- added
numFrames()bysprite() - added
screenshot()that returns of a png base64 data url for a screenshot
- BREAK removed
pause()andpaused()in favor tokaboom.debug.paused - BREAK removed
velY,curPlatformandmaxVelfields bybody() - BREAK changed
curAnimbysprite()to methodcurAnim() - fixed
dt()surge on page visibility change (#20) - pause audio when page is not visible
- added built in debug control with
init({ debug: true, })`: toggleshowLog(default on withdebug: true)f1: toggleshowAreaf2: togglehoverInfof8: togglepausedf7: decreasetimeScalef9: increasetimeScalef10:stepFrame()
- added on screen logging with
log()anderror() - fixed
loadRoot()sometimes doesn't work in async tasks
- BREAK removed
aseSpriteSheetconf field fromloadSprite(name, src, conf) - added
pause(),resume(),stop(),loop(),unloop(),volume(),detune(),speed()methods to the handle returned byplay() - added
camShake()for built in camera shake - added
loadAseprite(name, imgSrc, jsonSrc) - added area component generation for
text() - added
noAreato conf field ofsprite(),rect()andtext(), allowing to disable auto area component generation - added a
quadfield to sprite comp creation configsprite(id, { quad: quad(0, 0, 0.5, 0.5) }) - fixed
resolve()not working if the obj also hassolid, so it does not check for itself (#8) mousePos()accepts a layer argument, which returns the mouse position affected by camera transform if that layer is notcamIgnore()-ed- fixed camera position getting calculated before completing every object's update (#14)
- fixed some cases
on("grounded", f)called multiple times when moving on a smooth platform - added
revery()to iterate objects in reverse order - added
readd()to re-add an object to the scene without triggering events - added
level.spawn()
- BREAK changed default origin point to
"topleft", so if you want object origin point to be at center you'll need to manualorigin("center") - BREAK integrated
kit/physicsandkit/levelto main lib - BREAK makes
collides()only run on first collision, not run every frame during the same collision - BREAK
camPos()by default focuses to center, socamPos(player.pos)puts player in the center of the screen - BREAK renamed
kaboom.import()tokaboom.global() - added an arg field to
start(scene, ...)to forward args to start scene - added
camScale(),camRot()andcamIgnore() - added
obj.overlaps()byarea(), andoverlaps() - added 3 ext fonts under
ext/fonts