Skip to content

Instantly share code, notes, and snippets.

@canadaduane
Last active April 28, 2025 04:47
Show Gist options
  • Save canadaduane/c4ae93d0e2e2425c540bcb16a2bb3de1 to your computer and use it in GitHub Desktop.
Save canadaduane/c4ae93d0e2e2425c540bcb16a2bb3de1 to your computer and use it in GitHub Desktop.
Kaplay JS Docs - llms.txt
# The fun and open source game library for HTML5 Games
Warriors! Level up the fun with our brand new [Colyseus multiplayer guide!](guides/how-to-make-a-multiplayer-game-with-colyseus-and-kaplay)
**KAPLAY** (/ˈkæpleɪ/) is a JavaScript and TypeScript game library that makes it easy to create games for the web. It's free, open-source and fun.
[Explore Docs](/guides/) [Play in KAPLAYGround](https://play.kaplayjs.com) [Join our Discord](https://discord.com/invite/aQ6RuQm3TF)
Friendly API. Easy to learn, easy to teach.
A bunch of examples and assets to get started.
Strong support for TypeScript included.
It's Open Source, free and always will be.
## An enjoyable API based on blocks
KAPLAY is a lot of fun to use and easy to learn. It was uniquely designed with **blocks and functions** to make it intuitive and engaging. Just take a look at the examples below and experience it for yourself!
### Start game
``` js
kaplay({
background: "darkSalmon",
debug: true,
burp: true,
// and more uselful opts, like burp is
});
debug.log("Press (B) button to burp!");
```
### Add an object
``` js
const bean = add([
sprite("bean"),
pos(center()),
health(5),
body(), // adds physics
area(), // adds collisions
]);
```
### ~~Kill~~ destroy an object
``` js
setGravity(1000);
bean.jump();
bean.onCollide("spikes", () => {
bean.hurt(5);
bean.destroy();
shake(5);
flash("#cc425e", 0.2);
});
```
### Add custom components
``` js
// returns an object
const spillTheBeans = (count) => ({
id: "chaos",
add() { /* code */ },
});
add([
spillTheBeans(30), // adds chaos :O
]);
```
### Say goodbye
``` js
const bubble = add([
anchor("center"),
pos(center()),
rect(400, 100, { radius: 8 }),
outline(4, BLACK),
]);
bubble.add([
anchor("center"),
text("ohhi, I mean.. oh bye!", {
size: 26,
}),
color(BLACK),
]);
```
## Plus many more simple and fun to use methods and functions
No more long nested methods like\
` obj​.position​.transform​.translate(10, 20) `
[Get Started (Docs)](/guides/install/) [Explore more examples](https://play.kaplayjs.com/)
## Voices of KAPLAYers
Don't just take our word for it, see what our users say about **KAPLAY**! We're proud to have such a great community.\
[ Join our Discord](https://discord.com/invite/aQ6RuQm3TF) to be a part of it!
Endel [\@endel](https://x.com/endel)
Colyseus.io, Brawlball.io & Mazmorra.io creator
> KAPLAY API is incredibly intuitive and easy to read. I love how it combines simplicity with power, it's a truly innovative library that brings HTML5 games to life!
Isaac Pante [\@ipante](https://gist.github.com/ipante/b5a1599a07db9a1671fe7a9887e85d24)
Game Designer & College Teacher
> KAPLAY is the best framework to teach programming and create fast and furious video games. We already won three awards with it, and counting!
JSLegend [\@jslegenddev](https://youtube.com/@jslegenddev)
JavaScript content creator
> KAPLAY has a very intuitive and easy to use API that makes gamedev a breeze compared to other alternatives.
Candy&Carmel
Representative of Ghosts community
> KAPLAY has amazing and easy to use features for any type of game. It's made making FIGHT fun and interesting.
Amy [\@amyspark-ng](https://amyspark-ng.newgrounds.com/)
Clickery Hexagon's developer
> The development of KAPLAY has allowed me to make Clickery an awesome game.
niceEli [\@niceEli](https://mastodon.gamedev.place/@niceEli)
Developer
> KAPLAY is one of the best libraries for TypeScript I've tried. It's a very simple API yet very powerful.
## Our great Sponsors
## People who contributed to KAPLAY.js
KAPLAY is the result of a great community effort. You can support us, too, by contributing or donating.
[ Consider Donating](https://opencollective.com/kaplay/donate) [ Contribute on GitHub](https://github.com/kaplayjs/kaplay)
[+49 more contributors](https://github.com/kaplayjs/kaplay/graphs/contributors)
And also..
We got the funkiest [lore](/crew) in the KAWorld!
Wow!
## Guides
# Basics
Every animation in KAPLAY is basically a handler attached to onUpdate, changing values according to the elapsed time, dt(). So we could animate our position by doing the following
``` js
kaplay();
loadSprite("bean", "sprites/bean.png");
const obj = add([
pos(50, 50),
sprite("bean"),
{
time: 0,
},
]);
obj.onUpdate(() => {
obj.time += dt();
const t = (obj.time % 5) / 5;
obj.pos = lerp(vec2(50, 50), vec2(100, 50), t);
});
```
This will loop an animation with a duration of 5 seconds of the object moving between two points. The lerp function linearly interpolates between two values. This means that it follows the line between the two values at constant speed. While everything can be animated using such an onUpdate handler, there are some components which make this easier.
# Tween
Tweening is basically a linear interpolation happening during a specific time interval. The tween function in the timer component is one of the earliest general animation functions. It is limited to animating between two values, and needs a function parameter which sets the value. This makes it a bit dangerous since you can animate a value which is not on the object you call tween on. If the object gets destroyed before the tween ends, your application may crash. It is advised to not use the global tween function for this reason, but use the local one on the object, and only change properties of said object.
``` js
kaplay();
loadSprite("bean", "sprites/bean.png");
const obj = add([pos(50, 50), sprite("bean"), timer()]);
obj.tween(vec2(50, 50), vec2(100, 50), 5, (value) => (obj.pos = value));
```
# Animate
Animate is the newer animation function. It has more functionality, yet is more lightweight since you can animate more than one property, and you don't need to chain if you need more than two interpolation values. Animate works with keyframes. A simple animation of one property similar to the tween above would be
``` js
kaplay();
loadSprite("bean", "sprites/bean.png");
const obj = add([pos(50, 50), sprite("bean"), animate()]);
obj.animate("pos", [vec2(50, 50), vec2(100, 50)], { duration: 2 });
```
This animates the position from 50,50 to 150,100 during 2 seconds. As said before, we can also use more than two points, for example
``` js
obj.animate("pos", [vec2(50, 50), vec2(100, 50), vec2(100, 150)], {
duration: 4,
});
```
By default, the time is divided by all keyframes. Thus it takes 2 seconds between the first and second, as well as two seconds between the second and third keyframe. This means that the speed will be faster in the last part, since it is doing double the distance in the same time span. We can change this by giving it a timing parameter which gives a percentage value of where each keyframe is situated in time (the reason why it doesn't use timestamps directly is because it makes it easier to change the duration of the animation without having to change all the timing values)
``` js
obj.animate("pos", [vec2(50, 50), vec2(100, 50), vec2(100, 150)], {
duration: 3,
timing: [0, 1 / 3, 1],
});
```
Now the first part takes one third of the time, 1 second, and the second part takes 2 thirds of the time, or 2 seconds. So the speed stays the same. Like tween we can use easing. Either on the entire animation, or each individual segment. We can also alter the animation direction. For example reverse or ping-pong the animation, as well as set the maximum amount of loops.
``` js
obj.animate("pos", [vec2(50, 50), vec2(100, 50), vec2(100, 150)], {
duration: 3,
timing: [0, 1 / 3, 1],
direction: "ping-pong",
loops: 4,
});
```
We can indicate how we want the values interpolated, linear or following a spline. Or no interpolation ("none"), when we want to animate a sprite's frame for example
``` js
obj.animate("pos", [vec2(50, 50), vec2(100, 50), vec2(100, 150)], {
duration: 3,
timing: [0, 1 / 3, 1],
interpolation: "spline",
});
```
We can make the object rotate according to its motion by setting the followMotion option to true. Beware that the object requires a rotate component for this to work. If we want to assign the same animation to different objects, we can choose the animation to be relative. This makes the animation mix the initial state with the animation state.
``` js
const obj = add([
sprite("bean"),
pos(150, 0),
anchor("center"),
animate({ relative: true }),
]);
```
Previous
Optimization
Next
Canvas
# Playing sounds
In KAPLAY, you can easily add background music and sound effects to your game. You can play music, audios and sounds using the `play()` function.
## Loading sounds
For load audio files, you can use the `loadSound()` function. This function takes two parameters, the sound name and the sound path.
``` js
kaplay();
loadSound("soundName", "/path/to/sound.mp3");
```
## Playing sounds
You can play sounds using the \[`play()`\](. The `play()` function takes the name of the sound, and some options proper of [AudioPlayOpt](/doc/AudioPlayOpt/) interface.
``` js
play("soundName", {
volume: 0.5, // set the volume to 50%
speed: 1.5, // speed up the sound
loop: true, // loop the sound
});
```
## Stopping sounds
All `play()` returns an [AudioPlay](/doc/AudioPlay/) object that you can use to stop the sound.
``` js
const sound = play("soundName");
sound.stop();
```
Previous
Sprites
Next
Video
# Introduction
A Kaplay canvas is basically a framebuffer texture. It is used for optimization in some cases, though sometimes a picture may be better, since a picture uses less memory and is resolution independent. The most important reason to use a canvas is to create procedural sprites or render a multi-stage shader. This is the normal pipeline, where everything is rendered to the screen framebuffer.
When a canvas is active, everything is drawn to the canvas framebuffer texture instead.
# Creating a canvas
A canvas is created by calling `makeCanvas` and passing its `width` and `height`.
``` ts
const canvas = makeCanvas(320, 200);
```
There are multiple ways to put content in a canvas.
# Drawing in a canvas
We can draw directly into a canvas by calling `draw()` and passing a function or lambda with our draw routine.
``` ts
canvas.draw(() => {
drawSprite({
sprite: "bean",
});
});
```
This is actually a helper function which binds and unbinds the canvas for you. If your code is more complex than a simple draw routine, it may be more practical to use these directly.
``` ts
canvas.bind();
drawSprite({
sprite: "bean",
});
canvas.unbind();
```
There is also a component, which makes sure this object and all its children are drawn into the canvas instead of the screen.
``` ts
add([sprite("bean"), drawon(canvas)]);
```
# Drawing a canvas
You can draw a canvas by using drawCanvas, or by drawing an uvquad.
``` ts
drawCanvas({
canvas: canvas,
});
drawUVQuad({
width: canvas.width,
height: canvas.height,
tex: canvas.tex,
});
```
You can also add an object with an uvquad component. Though since you can't pass a texture easily, this won't work for now.
``` ts
add([
// TODO: Where to pass the texture?
uvquad(canvas.width, canvas.height),
]);
```
# Saving a canvas
A canvas can be saved to an image or a dataURL. This dataURL can be passed to loadSprite in order to load the image created on the canvas into the spritesheet.
``` ts
const img: ImageData = canvas.toImageData();
const dataURL: string = canvas.toDataURL();
loadSprite("proceduralSprite", dataURL);
```
# Disposing of a canvas
When done, a canvas needs to be freed in order to free the WebGL buffer.
``` ts
picture.free();
```
Previous
Animation
Next
Fake Mouse
# Components
A component is a piece of code that defines a specific behavior of a game object. It returns a set of **properties** and **methods** that are attached to the game object.
## Using a component
For use components we have to attach them in the `add()` function.
``` js
const player = add([
// rect(width, height) comp draws a rectangle in the obj
rect(40, 60),
// pos(x, y) comp sets the obj position
pos(10, 10),
]);
// method given by pos() comp
player.move(100, 0); // moves the player 100px to the right
// property given by rect() comp
debug.log(player.height); // will log 60
```
There are a lot of useful components in KAPLAY like:
- [`sprite()`](/doc/ctx/sprite) to make the object draw an image, and play animations
- [`area()`](/doc/ctx/area) to make the object do collision detection, with methods like [`onCollide()`](/doc/AreaComp#AreaComp-onCollide)
- [`text()`](/doc/ctx/text) to make the object draw text
- [`scale()`](/doc/ctx/scale) to make the game object bigger or smaller or to stretch it
You can see all the components in the [API Reference](/doc/ctx/pos).
## Components operations
All components have an *id*, this is the **name** of the component, `sprite()`'s id is `"sprite"`. This is used in many operations.
### How to add components
``` js
loadSprite("bean", "sprites/bean.png");
// Add the component on creation
const bean = add([
sprite("bean"), // bean the frog :D
opacity(0.6), // a ghost bean???
]);
// Add the component after creation
bean.use(color("#ff00ff")); // green bean <:
```
### How to remove components
``` js
// We pass the component id for remove it.
bean.unuse("sprite"); // bye bean
```
### How to know if a game object have a component
``` js
// We pass the component id:
bean.has("sprite"); // false - true if comp is there, otherwise false
```
Important!
Do note that you can't pass the component itself to `.unuse()` / `.has()`, you have to pass the component *name*!
## Making your own components
If you are creating a larger game, it's probably a good idea to bundle some of your game's functionality into custom components. You can check out how to do that in [this guide](/guides/custom_components/).
Previous
Game Objects
Next
Tags
# Creating your first game
This is an intro tutorial that will cover the basic concepts and make a very simple [Chrome Dino](https://en.wikipedia.org/wiki/Dinosaur_Game) - ish game. For setting up KAPLAY development, see the [Installation Guide](/guides/install).
Let's start by initializing the context with the `kaplay()` function.
``` js
kaplay();
```
This should give you a blank canvas with a nice checkerboard pattern like this
Then let's add some stuff to screen, like an image. Copy this piece of code to your editor and see what happens when you run the game.
``` js
// load a sprite "bean" from an image
loadSprite("bean", "sprites/bean.png");
// add something to screen
add([sprite("bean"), pos(80, 40)]);
```
Introducing Frog the "Bean"! A happy frog that enjoys life. You'll see Bean a lot around here.
Before explaining what this code does, let's try adding some more stuff to it and see what happens:
``` js
// add something to screen
add([sprite("bean"), pos(80, 40), scale(3), rotate(30), color(0, 0, 255)]);
```
Feel free to tweak some parameters and see how it affects what happens on screen.
In KAPLAY, each game object is composed from multiple components. Each component will give the game obj certain functionality.
> A game object is basically any character in the game, like the player character, a bullet, a rock, a cloud
For example, some component might decide what's the shape, some components might decide if it should subject to gravity, some components might decide what color it is, some component might decide how long it can live.
If you're having trouble understanding, consider this Human Bean:
Human are also composed from a list of components, each component provides different functionalities, which is exactly what component means in KAPLAY. `add()` is the function you use to assemble all the components into a game object in KAPLAY:
It's actually kinda like playing with lego pieces! Let's keep this in mind and start making the actual player character in our game:
``` js
// putting together our player character
const bean = add([sprite("bean"), pos(80, 40), area(), body()]);
// .jump() when "space" key is pressed
onKeyPress("space", () => {
bean.jump();
});
```
Let's see what components we're using:
- `sprite()` makes it render as a sprite, with the `"bean"` sprite we just loaded with `loadSprite()`
- `pos()` gives it a position on screen, at X: 80 Y: 40
- `area()` gives it a collider area, so we can check for collisions with other characters later on
- `body()` gives it a physical body, making it fall due to gravity and ability to jump,
We're also testing out our player character with a little interaction here. `onKeyPress()` registers an event that runs every time user presses a certain key. In this case, we're calling the `.jump()` method (which is provided by the `body()` component) when `"space"` key is pressed. Go ahead and slap that space key!
With the `body()` component, our Bean is going to keep falling into oblivion if we don't hit "space" key enough. Let's add a static platform for Bean to land on.
``` js
// add platform
add([
rect(width(), 48),
pos(0, height() - 48),
outline(4),
area(),
body({ isStatic: true }),
color(127, 200, 255),
]);
```
Woah! That looks like a lot, but it's actually really simple, let's look at each component
- `rect()` renders a rectangle. It accepts 2 arguments, the width and height, which we give it the game width (returned by `width()`) and height of 48 pixels
- `pos()` position. We give it a x: 0 and y: `height() - 48` so it sits right on the bottom of the screen
- `outline()` renders an outline of `4` pixels
- `area()` adds a collider to it
- `body({ isStatic: true })` the object won't move, and all non static objects won't move past it
- `color()` makes it render with an RGB color, we give it a R: 127 G: 200 B: 255 which is a blue-ish color
Now, before run, we should define the gravity of our world:
``` js
setGravity(1600);
```
Pretty straightforward! Refresh the game and you should see our Bean is now safely landed on a static blue platform.
Let's also make sure our Bean can only jump when isGrounded.
``` js
onKeyPress("space", () => {
if (bean.isGrounded()) {
bean.jump();
}
});
```
`isGrounded()` is another function provided by `body()` component which checks if currently landed on a platform. Now our game is slightly more physically correct.
Bean loves challenges. Let's start adding in obstacles to jump over! Time to build a game object from components again.
``` js
// add tree
add([
rect(48, 64),
area(),
outline(4),
pos(width(), height() - 48),
anchor("botleft"),
color(255, 180, 255),
move(LEFT, 240),
]);
```
A lot of these we have already seen you should know what they do, but some new ones here:
- `anchor()` defines the origin point of positioning. By default `pos()` defines the top left point of the shape, here we change it to the bottom left point because we want it to be just above the platform, so we give it Y position of `height() - 48`
- `move()` makes it move towards a direction infinitely. In this case we move towards the `LEFT` by `480` pixels per second
Challenger appears! Try jumping over it.
Oh but it's.. not really fun! Or rather, there's no feedback to whether we managed to jump over the ramp. Let's add some feedback.
To do this we'll need to check for collision between the two.
First we'll need to give the tree a tag. Any game object can have any number of tags, they're kinda like components but much more light weight. We often use tags to quickly describe behaviors for a group of objects.
``` js
// add tree
add([
rect(48, 64),
area(),
outline(4),
pos(width(), height() - 48),
anchor("botleft"),
color(255, 180, 255),
move(LEFT, 240),
"tree", // add a tag here
]);
```
To add a tag we simply put a string in the component array. Then we can check for collision between Bean and any object with tag "tree".
``` js
bean.onCollide("tree", () => {
addKaboom(bean.pos);
shake();
});
```
`.onCollide()` is a function provided by the `area()` component. It registers an event that runs every time the object collides with another object with a certain tag, passed by the first argument. In this case, it means every time Bean collides with another game obj with tag `"tree"`, run the callback.
Inside the callback we're doing 2 things. `addKaboom()` spawns an explosion animation, it accepts 1 argument the position to spawn, which we pass in the player's current position with `.pos` (which is provided by the `pos()` component).
The second thing is `shake()`, which just shakes the screen,
Here's a trick. Try pressing `F1` in the game. See all the blue outlines? This is inspect mode and it'll show all the bounding boxes of every game obj with `area()` component. Also try hovering over each game object to inspect its states like position and tags.
Now it's time to add more trees. How can we keep them spawning constantly?
Let's try the `loop()` function, which performs an action every x seconds.
``` js
loop(1, () => {
// add tree
add([
rect(48, 64),
area(),
outline(4),
pos(width(), height() - 48),
anchor("botleft"),
color(255, 180, 255),
move(LEFT, 240),
"tree", // add a tag here
]);
});
```
Let's just put the tree adding code inside a `loop()`. The first argument is the time in seconds here, so it'll spawn a tree every 1 seconds.
Sick! Lots of trees coming to you now. Now we already have most of the game mechanics done. Some improvements we can make:
1. It might be better if trees all have different random heights. We can use `rand()` to assign different value to the tree's rect height:
``` js
rect(48, rand(24, 64)),
```
2. It'll be more fun if the trees spawn at different intervals. We cannot do that from `loop()`, but we can compose that with recursive `wait()`s, which waits for x seconds to execute some code.
``` js
function spawnTree() {
add([
// the tree components
]);
wait(rand(0.5, 1.5), () => {
spawnTree();
});
}
spawnTree();
```
See? We're calling `spawnTree()` recursively / endlessly, with a random interval between 0.5 - 1.5 seconds each time.
Before adding a score counter, let's actually complete the game loop first, by sending player to a game-over scene when they hit a tree. We can achieve this with KAPLAY's `scene()` system
``` js
scene("game", () => {
add([sprite("bean")]);
});
scene("lose", () => {
add([text("Game Over")]);
});
go("game");
```
Consider this example above, we're declaring 2 scenes here, "game" and "lose". The function we pass to `scene()` is the function to run when this scene is activated (by `go()`). In this case, we want to add a "bean" sprite on "game" scene, and want to add a "Game Over" text on the "lose" scene.
Let's first move everything game code we have into a scene.
``` js
kaplay();
loadSprite("bean", "sprites/bean.png");
scene("game", () => {
// add bean
// add platform
// spawn trees
});
go("game");
```
Try this, this shouldn't change any of your game's content.
Then we can add a "lose" scene independent to your core game content here.
``` js
scene("lose", () => {
add([text("Game Over"), pos(center()), anchor("center")]);
});
```
So in the "lose" scene, we'll add a piece of text in the center says "Game Over" (`text()` is a component that renders text). Go ahead and go to this scene when player collides with a tree:
``` js
player.onCollide("tree", () => {
addKaboom(bean.pos);
shake();
go("lose"); // go to "lose" scene here
});
```
Ok! Now we've arrived at the final part of our game: score counter.
``` js
let score = 0;
const scoreLabel = add([text(score), pos(24, 24)]);
```
Here we've declared a number variable to store the score, and added a game obj with `text()` component to display the text.
Let's keep it simple and just use time as score.
``` js
// increment score every frame
onUpdate(() => {
score++;
scoreLabel.text = score;
});
```
We can use the `onUpdate()` function, which takes a function, and runs it every frame. In this case we're going to increment the score, and update the score label's text every frame.
Full game code here:
``` js
const FLOOR_HEIGHT = 48;
const JUMP_FORCE = 800;
const SPEED = 480;
// initialize context
kaplay();
// load assets
loadSprite("bean", "sprites/bean.png");
scene("game", () => {
// define gravity
setGravity(1600);
// add a game object to screen
const player = add([
// list of components
sprite("bean"),
pos(80, 40),
area(),
body(),
]);
// floor
add([
rect(width(), FLOOR_HEIGHT),
outline(4),
pos(0, height()),
anchor("botleft"),
area(),
body({ isStatic: true }),
color(127, 200, 255),
]);
function jump() {
if (player.isGrounded()) {
player.jump(JUMP_FORCE);
}
}
// jump when user press space
onKeyPress("space", jump);
onClick(jump);
function spawnTree() {
// add tree obj
add([
rect(48, rand(32, 96)),
area(),
outline(4),
pos(width(), height() - FLOOR_HEIGHT),
anchor("botleft"),
color(255, 180, 255),
move(LEFT, SPEED),
"tree",
]);
// wait a random amount of time to spawn next tree
wait(rand(0.5, 1.5), spawnTree);
}
// start spawning trees
spawnTree();
// lose if player collides with any game obj with tag "tree"
player.onCollide("tree", () => {
// go to "lose" scene and pass the score
go("lose", score);
burp();
addKaboom(player.pos);
});
// keep track of score
let score = 0;
const scoreLabel = add([text(score), pos(24, 24)]);
// increment score every frame
onUpdate(() => {
score++;
scoreLabel.text = score;
});
});
scene("lose", (score) => {
add([
sprite("bean"),
pos(width() / 2, height() / 2 - 80),
scale(2),
anchor("center"),
]);
// display score
add([
text(score),
pos(width() / 2, height() / 2 + 80),
scale(2),
anchor("center"),
]);
// go back to game with space is pressed
onKeyPress("space", () => go("game"));
onClick(() => go("game"));
});
go("game");
```
Previous
Multiplayer with Colyseus
Next
Publishing
# Custom Components
KAPLAY uses a flexible component system that helps you compose game logic.
Let's take a look at how the default component `lifespan()` is implemented.
``` js
function lifespan(time) {
let timer = 0;
return {
id: "lifespan",
update() {
timer -= dt();
if (timer <= 0) {
destroy(this);
}
},
};
}
```
Components are just plain functions that returns an object. The return object will contain all the exposed states, methods, and event hooks of the component. In this case, the `lifespan()` component returns an `id`, which is a string which serves as an unique identification of the comp. There's also an `update()`, which is an event hook that'll run every frame. All `this` inside the component functions refer to the game obj it's attached to.
All special fields:
``` js
function mycomp() {
// use closed local variable for internal data
let data = 123;
return {
id: "mycomp",
// if this comp requires other comps to work
require: ["area", "pos"],
// runs when the obj is added to scene
add() {
debug.log("Hi! This should only be fire once.");
},
// runs every frame
update() {
// we're using a method from "pos" comp here, so we declare require "pos" above
this.move(200, 0);
},
// runs every frame, after update
draw() {
drawLine(this.pos, mousePos());
},
// runs when obj is destroyed
destroy() {
debug.log("Oh bye");
},
// what to display in inspect mode
inspect() {
return "some state that deserves to be shown in inspect mode";
},
};
}
```
Most KAPLAY built-in components are built using public interfaces, feel free to check them out. Also check out the "drag", "platformer", "doublejump" demos with their own custom components.
Check out the [component demo](https://play.kaplayjs.com/?example=component).
Previous
Input Bindings
Next
Plugins
# Debug Mode
The debug mode is a KAPLAY integrated tool that helps you to debug your game. Now, we will see how to use it.
## Inspect Mode
You can enable inspect mode by pressing `F1` key. This will open the debug panel.
You will see
- The current FPS
- Object areas (blue rectangle)
- Object anchor points (red dot)
- Object components properties
## Logging
You can use (with or without the inspect mode) the `debug.log()` function to log messages in the game screen.
``` js
debug.log("Hello, world!");
```
With F2, you can clear the log.
## Controlling time
With the keys F7, F8, F9 you can control the time of the game.
F7 and F9 will decrease and increase the time speed, respectively. F8 will pause the game.
This is useful to test features in slow motion or to pause the game to inspect the objects.
## Changing the default key for activate the debug mode
You can set the property [`KAPLAYOpt.debugKey`](/doc/KAPLAYOpt/#KAPLAYOpt-debugKey) to change the default key for activate the debug mode.
``` js
kaplay({
debugKey: "r",
});
```
## Disabling the debug mode
If your game is ready to be published, you can disable the debug mode by setting the property [`KAPLAYOpt.debug`](/doc/KAPLAYOpt/#KAPLAYOpt-debug) to `false`.
``` js
kaplay({
debug: false,
});
```
Previous
Shaders
Next
Input Bindings
# Events
An **Event** is something that *happens* in the game, for example, the player pressing a key, clicking the mouse or an enemy being hurt.
An **Event Handler** is a method that listens for events and run code when they happen. These functions are named as `on{EventName}`.
``` js
// onKeyPress() will run every time user press any key
onKeyPress((key) => {
// Some events send you args related to them, in this case the key pressed
debug.log(key); // will log the key pressed
});
```
**Event Handlers** also return an **Event Controller**. It works for cancel the event or pause it:
``` js
const pressEvent = onKeyPress((key) => {
debug.log(key);
});
pressEvent.cancel(); // stop running the handler
```
There's many type of events that runs in different contexts:
### App events
**App events** run without neccesity of being attached to a game object. They are related to things like the game screen, input, etc.
``` js
// Only runs when user press "a"
onKeyPress("a", () => {
debug.log("aaa");
});
// Only runs when assets finish loading
onLoad(() => {});
```
App events are also in objects
There's some events like `onKeyPress()` which also have a `obj.onKeyPress()` version. They are still App events but they got removed when the object is destroyed. See the [App Events list](/#app-events-list) below
### Root events
**Root events** run during the lifecycle of the **Root Game Object**, or the same, forever.
``` js
// onUpdate() event runs every frame.
onUpdate(() => {
// Bean moves 10px to the right every frame
bean.moveBy(10, 0);
});
// onDraw() event runs after update and must be used with drawXXXX functions.
onDraw(() => {
// The sprite is drawn here to prevent it from disappearing after 1 frame.
drawSprite("bean");
});
```
You can also associate these event handlers with **Tags**, this means you can run an event handler code *4 times* if there's *4 objects* with that tag. The **first argument** is always **the game object** is running for.
``` js
// imagine there's 4 objects with tag "friend"
// onUpdate("friend") will be executed 4 times per frame (or the same, 1 time per object)
onUpdate("friend", (o) => {
// o will take 4 different values
debug.log(o.id);
});
```
### Game Object events
**Game Object events** are like Root events, but they operate on individual **Game Objects**. These events run during specific points in the object's lifecycle, such as when it's added, updated, or removed.
``` js
const obj = add([]);
// Runs when the object is added
obj.onAdd(() => {});
// Runs when the object is destroyed
obj.onDestroy(() => {});
// They run while obj exists
obj.onUpdate(() => {});
obj.onDraw(() => {});
```
Both Object and Root events operate with [Object Events List](#object-events)
## Game Object events given by components
There are events and events handlers that comes from some components. They become events of the object after add the comp:
``` js
const kat = add([
// health(initialHp) comp gives to the object a health system
health(4),
]);
// Given by health(), runs when we hurt the obj
kat.onHurt(() => {
debug.log("you're a monster!");
});
// Run when user clicks
onMousePress(() => {
kat.hurt(1); // we remove 1 hp, ouch
});
```
## Generic handler
`on()` is a way to create handlers without they being premade. In fact, all events handler are an `on()`.
You can use **global** `on()`, it works for use **Game Object events** with certain tags. The first argument is always the object. It is useful when there's no a handler for tags, for example in the component events:
``` js
// obj.onHurt() but for many objects
on("hurt", "friend", (o) => {
debug.log(o.id);
});
on("update", "friend", (o) => {
debug.log(o.id + "exists");
});
```
There's also the object version, `obj.on()`. Useful for listen to an event only in that obj:
``` js
kat.on("hurt", () => {
});
```
## Custom events
Sometimes you will need create a custom event. For this, we use the `on()` and `obj.trigger()` functions.
``` js
// Eat event for all objects with cake tag
on("eat", "cake", () => {
debug.log("The cake is a lie!");
});
onKeyPress(() => {
obj.trigger("eat");
});
```
## Events operations
### How to listen for an event
``` js
// a global event
onUpdate(() => {});
// an object event
obj.onUpdate(() => {});
// a custom event
obj.on("hi", () => {});
```
### How to trigger an event
``` js
// will execute obj.on("hi", () => {})
obj.trigger("hi"); // :>
```
## List of events
- 🏷️ = Require tags for working
### Object Events List
| Event | Comp | Description | Global Handler | Object Handler |
|----|----|----|----|----|
| `update` | None | Runs every frame | [`onUpdate()`](/doc/ctx/onUpdate) | [`obj.onUpdate()`](/doc/GameObjRaw/#GameObjRaw-onUpdate) |
| `draw` | None | Runs every frame after update | [`onDraw()`](/doc/ctx/onDraw%5D) | [`obj.onDraw()`](/doc/GameObjRaw/#GameObjRaw-onDraw) |
| `add` | None | Runs when an object is added as child | [`onAdd()`](/doc/ctx/onAdd) | [`obj.onAdd()`](/doc/GameObjRaw/#GameObjRaw-onAdd) |
| `destroy` | None | Runs when an object is destroyed | [`onDestroy()`](/doc/ctx/onDestroy) | [`obj.onDestroy()`](/doc/GameObjRaw/#GameObjRaw-onDestroy) |
| `use` | None | Runs when a component is added | [`onUse()`](/doc/ctx/onUse) | [`obj.onUse(comp)`](/doc/GameObjRaw/#GameObjRaw-onUse) |
| `unuse` | None | Runs when a component is unused | [`onUnuse()`](/doc/ctx/onUnusue) | [`obj.onUnuse(comp)`](/doc/GameObjRaw/#GameObjRaw-onUnuse) |
| `tag` | None | Runs when a tag is added | [`onTag()`](/doc/ctx/onTag) | [`obj.onTag(tag)`](/doc/GameObjRaw/#GameObjRaw-onTag) |
| `untag` | None | Runs when a tag is removed | [`onUntag()`](/doc/ctx/onUntag) | [`obj.onUntag(tag)`](/doc/GameObjRaw/#GameObjRaw-onUntag) |
| `collide` | [`area()`](/doc/ctx/area) | Runs when object collides with another object | [`onCollide()`](/doc/ctx/onCollide) 🏷️ | [`obj.onCollide(other, col)`](/doc/AreaComp/#AreaComp-onCollide) |
| `collideUpdate` | [`area()`](/doc/ctx/area) | Runs every frame when objects are colliding | [`onCollideUpdate()`](/doc/ctx/onCollideUpdate) 🏷️ | [`obj.onCollideUpdate()`](/doc/AreaComp/#AreaComp-onCollideUpdate) |
| `collideEnd` | [`area()`](/doc/ctx/area) | Runs when object stops colliding | [`onCollideEnd()`](/doc/ctx/onCollideEnd) 🏷️ | [`obj.onCollideEnd()`](/doc/AreaComp/#AreaComp-onCollideEnd) |
| `hurt` | [`health()`](doc/ctx/health) | Runs when object is hurt | Using `on()` | [`obj.onHurt(damage)`](/doc/HealthComp/#HealthComp-onHurt) |
| `heal` | [`health()`](doc/ctx/health) | Runs when object is healed | Using `on()` | [`obj.onHeal(amount)`](/doc/HealthComp/#HealthComp-onHeal) |
| `death` | [`health()`](doc/ctx/health) | Runs when object dies | Using `on()` | [`obj.onDeath()`](/doc/HealthComp/#HealthComp-onDeath) |
| `beforePhysicsResolve` | [`body()`](doc/ctx/body) | Runs before physics resolves | Using `on()` | [`obj.onBeforePhysics(col)`](/doc/BodyComp/#BodyComp-onBeforePhysicsResolve) |
| `physicsResolve` | [`body()`](doc/ctx/body) | Runs after physics resolves | Using `on()` | [`obj.onPhysics(col)`](/doc/BodyComp/#BodyComp-onPhysicsResolve) |
| `ground` | [`body()`](doc/ctx/body) | Runs when object is on the ground | Using `on()` | [`obj.onGround()`](/doc/BodyComp/#Body-onGround) |
| `fall` | [`body()`](doc/ctx/body) | Runs when object starts falling | Using `on()` | [`obj.onFall()`](/doc/Body/#BodyComp-onFall) |
| `fallOff` | [`body()`](doc/ctx/body) | Runs when object stops falling | Using `on()` | [`obj.onFallOff()`](/doc/BodyComp/#BodyComp-onFallOff) |
| `headbutt` | [`body()`](doc/ctx/body) | Runs when object headbutts | Using `on()` | [`obj.onHeadbutt()`](/doc/BodyComp/#BodyComp-onHeadbutt) |
| `land` | [`body()`](doc/ctx/body) | Runs when object lands | Using `on()` | [`obj.onLand()`](/doc/BodyComp/#BodyComp-onLand) |
| `headbutted` | [`body()`](doc/ctx/body) | Runs when object is headbutted | Using `on()` | [`obj.onHeadbutted()`](/doc/BodyComp/#BodyComp-onHeadbutted) |
| `doubleJump` | [`doubleJump`](doc/ctx/doubleJump) | Runs when object double jumps | Using `on()` | [`obj.onDoubleJump()`](/doc/DoubleJumpComp/#DoubleJumpComp-onDoubleJump) |
| `exitView` | [`offscreen()`](doc/ctx/offscreen) | Runs when object goes out of view | Using `on()` | [`obj.onExitView()`](/doc/OffscreenComp/#OffScreenComp-onExitView) |
| `enterView` | [`offscreen()`](doc/ctx/offscreen) | Runs when object enters view | Using `on()` | [`obj.onEnterView()`](/doc/OffscreenComp/#OffScreenComp-onEnterView) |
| `animStart` | [`sprite()`](doc/ctx/sprite) | Runs when animation starts | Using `on()` | [`obj.onAnimStart(anim)`](/doc/SpriteComp/#SpriteComp-onAnimStart) |
| `animEnd` | [`sprite()`](doc/ctx/sprite) | Runs when animation ends | Using `on()` | [`obj.onAnimEnd(anim)`](/doc/SpriteComp/#SpriteComp-onAnimEnd) |
| `navigationNext` | [`agent()`](doc/ctx/agent) | Runs when navigation moves to the next point | Using `on()` | [`obj.onNavigationNext()`](/doc/AgentComp/#AgentComp-onNavigationNext) |
| `navigationEnded` | [`agent()`](doc/ctx/agent) | Runs when navigation ends | Using `on()` | [`obj.onNavigationEnded()`](/doc/AgentComp/#AgentComp-onNavigationEnded) |
| `navigationStarted` | [`agent()`](doc/ctx/agent) | Runs when navigation starts | Using `on()` | [`obj.onNavigationStarted()`](/doc/AgentComp/#AgentComp-onNavigationStarted) |
| `targetReached` | [`agent()`](doc/ctx/agent) | Runs when navigation target is reached | Using `on()` | [`obj.onTargetReached()`](/doc/AgentComp/#AgentComp-onTargetReached) |
| `patrolFinished` | [`patrol()`](doc/ctx/agent) | Runs when patrol finishes | Using `on()` | [`obj.onPatrolFinished()`](/doc/PatrolComp/#PatrolComp-onPatrolFinished) |
| `objectSpotted` | [`sentry()`](doc/ctx/sentry) | Runs when object spots another | Using `on()` | [`obj.onObjectSpotted()`](/doc/SentryComp/#SentryComp-onObjectSpotted) |
| `animateChannelFinished` | [`animate()`](doc/ctx/animate) | Runs when animation channel finishes | Using `on()` | [`obj.onAnimateChannel()`](/doc/AnimateComp/#AnimateComp-onAnimateChannelFinished) |
| `animateFinished` | [`animate`](doc/ctx/animate) | Runs when animation finishes | Using `on()` | [`obj.onAnimateFinished()`](/doc/AnimateComp/#AnimateComp-onAnimateFinished) |
| `spatialMapChanged` | [`level()`](doc/ctx/level) | Runs when spatial map changes | Using `on()` | [`obj.onSpatialMapChanged()`](/doc/LevelComp/#LevelComp-onSpatialMapChanged) |
| `navigationMapInvalid` | [`level()`](doc/ctx/level) | Runs when navigation map becomes invalid | Using `on()` | [`obj.onNavigationMapInvalid()`](/doc/LevelComp/#LevelComp-onNavigationMapInvalid) |
| `avigationMapChanged` | [`level()`](doc/ctx/level) | Runs when navigation map changes | Using `on()` | [`obj.onNavigationMapChanged()`](/doc/LevelComp/#LevelComp-onNavigationMapChanged) |
### App Events List
| Event | Description | Global Handler | Object Handler |
|----|----|----|----|
| `mouseMove` | Runs continuously while mouse moves | [`onMouseMove()`](/doc/ctx/onMouseMove) | [`obj.onMouseMove()`](/doc/GameObjRaw/#GameObjRaw-onMouseMove) |
| `mouseDown` | Runs continuously while mouse is clicked | [`onMouseDown()`](/doc/ctx/onMouseDown) | [`obj.onMouseDown()`](/doc/GameObjRaw/#GameObjRaw-onMouseDown) |
| `mousePress` | Runs once when mouse button is pressed | [`onMousePress()`](/doc/ctx/onMousePress) | [`obj.onMousePress()`](/doc/GameObjRaw/#GameObjRaw-onMousePress) |
| `mouseRelease` | Runs once when mouse button is released | [`onMouseRelease()`](/doc/ctx/onMouseRelease) | [`obj.onMouseRelease()`](/doc/GameObjRaw/#GameObjRaw-onMouseRelease) |
| `charInput` | Runs continuously while user write in the keyboard | [`onCharInput()`](/doc/ctx/onCharInput) | [`obj.onCharInput()`](/doc/GameObjRaw/#GameObjRaw-onCharInput) |
| `keyPress` | Runs once when a key is pressed | [`onKeyPress()`](/doc/ctx/onKeyPress) | [`obj.onKeyPress()`](/doc/GameObjRaw/#GameObjRaw-onKeyPress) |
| `keyDown` | Runs continuously while a key is held down | [`onKeyDown()`](/doc/ctx/onKeyDown) | [`obj.onKeyDown()`](/doc/GameObjRaw/#GameObjRaw-onKeyDown) |
| `keyPressRepeat` | Runs once when a key is repeatedly pressed | [`onKeyPressRepeat()`](/doc/ctx/onKeyPressRepeat) | [`obj.onKeyPressRepeat()`](/doc/GameObjRaw/#GameObjRaw-onKeyPressRepeat) |
| `keyRelease` | Runs once when a key is released | [`onKeyRelease()`](/doc/ctx/onKeyRelease) | [`obj.onKeyRelease()`](/doc/GameObjRaw/#GameObjRaw-onKeyRelease) |
| `touchStart` | Runs once when a touch starts | [`onTouchStart()`](/doc/ctx/onTouchStart) | [`obj.onTouchStart()`](/doc/GameObjRaw/#GameObjRaw-onTouchStart) |
| `touchMove` | Runs continously while a touch moves | [`onTouchMove()`](/doc/ctx/onTouchMove) | [`obj.onTouchMove()`](/doc/GameObjRaw/#GameObjRaw-onTouchMove) |
| `touchEnd` | Runs once when a touch ends | [`onTouchEnd()`](/doc/ctx/onTouchEnd) | [`obj.onTouchEnd()`](/doc/GameObjRaw/#GameObjRaw-onTouchEnd) |
| `gamepadButtonDown` | Runs continously while a gamepad button is held down | [`onGamepadButtonDown()`](/doc/ctx/onGamepadButtonDown) | [`obj.onGamepadButtonDown()`](/doc/GameObjRaw/#GameObjRaw-onGamepadButtonDown) |
| `gamepadButtonPress` | Runs once when a gamepad button is pressed | [`onGamepadButtonPress()`](/doc/ctx/onGamepadButtonPress) | [`obj.onGamepadButtonPress()`](/doc/GameObjRaw/#GameObjRaw-onGamepadButtonPress) |
| `gamepadButtonRelease` | Runs once when a gamepad button is released | [`onGamepadButtonRelease()`](/doc/ctx/onGamepadButtonRelease) | [`obj.onGamepadButtonRelease()`](/doc/GameObjRaw/#GameObjRaw-onGamepadButtonRelease) |
| `gamepadStick` | Runs continuously while a gamepad stick moves | [`onGamepadStick()`](/doc/ctx/onGamepadStick) | [`obj.onGamepadStick()`](/doc/GameObjRaw/#GameObjRaw-onGamepadStick) |
| `gamepadConnect` | Runs once when a gamepad connects | [`onGamepadConnect()`](/doc/ctx/onGamepadConnect) | [`obj.onGamepadConnect()`](/doc/GameObjRaw/#GameObjRaw-onGamepadConnect) |
| `gamepadDisconnect` | Runs once when a gamepad disconnects | [`onGamepadDisconnect()`](/doc/ctx/onGamepadDisconnect) | [`obj.onGamepadDisconnect()`](/doc/GameObjRaw/#GameObjRaw-onGamepadDisconnect) |
| `buttonDown` | Runs continuously while an input binding is held down | [`onButtonDown()`](/doc/ctx/onButtonDown) | [`obj.onButtonDown()`](/doc/GameObjRaw/#GameObjRaw-onButtonDown) |
| `buttonPress` | Runs once when an input binding is pressed | [`onButtonPress()`](/doc/ctx/onButtonPress) | [`obj.onButtonPress()`](/doc/GameObjRaw/#GameObjRaw-onButtonPress) |
| `buttonRelease` | Runs once when a binding button is released | [`onButtonRelease()`](/doc/ctx/onButtonRelease) | [`obj.onButtonRelease()`](/doc/GameObjRaw/#GameObjRaw-onButtonRelease) |
| `scroll` | Runs continuously while a scroll event occurs | [`onScroll()`](/doc/ctx/onScroll) | [`obj.onScroll()`](/doc/GameObjRaw/#GameObjRaw-onScroll) |
| `hide` | Runs once when the game tab is hidden | [`onHide()`](/doc/ctx/onHide) | No ❌ |
| `show` | Runs once when the game tab is showed | [`onShow()`](/doc/ctx/onShow) | No ❌ |
| `resize` | Runs continously when the game screen is resizing | [`onResize()`](/doc/ctx/onResize) | No ❌ |
| `input` | Runs when the input is processed | No ❌ | No ❌ |
Previous
Tags
Next
Scenes
# Fake mouse
Sometimes you want your game using a fake mouse in game-pad devices (i.e: Ultimate Chicken Horse), you want to use a Game Object as a cursor. There's a special component for it, `fakeMouse`.
Using a game object as a mouse has many advantages like use shaders, transform, rotation or even physics if you want, the possibilities are infinite.
## `fakeMouse` component
The `fakeMouse` component actives the behaviors of events like `onHover` and `onClick` and them listen for this object too. It creates a virtual mouse that is connected with the physical one.
The default behavior is that the fakeMouse moves when the mouse is moved. This allow the user change between mouse and keys/gamepad cursor. The behavior can be disabled passing `followMouse: false` to the comp options.
``` js
loadSprite("cursor", "cursor.png");
const cursor = add([
sprite("cursor"), // sprite
fakeMouse({
followMouse: true, // disable if you want
}),
]);
```
Now, you need to bind `FakeCursorComp.press()` and `FakeCursorComp.release()` to a key. It can be a keyboard click for example:
``` js
cursor.onKeyPress("f", () => {
cursor.press();
});
cursor.onKeyRelease("f", () => {
cursor.release();
});
```
Now our mouse will also trigger `click` events.
## Moving the mouse
Now you can move the cursor as you want, usually you would use keys or a gamepad stick. Here's an example of moving it with arrows:
``` js
cursor.onKeyDown("left", () => {
cursor.move(-MOUSE_VEL, 0);
});
cursor.onKeyDown("right", () => {
cursor.move(MOUSE_VEL, 0);
});
cursor.onKeyDown("up", () => {
cursor.move(0, -MOUSE_VEL);
});
cursor.onKeyDown("down", () => {
cursor.move(0, MOUSE_VEL);
});
```
You can see an example of how it works in the [KAPLAYGROUND](https://play.kaplayjs.com?example=fakeMouse)
Previous
Canvas
Next
Particles
# Game Objects
Game objects are the entity unit of KAPLAY. They are the actors of your game, the entities that move, interact, and make the game interesting.
## Creating Game Objects
We create game objects with the `add()` function. It creates the object and attach it to the scene. It receives **components** and **tags**.
``` js
const dinosaur = add([
// while components gives different behaviours to the game obj
rect(32, 32), // draw a rect
pos(80, 80), // set a position
// tags classify the game object
"dangerous",
"big",
]);
```
We will see in deep components and tags in their respective guides.
## Parents, childs and root
A game object can have child game objects. This will give to the children the possibility of follow parent's position, rotation and scale.
``` js
const player = add([
rect(32, 32),
pos(80, 80),
]);
const head = player.add([
circle(16),
pos(0, -16), // relative to player position
]);
```
**Every game object** is a child of the **root game object**. The root game object is the game object that contains all the game objects in the scene.
That's why the `add()` function is, in fact, a `GameObjRaw.add()` method.
## Game Objects operations
### How to create a game object
``` js
const bag = add([
sprite("bag"),
]);
```
### How to remove a game object
``` js
// you can use .destroy() method or the destroy() function
bag.destroy();
destroy(bag);
```
### How to get all game objects
``` js
// get a list with all game objects
get("*");
// get a list of friends objects
get("friends");
```
### How to add a child
``` js
// It adds a mini-bag to bag
const miniBag = bag.add([
sprite("minibag"),
]);
const superMiniBag = bag.add([
sprite("superminibag"),
"favorite", // is the favorite
]);
```
### How to remove a child
``` js
// We pass the game object reference
bag.remove(miniBag); // 18, independency
```
### How to get childs
``` js
bag.get("*"); // all children
bag.get("favorite"); // [superMiniBag] - all children with tag favorite
```
You can see the full list of operations in the [`GameObjRaw`](/doc/GameObjRaw) documentation.
## The `make()` function
`make()` is used for creating a game object without adding it to the scene.
``` js
// Same syntax as add()
const bean = make([
sprite("bean"),
rotate(0),
]);
// No bean appears, but we can modify it
bean.angle = 270;
// Now make bean appears!
add(bean); // ohhi
```
## Creating game object dynamically
One way for create a game object is create a function that returns a list of components:
``` js
function createBullet() {
return [
rect(6, 18),
pos(80, 80),
color(0.5, 0.5, 1),
];
}
const bullet1 = add(createBullet());
```
Another option is return an object with `make()`, and then add it.
``` js
function createBullet(spr) {
const obj = make([
pos(80, 80),
color(0.5, 0.5, 1),
]);
// we use a sprite if passed, if not a rect
if (spr) {
obj.use(sprite(spr));
}
else {
obj.use(rect(6, 18));
}
return obj; // IMPORTANT: return the object reference
}
const bullet2 = add(createBullet("bullet")); // sprite
const bullet3 = add(createBullet()); // a rect
```
Previous
Basic Concepts
Next
Components
# How to make a multiplayer game with Colyseus and KAPLAY
If you have ever dreamed about making a multiplayer game but had no idea where to start or found it too hard to give it a try, now it's great time to give it a shot! There are many options to implement multiplayer in your game, but this time we are going to do so with a particular one, that is very easy to work with!
## About Colyseus
**[Colyseus](https://colyseus.io/)** is a fully-featured open source multi-player framework. It's versatile and scalable for any game genre. The key features we are going to take an advantage of are automatic state synchronization and creating a game room on demand. Having this ready out-of-the-box is a great initial help so you can focus on your game itself, instead of doing (basically a lot of) boilerplate work. All these concepts and more will be explained further.
## **This guide will cover:**
- How to **get started** with [Colyseus](https://colyseus.io/)
- Explanation and creation of **state schemas** your game will and might use
- Creating a **simple game** with concepts mentioned
- Some **tips and tricks** by **Mark** himself (he's actually smart) :mark:
### **Prerequisites or good to know/have:**
- Same as **KAPLAY**'s: Node.js, npm and Git installed ideally
- There will be some TypeScript here and there, but very understandable
- Terms like client and server are shuffled a lot - client is either the game part of our client/server setup or person connecting to the server, server is the room/Colyseus part or dev server running in your terminal for each of them
Grab a coffee or tea - it's going to be long but a fun one!
Also, if you are not interested in multiplayer that much, it still might be worthwhile for you as you can still learn a lot in the game-making section. 😉
## How to get started with Colyseus
The easiest way to make a game with Colyseus is by using the official [KAPLAY + Colyseus quickstart repository](https://github.com/colyseus/kaplay).
1. Navigate to your project folder and clone the starting repository
``` bash
git clone https://github.com/colyseus/kaplay.git kaplay-colyseus
```
2. Make it your own repository
``` bash
# Linux (Bash)
cd kaplay-colyseus; rm -rf .git; git init; git add .; git commit -m "Init commit"
# Windows (PowerShell)
cd kaplay-colyseus; rm -r -Force .git; git init; git add .; git commit -m "Init commit"
# Windows (CMD)
cd kaplay-colyseus && rmdir /s /q .git && git init && git add . && git commit -m "Init commit"
```
Git will make your life easier checking the file changes you have done since cloning the repository.
After doing so, created `kaplay-colyseus` folder should contain two folders, `client` and `server`. As you might already suspect, all KAPLAY code will reside in the former and Colyseus in the latter folder. The most important files to us will be `/server/src/rooms/MyRoom.ts` and `/server/src/rooms/schema/MyRoomState.ts`. We will get to the client one later on.
### How is KAPLAY (client) communicating with Colyseus (server)
First of all, alongside your regular KAPLAY setup, there is also a Colyseus npm package installed alongside. This is an SDK library that initiates connection and communicates with your Colyseus server running. It provides various helpful methods such as connection to the rooms, two-way state syncing, broadcasting and listening to the messages.
**The connection itself is done in two parts:**
1. Establishing the server connection with the endpoint of your server `/client/src/core/colyseus.ts`
``` ts
import { Client } from "colyseus.js";
export const colyseusSDK = new Client(
`${location.protocol}//${location.host}/colyseus`,
);
```
2. Connecting the client to it `/client/src/App.ts`
``` ts
import { colyseusSDK } from "./core/colyseus";
const room = await colyseusSDK.joinOrCreate<MyRoomState>("my_room", {
name: "Ka",
});
```
It really is that easy!
### What are rooms in Colyseus
As we mentioned rooms multiple times and you could notice `rooms` folder and its files inside, it's the right time to talk about them a little more.
Room is basically a connection instance that players connect to. You can have many rooms like lobby and then game modes, but a single room is enough as well. You also define max clients per room, so when you have a game for 2 players, each couple will have their own separate room. And as soon as both players disconnect, the room is disposed, by the default. This will Colyseus do for you automatically, so you don't have to worry about anything. It's just good to know. 🙂
There is also a state of your game defined in the room and synced to clients. Room is also where you define all the events like `onJoin` or `onLeave`, as you might be guessing - when a player (client) connects or disconnects.
### How does room state work
In Colyseus for room state to work, you need to define a schema with all the properties your objects will have. For example, your room state will include players and each player will have an id, name, avatar, etc. Depending on the game type, also the other data like x and y position. You will define all of that in the state schema so room can expect and enforce data type on all these properties.
Example of the room state in `/server/src/schema/MyRoomState.ts`:
``` ts
import { MapSchema, Schema, type } from "@colyseus/schema";
export class Player extends Schema {
@type("string")
public sessionId: string;
@type("string")
public userId: string;
@type("string")
public avatar: string;
@type("string")
public name: string;
@type("number")
public x: number = 0;
@type("number")
public y: number = 0;
}
export class MyRoomState extends Schema {
@type({ map: Player })
players = new MapSchema<Player>();
}
```
You can later send a message to the room to update the state. For example, updating your player's position:
In your game:
``` ts
k.onClick(() => room.send("move", k.mousePos())); // { x: 200, y: 100 }
```
And listening on server side, inside of `onCreate` room event:
``` ts
this.onMessage("move", (client, message) => {
const player = this.state.players.get(client.sessionId);
player.x = message.x;
player.y = message.y;
});
```
Client side, your `room.state` will be updated automatically, but you can also listen to changes yourself, like:
``` ts
import { client, getStateCallbacks } from "colyseus.js";
// ...
const $ = getStateCallbacks(room);
$(room.state).players.onAdd((player, sessionId) => {
// Listen to any instance change
$(player).onChange(() => k.debug.log(`Player ${player.name} is alive!`));
// Listen to a property change
$(player).listen(
"x",
(x, prevX) => k.debug.log("Player moved to", x, "from", prevX),
);
$(player).listen(
"y",
(y, prevY) => k.debug.log("Player moved to", y, "from", prevY),
);
});
```
`$` is a `getStateCallbacks` proxy helper imported from Colyseus SDK. You need to wrap the room state to be able to register `onChange` and `isten` listeners for their instance or property changes.
And finally, you can also `broadcast` your custom messages from the server with any data.
**On server:**
``` ts
this.broadcast("chat", message);
```
**In game:**
``` ts
room.onMessage("chat", (message) => k.debug.log(message));
```
In general, all communication is based on updating the state, listening to its changes and broadcasting messages between the server and clients
There is also a nice breakdown for everything state related in the official [Colyseus documentation](https://docs.colyseus.io/state).
## Starting your game dev servers
Now that we have the basic knowledge of the library concepts and client-server communication, we are finally ready to start our dev servers. 🥳
First, we need to get our Colyseus server started:
``` bash
cd server
npm install
npm start
```
Second, open new terminal tab/window and start your KAPLAY game dev server:
``` bash
cd client
npm install
npm start
```
For KAPLAY it's usually `npm run dev`, start is an alias for dev to match the Colyseus'
Navigate to your game at `http://localhost:5173`, you should see a simple KAPLAY setup with a random crew member! And you know what, open the game in another window, side by side and you got yourself the multiplayer part already working! ✨
<figure>
<figcaption>Best friends. Twice.</figcaption>
</figure>
## Creating a fun game as an example
With the knowledge gained so far, you could already go and try to make a game yourself. But we are just getting started. There is much more to learn. Some (best) practices and caveats, depending on the game itself. And I think, by making an **Air Hockey game** is a good example to show many of them. As you might have been already suspecting from the thumbnail. 🙂
> The whole game code can be found [here](https://github.com/imaginarny/kaplay-colyseus), but we encourage you to code along with us throughout the guide. There is also a live demo towards the end (just so you don't get spoiled too early).
------------------------------------------------------------------------
**Let's summarize what our game will be about, it's features and restrictions:**
- Playground/field **size** similar to hockey
- **Two players** game, each **movement restricted to** their own **half** of the field. Imagine having a paddle that you move with your hand at the top of one of the sides of the table/field. You can't reach past your half.
- **Ice-like** sliding **physics** for players, puck, and bounciness when hitting the walls
- **Score** counting for goals, each goal resetting both players and the puck
### Common data
For the field size, we will create a separate `globals.ts` file at the root of the project, as we will need it for both, client, and server. This will ultimately be the canvas size and will be used to calculate spawn positions. We will address those later.
``` ts
export const GAME_WIDTH = 800;
export const GAME_HEIGHT = 600;
```
### Updating state schema
From our game summary, we can already think of the state properties we will going to need (besides those we already have):
- Player team/side (simply "left" or "right")
- Puck X & Y position coordinates
- Score for each team/side
Let's update the schema state file `/server/src/rooms/schema/MyRoomState.ts`:
``` ts
// Player schema
export class Player extends Schema {
// ...
@type("string")
public team: "left" | "right" = "left";
}
```
We added `team` for the player. See, TypeScript is here to define possible values. Still understandable even if you are still "team JavaScript" 🙂. We also set `"left"` as the default.
``` ts
// Room schema (below the player)
export class MyRoomState extends Schema {
@type({ map: Player })
players = new MapSchema<Player>();
@type("number")
public puckX: number;
@type("number")
public puckY: number;
@type("string")
public lastHitBy: string;
@type("number")
public leftScore: number = 0;
@type("number")
public rightScore: number = 0;
}
```
And these are the rest of the properties that are good enough to be defined right in the room state schema. For example, we could do separate schema for puck with x/y props, but it doesn't make much sense for a single object that has no multiple instances.
You might need to restart the Colyseus dev server when updating the schema(s)
### Updating the room
Besides adding the new team property, we are also going to update max player count and some values to address the game dimensions we earlier prepared globals for. Add to the top of the `/server/src/rooms/MyRoom.ts` file:
``` ts
import { GAME_HEIGHT, GAME_WIDTH } from "../../../globals";
```
Next we change the max players count from 4 to 2 and add a little helper method for the player count per team:
``` ts
// ...
export class MyRoom extends Room { 
maxClients = 2;
state = new MyRoomState();
teamPlayersCount(team: "left" | "right" = "left") {   
return [...this.state.players.values()].filter(p => p.team == team).length; 
}
```
Now, within the same file, find the `onJoin` method and update it so `team` is assigned to the player once joined and change the spawn positions from random to the center of the side (quarter), depending on the team:
``` ts
onJoin (client: Client, options: any) {   
console.log(client.sessionId, "joined!");
const player = new Player();   
player.team = this.teamPlayersCount() % 2 ? "right" : "left";
player.x = player.team == "left" ? GAME_WIDTH / 4 : GAME_WIDTH - (GAME_WIDTH / 4);   
player.y = GAME_HEIGHT / 2;
//...
}
```
You might wonder why assigning team by even number. That's if we later decide to increase the max player count, so users will join each team evenly in altered way.
Now, if you open your game three times, you can see you will be alone in the third one. That means the max player count is working. We can also see the players spawn on fixed spots but it's not quite at the sides of the screen yet, as we haven't updated our canvas size yet. Let's fix that.
### Updating the game
First things first, let's update our KAPLAY library to `^4000.0.0-alpha.17` to get some goodies that will help with our game. Namely, circle shapes for collisions. You know, the puck is round. And `restitution` option to make the puck bounce off the walls. Instead of doing it ourselves, since we have a lot ahead of us. 🙂
``` bash
cd client
npm install kaplay@^4000.0.0-alpha.17
```
Don't forget to re-run the client dev server
Now, let's change the general setup of our game. Such as canvas size mentioned, so it's the same for both players and not affected by their screen size. And other options like background.
We will add these options to the `kaplay()` init function, update `/client/src/App.ts` file like this:
``` ts
import "./index.css";
import { GAME_HEIGHT, GAME_WIDTH } from "../../globals";
// ...
// Initialize kaplay
export const k = kaplay({
width: GAME_WIDTH,
height: GAME_HEIGHT,
letterbox: true,
pixelDensity: Math.min(window.devicePixelRatio, 2), // crispier on phones
background: "8db7ff",
});
```
At this point, I think we would benefit of having a nicer background to look at, which will also help us visualize the movement restriction we will do next. But let's not get ahead of ourselves and add the playground first!
We will create a new folder `/client/src/objs` where we will put all of our future objects. Each file will export an array of components, as it's what an object is composed in KAPLAY of.
Let's create `playground.ts` in the folder. It will be basically an object with boundaries to keep the puck in, field background and the goal nets. We could use one sprite for all of that, but we are going to draw it all in KAPLAY instead! 😮
``` ts
import type { GameObj } from "kaplay";
import { k } from "../App";
export default () => [
k.pos(),
k.z(0),
{
add(this: GameObj) {
const thickness = 500;
const bleed = 5;
this.boundaries = [
{
x: -thickness,
y: -thickness,
w: k.width() + thickness * 2,
h: thickness + bleed,
},
{
x: -thickness,
y: k.height() - bleed,
w: k.width() + thickness * 2,
h: thickness + bleed,
},
{
x: -thickness,
y: -thickness,
w: thickness + bleed,
h: k.height() + thickness * 2,
},
{
x: k.width() - bleed,
y: -thickness,
w: thickness + bleed,
h: k.height() + thickness * 2,
},
].map(({ x, y, w, h }) => {
this.add([
k.pos(x, y),
k.rect(w, h, { fill: false }),
k.area({ collisionIgnore: ["boundary"] }),
k.body({ isStatic: true }),
"boundary",
]);
});
},
},
];
```
Here we added invisible boundaries, that are outside of our screen, but bleed 5 pixels in. So if we enabled rectangles fill, we would see just 5px lines instead of 500px. Also, with thickness like that, we ensure the puck won't break out instead of bouncing away. It will be rejected back to the field as the distance back would be shorter than past it, if it manages to get a few pixels in (physics are updated at 50fps). I thought Mark was smart enough to say it himself.
I'm smart. *I'm am!*
Also, we added them to `collisionIgnore` array as they would be touching continuously forever and we don't need to waste our resources on it. We made them static as well, as they should never move.
Let's continue with the field, right under the `this.boundaries` code. We will center it as it will be easier to draw from the center as well:
``` ts
const field = this.add([
k.anchor("center"),
k.pos(k.center()),
k.rect(k.width() - 20, k.height() - 20, { radius: 100 }),
k.outline(10, k.WHITE),
k.opacity(0.4),
]);
```
I don't have anything smart to say about this either, so let's just add the nets as well right after:
``` ts
const nets = [-1, 1].map(side =>
field.add([
k.anchor("center"),
k.pos(field.width / 2 * side, 0),
k.rect(8, 200, { radius: side == -1 ? [0, 2, 2, 0] : [2, 0, 0, 2] }),
k.color(k.Color.fromHex("834dc4")),
k.outline(4, k.Color.fromHex("1f102a")),
k.area({ collisionIgnore: ["boundary", "player"] }),
"net",
{
team: side == -1 ? "left" : "right",
},
])
);
```
There are two things interesting here. The first one is that we are doing nets for both left and right side in one go and we are setting the `net.team` property for us to use later, for example to determine what net was scored into. And similarly, we don't need the collisions to bother with boundaries or players.
Nets are only interested in puck 😳
I promised we will draw the field in KAPLAY. We will do so in one draw event, right below the `nets` like this (brace yourself):
``` ts
field.onDraw(() => {
k.drawMasked(() => {
// Background center circle
k.drawCircle({
radius: 114,
color: k.Color.fromHex("c9ddff"),
});
// Middle line
k.drawRect({
anchor: "center",
height: field.height - 5,
width: 20,
color: k.Color.fromHex("adb2f0"),
outline: {
width: 4,
color: k.Color.fromHex("c9ddff"),
},
});
// Foreground center circle
k.drawCircle({
radius: 100,
color: k.Color.fromHex("bbd4ff"),
outline: {
width: 20,
color: k.Color.fromHex("adb2f0"),
},
});
// Small middle circle
k.drawCircle({
radius: 16,
color: k.Color.fromHex("834dc4"),
outline: {
width: 4,
color: k.Color.fromHex("d6e5ff"),
},
});
// Nets :)
nets.forEach(net => {
k.drawCircle({
anchor: "center",
pos: net.pos,
radius: net.height / 2,
color: k.Color.fromHex("adb2f0"),
outline: {
width: 4,
color: k.Color.fromHex("c9ddff"),
},
});
});
// Reflections
[
[-450, 20],
[-400, 60],
[0, 60],
[50, 20],
].forEach(([x, w]) =>
k.drawLine({
p1: k.vec2(x + 400, -field.height),
p2: k.vec2(x, field.height),
width: w,
opacity: 0.2,
})
);
}, () => {
// Field mask
k.drawRect({
anchor: "center",
width: field.width - 10,
height: field.height - 10,
radius: +(field?.radius ?? 100) - 10,
});
});
});
```
It looks complicated but there is no science to it. The only thing worth mentioning here is that we used `drawMasked()`, so any overflowing drawings, like the net circles, are cut off to not overflow the field. Field rectangle excluding the outline is used as a mask.
And finally, let's import the playground to the game, in `/client/src/scenes/lobby`:
``` ts
// at the top after the other imports
import playground from "../objs/playground";
export function createLobbyScene() {
k.scene("lobby", (room: Room<MyRoomState>) => {
k.add(playground());
// ...
```
Finally something nicer to look at.
### Player movement
Now that we have a reference point where the middle line is, let's implement the player object with restricted mouse movement that we defined as a game pattern earlier. Similar as you would use your hand to move the air-hockey paddle.
To better separate concerns in our code, we will create a `player.ts` file in our `/client/src/objs` folder:
``` ts
import type { GameObj, Vec2 } from "kaplay";
import type { MyRoomState, Player } from "../../../server/src/rooms/schema/MyRoomState";
import { k } from "../App";
import { Room } from "colyseus.js";
// Needs room state and player instance for server communication and player data
export default (room: Room<MyRoomState>, player: Player) => ([
k.sprite(player.avatar, { flipX: player.team == "right" }), // player on the right side will face center
k.pos(player.x, player.y), // initial pos by server
k.anchor("center"),
k.area({ shape: new k.Circle(k.vec2(0), (k.getSprite(player.avatar)?.data?.width ?? 32) * 0.4) }), // smaller area than sprite to not collide with transparent parts
k.body({ isStatic: true }), // won't be affected/moved when hit
k.scale(0), // we will scale-in player on spawn
k.z(player.y), // update Z sorting as well by matching it to Y
"player",
{
// Define a bunch of useful properties
sessionId: player.sessionId,
team: player.team,
startPos: k.vec2(player.x, player.y),
moveLerp: 12, // for position interpolation
overshootLerp: 30, // for fast movement interpolation
controllable: true, // e.g. disable when resetting player on goal
```
So far this is the base object for our player with more or less simple values. You can see some `lerp` properties, we will address those later. Let's continue with some more complicated ones for the restricted movement itself and the logic how the position will be updated and synced.
``` ts
add(this: GameObj) {
// Scale player in with nice transition once added
k.tween(this.scale, k.vec2(1), 0.25, v => this.scale = v, k.easings.easeOutBack);
// Raytracing :)
this.add([
k.anchor("center"),
k.sprite(player.avatar, { flipX: this.flipX, flipY: true }),
k.pos(0, k.getSprite(player.avatar)?.data?.height ?? this.height),
k.opacity(0.2),
]);
const moveOffset = {
x: this.width / 2,
y: this.height / 2,
overshoot: 10,
};
this.moveMinMax = {
x: Object.values(player.team == "left" ? {
min: moveOffset.x,
max: k.width() / 2 - moveOffset.x + moveOffset.overshoot,
} : {
min: k.width() / 2 + moveOffset.x - moveOffset.overshoot,
max: k.width() - moveOffset.x,
}),
y: Object.values({
min: moveOffset.y,
max: k.height() - moveOffset.y,
})
};
if (player.sessionId == room.sessionId) onLocalPlayerCreated(room, this);
},
},
]);
```
The most important thing here is we added raytracing for players by flipping the player sprite by Y axis and positioning it under the player. Reflections kinda work like that.
Well, the actual most important thing here is the `moveMinMax`, the minimum and maximum position coordinates for the players. Player on the left side, can move from 0 to half of the screen, where the middle line is. With player object size taken into account, as well as the `overshoot`. We have that so you can go slightly past the line, to not loose all the momentum right in front of it, like when trying to hit the puck in the center, but barely reaching it.
If you are confused seeing `Object.values`, it's just to visualize the min and max better than in a simple array. As the array will be easier to use in code later. And last but not least, we will call `onLocalPlayerCreated()` function that we are going to code next.
To determine if the player is the "local" one (you and not the others) we can compare `player.sessionId` and `room.sessionId`. Those will be the same in that case.
Why do we need the "local" player you may ask? Well, for example, we want you to control just one of the player objects. The one that belongs to you. Among the many other occasions where you need to think of if the event should trigger for all, or just for you, or if you want to sync your state and let the other's sync theirs.
So let's create the `onLocalPlayerCreated()` function, at the end of the file:
``` ts
function onLocalPlayerCreated(room: Room<MyRoomState>, playerObj: GameObj) {
// differentiate local player with tag
playerObj.tag("localPlayer");
// save mouse pos locally
let mousePos = playerObj.startPos;
const [moveMinX, moveMaxX] = playerObj.moveMinMax.x;
const [moveMinY, moveMaxY] = playerObj.moveMinMax.y;
const move = (_: Vec2, delta: Vec2, isMouse = true) => {
if ((isMouse && !k.isCursorLocked()) || !playerObj.controllable) return;
const { x, y } = mousePos;
const newX = x + delta.x;
const newY = y + delta.y;
mousePos = k.vec2(
k.clamp(moveMinX, newX, moveMaxX),
k.clamp(moveMinY, newY, moveMaxY),
);
room.send("move", mousePos);
};
k.onMouseMove(move);
}
```
Here, in the move function, we are checking if player has cursor locked - players will have to click first to take control so their cursor won't fly out of the window losing focus and control. In general, to update new position, we would do `axis + delta.axis`, but the movement is clamped and isn't applied to the player object immediately. Instead is sent to the server, where we will account for latency as well. Let's head back to our player object above, and update the players position so you can understand it better. Add this below the `add()` function:
``` ts
update(this: GameObj) {
this.pos.x = k.lerp(
this.pos.x,
player.x,
k.dt() * (this.moveMinMax.x.includes(player.x) ? this.overshootLerp : this.moveLerp)
);
this.pos.y = this.z = k.lerp(
this.pos.y,
player.y,
k.dt() * (this.moveMinMax.y.includes(player.y) ? this.overshootLerp : this.moveLerp)
);
},
```
First of all, notice we use `player.x` and `player.y`. This comes right from our server state which is always updated, especially as we are sending new position with `room.send("move", mousePos);` on mouse move event. Instead of applying it directly to the object pos as e.g. `this.pos.x = player.x`, we are going to apply linear interpolation `k.lerp()` between those values. That makes the movement smooth instead of being laggy or jumpy, as the server updates the value with a slight delay. We stored the lerp amount value as the property `this.moveLerp`. Basically, lower the number, the smoother the movement will be. But also slower and with higher delay, so with `12` we found a good middle-ground. But that isn't all. We are also accounting for the mouse overshoot, when you try to move it rapidly and hit the max position. Instead of going to the max quickly, you would see it going slowly in the curve and slowing down gradually, as you would get to the end position later due to the lerp. This image should make it more clear.
In that case, we check if player's final position is at the max (or min) and increase the lerp amount to a higher value `this.overshootLerp`. That way player can zoom there much more quickly and by that you eliminate the curve that would happen otherwise. The curve is also happening because even if you think you are moving with mouse in a perfect straight line, once you reach the max abruptly, you also move your hand up or down, naturally. And this looks much more exaggerated once you hit the imaginary barrier earlier than you anticipate and move your mouse past it.
All that is running in `update` function each frame and the lerp value is multiplied by the delta time (time passed since the last frame update).
You might also wonder why we are not updating the player pos immediately and send it to the server first. You could do that, but by sending first we are making both players have the same movement, making the server to have "the last word" over the pos, which makes it more fair and visually equal. And as a bonus, we are getting an on-ice effect as well.
This is close to the "server authority" but not quiet. Real server authority would be if we were sending just movement inputs and calculate player's coordinates server side. In this case, server would only have the state authority, but clients still control state of their objects, making it shared authority instead.
### Using our player object
Right now, you can see players spawn on their half, but you can still point & click to move anywhere instead. Code responsible for that is somewhere in the `/client/src/scenes/lobby.ts` file. If you have managed to find it on your own, you can ask for a digital banana sticker on our [Discord](https://discord.com/invite/aQ6RuQm3TF) (while the supply lasts). We will change the file gradually and get there. Add to the top after the other imports:
``` ts
import player from "../objs/player";
```
Find these lines with `onAdd` listener and replace them like this:
``` ts
// listen when a player is added in server state
$(room.state).players.onAdd(async (player, sessionId) => {
spritesBySessionId[sessionId] = await createPlayer(room, player);
});
```
We changed it to be asynchronous. You might have noticed we haven't used any sprite loading yet. We will change that for `createPlayer()`. But let's replace that click to move code first with this, along the way down at the bottom of the scene function:
``` ts
k.onClick(() => {
k.setCursorLocked(true);
});
```
We will still use mouse for the movement (obviously). And as that can be really frantic at times, we will lock the cursor to the canvas so you don't move away from the window accidentally. Which would result in player stopping, as we mentioned earlier. We have moved the movement logic to the `player` itself already.
So let's change `createPlayer()` function to use our player object:
``` ts
async function createPlayer(room: Room<MyRoomState>, playerState: Player) {
await k.loadSprite(playerState.avatar, `assets/${playerState.avatar}.png`);
await k.getSprite(playerState.avatar);
return k.add(player(room, playerState));
}
```
As you can see, we made it asynchronous to load player's avatar as a sprite first and made sure sprite data are loaded as well, before we create `player` object and return it.
Now, you can test the silly movement we have worked on so hard! 🥳
Woah, ice is slippery. Ok, I'm cold now.
### Adding the puck
So far it looks relatively simple with the movement client/server-wise, but syncing physics is a huge topic. Maybe for multiple guides with different approaches. Especially, when syncing a fast paced object like a puck that players interact with. You could do physics server-side, choose one client to be a "host", determine the outcome and sync it to the other clients, etc... Or we can be smart and do something you wouldn't have a headache from.
As the Air Hockey is basically one player hitting puck at the time, we can switch the "host" or **authority** - player that will let the physics to play out as they happen, and just sync it to the others. As soon as someone hits the puck, it changes them to be the host/authority. This way you get 100% accuracy where the puck is supposed to go, as the player hitting (you) is dictating it. If we were just syncing position of the puck itself, the chances the puck would go two different ways is very high as there can be a difference of just a few pixels when the hit happens for both players depending on their last updated position. Thanks to the **authority switching**, you avoid that by having the one source of truth at the time.
Let's create the puck object, at our usual objects location `/client/src/objs/puck.ts`:
First, we import all things used, as always:
``` ts
import { getStateCallbacks, Room } from "colyseus.js";
import type { Collision, DrawRectOpt, GameObj } from "kaplay";
import type { MyRoomState } from "../../../server/src/rooms/schema/MyRoomState";
import { k } from "../App";
```
Next, we define a couple of constants we will use. The puck `size` and the center `startPos`:
``` ts
const size = 48;
const startPos = () => (k.center().sub(0, 6));
```
We made `startPos` a function to recalculate the center, just in case. Also, the `sub` part is an offset to compensate the fake 3D perspective it has.
And now to the object itself:
``` ts
export default (room: Room<MyRoomState>) => [
k.pos(startPos()),
k.anchor("center"),
k.area({
shape: new k.Circle(k.vec2(0), size / 2),
restitution: 0.2, // bounciness
}),
k.body(),
k.scale(0), // we will scale-in the puck on spawn
k.z((k.height() - size) / 2), // starting Z is the the center of Y
"puck",
{
add(this: GameObj) {
const $ = getStateCallbacks(room);
const localPlayerId = room.sessionId;
// scale the puck in
// delay it if joining mid-game/resetting
k.wait(
room.state.puckX || room.state.puckX ? 1.25 : 0,
() =>
k.tween(
this.scale,
k.vec2(1),
0.25,
v => this.scale = v,
k.easings.easeOutBack,
),
);
this.onCollide("localPlayer", (_: GameObj, col: Collision) => {
// inform server of the hit
room.send("puck", { ...this.pos, hit: true });
// reset the current velocity
this.vel = k.vec2(0);
// simulate new hit with force by scaling the collision direction
this.applyImpulse(col.normal.scale(col.distance).scale(100));
});
this.onCollide("boundary", () => {
k.shake(2);
});
// reset velocity when lastHitBy changes as at this point the other player will only listen for the pos change
$(room.state).listen("lastHitBy", (id) => {
if (id == localPlayerId) return;
this.vel = k.vec2(0);
});
this.onCollide("net", async (net: GameObj) => {
// inform server only once, when local player registers the hit
if (room.state.lastHitBy != localPlayerId) return;
k.addKaboom(
k.vec2(
k.clamp(100, room.state.puckX, k.width() - 100),
room.state.puckY,
),
{ scale: 0.8 },
);
room.send("goal", net.team);
room.send("puck", startPos());
});
// update puck depending on authority/local player
this.onUpdate(() => {
// when local player is authority, just report the puck pos
if (localPlayerId == (room.state?.lastHitBy ?? localPlayerId)) {
room.send("puck", this.pos);
// when player isn't authority, lerp the reported pos
}
else {
this.pos.x = k.lerp(
this.pos.x,
room.state.puckX,
12 * k.dt(),
);
this.pos.y = k.lerp(
this.pos.y,
room.state.puckY,
12 * k.dt(),
);
}
// sync Z sorting by the Y axis
this.z = this.pos.y;
});
},
draw() {
const side: DrawRectOpt = {
pos: k.vec2(0, size / 4),
anchor: "center",
width: size,
height: size * 0.75,
color: k.Color.fromHex("4a3052"),
outline: {
width: 4,
color: k.Color.fromHex("1f102a"),
},
radius: [8, 8, size, size],
};
// Raytracing :)
k.drawRect({ ...side, pos: side.pos?.scale(2), opacity: 0.2 });
k.drawRect(side);
k.drawEllipse({
anchor: "center",
radiusX: size / 2,
radiusY: size / 2 - 4,
color: k.Color.fromHex("7b5480"),
outline: {
width: 4,
color: k.Color.fromHex("1f102a"),
},
});
},
},
];
```
The biggest point to take from this code is, that we had to think of how to setup collisions and when to send the puck data or when to just apply them. Once again, the local player is the one who is the authority of the puck physics, so as soon it's hit, besides sending the new pos, it informs about the hit itself `room.send("puck", { ...this.pos, hit: true });`. Then, it's checked in `onUpdate` if the `lastHitBy` was the local player. In that case, it continues in sending updates of the puck's position, each frame. Or if not, it means it's the other player, which will just apply the updated position from the `room.state`.
Another thing to mention is, that whenever the `lastHitBy` changes, we need to reset puck's velocity for the other player, otherwise it would battle with the manual position that is sent and applied from the server. It would make the puck shake if the other player hit the puck, but the local player didn't register that hit, due to the latency or lerp.
Besides the position and player hit event, we have already set up the goal event, when it collides with the net. It explodes, of course, then informs the server about it and resets its pos. We will expand on this later, when we implement the score. But for the `"puck"` event to work, we still need to listen for it on the server. So let's head to the `/server/src/rooms/MyRoom.ts` and add the listener to `onCreate`, below the `"move"` event:
``` ts
this.onMessage("puck", (client, message) => {
if (message?.hit) this.state.lastHitBy = client.sessionId;
this.state.puckX = message.x;
this.state.puckY = message.y;
});
```
And finally, let's import it to the game scene itself `/client/src/scenes/lobby.ts`:
Below the other imports:
``` ts
import puck from "../objs/puck";
```
In the lobby scene function opening code, below the playground object:
``` ts
k.scene("lobby", (room: Room<MyRoomState>) => {
k.add(playground());
k.add(puck(room));
// ...
```
Finally, we can have some fun on the field! Although, we have to finalize the goal mechanic and the score.
### Goal! & The Score
If you were paying attention, you would remember we were already sending the `"goal"` message when the puck hits the net. Let's head back to the server code and listen for it. In the `/server/src/rooms/MyRoom.ts` we will add a new listener below the `this.onMessage("puck", ...)`:
``` ts
this.onMessage("goal", (client, teamNet) => {
const team = teamNet == "left" ? "right" : "left";
this.state[`${team}Score`] += 1;
const pad =
Math.max(this.state.leftScore, this.state.rightScore).toString().length;
this.broadcast(
"score",
`${String(this.state.leftScore).padStart(pad, "0")}:${
String(this.state.rightScore).padStart(pad, "0")
}`,
);
});
```
Notice that the team score is the opposite one than the net that puck went in. We are also doing a fancy formatting, padding the number to be the same digits length, e.g. 0:0, 10:00. Then you should notice we are doing `this.broadcast("score", ...);` to send the message to all clients, so we can easily listen to this event.
We are doing fancy things. I might open a champagne.
We are getting close, but we are not done yet. We need to do multiple things and edit multiple files to address the goal/scoring.
Let's start with the puck as we might still have it in mind. It's at the `/client/src/objs/puck.ts` if you forgot like Mark did. Find the line with net collision `this.onCollide("net", ...);` and add below the new message listener:
``` ts
room.onMessage("score", async (score) => {
// reset puck physics
this.vel = k.vec2(0);
// ignore player collisions until we start new round
this.collisionIgnore.push("player");
// add some effects
if (score != "0:0") {
k.shake(10);
k.flash(k.getBackground() ?? k.WHITE, 0.25);
k.burp();
}
// scale out the puck before resetting it
await k.tween(
this.scale,
k.vec2(0),
0.25,
v => this.scale = v,
k.easings.easeOutQuad,
);
room.send("puck", startPos());
this.pos = startPos();
// scale it in after round starts and restore player collisions
k.wait(1, () => {
this.collisionIgnore = this.collisionIgnore.filter((c: string) =>
c != "player"
);
k.tween(
this.scale,
k.vec2(1),
0.25,
v => this.scale = v,
k.easings.easeOutQuad,
);
});
});
```
With this code we added some sort of rounds mechanic. Puck will disappear and reappear after one second after scoring to the net. At the same time, we are going to reset players to their starting positions as well. In the meantime, we disabled the collisions for the accidental hits while doing so. Let's implement it for the players as well.
Open `/client/src/objs/player.ts` and scroll down to the `onLocalPlayerCreated` function. We will add new listener, above the `const move`:
``` ts
room.onMessage("score", () => {
mousePos = playerObj.startPos;
playerObj.controllable = false;
room.send("move", mousePos);
k.wait(1.25, () => playerObj.controllable = true);
});
```
I think this code is fairly self-explanatory. But Mark needs it to be summed up. We are resetting our local `mousePos` to the player's start position, disabling player movement by using the `controllable` property that we have prepared earlier for, sync the position back to the server, and make the player controllable again after the new round starts.
Lovely. But I'm winning and no one will believe me as there is no score shown!
### Adding the score object
Before we add the score info to the game, let's download a nicer font and set it as the default.
Get the font by right clicking [this link](https://raw.githubusercontent.com/imaginarny/kaplay-colyseus/refs/heads/main/client/public/assets/happy-o.png) and save it as `happy-o.png` to the `/client/public/assets` folder. Then open the `/client/src/App.ts` file and change the default font in the `kaplay()` init options:
``` ts
// Initialize kaplay
export const k = kaplay({
// ...,
font: "happy-o",
});
```
Load the font right at the start of the `main()` function:
``` ts
async function main() {
await k.loadBitmapFont("happy-o", "./assets/happy-o.png", 31, 39);
// ...
```
Also, update the joining text font size below:
``` ts
const text = k.add([
k.text("Joining room ...", { size: 28 }),
// ...
```
And the final "puzzle" to our game is the score object itself. So let's create it at `/client/src/objs/score.ts`:
``` ts
import { Room } from "colyseus.js";
import type { GameObj } from "kaplay";
import type { MyRoomState } from "../../../server/src/rooms/schema/MyRoomState";
import { k } from "../App";
export default (room: Room<MyRoomState>) => [
{
textWidth: 24 * 3,
draw() {
k.drawRect({
anchor: "top",
pos: k.vec2(0, -6),
width: this.textWidth + 30,
height: 54,
radius: [0, 0, 16, 16],
color: k.Color.fromHex("1f102a"),
opacity: 0.8,
});
},
},
k.anchor("top"),
k.pos(k.width() / 2, 6),
k.fixed(),
k.z(9999),
k.text(`${room.state.leftScore ?? 0}:${room.state.rightScore ?? 0}`),
k.animate(),
{
add(this: GameObj) {
this.textWidth = this.width;
room.onMessage("score", (score) => {
this.text = score;
this.textWidth = this.width;
this.animation.seek(0);
this.animate("scale", [
k.vec2(1),
k.vec2(0.75, 1.05),
k.vec2(1.2),
k.vec2(1),
], {
duration: 0.2,
loops: 1,
});
});
},
},
];
```
We added a small bar to the top of the screen, centered horizontally. And made it fixed and on top of everything as well, so it's not affected by the game underneath. The most important part is that we listen to `"score"` message and update the in-game score with received updated score string. As a bonus, we added a little animation to nudge the whole score bar as well.
And finally, let's import it in the lobby scene, as always `/client/src/scenes/lobby.ts`:
In the beginning of the file, below the other imports add:
``` ts
import score from "../objs/score";
```
And `add` it below the other objects in the `createLobbyScene` function:
``` ts
export function createLobbyScene() {
k.scene("lobby", (room: Room<MyRoomState>) => {
k.add(playground());
k.add(puck(room));
k.add(score(room));
// ...
```
Too bad we are finally getting the hang of it towards the end. Or actually, nice job learning the ropes!
Nice indeed. I think we got us some Air Hockey game. 🥳
### Resetting the game
Hold on! We forgot one thing about the score. Mark almost tricked us so he can cheat. When one of the player leaves, the other would keep the score. So Mark could be winning immediately after you join. Same when he starts playing alone. We need to reset the game, when any player joins or leaves!
Let's head to the `/server/src/rooms/MyRoom.ts` and find both `onJoin` and `onLeave` events. Add the following as the last lines in the each of them:
``` ts
this.state.leftScore = 0;
this.state.rightScore = 0;
this.broadcast("score", "0:0");
```
Not only we reset the score, but we also informed the remaining player. For that, we reused the `"score"` message that our game already implemented. It resets the puck's position to the center, player to its initial position and resets the score as well. Neato, finito.
Note that when the second player joins, it could take a few seconds until the player object is created and spawned. Ideally, you should wait for that instead when resetting or starting the round, if you are letting the first player to play on their own in the meantime, as we do.
## Where to go with the game next
We could improve it further (and forever). By adding some small features, like doing countdown after each goal with proper round timing. Or some bigger ones, like adding the goalkeepers! I think that could be your homework.
Although, we surely all agree it could use at least a one more sound, besides the burp one on goal (this one will have to stay). And it's the sound of the puck hitting the wall. And the player hitting the puck (although adding burp here is tempting too).
Ok, right click [this link](https://github.com/kaplayjs/kaplay/raw/refs/heads/master/examples/sounds/hit.mp3) to download the sound and save it to the new folder at `/client/public/sounds` as `hit.mp3`.
Load it in the `/client/src/App.ts` file, in the `main()` function below the `k.loadFont(...);`:
``` ts
k.loadSound("hit", "sounds/hit.mp3");
```
Now, you might think this is going to be an easy change and we chose it because of the sake of it. Quite the opposite. And you will learn one more important thing.
Normally, we would do something for the puck object, like this:
``` ts
this.onCollide("boundary", () => k.play("hit"));
```
But this will only play when the local player is the authority. It's due to the puck's position either being lerped, or having a latency. So there is a very high probability that when the other player hits the puck to the wall, it won't sync position for you exactly when the puck hits the wall. We will have to split it for the local player, and the other players as well, similarly as we were doing with the puck position. And instead of limiting it only to the sound, let's also make it more general, to give you one more idea how to sync in-game events and data.
### Events & data syncing
Let's implement it on the server side first. We will listen for `"event"` message and broadcast another message to all clients, based on received data. Open `/server/src/rooms/MyRoom.ts` and add this below the `this.onMessage("goal", ...);`:
``` ts
this.onMessage(
"event",
(
client,
{ name, exceptLocal, data }: {
name?: string;
exceptLocal?: boolean;
data?: any;
} = {},
) => {
this.broadcast(
name ? `event:${name}` : "event",
data,
exceptLocal && { except: client },
);
},
);
```
We are expecting the second message argument to be an object, with the optional `name` property like `"hit"`, optional `exceptLocal` to exclude the "sender" and any `data` (we will use it later). Once server receives this event message, we will `broadcast` another one to inform all clients, optionally except the local one. We have already used `broadcast` once, but we haven't used the `except` option it offers. So thanks to that, the message will be broadcast only to the other players without any additional work on our part!
First, we will add the hit sound on collision with `"localPlayer"`. Open the `/client/src/objs/puck.ts`, find the `this.onCollide("localPlayer", ...);` and update it like this:
``` ts
this.onCollide("localPlayer", (_: GameObj, col: Collision) => {
room.send("puck", { ...this.pos, hit: true });
this.vel = k.vec2(0);
this.applyImpulse(col.normal.scale(col.distance).scale(100));
k.play("hit");
});
```
And for the other players, add this below the `"localPlayer"` collision code:
``` ts
this.onCollide("player", (obj: GameObj) => {
if (obj.is("localPlayer")) return;
room.send("event", { name: "hit" });
});
```
We are checking if the player isn't local one, meaning the other player. In that case we send the hit event. All players will listen to this event.
In the similar fashion, we are going to update `"boundary"` collision as well, it's right below it:
``` ts
this.onCollide("boundary", () => {
if (room.state.lastHitBy != localPlayerId) return;
k.shake(2);
k.play("hit");
room.send("event", { name: "hit", exceptLocal: true, data: "boundary" });
});
```
First, we are checking if the `localPlayer` is currently the authority, meaning the source of truth of the puck movement and the hit. Server will inform us about this hit instead. However, we are excluding the local player from receiving this event as the sound already played for them. Otherwise we could potentially hear the hit twice. This time we are also sending `data` property to differentiate the hit target. When hitting the walls, we are also shaking the screen.
Final code to listen for the hit event sent by the other players will look like this. Paste it below:
``` ts
room.onMessage("event:hit", async (target) => {
k.play("hit");
if (target == "boundary") k.shake(2);
});
```
This was and always will be confusing. We could do it easier, by not playing any sound for the "local" or "authority" player first and just send the event in all cases to listen to. This although could introduce some delay, when the latency is high, or duplication as already mentioned. Nevertheless, this caveat is good to know about and more importantly, know how to solve it.
### Syncing the other collisions
Now that we have another trick upon our sleeve, let's fix another collision that is not syncing. You might have noticed that the kaboom animation on goal is only showing for the player that scored. Or in other words, the local one with authority over the puck. This is also because of the lerp and the latency. For the local player, the puck collides with the net. But that doesn't happen for the other player, they are just informed about it. You can try to fix it yourself to test if you understood the past learning, it's very simple this time, just moving one line. Or, you can continue with us right away.
Once again, we are going to edit `/client/src/objs/puck.ts`. Find the `this.onCollide("net", ...);` function and remove the `k.addKaboom(...);` line. We are moving it to the `room.onMessage("score", ...);` listener, right after the `if (score != "0:0") {` condition opening. Like this:
``` ts
if (score != "0:0") {
k.addKaboom(k.vec2(k.clamp(100, room.state.puckX, k.width() - 100), room.state.puckY), { scale: 0.8 });
// ...
```
An easy fix, at last. Now the kaboom is added for both players, as both players are informed about the score update at the same time after scoring a goal.
### "Sync" about it
You will always have to think, if the thing you are doing will happen for both players and/or needs to be synced. For that case, now you should know the idea of "local" player and all the syncing methods available.
Let that pun "sync" in. 🙊🙂
## Bonus: Adding touch support for easier multi-device testing
Nowadays, almost everyone owns a smartphone. And you can't play with one mouse in two browser windows at the same time. So it makes sense that you would like to try play-testing against yourself more interactively and use your phone as the second player. Let's add support for it, it's going to be a quick one!
Open `/client/src/objs/player.ts` and look for the `let mousePos = playerObj.startPos;` line. Add new variable below it:
``` ts
let mousePos = playerObj.startPos;
let touchPos = playerObj.startPos;
```
Now, look for the `k.onMouseMove(move);` line. Add this code below it:
``` ts
k.onTouchStart(pos => touchPos = pos);
k.onTouchMove((pos) => {
move(pos, pos.sub(touchPos).scale(window.devicePixelRatio), false);
touchPos = pos;
});
```
First, we are saving the initial touch position on touch start. Then, we are using the same `move` function that mouse uses and we simulate the needed arguments for it. `pos` is a reported position by touch move, next argument is simulating the `delta` - just the difference between the new and the last pos, additionally scaled by the device pixel ratio (as the phone has different screen size/resolution/density). Without it, it would move slightly slower than you would expect. And the last one `false` is for the `isMouse` parameter.
We were already thinking about it when implementing move function because of the fact that we are using cursor lock and checking if the cursor is locked. And we made sure to check for it only when the input device is mouse (true as default). On the other hand with touch, there is no cursor to lock and we can't lock your finger (yet).
Now you will be able to control the player by touch. Time to learn how to test it on different devices.
## Testing your game with family members and friends
You can test your game on multiple devices in the same network by simply passing `--host` before starting the client dev server.
``` bash
cd client
# Linux
npm run start -- --host
# Windows
npm run start -- -- --host
```
Now you can notice it generated multiple addresses, we are interested in the **Network** one, like following:
``` bash
-> Network: http://192.168.1.2:5173/
```
The IP would be of your PC that is running this command, which you would navigate to on your other devices.
To eliminate the additional step of passing `--host` parameter to expose host each time, we can tell Vite to do it by the default. Just open `/client/vite.config.ts` and add `server.host` option:
``` ts
server: {
// proxy, etc...,
host: true,
}
```
That would cover the testing with family members or simply testing your game on your multiple devices.
### Testing with friends
To test your game with friends, your IP would have to be public, accessible to the outside world and port forwarded. Or you could simply use included tools to expose it for you securely, for free. You can use either `cloudflared`, or `ngrok`. Both are well known and established solutions. If you run into issues with any, just simply try the other one.
**Cloudflared**
``` bash
cd client
npm run cloudflared
```
**Ngrok**
You need to register a free account on [ngrok.com](https://ngrok.com/). Follow instructions after the first run.
``` bash
cd client
npm run ngrok
```
Remember to start the client dev server before running any of these.
**You will get the randomly generated URL that you can send to your friends to test your game with.**
<figure>
<figcaption>Cloudflared URL example</figcaption>
</figure>
Note that Cloudflare will do a bunch of request when you start the tunnel and open the link, resulting in a few connected players across multiple rooms. Just give them a minute to disconnect so you are actually alone in the game, to ensure the next connection will be an actual person. You can see them joining/leaving in your server terminal. Sadly, there is no way to detect and filter them out.
Also, beware that overseas connection latency to your PC will be higher. Performance also depends on your PC specs.
## Publishing your game
This will be the two part section as you need to deploy your server and host your game (client) somewhere online. These can depend a lot on your experience and skills, but there are some user friendly options as well.
### Deploying Colyseus server
You have two options how to deploy your Colyseus server.
1. **Self-hosting**
- You are free to host your Colyseus server anywhere you want and Colyseus itself provides you with a few options and guides on this topic at <https://docs.colyseus.io/deployment>
2. **Colyseus cloud, premium managed hosting**
- This is the easiest option that would take you around 10 minutes to get your server up and ready for production
- Learn more about that at <https://docs.colyseus.io/deployment/cloud>
> Note that both options are paid and require a use of credit card
### **Using Colyseus cloud**
Choosing Colyseus cloud is the easiest option as you are almost ready to deploy your server.
At this point, you should commit and push all your changes to your git repository. Then, all you need is to register an account at <https://cloud.colyseus.io/> and connect your GitHub repository.
Before running the deploy script, we need to update our build settings within the dashboard/project, as our Colyseus server is located inside of `/server` directory.
Now, you can run the deploy script. The first time doing so, you will be redirected to your browser to choose the application you want to deploy.
``` bash
cd server
npx @colyseus/cloud deploy
```
After following instructions in browser, It will create `.colyseus-cloud.json` file in the server folder with credentials for further deployments without any additional steps. You should not commit this file so better add it to your `.gitignore`.
After a while your server should be up and running! 🥳
Automated deployment
You can also automate deployment with GitHub actions. That means that every time you push your changes, GitHub would build and deploy it to Colyseus cloud for you. You can read more about that in their [continuous deployment](https://docs.colyseus.io/deployment/cloud/continuous-deployment) documentation entry.
### Publishing your game (client)
If you remember in the section about how the game communicates with the server, there was an endpoint URL to your server. We need to change this for the production as your game won't be running on the same server. You can get your endpoint in the [Colyseus cloud dashboard](https://cloudf.colyseus.io/), it will look like `https://<region-random-code>.colyseus.cloud`. Now we update our `/client/src/core/colyseus.ts` file like this.
``` ts
export const SERVER_URL = !import.meta.env.PROD
? `${location.protocol}//${location.host}/colyseus`
: "https://<region-random-code>.colyseus.cloud";
export const colyseusSDK = new Client(SERVER_URL);
```
`import.meta.env.PROD` comes from the Vite and is `true` when we build our game. So in production there will be the live Colyseus endpoint.
Now we can run the build command in the `/client` folder:
``` bash
cd client
# Linux
npm run build
# Windows
npx vite build
```
Game will be built in the `/client/dist` folder, ready to be uploaded. You can also test the build by running `npm run preview` command. From there, you should see you are connecting to the live Colyseus server instead of your local one.
Finally, you can upload your `/client/dist` online! You can learn more about it in the [publishing guide](https://kaplayjs.com/guides/publishing/), there is an example for itch.io and NewGrounds. Other free options could be Cloudflare Pages, Vercel, Netlify or simply GitHub pages, to name a few.
Play it now!
You can try our live demo [here](https://colyseus.kaplayjs.com). Note that the server is hosted in EU region so overseas latency will be very high. You might get better results with Cloudflared as mentioned earlier.
## Final notes and where to look further
As we mentioned earlier, you can refer to [Colyseus documentation](https://docs.colyseus.io/) or ask for further assistance on the official [Colyseus Discord](http://chat.colyseus.io/) server with library's excellent creator Endel himself present. 🙂
Similar for KAPLAY, you can find our other guides and API docs in the left sidebar as usual and are very welcome to our helpful [KAPLAY Discord](https://discord.com/invite/aQ6RuQm3TF) as well!
Also, don't forget to share your creations or any feedback with us. Good luck with your games!
Ohhi, I mean.. oh bye!
Previous
Video
Next
Creating your first game
# Welcome to KAPLAY Docs
In the KAPLAY Docs you will found guides, resources and all what you need for start using KAPLAY!
## Getting Started
Get started with KAPLAY
- [Installing](/guides/install)
- [Basic Concepts](/guides/starting)
- [Game Objects](/guides/game_objects)
- [Components](/guides/components)
## Create your first game
You can start learning KAPLAY.js basics creating a Chrome Dino-like game [Read \"Creating your first game\"](/guides/creating_your_first_game)
Psst!
Creating games is an adventure, but it's not a single player! Join our [Discord Server](https://discord.com/invite/aQ6RuQm3TF), where you can share your progress or ask for help if you run into any problems.
## NEWMultiplayer Integration
Integrate your KAPLAY games with a flexible and fun multiplayer framework, Colyseus. In our new [Multiplayer Guide](/guides/how-to-make-a-multiplayer-game-with-colyseus-and-kaplay) you will learn how to from start to deploying!
Remember that KAPLAY is a new born open source project. This documentation is constantly evolving and advancing :D
# Input Bindings
Input bindings allows you to use the same event for mouse, keyboard and gamepad. Also you can set a generic name like `jump` and bind it to the keys or buttons you want.
## Creating input bindings
You can define the bindings in the `buttons` object in `kaplay()`
``` js
// bind your buttons
kaplay({
buttons: {
jump: {
keyboard: ["space", "up"],
gamepad: ["south"],
},
},
});
```
Now you can use the different input handlers to listen to the `jump` event
``` js
onButtonPress("jump", () => {
player.jump();
});
onButtonDown("jump", () => {
player.jump();
});
onButtonRelease("jump", () => {
player.jump();
});
```
## Getting and setting bindings
Maybe you can dynamically change the bindings in your game. Depending for example of a configuration or a level.
You can use the `getButton(btn)` and `setButton(btn)` functions to get and set
``` js
// for example, get the keyboard bindings of the jump button then draw ui
getButton("jump").keyboard;
```
``` js
// change the jump button in keyboard to "w"
setButton("jump", {
keyboard: ["w"],
// gamepad binding is not changed
});
```
## Virtually trigger buttons
Sometiems there's a need to trigger a button virtually, for example when you want to simulate a button press in mobile or in a cutscene.
You can use `pressButton(btn)` and `releaseButton(btn)` to trigger the button:
``` js
pressButton("jump"); // triggers onButtonPress and starts onButtonDown
releaseButton("jump"); // triggers onButtonRelease and stops onButtonDown
```
Previous
Debug Mode
Next
Custom Components
# Installation
The most easy way to get started with KAPLAY is to use the [CLI tool](https://www.npmjs.com/package/create-kaplay), which will generate a project for you:
``` sh
$ npx create-kaplay mygame
$ cd mygame
$ npm run dev
```
This will create your game in the `mygame` folder, and start a development server for you to preview your game. If you edit `src/main.js` and refresh the page, you will see your changes.
To see all options, run:
``` sh
$ create-kaplay --help
```
## Using a CDN
If you prefer to use KAPLAY without any bundlers, you can use a CDN to include it directly in your HTML file, or import it with ECMAScript modules.
``` html
<script type="module">
// import kaplay
import kaplay from "https://unpkg.com/kaplay@3001/dist/kaplay.mjs";
// start kaplay
kaplay();
</script>
```
You can also just include it with a `<script>` tag.
``` html
<script src="https://unpkg.com/kaplay@3001/dist/kaplay.js"></script>
<script>
kaplay();
</script>
```
## Setup your own Node.js environment
With Node.js and npm it's easier have some other packages and use version control, also it's easier to get typescript autocomplete support, but it requires a bit more setup. (This is the way of `create-kaplay`)
``` sh
$ npm install kaplay
```
You'll need to use a bundler to use Kaboom with NPM. There's a lot of options like:
- `esbuild`,
- `webpack`,
- `parcel`,
- `vitejs`,
This is a short example of how to use Kaboom with ["esbuild"](https://esbuild.github.io/).
Once you have `esbuild` installed, and you have this in a `.js` or `.ts` file:
``` js
import kaplay from "kaplay";
kaplay();
```
just run
``` sh
$ esbuild game.js --bundle > build.js
```
and it'll find the KAPLAY package and include it in the built `build.js`, include `build.js` in your HTML and you're good to go. Feel free to automate this process.
## Loading Assets
You might have encountered errors when trying to `loadSprite()` from local file system, that is because browser won't allow loading local files with JavaScript. To get around that you'll need to use a static file that serves the files through HTTP. There're a lot of programs that helps you to do that.
- `$ python3 -m http.server` if you have [python3](https://www.python.org) installed
- `$ python -m SimpleHTTPServer` if you have [python2](https://www.python.org) installed
- `$ serve` if you have [serve](https://github.com/vercel/serve) installed
- `$ caddy file-server` if you have [caddy](https://caddyserver.com/) installed
- `$ static-here` if you have [static-here](https://github.com/amasad/static-here) installed
- `$ ruby -run -ehttpd . -p8000` if you have [ruby](https://www.ruby-lang.org/en) installed
- `$ php -S localhost:8000` if you have [php](https://php.net) installed
Let's say you have a folder structure like this:
``` sh
.
├── sprites
│   ├── froggy.png
│   └── cloud.png
├── sounds
│   └── horse.mp3
└── index.html
```
and you have the static file server running on port `8000`, just go to `http://localhost:8000/index.html`, and you should be able to load stuff from relative paths like
``` js
loadSprite("froggy", "sprites/froggy.png");
loadSound("horse", "sounds/horse.mp3");
```
To learn more check out this [MDN doc](https://developer.mozilla.org/en-US/docs/Learn/Common_questions/set_up_a_local_testing_server).
Previous
Plugins
Next
Basic Concepts
# Migrating from Kaboom.js to KAPLAY
KAPLAY is the fork of Kaboom.js, with the goal of continuing the development of the library.
This guide is in general, how to pass from Kaboom to KAPLAY.
## Updating the package
As KAPLAY is a fork of Kaboom, you can update the package in your project to `kaplay` and everything should work as before.
``` sh
npm install kaplay@3001
```
``` js
// before:
import kaboom from "kaboom";
// after:
import kaboom from "kaplay";
```
### CDN
``` js
// before:
import kaboom from "https://unpkg.com/[email protected]/dist/kaboom.mjs";
// after:
import kaboom from "https://unpkg.com/[email protected]/dist/kaboom.mjs";
```
## Trying out new features
To try out new features, you have to install the `@next` version of KAPLAY.
Check the [Installation Guide](/guides/install) for more information about installing KAPLAY.
Check the [Changelog](https://github.com/kaplayjs/kaplay/blob/master/CHANGELOG.md#v30010) for the new features and changes.
Previous
Publishing
# Optimization Tips
Here's some tips on optimizing performance / maintainability for KAPLAY games
## Game Object is not always the answer
Game objects are great for managing game entities, but they have a cost. If you are only rendering a static image, or a simple shape, you can use `onDraw` with `drawSprite` or `drawRect` instead of creating a game object.
``` js
// create a game object
const player = k.add([
k.sprite("bean"),
k.pos(100, 200),
k.scale(4),
k.opacity(0.5),
]);
// draw a sprite directly
k.onDraw(() => {
k.drawSprite({
sprite: "bean",
pos: k.vec2(100, 200),
});
});
```
If you're creating and destroying objects in an absurd rate, you should find another solution.
- Particles: `particle()` component instead of creating and destroying objects for each particle.
- Rendering: `onDraw` for rendering static images or shapes.
- Text: `text()` or `drawText()` transform instead of creating a game object for each letter/word.
- Data: `const gameData = {}` for storing game state instead of creating a game object the state.
## Cleanup One-off Objects
Sometimes there are some objects that gets created, leaves screen, and never seen again, like a bullet. These objects will keep being rendered / updated and be detrimental to performance if they get created a lot, it's better to remove them when they leave screen.
`offscreen()` is a component that helps you define behavior when objects go off-screen.
``` js
k.add([
k.sprite("bullet"),
k.pos(player.pos),
// the bullet move left forever
k.move(LEFT, 600),
// destroy the bullet when it's far out of view
k.offscreen({ destroy: true }),
]);
```
## Hide Off-Screen Objects
Sometimes you might be drawing a lot of objects that's not on screen (e.g. if you have a big map and your camera only sees a small area), this is very unnecessary, use `offscreen()` component to define object's behavior when they're not on screen.
``` js
// planting flowers all over the map
for (let i = 0; i < 1000; i++) {
k.add([
k.sprite("flower"),
k.pos(k.rand(-5000, 5000), k.rand(-5000, 5000)),
// don't draw or update the flower when they're out of view
k.offscreen({ hide: true, pause: true }),
]);
}
```
## Avoid Global Namespace
By default KAPLAY uses a lot of common names like `pos`, `sprite` that occupies global namespace, it's often better to use `global: false` to not export KAPLAY functions to `window`
``` js
const k = kaplay({
global: false,
});
const pos = k.vec2(120, 200);
```
Browsers replace the global namespace whenever they feel like it.
Another reason for avoid global namespace is that browsers can patch global namespace with their own functions, which can cause conflicts with KAPLAY functions. That happened with `navigate` component in the past.
## Compress Assets
Loading assets takes time, compress them when you can.
- Compress `.ttf` or `.otf` to `.woff2` (with [google/woff2](https://github.com/google/woff2))
- Compress `.wav` files to `.ogg` or `.mp3`
## Use Game Object local timers
When programming timer / tween behavior for a specific game object, it's better to attach `timer()` component to the game object and use that instead of global timer functions. This way the timer is tied to the life cycle of the game object, when then game object pauses or gets destroyed, the timer will not run.
``` js
// prefer
const player = k.add([
k.sprite("bean"),
k.pos(100, 200),
k.timer(),
k.state("idle"),
]);
// these timers will only run when player game object is not paused / destroyed
player.wait(2, () => {
// ...
});
await player.tween(
player.pos,
k.mousePos(),
0.5,
(p) => (player.pos = p),
k.easings.easeOutQuad,
);
// this will pause all the timer events
player.paused = true;
// this will stop all the timer events
player.destroy();
player.onStateEnter("attack", async () => {
// ... state code
// if we use global k.wait() here it'll create infinitely running state transitions even when player game object doesn't exist anymore
await player.wait(2);
player.enterState("idle");
});
player.onStateEnter("idle", async () => {
// ... state code
// if we use global k.wait() here it'll create infinitely running state transitions even when player game object doesn't exist anymore
await player.wait(1);
player.enterState("attack");
});
```
## Use Game Object local input handlers
Similar to above, it's often better to use local input handlers as opposed to global ones.
``` js
const gameScene = k.add([]);
const player = gameScene.add([
k.sprite("bean"),
k.pos(100, 200),
k.area(),
k.body(),
]);
// these
gameScene.onKeyPress("space", () => {
player.jump();
});
// this will pause all the input events
gameScene.paused = true;
// this will stop all the input events
gameScene.destroy();
```
Next
Animation
# Introduction
In this guide we will learn how to use the [`particles()` component](/doc/ctx/particles)
The particles component is a very efficient way of display tons of visual feedback, due to its optimized nature internally on KAPLAY.
## Creating a Particle Emitter
There are two parts to particles in KAPLAY, the particle emitter and the particles themselves. Both the particles and the particle emitter have options for us to modify, and come with important features to affect how our particles will appear.
``` js
let particleEmitter = add([
pos(center()),
particles(
{
max: 20,
speed: [50, 50],
lifeTime: [1, 2],
},
{
direction: 0,
spread: 45,
},
),
]);
```
Above is what the general setup of a particle emitter should look like.. The first set of options is the `ParticlesOpt`, and the second set is the `EmitterOpt`. The `ParticlesOpt` is composed of options related to what the particle will be doing after it is emitted, while the `EmitterOpt` is composed of options related to where, when, and what direction each particle will be emitted.
## Particle Textures in a Particle Emitter
Using a particle emitter requires us to use the texture and frames data of a sprite. There are multiple options for how to access this, but the easiest is using the built-in `getSprite().data` function to generate our particles. Below is an example on how to use textures for a particle emitter. *Don't forget to wait for your sprites to load!*
``` js
// load the sprite, and wait for the sprite to fully load before making the particle emitter
// NOTE: this is the easiest way to ensure your a sprite has been loaded, but not the best
loadSprite("bean", "./sprites/bean.png").then((data) => {
let loadedSpriteData = getSprite("bean").data;
// Fun fact: the data parameter passed from the promise is the same as getSprite().data
let particleEmitter = add([
pos(center()),
particles(
{
max: 20,
lifeTime: [1, 3],
texture: loadedSpriteData.tex, // texture of the sprite
quads: loadedSpriteData.frames, // to tell whe emitter what frames of the sprite to use
},
{
direction: 0,
spread: 45,
},
),
]);
});
```
## Using a Complete Particle Emitter
To spawn particles from the emitter, we can just use `particleEmitter.emit(n)`, where n is the amount of particles we want to spawn.
``` js
// Emit at runtime
particleEmitter.emit(5);
// Emit once a frame, good for prolonged effects
onUpdate(() => {
particleEmitter.emit(1);
});
// Emit on event call, good for bursts of projectiles. (like an explosion)
on("randomEvent", () => {
particleEmitter.emit(25);
});
```
Below is a complete example of how we should use the `particles()` component, along with explanations on each option in the options for `particles()`
``` js
// load the sprite, and wait for the sprite to fully load before making the particle emitter
// NOTE: this is the easiest way to ensure your sprites have been loaded, but not the best
loadSprite("bean", "./sprites/bean.png").then((data) => {
// Fun fact: the data parameter passed from the promise is the same as getSprite().data
let loadedSpriteData = getSprite("bean").data;
let particleEmitter = add([
pos(center()),
particles(
{
max: 20, // the max amount of particles generated from this emitter at one time
lifeTime: [2, 5], // how long the particles last before being destroyed
speed: [50, 100], // how fast the particles are moving
acceleration: [vec2(0), vec2(0, -10)], // changes the speed of the particle over its lifetime
damping: [0, 0.5], // slows down the particle over its lifetime
angle: [0, 360], // the rotation of each particle
angularVelocity: [0, 100], // how fast each particle should be rotating
scales: [1.0, 0.5, 0.0], // how large the particle is over its lifetime
colors: [RED, GREEN, BLUE], // the color of the particle over its lifetime
opacities: [1.0, 0.0], // the opacity of the particle over its lifetime
texture: loadedSpriteData.tex, // texture of the sprite
quads: loadedSpriteData.frames, // to tell whe emitter what frames of the sprite to use
},
{
shape: new Rect(vec2(0), 32, 32), // the area where particles should be emitted from (can be empty)
lifetime: 5, // how long the emitter should last
rate: 5, // the rate at which particles are emitted
direction: 0, // the direction where particles should be traveling
spread: 45, // variance in the direction where particles should be traveling
},
),
]);
// .onEnd is called when the emitter's lifetime (in this example 5 seconds), has expired.
particleEmitter.onEnd(() => {
destroy(particleEmitter);
});
// Emit Particles at runtime
particleEmitter.emit(5);
// Wait 1 second, then emit more
wait(1, () => {
particleEmitter.emit(15);
});
});
```
Previous
Fake Mouse
Next
Pathfinding
# Introduction
Pathfinding means searching for a path between one location and the other. It is mostly used in adventure or realtime strategy games, but is found in a lot of other game genres as well. There are both high level and low level pathfinding APIs available in Kaplay. This outlines their use.
# Using Level
Using the ready to go solution of the level, tile and agent components.
## Level component
Level has built-in pathfinding when using the agent component. By giving the player or enemy the agent component and spawning them inside a level, pathfinding is as simple as giving them a goal to move towards. They will avoid obstacles, reroute when the situation changes and announce when they reach their goal. The map they use is derived from the level itself.
``` js
const bean = level.spawn(
[
sprite("bean"),
anchor("center"),
pos(32, 32),
tile(),
agent({ speed: 640, allowDiagonals: true }),
"bean",
],
vec2(1, 1),
);
```
## Tile component
The tile component is a component automatically added to objects spawned within the level if it is not present already. The tile component has properties which can set the possibility of a tile, either global (isObstacle) or for each direction separately (edges). The difficulty of moving over a tile can be set as well (cost), making agents avoid sand or swamps if solid soil, grass or rock is available.
``` js
const level = addLevel(createMazeLevelMap(15, 15, {}), {
tileWidth: TILE_WIDTH,
tileHeight: TILE_HEIGHT,
tiles: {
"#": () => [sprite("steel"), tile({ isObstacle: true })],
},
});
```
# Custom pathfinding
While level supplies a ready made solution, your game might need more specific behavior.
## Maps or graphs
While level provides a map based on its tiles, there are situations when you may want to use a custom map. A map is a graph with nodes and connections. A node is a location, while the connection is a path between locations. There are two graphs you can use if you don't feel the need to implement your own. There is a grid graph which allows you to built a similar system as used in level. It is good for tile based games There is also a navigation mesh graph. This one uses polygons for nodes and edges for connections. It is more performant since there are less nodes, but harder to configure since there is no navigation mesh editor yet.
``` js
const nav = new NavMesh();
nav.addPolygon([vec2(20, 20), vec2(1004, 20), vec2(620, 120), vec2(20, 120)]);
```
## Navigation component
The navigation component simplifies using a map for navigation. It can be assigned a map to use, or it will look for an object with a navigationMap component in its ancestors.
``` js
// Use the navigation component with the given graph
add([
...navigation({
graph: nav,
navigationOpt: {
type: "edges",
},
}),
]);
```
Like agent, it can plot out a course, but won't move. It only calculates the waypoints to follow.
``` js
// Compute a path towards the player
path = enemy.navigateTo(player.pos);
```
## Patrol component
The patrol component can follow a set of waypoints, like the ones calculated by the navigation component. Like this, the two components can be used to simulate some of the functionality of agent.
``` js
// Use the patrol component with a speed of 100px per second
add([...patrol({ speed: 100 })]);
// Use the previously computed path
enemy.waypoints = path;
```
## Sentry component
The sentry component is made to sense when certain objects come into view. It is made to make enemies act on visual cues like noticing the player.
``` js
// Use the sentry component to look for the player using line of sight
add([
...sentry(
{ includes: "player" },
{
lineOfSight: true,
raycastExclude: ["enemy"],
},
),
]);
```
See [ghosthunting](https://play.kaplayjs.com/?example=ghosthunting) for a more complete example.
Previous
Particles
Next
Physics
# Introduction
There are two main components which implement physics in KAPLAY. Area and Body.
## Area
Area is used to define the area of the object. This can be seen as the collision shape, whether the object is actually solid or not. When using just area, without body, the object is not solid, but still reports overlapping with other areas. Area has three events for this:
- onCollide which is fired when the collision starts.
- onCollideUpdate which is fired during collision.
- onCollideEnd which is fired when the collision ends.
By default, an area component creates a shape similar to the shape which is drawn. Thus a sprite receives an area which has the size and position of the sprite. A custom shape can be passed if this is not what is needed.
## Body
Body makes an object with an area solid, as well as makes it being affected by gravity if gravity is set.
``` ts
setGravity(100);
// Inverse gravity
setGravityDirection(vec2(0, -1));
```
To make an object with a body not affected by gravity, like a platform, it can be made static using `isStatic: true`.
``` ts
add([pos(80, 400), rect(250, 20), area(), body({ isStatic: true })]);
```
A body has a velocity `obj.vel` (px/s). This velocity can changed by using impulses and forces. An impulse (px/s) is a sudden change in velocity, its effect does not depend on the mass (kg) of the object.
``` ts
obj.applyImpulse(vec2(100, 0));
```
A force (kg\*px/s\^2) is applied for one physics frame, and its effect depends on the mass of the object. The higher the mass, the less the force changes the velocity.
``` ts
obj.addForce(vec2(100, 0));
```
Even if the mass of the object is 1, these two calls will not have the same effect. The force will only be active during one physics frame (1/50th of a second), so it will not cause the horizontal velocity to increase by 100px, but only 2px. It has to be added for a duration of 2 seconds to have the same effect as the impulse.
### Mass
For simple games, mass doesn't need to be passed, as it defaults to 1 and will thus make no noticeable difference (force will be divided by 1). There are two places where mass makes a difference.
1. Collisions. When two objects collide, they will move away from each other (it is an elastic collision). The distance they move depends on their mass and velocity. A heavier object will impart a larger reaction force on the lighter object. Thus a light object colliding with a heavy object will have little effect, while a heavy object colliding with a light object will impart a large impulse.
2. Effectors. Effectors use forces. The larger the mass of an object, the larger the force is needed to accelerate it.
Where mass plays no role is gravity. Like in reality, an object's mass does not affect how fast it falls. Gravity is not a force, but an acceleration caused by the curvature of space-time (which is caused by the presence of mass). This acceleration is the same for all objects (9.806 meters/second\^2 on earth).
## Angular velocity and torque
Currently both the impulses and forces are applied at the center of mass of the area, causing no torque and thus no change in angular velocity. Once the collision module supports contact points, a more realistic simulation will be added.
# Effectors
Effectors implement forces which can be used to simulate various real world situations. They can be used by just adding one of the following components.
## AreaEffector
The areaEffector implements a directional force within a certain area. For example there can be a strong wind preventing a player to quickly run past traps, or an elevator using water flow. This effector is used without a body, since objects need to be able to travel through its area to be affected.
``` ts
add([
pos(20, 150),
rect(50, 300),
area(),
areaEffector({
forceAngle: -90,
forceMagnitude: 150,
}),
]);
```
## SurfaceEffector
The surfaceEffector implements a tangential force along the edges of an area. It's most common usage is to implement a conveyor belt. Unlike areaEffector, which takes a force, this effector takes a speed. It will adjust the force it uses according to the body's mass in order to reach the given speed. This effector is used with a static body, since objects need to rest on it, not penetrate the area.
``` ts
add([
pos(100, 300),
rect(200, 20),
area(),
body({ isStatic: true }),
surfaceEffector({ speed: 20 }),
]);
```
## PointEffector
The PointEffector implements a force towards or away from a point. The point in question is the position of the object in world space. All objects within its area are affected. The force can be constant, or depend on distance or squared distance. This effector is used without a body, since objects need to be able to travel through its area to be affected.
``` ts
add([
pos(85, 50),
rect(90, 90),
anchor("center"),
area(),
pointEffector({ forceMagnitude: 300 }),
]);
```
## BuoyancyEffector
The buoyancyEffector implements fluid buoyancy and flow. Objects falling in it will float depending on the density of the fluid. This effector is used without a body, since objects need to be able to travel through its area to be affected.
``` ts
add([
pos(400, 200),
rect(200, 100),
color(BLUE),
opacity(0.5),
area(),
buoyancyEffector({ surfaceLevel: 200, density: 6 }),
]);
```
## PlatformEffector
The platform effector makes it easier to implement one way platforms or walls. This effector is commonly used with a static body, and it will only be solid depending on the direction the object is traveling from.
``` ts
add([pos(100, 100), rect(100, 100), area(), body(), platformEffector()]);
```
The default is for the platform effector to allow all everything to collide with it *except* if the object collided on the bottom side of the platform --- this allows players to jump up "through" the platform, but not fall back down through it.
If you want to allow the player to collide with the platform *only* from the top, so that they can walk past the platform freely, pass in the sides that you don't want collisions to occur on:
``` ts
platformEffector({ ignoreSides: [UP, LEFT, RIGHT] });
```
You can also pass in a custom function to override the behavior and explicitly decide when to collide. For example, you can let the player choose whether they wnat to walk past items, or push them:
``` ts
platformEffector({
shouldCollide(obj, normal) {
// Collide with the floor (and everything else)
if (obj !== player) return true;
// Let the player push this platform if they hold shift
if (isKeyDown("shift")) return true;
if (normal.eq(LEFT) || normal.eq(RIGHT)) return false;
return true;
}
}),
```
Finally, you can add an object temporatily to a platform effector's `platformIgnore` set, and this will prevent the object from colliding even if it normally would:
``` ts
// Fall through when down is pressed
onKeyDown("down", () => {
const p = player.curPlatform();
if (p != null && p.is("platformEffector")) {
p.platformIgnore.add(player);
}
});
```
# ConstantForce
This is not an effector, since it doesn't need an area. It just adds a constant force each frame. It is good for an object which needs a constant acceleration, like a rocket for example.
Previous
Pathfinding
Next
Picture
# Introduction
Pictures contain drawing commands which can be replayed by drawing the picture. Pictures are an optimization primitive. By using a picture, a large part of the drawing pipeline can be shortcut. This is the normal pipeline, where everything is rendered to the screen framebuffer.
When a picture is active, the vertex data is sent to the picture instead. Later, when the picture is drawn, only the rendering step needs to be done.
# Creating a picture
Creating a picture is as easy as calling `beginPicture()`, drawing some primitives and finally calling `endPicture()` to get the finished picture.
``` ts
kaplay();
loadSprite("bean", "sprites/bean.png");
onLoad(() => {
beginPicture(new Picture());
for (let i = 0; i < 16; i++) {
for (let j = 0; j < 16; j++) {
drawSprite({
pos: vec2(64 + i * 32, 64 + j * 32),
sprite: "bean",
});
}
}
const picture = endPicture();
});
```
Note that we do this inside onLoad, since we need to be sure bean is loaded. If not, there won't be anything visible in the picture. Unlike a bean sprite component, which is drawn every frame, the draw method for the picture data is only really drawn once.
# Drawing a picture
A picture has no meaning in life if it isn't drawn. To draw a picture, use drawPicture, passing the picture as well as the desired transformation parameters.
``` ts
kaplay();
loadSprite("bean", "sprites/bean.png");
onLoad(() => {
beginPicture(new Picture());
for (let i = 0; i < 16; i++) {
for (let j = 0; j < 16; j++) {
drawSprite({
pos: vec2(64 + i * 32, 64 + j * 32),
sprite: "bean",
});
}
}
const picture = endPicture();
onDraw(() => {
drawPicture(picture, {
pos: vec2(400, 0),
angle: 45,
scale: vec2(0.5),
});
});
});
```
# Appending to a picture
When `appendToPicture()` is used instead of `beginPicture()`, new drawing commands can be added to an existing picture.
# Disposing of a picture
When done, a picture needs to be freed in order to free the WebGL buffers. This does not remove the picture data itself, so by appending and ending the picture, the picture can be restored.
``` ts
picture.free();
```
Previous
Physics
Next
Shaders
# Plugins
KAPLAY uses a flexible plugin system that helps you extend the library's functionality with new methods, constants, or even new components.
Let's take a look at how the default plugin `myPlugin()` is implemented.
``` js
// k is the KAPLAY context, what kaplay() returns
function myPlugin(k) {
return {
hi() {
k.debug.log("Hi from myPlugin!");
},
};
}
```
Now you can use the plugin in your game:
``` js
const k = kaplay({
plugins: [myPlugin],
});
k.hi(); // from myPlugin
```
## Creating a plugin
We recommend using our templates:
- [`kaplay-plugin-template`](https://github.com/kaplayjs/kaplay-plugin-template)
- [`kaplay-plugin-template-ts`](https://github.com/kaplayjs/kaplay-plugin-template-s) (for TypeScript)
Both are minimal and simple templates for create and publish plugins on NPM.
## Browse Plugins
### Community Plugins
- [kaplanck](https://kesuave.github.io/KaPlanck/) - Plank.js physics for KAPLAY
- [kaplay-rapier-physics](https://www.npmjs.com/package/kaplay-physics-rapier) Rapier physics for KAPLAY
You can explore all plugins made by the community in our [Discord](https://discord.gg/kaboom-883781994583056384).
Previous
Custom Components
Next
Installation
# Publishing a KAPLAY game
When we finish our game, the most important moment is to... Publish it!
## Preparing the game
We should prepare our game to pubish in the different platforms.
### Assets and source code
The first thing you should know it's both your `public` and `dist` folders (or whatever they are called) should be the same folder. We recommend having a file tree like:
``` plaintext
game/
┣ public/
┃ ┣ sprites/
┃ ┣ sounds/
┃ ┣ index.html - Your bundled index.html file
┃ ┣ game.js - Your bundled game file
```
This way, when you zip `public`, you will have all your assets and code files in the same folder. This is usually the folder you upload to game platforms like **Itch.io** and **Newgrounds.com**.
If you use create-kaplay\...
If you use `create-kaplay` template, you start with `public` dir by by default.
### Asset paths
When you host your games in web portals, you should use *relative paths*
Actually you may have something like this:
``` js
loadSprite("bean", "/sprites/bean.png");
```
There's two ways to handle this:
- Update all your imports to start with `./`
- Use `loadRoot()`
`loadRoot()` inserts what it's passed at start of every url:
``` js
loadRoot("."); // will add "." at start of every url
loadSprite("bean", "/sprites/bean.png"); // -> ./sprites/bean.png
```
Watch out!
Your `loadRoot()` depends of how your urls are. Maybe using `loadRoot("./")` *is a better option*
``` js
loadRoot("./"); // will add "./" at start of every url
loadSprite("bean", "sprites/bean.png"); // -> ./sprites/bean.png
```
## Itch.io
First, go to your account, then **Upload a new project**
Then, in **Kind of project**, you should select **HTML**, so itch.io will let you upload a web game
After that, the only thing left to do is to upload your zip with your game files, or if you have a single `index.html` file (very tasteful) upload it!
[**Itch.io Documentation about HTML5 games**](https://itch.io/docs/creators/html5)
## Newgrounds.com
First, go to the up arrow and select Game
Now, as Itch.io, only upload a zip with your fabulous `index.html` game file.
You can tag your game in the different platforms with the tag `kaplayjs` and
`kaplay`. Probably we will see it and even promote in our social medias :D
Previous
Creating your first game
Next
Migrating from Kaboom.js to KAPLAY
# Scenes
Scenes are the way to organize your game. They are like the chapters of a book, each scene is a different part of your game.
## Creating Scenes
To create a scene, we use the `scene()` function. This function receives a name and a callback function. The callback function is executed when the scene is activated.
``` js
scene("game", () => {
// your game code here
});
```
## Changing Scenes
When you want to change the current scene, you use the `go()` function. This function receives the name of the scene you want to go.
``` js
go("game");
```
## Passing Data Between Scenes
Passing data between scenes is quite easy, `go()` and `scene()` functions have parameters to pass data.
We can handle the score in the `game` scene:
``` js
scene("game", (score) => {
add([text(score), pos(12, 12)]);
});
```
Now we need to pass the score to the `game` scene, we do it with the `go()` function:
``` js
go("game", 100);
```
### Passing multiple parameters
If you have many parameters to pass, you can use an object to pass them:
``` js
scene("game", ({ score, level }) => {
add([text(`Score: ${score}`), pos(12, 12)]);
add([text(`Level: ${level}`), pos(12, 24)]);
});
```
And pass the object to the `go()` function:
``` js
go("game", { score: 100, level: 1 });
```
## Why can I use KAPLAY outside scenes?
You can use KAPLAY outside scenes, this have some advantages and disadvantages.
- **Advantage**: You can create simple games/examples without worrying about scenes.
- **Disadvantage**: If you add scenes later, your code outside scenes can't be run again. You can't do a `go()` without scenes.
``` js
k.add([sprite("mark")]);
k.scene("bean", () => {
k.add([sprite("bean")]);
});
// after this go, you can't return to mark :(
k.go("bean");
```
Fix it by putting your code inside a scene:
``` js
k.scene("mark", () => {
k.add([sprite("mark")]);
});
k.scene("bean", () => {
k.add([sprite("bean")]);
});
k.go("bean"); // we can do go("mark") later! :D
```
Previous
Events
Next
Sprites
# Shaders
In this guide you will learn how to write and use custom shaders in KAPLAY.
## Writing a shader
### Vertex shader
A vertex shader can manipulate data on vertex level. Usually a vertex shader can change any of the vertex's properties, but for KAPLAY only the position can be altered. In most instances the mesh will be a four point quad, thus the shader is called 4 times, once for each point in the quad. A default vertex shader would look like this. The function is passed the position, uv coordinate and color of the vertex and needs to return the updated position.
``` js
vec4 vert(vec2 pos, vec2 uv, vec4 color) {
return def_vert();
}
```
The default vertex shader returns the primitive's vertex unchanged. If a modified vertex is to be returned, it should be a 4 dimensional vector with x, y the position of the vertex, z=0 and w=1. Since there is no z-buffer, and the view is orthogonal, z has no effect. The w coordinate is 1 because we are returning a point, not a vector. Vectors can't be moved, therefore their w would be 0 and would not be influenced by the translation part of the matrix.
### Fragment shader
Once the positions of all vertices is determined, the primitive is rasterized. For each pixel drawn, the fragment shader is called. This shader can no longer change the position, but it can affect the color. A default fragment shader would look like this.
``` js
vec4 frag(vec2 pos, vec2 uv, vec4 color, sampler2D tex) {
return def_frag();
}
```
This default shader mixes the base color and texture colors together. If an altered color is to be returned, it should be a vec4 containing the r, g, b and a channels as floating point numbers between 0 and 1. For example, the following shader only uses the texture channel's alpha, while using the base color.
``` js
vec4 frag(vec2 pos, vec2 uv, vec4 color, sampler2D tex) {
return vec4(color.rgb, texture2D(tex, uv).a);
}
```
The following shader takes the texture color, grayscales it and then recolors it with the base color.
``` js
vec4 frag(vec2 pos, vec2 uv, vec4 color, sampler2D tex) {
vec4 tcolor = texture2D(tex, uv);
float gray = dot(tcolor.rgb, vec3(0.299, 0.587, 0.114));
return vec4(color.rgb * gray, tcolor.a);
}
```
## Loading a shader
There are two ways to load a shader:
- loadShader takes two strings with the vertex and fragment shader code.
- loadShaderURL takes file URLs for the vertex and fragment shaders.
## Passing data
Without parameters, a shader would be static, or would have to be redefined each frame if some dynamism was expected. Therefore a shader can have parameters which can change every time the scene is rendered. These parameters are called uniforms. Every function passing a shader also has a parameter to pass uniforms to the shader. For example, the following sprite effect defines a function which returns an object with a uniform called u_time. This function is called each frame, and the parameters are sent to the shader before rendering.
``` js
loadShader(
"invert",
null,
`
uniform float u_time;
vec4 frag(vec2 pos, vec2 uv, vec4 color, sampler2D tex) {
vec4 c = def_frag();
float t = (sin(u_time * 4.0) + 1.0) / 2.0;
return mix(c, vec4(1.0 - c.r, 1.0 - c.g, 1.0 - c.b, c.a), t);
}
`,
);
add([
sprite("bean"),
pos(80, 40),
scale(8),
// Use the shader with shader() component and pass uniforms
shader("invert", () => ({
u_time: time(),
})),
]);
```
Instead of a function, an object can be passed. This can be used in case the uniforms are not frame dependent. Note though that to replace uniforms set using an object, the function needs to be called once more (in case of usePostEffect) or the component readded (in case of the shader component). When using the direct draw API, like drawSprite or drawUVQuad, the shader and uniforms are passed through the render properties.
``` js
drawSprite({
sprite: "bean",
pos: vec2(100, 200),
shader: "invert",
uniforms: {
u_time: time(),
},
});
```
## Multipass shaders
Some shaders, like gaussian blur, need multiple passes in order to work. This can be done by making a framebuffer (makeCanvas), drawing inside this framebuffer (by using the drawon component or Canvas.draw), and using the famebuffer's texture (frameBuffer.tex) to draw a quad (uvquad component or drawUVQuad).
## Learning more about shaders
GLSL has a variety of functions which makes it easier to express your ideas in code. So be sure to look these up. Here are some resources to get started on writing GLSL shaders.
- [The Book of Shaders](https://thebookofshaders.com/)
- [WebGL reference card](https://www.khronos.org/files/webgl/webgl-reference-card-1_0.pdf)
Previous
Picture
Next
Debug Mode
# Rendering sprites
The sprites are probably most of your visual aspects of your game.
## Loading Sprites
For load a sprite, you can use the `loadSprite()` function. This function mainly takes two parameters, the sprite name and the sprite path.
``` js
loadSprite("bean", "sprites/bean.png");
```
This will load the sprite `bean` from the `sprites/bean.png` file.
### Spritesheets
When you have a spritesheet, you probably have animations. For these cases, the best option for you is to use the `loadSprite()`'s third argument, where you can set options related to animations.
``` js
loadSprite("player", "sprites/player.png", {
sliceX: 2, // how many sprites are in the X axis
sliceY: 2, // how many sprites are in the Y axis
anims: {
crack: { from: 0, to: 3, loop: false },
ghosty: { from: 4, to: 4 },
},
});
```
This will load the spritesheet, and create two animations, `crack` and `ghosty`.
## Using sprites
To use a sprite in a Game Object, you must use the `sprite()` component.
``` js
kaplay();
loadSprite("bean", "sprites/bean.png");
const bean = k.add([sprite("bean"), pos(100, 100)]);
```
And your bean will be here!
You can also set different parameters
``` js
const bean = k.add([
sprite("bean", {
frame: 1, // the frame of the sprite
flipX: true, // flip the sprite in the X axis
flipY: true, // flip the sprite in the Y axis
anim: "crack", // the animation to play at the start
}),
pos(100, 100),
]);
```
## Playing animations
To play an animation, you can use the `SpriteComp.play()` method.
``` js
const player = k.add([sprite("player"), pos(100, 100)]);
player.play("crack");
```
Previous
Scenes
Next
Sounds
# Basic Concepts
To get started with KAPLAY, you must know 4 main concepts: **Scenes**, **Game Objects**, **Components** and **Events**
You can think of your game as a theater: scenes are the acts, game objects are the actors and components are the script the actors follow.
## Initialization
All KAPLAY games start with the `kaplay()` function. This function makes available all methods and functions that you will use to create your game.
``` js
kaplay();
```
## Game Objects
The **game object** is the basic unit of KAPLAY. The player, a butterfly, a tree, or even a piece of text are all game objects. they are our actors, they move, interact, and make the game interesting.
You can create objects with the `add()` function, which takes an array of **components** that define the object's behavior (your actor's "script").
``` js
kaplay(); // remember to initialize the game
const obj = add([
// this is a component that draws a rectangle
rect(32, 32),
]);
```
## Components
Components are the building blocks of game objects. They define the behavior of the object, like how it moves, looks, and interacts with other objects.
In KAPLAY, there are many built-in components that you can use to create your game objects. For example:
- `pos(x, y)` sets the position of the object.
- `rect(width, height)` draws a rectangle.
- `color(r, g, b)` sets the color of the object.
We will go in deep on components in the [**Components**](/guides/components) guide.
## Scenes
Scenes are what wrap the game objects --- the acts of the stageplay. Typical scenes might include a main menu, the game itself, and a game over screen.
In KAPLAY, you create scenes with the `scene()` function:
``` js
kaplay(); // remember to initialize the game
scene("game", () => {
const rect = add([
// a component
rect(32, 32),
]);
});
```
## Events
Events are specific moments of your game execution that you can handle and execute code when that happens.
``` js
onUpdate(() => {
// this code is executed every frame (normally 60 times per second)
});
onKeyPress("space", () => {
// this code is executed only when the space key is pressed
});
```
We go in deep with events on the [**Events guide**](/guides/events) guide.
Previous
Installation
Next
Game Objects
# Tags
Tags are names, labels or keywords that group game objects, such as enemies, friends, trees, etc. They are useful for classifying different types of objects.
## Using tags
Tags can be added on the `add([])` function array as a string.
``` js
const ghost = add([
sprite("ghosty"),
"enemy",
]);
```
This make ghosty to have a tag enemy, and there's much operations you can do with it.
## Tags operations
### How to add a tag
``` js
// Add a tag on creation
const ghosty = add([
sprite("ghosty"),
"enemy";
]);
// Add 1 tag or many tags!
ghosty.tag("friend"); // now is a friend :D
ghosty.tag(["friend", "invisible"]); // invisible forever
```
### How to remove a tag
``` js
ghosty.untag("friend"); // D:
```
### How to know if a tag exists in a game object
``` js
ghosty.is("enemy"); // true if tag is there, otherwise false
```
### How to get a list of all tags
``` js
ghosty.tags; // readonly array with all tags.
// result: ["enemy"]
```
Important!
Don't try to push or modify this array. Is only for read purposes. If you want to add or remove a tag, use `.tag()` and `.untag()` instead.
## Using tags in events and methods
A big quantity of methods and functions works using tags.
``` js
obj.get("enemy"); // returns an array with all enemy game objects
```
## Special tag: \*
All game objects have the `*` tag by default. This can be useful for example to get all game objects
``` js
get("*"); // list of all game objects
```
## Components as tags
In v3001, KAPLAY by default will take component id's as tags:
``` js
// this means if your object have a sprite() component, it also have a "sprite" tag
const tga = add([
sprite("tga"),
]);
tga.is("sprite"); // true
```
In next versions this is disabled by default, but if you want to enable it or disable it in v3001 version, you can use the `tagsAsComponents` option:
``` js
kaplay({
tagsAsComponents: false,
});
tga.is("sprite"); // false
```
Previous
Components
Next
Events
# Introduction
A video can be played using the video component. This can be used for intros, or cut-scenes for example.
# The video component
``` ts
const intro = add([
pos(200, 100), // Where to place the video
video("intro.mp4"),
]);
intro.play();
```
# Play, pause, rewind
The video doesn't automatically start playing, for that `start()` needs to be called. To pause the video there is `pause()`. If you want stop functionality, you can call `pause()` and set `currentTime` to 0.
# Play position
The play position, aka `currentTime`, can be get and set. The relative position can be computed by dividing by `duration`.
Previous
Sounds
Next
Multiplayer with Colyseus
## Books
# Scalars or numbers
The real numbers form an algebra. We can add, subtract, multiply and divide them. The addition and multiplication is left and right distributive
$$a * (b + c) = a * b + a * c$$ $$(b + c) * a = b * a + c * a$$
Obviously the multiplication is compatible with scalars.
Multiplication is also commutative.
$$a * b = b * a$$
Numbers have their negation $-a$ which gives zero when added, as well as their reciprocal $\frac{1}{a}$ which gives 1 when multiplied.
## Powers
Multiplication is a shorthand for addition
$$a + a + a = 3a$$
Likewise powers are a shorthand for multiplication
$$a * a * a = a^3$$
Numbers to a negative power are the reciprocal of the same number to the positive power.
$$a^{-2} = \frac{1}{a^2}$$
Fractional powers gives use operations like square root
$$a^{\frac{1}{2}} = \sqrt{2}$$
# Vectors
Vectors take on many forms in games. We can find them for example as points, translations, forces or even rotations. A vector is something which can't be expressed using one number. For example a point in 2D needs 2 numbers, an x and an y value.
## Addition
There are different ways to see a vector. We can use a 2D vector to identify a point in 2D space. For example the point (3, 2) can be seen as the absolute coordinates of a specific point. But we can also see it a translation of the origin 3 units in the horizontal direction, and 2 units in the vertical direction. We can apply this translation to any point by using vector addition.
$$(0, 0) + (3, 2) = (3, 2)$$ $$(4, 4) + (3, 2) = (7, 6)$$ $$u + v = (u_x + v_x, u_y + v_y)$$
Even though all three terms are vectors, we can see this expression as point + vector = point.
## Multiplication with a scalar
We can't multiply two vectors. But if we multiply a vector by a scalar, we get a new, scaled vector.
$$2 * (2, 4) = (4, 8)$$ $$s * u = (s * u_x, s * u_y)$$
When we scale, only the distance traveled changes, not the direction. This is because the scale is uniform, both dimensions are scaled equally.
## Subtraction
Since we can multiply with the scalar -1, and in that way obtain the opposite vector, we can also subtract vectors.
$$(4, 4) - (3, 2) = (1, 2)$$ $$u - v = (u_x - v_x, u_y - v_y)$$
This allows us to make the translation vector t which translates a point u to another point v.
$$t = v - u$$
So in this case we see the expression as vector = point - point. Note that to make a vector from two points, you subtract the origin from the destination. The order is important.
## Division by a scalar
Since scalars have a reciprocal, we can divide by a scalar as well.
$$u / s = (u_x / s, u_y / s)$$
## Unit vector
If we scale a vector by the reciprocal of its length, we obtain a unit vector. A unit vector always has length 1.
$$unit(v) = v / length(v)$$
In situations where only the direction of the vector matters, it is often important to use a unit vector.
## Polar coordinates
If we look at a vector as a translation, we can see that it moves a point along a certain distance and in a certain direction.
Until now, we saw a vector as a Cartesian coordinate $(x, y)$. But if we look at it as a length r and an angle $\phi$ we can see it as a Polar coordinate $(r, \phi)$. It is still a vector, but the meaning of the elements is different. It is fairly easy to convert between the two. From Cartesian coordinates we can find the corresponding Polar coordinates as
$$r = \sqrt{(x^2 + y^2)}$$ $$\phi = atan2(y, x)$$
Why the length of the vector is the square root of the sum of the squares of its elements will be discovered shortly. We get the angle by turning the slope into an angle using atan2. The atan function takes just a slope and returns the corresponding angle as between $-\pi/2$ (-90) and $\pi/2$ (90). The atan2 function is similar, but looks at the signs of both x an y to determine the correct quadrant and returns an angle between 0 and $2\pi$ (360).
From Polar coordinates we can find the corresponding Cartesian coordinates as
$$x = r * cos(\phi)$$ $$y = r * sin(\phi)$$
Remember, cosine and sine are the x and y coordinate respectively of the unit vector pointing in the direction of the given angle. If we scale the cosine and sine by the length of the vector, we obtain the elements of the vector itself.
Now we might think that we are able to rotate a vector, by converting it to Polar coordinates, changing the angle and converting it back to Cartesian coordinates. And indeed, we could do that, but it would be slow. This is because trigonometric functions come with some cost. Why this is, is explained in the chapter on calculus.
To find a better way to rotate a vector we need to look at complex numbers.
# Complex numbers
Complex numbers in math classes are mostly seen as a way to take the square root of a negative number. This is possible because $i^2=-1$, thus for example $\sqrt{-4}=2i$. The letter $i$ stands for the imaginary number. For game developers complex numbers are much more valuable than that though.
A complex number is usually written as $a + bi$.
We can visualize it just like a vector, with $x=a$ and $y=b$.
## Addition and subtraction
Like numbers, and vectors, complex numbers can be added and subtracted.
$$(a + bi) + (c + di) = a + c + (b + d)i$$ $$(a + bi) - (c + di) = a - c + (b - d)i$$
## Multiplication
However, unlike vectors, complex numbers can also be multiplied.
$$(a + bi) \cdot (c + di) = ac - bd + (ad + bc)i$$
If we look at the angle of the direction of this product, its angle is the sum of the angles of $(a + bi)$ and $(c + di)$. Thus multiplying complex numbers adds their angles. This is what we can use to rotate vectors. If we want to rotate a vector (x, y) by an angle $\phi$, we only need to convert this angle to a vector, which we saw is $(cos(\phi), sin(\phi))$, and use complex multiplication to obtain the rotated vector.
$$(x * cos(\phi) - y * sin(\phi), x * sin(\phi) + y * cos(\phi))$$
Note that it is important that we multiply with a unit vector, if not, we would introduce a scale.
You might recognize this rotation formula, possibly in its following matrix form.
$$\begin{bmatrix}
x & y
\end{bmatrix} \times
\begin{bmatrix}
cos(\phi) & -sin(\phi)\\
sin(\phi) & cos(\phi)
\end{bmatrix}$$
This result is quite important as it shows that we are not really rotating using an angle, we are rotating using the unit vector $(cos(\phi), sin(\phi))$. It is important to realize this as we often do unnecesary conversions. For example when we want to make a sprite point towards the mouse, we often create a vector
$$dir = mousePos() - sprite.pos$$
Then we take the angle from this vector
$$angle = atan2(dir.y, dir.x)$$
And rotate the sprite using this angle. However, to actually rotate, the angle is converted to cos(angle) and sin(angle). This is just the unit vector of dir.
$$unit(dir) = (cos(angle(dir)), sin(angle(dir)))$$ $$unit(dir) = = dir / length(dir)$$
We could as well have taken the unit vector of dir and rotated using this vector. Going through angles is a roundabout way. Blame bad math classes for the fact that most graphics APIs only have rotate(angle: number) and not rotate(direction: vec2).
## Division
Complex numbers have a reciprocal
$$\frac{1}{(c + di)} = \frac{c}{c^2+d^2} - \frac{d}{c^2+d^2}i$$
This means we can not only multiply complex numbers, but divide as well
$$\frac{(a + bi)}{(c + di)} = \frac{ac + bd}{c^2+d^2} + \frac{bc - ad}{c^2+d^2}i$$
When we examine the angles again, we see that complex division subtracts angles. If we have two vectors (a, b) and (c, d), complex division can give us a vector which has an angle equal to the angle of (a, b) minus the angle of (c, d). This gives us a formula to calculate the angle between two vectors, without having to calculate their individual angles. We don't need to go through Polar coordinates.
Remember that we could get the angle of a vector using atan2.
$$\phi = atan2(y, x)$$
We can fill in the result of the quotient of our vectors. (observant people will have noticed that we switched the sign of the imaginary part. This is because in our 2D game engine the y axis goes down instead of up as is usual in mathematics).
$$\phi = atan2(\frac{ad - bc}{c^2+b^2}, \frac{ac + bd}{c^2+b^2})$$
But wait, atan2 just needs the slope y/x, and the individual signs of x and y. So the denominator isn't needed. It will get divided away anyway. So to get the angle between two vectors we just need to use
$$\phi = atan2(ad - bc, ac + bd)$$
These two formulas for y and x do look familiar don't they? this is because they are the 2D dot and cross products.
# Vector dot and cross products
$$dot(u, v) = u_x * v_x + u_y * v_y$$ $$cross(u, v) = u_x * v_y - u_y * v_x$$
If we have these functions, derived from complex division we can write the angle between two vectors as
$$angle(u, v) = atan2(cross(u, v), dot(u, v))$$
Note that the order of the operants is important, as it is for the cross product. Thus
$$angle(u, v) = -angle(v, u)$$ $$cross(u, v) = -cross(v, u)$$
We should by now realize that in the case of unit vectors, dot gives us the cosine of the angle between these vectors. While cross gives us the sine of the angle between these vectors. In case the vectors are not unit, we will have a multiplier equal to the product of the lengths of the vectors.
$$dot(u, v) = length(u) * length(v) * cos(\phi)$$ $$cross(u, v) = length(u) * length(v) * sin(\phi)$$
This is why dot(u, u) gives us the squared length of u. The angle between u and u is obviously zero, thus the cosine is 1.
$$dot(u, u) = length(u) * length(u) * cos(0) = (length(u))^2$$
Since
$$dot(u, u) = u_x^2 + u_y^2$$
We get the formula for length
$$length(u) = \sqrt{(u_x^2 + u_y^2)}$$
## 2D Vectors do not form an algebra
Since 2D vectors do not have a product which is left and right distributive, they do not form an algebra. The complex numbers do, as they do have a product which is not only bilinear (left and right distributive) but even both commutative and associative. So the complex numbers form an algebra. 3D vectors have a cross product which is left and right distributive and they form an algebra. Their cross product is neither associative nor commutative though. If we look at quaternions, the equivalent of complex numbers used in 3D, their Hamilton product is bilinear and associative.
# Polynomials
Polynomials are expressions containing a variable and using only operators +=\*/ and exponentiation with positive integer exponents. For example
$$2x + 4$$ $$x^2 + 4x + 2$$
Polynomials form an algebra, with polynomial multiplication.
## The line and linear interpolation
The most simple polynomial, one of degree 1, is the line. A line is typically written as $y = a + bx$. With a and b constants. The constant a is called the intercept (where we cross the y axis when x is 0), and b the slope.
We see that if we choose the slope as (b-a), that we obtain linear interpolation or lerp. What happens is that we create a line which goes from a to b as t goes from 0 to 1.
$$lerp(a, b, t) = a + (b-a) * t$$
Since we have addition, subtraction and scalar multiplication for vectors, we can do this for vectors a and b as well. Like this we can move from one location to another with constant speed.
What if the vector encodes a direction to use for rotation though. Say we have two vectors we use to rotate, can we just use linear interpolation? Not without modification. The problem is that a linear combination of two unit vectors will not give a new unit vector. This means we need to normalize the new vector, to make it a unit vector again. This gives normalized lerp.
$$nlerp(a, b, t) = unit(a + (b-a) * t)$$
However, this lerp does not have constant speed. There is a better way. The problem here is that we looked at direction vectors as vectors. But for direction vectors and the angles they represent, we should use complex number operations. As we saw, adding angles is multiplying complex numbers, and subtracting angles is dividing complex numbers. We're only left with multiply, which becomes exponentiation. Putting it together, we get slerp (spherical linear interpolation, which is actually exponential interpolation).
$$slerp(a, b, t) = a * (b / a)^t$$
This is what is used to interpolate between quaternions (the equivalent of complex numbers used in 3D graphics). While it looks promising, there is a caveat unfortunately. The power operation isn't that easy to do. While we know how to multiply complex numbers, and thus theoretically can calculate $(a+bi)^n$ where n is an integer, we're actually using real powers between 0 and 1, not integers. A solution is to use the Euler representation of a complex number.
$$e^{i\phi} = r * (cos(\phi)+sin(\phi)i)$$
Where r is the length of the vector and $\phi$ its angle. Knowing this, it is easy to take a power of a complex number using DeMoivre's Theorem
$$(e^{i\phi})^t = r^t * (cos(t*\phi)+sin(t*\phi)i)$$
However, to do this we need to convert the vector to Polar coordinates and back to Cartesian coordinates. Something we didn't like due to it's performance impact. So while slerp is quite an elegant solution mathematically, not being able to take a real power of a complex number directly kind of spoils the fun.
Still, slerp is not only for vectors or complex numbers in particular. It can be used on every multiplicative value. Now what is a multiplicative value? If we look at pos or angle, we combine two translations or angles by adding them.
$$pos = pos + translationVector$$ $$angle = angle + rotationAngle$$
However combining two scale factors is done by multiplying them.
$$scale = scale * scaleFactor$$
To add scale factors, you multiply them, just like you do with complex numbers. This means that scale actually should use slerp, not lerp. If we look what lerp gives for lerp(2, 8, 0.5), we get 5, while slerp(2, 8, 0.5) gives 4. If you think about scale, a scale halfway between 2 and 8 would be 4, not 5. Another place where we see this is audio. If we look for an audio sampling rate between 11025Hz and 44100Hz, then lerp gives us 27562.5Hz, while slerp gives us correctly 22050Hz.
So do all engines and editors interpolate scale wrong? Yes, yes they do. Just like the lack of a rotate function with a vector parameter, we are dealing with something which isn't well understood by most people. Some audio engineers know, but graphics people are still in the dark.
# Matrices
A matrix can be seen as a vector of vectors (though more dimensions, thus deeper nesting, is possible). The size or shape of a matrix depends on what we are using it for. In 2D games, the place where you might encounter it most frequently is transformations. Now you might ask, "why use a matrix?", as you can already translate, rotate and scale vectors now. The reason is mostly composition and inverting transformations. It is easy to compose two translations, by just adding them. But what if you add a rotation? How do you store both the rotation and translation. And when you translate after the rotation, your next translation should work according to the new rotated coordinate system.
To make all this easier, we use matrices. Though matrices are not the only way to do this, as we'll see later, there are other more compact constructs as well.
To add transformations, we multiply their matrices. Just like complex numbers.
## Matrix multiplication
Multiplying a matrix A with a matrix B means taking the dot product of the row vectors of A with the column vectors of B.
$$\begin{bmatrix}
a & b & c\\
d & e & f\\
g & h & i\\
\end{bmatrix} \times
\begin{bmatrix}
j & k & l\\
m & n & o\\
p & q & r\\
\end{bmatrix} =
\begin{bmatrix}
a*j+b*m+c*p & a*k+b*n+c*q & a*l+b*o+c*r\\
d*j+e*m+f*p & d*k+e*n+f*q & d*l+e*o+f*r\\
g*j+h*m+i*p & g*k+h*n+i*q & g*l+h*o+i*r\\
\end{bmatrix}$$
Note that this multiplication is not commutative, thus
$$A*B != B*A$$
This is good because transformations are not commutative.
## Identity matrix
To start with transformation specific matrices, here is an identity matrix. This matrix is like the number 1. If you multiply by 1, nothing happens. It's the same with this matrix. Multiplying by it gives you just the original matrix.
$$\begin{bmatrix}
1 & 0 & 0\\
0 & 1 & 0\\
0 & 0 & 1\\
\end{bmatrix}$$
$A * I = A$
## Translation matrix
Now, our vector is only 2 dimensional, so why a 3 dimensional matrix? It's to support translation. If we want to translate by a vector t, our translation matrix looks like
$$\begin{bmatrix}
1 & 0 & 0\\
0 & 1 & \\
t_x & t_y & 1\\
\end{bmatrix}$$
So let's multiply our vector v with that matrix to see what happens
$$\begin{bmatrix}
v_x & v_y & 1
\end{bmatrix} \times
\begin{bmatrix}
1 & 0 & 0\\
0 & 1 & 0\\
t_x & t_y & 1\\
\end{bmatrix} =
\begin{bmatrix}
v_x + t_x & v_y + t_y & 1
\end{bmatrix}$$
As you can see, we wrote our vector in the form of a row matrix, and we added a 1 to the end. Our result is a row matrix, also with a 1 at the end. As we can see, we successfully translated v by t, but what is that 1. The 1 at the end is actually a handy tool to distinguish points and normals. If our vector was a normal, it would have a 0 at the end. Let's see what would happen.
$$\begin{bmatrix}
n_x & n_y & 0
\end{bmatrix} \times
\begin{bmatrix}
1 & 0 & 0\\
0 & 1 & 0\\
t_x & t_y & 1\\
\end{bmatrix} =
\begin{bmatrix}
n_x & n_y & 0
\end{bmatrix}$$
Nothing seems to have happened. Which is exactly what we want. If we rotate a shape, normals will also rotate with the shape, but normals shouldn't translate if the shape is translated. This is because normals show the direction of the surface at the point where they are located, and the neither the surface , nor the normal's location relative to the surface changes under translation.
## Rotation matrix
So now that we have that established, let's rotate. We already saw how this matrix looks in the section about complex numbers.
$$\begin{bmatrix}
v_x & v_y & 1
\end{bmatrix} \times
\begin{bmatrix}
cos(\phi) & sin(\phi) & 0\\
-sin(\phi) & cos(\phi) & 0\\
0 & 0 & 1\\
\end{bmatrix} =
\begin{bmatrix}
v_x * cos(\phi) - v_y * sin(\phi) & v_x * sin(\phi) + v_y * cos(\phi) & 1
\end{bmatrix}$$
## Scale matrix
Scale is even easier. If we want to scale by s, we get
$$\begin{bmatrix}
v_x & v_y & 1
\end{bmatrix} \times
\begin{bmatrix}
s_x & 0 & 0\\
0 & s_y & 0\\
0 & 0 & 1\\
\end{bmatrix} =
\begin{bmatrix}
v_x * s_x & v_y * s_y & 1
\end{bmatrix}$$
Note that if we only want to allow a uniform scale, we need to keep $s_x=s_y$.
## Matrix transpose
The transpose of a matrix is one where rows are switched to columns.
$$\begin{bmatrix}
a & b & c\\
d & e & f\\
g & h & i\\
\end{bmatrix}^T =
\begin{bmatrix}
a & d & g\\
b & e & h\\
c & f & i\\
\end{bmatrix}$$
For a row vector that means that it becomes a column vector
$$\begin{bmatrix}
a & b & c
\end{bmatrix}^T =
\begin{bmatrix}
a \\
b \\
c \\
\end{bmatrix}$$
The transpose of the transpose of a matrix results in the original matrix.
## Pre and post-multiplication
What we used for our transformation matrices is pre-multiplication, as the vector went in front of the matrix.
$$\begin{bmatrix}
v_x & v_y & 1
\end{bmatrix} \times
\begin{bmatrix}
1 & 0 & 0\\
0 & 1 & 0\\
t_x & t_y & 1\\
\end{bmatrix} =
\begin{bmatrix}
v_x + t_x & v_y + t_y & 1
\end{bmatrix}$$
Most math and graphics systems use post multiplication. The matrices are the same, but transposed. Vectors are column vectors in this case.
# \$\$ \\begin{bmatrix} 1 & 0 & t_x\\ 0 & 1 & t_y\\ 0 & 0 & 1\\ \\end{bmatrix} \\times \\begin{bmatrix} v_x \\ v_y \\ 1 \\end{bmatrix}
\\begin{bmatrix} v_x + t_x \\ v_y + t_y \\ 1 \\end{bmatrix} \$\$
## Combining transformations
As said, the most common usage for matrices in a graphics API is combining transformations. They are combined using matrix multiplication. Since the multiplication is not commutative, the order matters. Most systems use a TRS transformation for nodes, translation, rotation and scale. For a post-multiplication system, it will look like this. This makes sure the points are first scaled, then rotated, finally translated. If we would use the reverse matrix order, the translation direction would be influenced by the rotation and the translation distance by the scale.
$$\begin{bmatrix}
1 & 0 & t_x\\
0 & 1 & t_y\\
0 & 0 & 1\\
\end{bmatrix} \times
\begin{bmatrix}
cos(\phi) & sin(\phi) & 0\\
-sin(\phi) & cos(\phi) & 0\\
0 & 0 & 1\\
\end{bmatrix} \times
\begin{bmatrix}
s_x & 0 & 0\\
0 & s_y & 0\\
0 & 0 & 1\\
\end{bmatrix} \times
\begin{bmatrix}
v_x \\ v_y \\ 1
\end{bmatrix}$$
If we would use the reverse matrix order, the translation direction would be influenced by the rotation and the translation distance by the scale.
Let's test this with a translate and scale matrix. As we can see, the scale leaves the translation alone.
$$\begin{bmatrix}
1 & 0 & t_x\\
0 & 1 & t_y\\
0 & 0 & 1\\
\end{bmatrix} \times
\begin{bmatrix}
s_x & 0 & 0\\
0 & s_y & 0\\
0 & 0 & 1\\
\end{bmatrix} =
\begin{bmatrix}
s_x & 0 & t_x\\
0 & s_y & t_y\\
0 & 0 & 1\\
\end{bmatrix}$$
Now let's switch them. We can see that the translation is affected by the scale, and the distance and possibly the direction we translate to has been modified.
$$\begin{bmatrix}
s_x & 0 & 0\\
0 & s_y & 0\\
0 & 0 & 1\\
\end{bmatrix} \times
\begin{bmatrix}
1 & 0 & t_x\\
0 & 1 & t_y\\
0 & 0 & 1\\
\end{bmatrix} =
\begin{bmatrix}
s_x & 0 & s_xt_x\\
0 & s_y & s_yt_y\\
0 & 0 & 1\\
\end{bmatrix}$$
## Anchor
We didn't incorporate the anchor yet. Currently the scale and rotation will happen from the local origin, after the translation. To rotate and scale from the anchor, we need to first translate the anchor to the origin, then perform the scale and rotation, and then translate back.
## Inverse Matrix
When we have a scalar $x$, the scalar $x^{-1}=1/x$ can be defined so that $x*x^{-1}=1$, as long as $x\ne0$. Similarly, we can calculate the inverse matrix $A^{-1}$ from $A$ so that $A*A^{-1}=I$.
The requirement for a matrix to be invertible is having a determinant which is not 0.
### The determinant
The determinant can be calculated in different ways, but what is it really? The determinant of $I$ is 1, so is the determinant of a translation or rotation matrix. Only a scale matrix or a transform containing a scale has a determinant different from 1. For a 2 by 2 matrix
$$\begin{bmatrix}
a & b \\ c & d
\end{bmatrix}$$
it is the surface area of a parallelogram made from (0, 0) (a , b) (c, d) and (a + c, b + d), thus the determinant is $ad - bc$. Note that if we write the vectors (a, b) and (c, d) as the previous matrix, their cross product is the determinant of this matrix.
$$det(\begin{bmatrix}
a & b \\ c & d
\end{bmatrix}) = (a,b) \times (c,d)$$
For a 3 by 3 matrix
$$\begin{bmatrix}
a & b & c \\ d & e & f \\ g & h & i
\end{bmatrix}$$
it is a volume equal to $aei+bfg+cdh-ceg-bdi-afh$. This determinant can also be written as a triple product consisting of dot and cross products
$$det(\begin{bmatrix}
a & b & c \\ d & e & f \\ g & h & i
\end{bmatrix}) = (a,b,c)\cdot((d,e,f)\times(g,h,i))$$
The determinant is used in various situations, but right now we'll use it to calculate the inverse matrix. It is logical that if we calculate the inverse of a matrix which scales, that we will need one which divides by that scale to negate it. This is why, if the matrix has a zero scale, we can't calculate the inverse, since we would divide by zero.
Later we will learn about decomposition as well as eigenvectors and eigenvalues which can give us the actual rotation and scale of the matrix. But for now we'll continue calculating the inverse.
### Calculating the inverse matrix
There are various ways to calculate the inverse. We can use the adjunct matrix, use various decompositions, solve equations, etc. For now, we will just give the solutions for 2 by 2 and 3 by 3 matrices. The inverse of a 2 by 2 matrix A is
$$\begin{bmatrix}
a & b \\ c & d
\end{bmatrix}^{-1}=
\frac{1}{det(A)}\begin{bmatrix}
d & -b \\ -c & a
\end{bmatrix}$$
The inverse of a 3 by 3 matrix A is
$$\begin{bmatrix}
a & b & c \\ d & e & f \\ g & h & i
\end{bmatrix}^{-1}=
\frac{1}{det(A)}\begin{bmatrix}
ei-fh & -(bi-ch) & bf-ce \\
-(di-fg) & (ai-cg) & -(af-cd) \\
(dh-eg) & -(ah-bg) & (ae-bd)
\end{bmatrix}$$
Why do we need the inverse? If we have an object which is transformed in order to place it in the world somewhere in a certain orientation with a certain scale, we have a transform which transforms local points to a point in the world. If we can invert this transform, we can transform world points to local points. If we have a transform from local to screen, we can calculate the inverse in order to calculate the mouse position into a coordinate local to an object. This are just a few examples, but there are really many places where this is useful. Like ellipses for example, these can be described as a matrix, which means we can find the transformation to transform an ellipse to a unit circle by inverting the matrix. This then helps us to simplify finding intersections with various shapes.
## Matrix decomposition
Before we look at more formal methods, let's take a look at our transformation matrix. We generally have the following form
$$\begin{bmatrix}
a & b & t_x \\ c & d & t_y \\ 0 & 0 & 1
\end{bmatrix}$$
We don't need to care about the last row. In fact we don't even need to store it, as it is always the same. The translation is very easy to extract, as it is always in the last column. Rotation and scale need a bit of math since the remaining 2 by 2 matrix is a mix of
$$\begin{bmatrix}
cos(\phi) & sin(\phi)\\
-sin(\phi) & cos(\phi)
\end{bmatrix}$$
and
$$\begin{bmatrix}
s_x & 0\\
0 & s_y
\end{bmatrix}$$
So
$$\begin{bmatrix}
cos(\phi) * s_x & sin(\phi) * s_y\\
-sin(\phi) * s_x & cos(\phi) * s_y
\end{bmatrix}$$
Since we know that $\sqrt{cos(\phi)^2+sin(\phi)^2} = 1$, We can get the scale as
$$s_x = \sqrt{a^2+c^2}$$ $$s_y = \sqrt{b^2+d^2}$$
Since $\phi = atan2(sin(\phi), cos(\phi))$, we can get the rotation angle as
$$\phi = atan2(-c, a) = atan2(b, d)$$
# Derivatives and differentiation
## Introduction
Derivatives are used extensively in games, even though many people don't realize that. When you are calculating the difference between this and last position, because you want to align an object along the path it follows, you are actually trying to calculate the derivative at the current position (Note that if you use physics with an integrator, you can just use the velocity. We are talking about the case where an analytical function is used instead).
$$f'(t) = \frac{f(t + dt) - f(t)}{dt}$$
The problem is that calculating the direction this way will depend a lot on the elapsed time. If dt is too large, you might be off a by a lot, and if dt is too small, your vector may become undefined.
A better way is to calculate the derivative of the function you use to decide the trajectory. See for example the following ballistics function:
$$f(t) = p_0 + v_0 * t + \frac{g * t^2}{2}$$
This function calculates the position of a projectile given the initial position $p_0$, the initial velocity $v_0$ and the gravity vector, which is most likely zero in the x dimension, e.g. $(0, g)$. So how do we get the direction of the trajectory at a time t? By calculating the velocity, which is the derivative of the position.
$$f'(t) = v_0 + g * t$$
This function will give us the velocity vector at each time t. If we take the angle of this vector, we can rotate our sprite in order to align it with the followed trajectory.
## Local minimum, maximum and inflection points
What if we want to know how high our projectile will go? Let's say we have an enemy in a cave system throwing stones. These stones follow the same kind of ballistic trajectory which we discussed before. The enemy is throwing the stones at random angles, but we don't want it to hit the ceiling. How do we get the highest point of the trajectory?
A local maximum or minimum of a function is a point on the function where the derivative is 0. This is logical as with a local minimum you go up (positive), reach the top, and go down (negative), so at the top your derivative is 0. So what if we set our derivative to 0? Note that we only look at the y output of our function
$$f'(t) = v_{y0} + g * t = 0$$
This happens when
$$t = \frac{-v_{y0}}{g}$$
Using this t in our original function gives the position where we reach a maximum.
$$p_{y0} + v_{y0} * (\frac{-v_{y0}}{g}) + \frac{g * (\frac{-v_{y0}}{g})^2}{2}$$
We see that this happens at
$$p_{y0} + \frac{-v_{y0}^2}{g} + \frac{v_{y0}^2}{2*g}$$
So the maximum position of our projectile for a given position and velocity is
$$p_{y0} - \frac{v_{y0}^2}{2*g}$$
We can now say, given an angle, how high the projectile will go, and only shoot when it won't hit the ceiling. But we can do better than that, since we know that
$$h = p_{y0} - \frac{v_{y0}^2}{2*g}$$
we can get the velocity in function of the height
$$v_{y0} = \sqrt(2 * g * (p_{y0} - h))$$
So we know our maximum y velocity given the height of our ceiling.
The ballistics case is special since the function has no local minimum and no inflection point. If our analytical function has minima or inflection points, we need to look at the sign of the second derivative. If it is negative, our point is a maximum, if it is positive a minimum, and if it is zero, we have found an inflection point. The second derivative of our ballistics function is
$$f''(t) = g$$
Thus whether we found a minimum, maximum or inflection point is completely dependent on the sign or value of g.
## Taylor series
Sometimes there are functions which we can't calculate directly. Let's say you need to calculate a cosine, but there is no cosine function. You only have mathematical operators (or a non-scientific calculator).
With derivatives, you can approximate the function around a given point. This approximation is a polynomial and is called a Taylor series. Given a function f, its Taylor series is
$$f(x) = f(a) + \frac{f'(a)}{1!}(x-a) + \frac{f''(a)}{2!}(x-a)^2 + \frac{f'''(a)}{3!}(x-a)^3 + ...$$
To give an example, let's take f(x) = cos(x). We know that its derivatives are
$$f'(x) = -sin(x)$$ $$f''(x) = -cos(x)$$ $$f'''(x) = sin(x)$$
So our Taylor series for cosine is
$$cos(x) = cos(a) − \frac{sin(a)}{1!}(x-a) − \frac{cos(a)}{2!}(x-a)^2 + \frac{sin(a)}{3!}(x-a)^3 + ...$$
For cos(x) around 0 (so a = 0) we get
$$cos(x) = cos(0) − \frac{sin(0)}{1!}(x-a) − \frac{cos(0)}{2!}(x-a)^2 + \frac{sin(0)}{3!}(x-a)^3 + ...$$
Since we know cos() = 1 and sin(0) = 0 we get
$$cos(x) = 1 − \frac{0}{1!}(x-0) − \frac{1}{2!}(x-0)^2 + \frac{0}{3!}(x-0)^3 + \frac{1}{4!}(x-0)^4 + ...$$
Cleaning this up we get an approximation for cosine around 0
$$cos(x) = 1 − \frac{x^2}{2!} + \frac{x^4}{4!} − ...$$
This is how trigonometric, logarithmic and other functions can be converted into polynomials which can then be calculated using basic operators. This is how also how libraries implement them.
## Calculating derivatives
In case you don't remember how to calculate the derivative of a function, here is a short guide. For a constant function, the derivative is 0.
$$f(x) = c$$ $$f'(x) = 0$$
The derivative of a sum is the sum of the derivatives
$$f(x) = a(x) + b(x)$$ $$f'(x) = a'(x) + b'(x)$$
The derivative of a product is
$$f(x) = a(x) + b(x)$$ $$f'(x) = a'(x)b(x) + b'(x)a(x)$$
The derivative of a nested function is
$$f(x) = a(b(x))$$ $$f'(x) = a'(b(x)) * b'(x)$$
Out of the product rule, we can derive the rule for polynomials. This is the rule which you'll use most of the time, as anything from ballistics to general splines are polynomials
$$f(x) = x^n$$ $$f'(x) = n * x^{(n-1)}$$
Out of the nested function rule, we can derive the rule for
$$f(x) = \frac{1}{a(x)}$$ $$f'(x) = \frac{a'(x)}{a(x)^2}$$
From this we can get the quotient rule
$$f(x) = \frac{a(x)}{b(x)}$$ $$f'(x) = \frac{a'(x)b(x) + b'(x)a(x)}{b(x)^2}$$
For the two most used trigonometric functions we have
$$f(x) = cos(x)$$ $$f'(x) = -sin(x)$$
and
$$f(x) = sin(x)$$ $$f'(x) = cos(x)$$
For logarithmic functions
$$f(x) = log_c(x)$$ $$f'(x) = \frac{1}{x*ln(c)}$$
and
$$f(x) = ln(x)$$ $$f'(x) = \frac{1}{x}$$
For exponential functions
$$f(x) = e^{ax}$$ $$f'(x) = ae^{ax}$$
and
$$f(x) = x^x$$ $$f'(x) = x^x(1 + ln(x))$$
## Partial derivatives
Sometimes we have functions with more than one input. In that case we can calculate partial integrals, which are integrals in one of the dimensions of the function.
For example the function
$$f(x, y) = x^2 + xy + y^2$$
Has a partial derivative in x equal to
$$f_x'(x, y) = 2x + y$$
This function gives the rate of change in the x dimension at every point $(x,
y)$.
# Integration
## Introduction
Integration is the opposite of differentiation. While differentiation looks for the rate of change of a give function, integration looks for a function given a rate of change.
Do we use that in games? Yes we do. Every physics simulation uses it. When we use simple Euler integration, we have
$$vel = vel + acc * dt$$ $$pos = pos + vel * dt$$
We integrate twice here, we calculate our new velocity from the rate of change of velocity, acceleration. Then we calculate our new position from the rate of change of position, velocity. Our velocity at a certain time is thus a sum of accelerations at certain points of time over a certain time span.
$$vel = vel_0 + \sum_{i=0}^{n}acc_i*dt_i$$
Same for position
$$pos = pos_0 + \sum_{i=0}^{n}vel_i*dt_i$$
These are Riemann sums. You can see them as rectangles with as height f(x) and width dt. Thus the result will be better the smaller dt is, as many thin boxes can approximate the function better than fewer larger boxes. This is why the KAPLAY physics engine runs at a fixed framerate. If it would run at the display framerate, results would be different between different devices. More performant devices would obtain better approximations for the same integral.
There are two kinds of integrals. What we just described is a definite integral. A calculation of the signed surface area under the function. An indefinite integral is a function called the anti-derivative.
## Indefinite integrals
If you know how to find the derivative of a function, you can find the anti-derivative of a function. What you need to look out for though is constants. The derivative of a constant was zero, this means that there are many anti-derivatives possible for the same function. For example both
$$x^2$$ $$x^2 + 5$$
derive to $2x$, thus any function $x^2 + c$, with c a constant is an anti-derivative of $2x$.
We can use integrals to calculate areas of various surfaces, water volumes or obtain a function when we know the rate of change of a certain value.
# How to be a Bean Wizard
> If you are reading this, you have been tricked by the promise of magic and fantasy (blame the person who selected the book title). Instead, your gruesome journey towards becoming a true game developer has started.
> Within these pages you will discover the reasons why you should have paid attention during you math classes instead of doodling or falling asleep. The blame for this inattention can of course be partially placed on your math teacher, who possibly didn't understand math good enough to come to the conclusion that math is everything and everything is math. Games are math, and without having a good enough grip on it to tame it, you will only be able to create a game which "kind of works", lacking the performance and grace of a true polished work of art. But fear not, math is not difficult once truly understood. Like language, it doesn't need (much) memorization, since everything follows naturally from simple concepts. All math mentioned here has practical uses in game development and is illustrated using examples from possible games. Now, you should get started. You can begin with any topic you like, as it is all connected, there is no beginning as there is no end.
--- MF
# We do books too!
## How to be a Bean Wizard
A guide to becoming a bean wizard.
## Docs
Redirecting to: /guides/install
[Redirecting from `/docs/` to `/guides/install`](/guides/install)
## API Reference
# [AddLevelOpt](#AddLevelOpt):
Options for the addLevel`addLevel()`.
# [pos](#AddLevelOpt-pos)?: Vec2
Position of the first block.
# [AgentComp](#AgentComp):
The agent`agent()` component.
# [agentSpeed](#AgentComp-agentSpeed): number
# [allowDiagonals](#AgentComp-allowDiagonals): boolean
# [getDistanceToTarget](#AgentComp-getDistanceToTarget)(): number
# [getNextLocation](#AgentComp-getNextLocation)(): Vec2 \| null
# [getPath](#AgentComp-getPath)(): Vec2\[\] \| null
# [getTarget](#AgentComp-getTarget)(): Vec2 \| null
# [isNavigationFinished](#AgentComp-isNavigationFinished)(): boolean
# [isTargetReachable](#AgentComp-isTargetReachable)(): boolean
# [isTargetReached](#AgentComp-isTargetReached)(): boolean
# [setTarget](#AgentComp-setTarget)(target: Vec2): void
# [onNavigationStarted](#AgentComp-onNavigationStarted)(cb: ()=\>void): KEventController
# [onNavigationNext](#AgentComp-onNavigationNext)(cb: ()=\>void): KEventController
# [onNavigationEnded](#AgentComp-onNavigationEnded)(cb: ()=\>void): KEventController
# [onTargetReached](#AgentComp-onTargetReached)(cb: ()=\>void): KEventController
[AgentCompOpt](#AgentCompOpt):
# [speed](#undefined-speed)?: number
# [allowDiagonals](#undefined-allowDiagonals)?: boolean
Options for the agent`agent()` component.
# [Anchor](#Anchor): topleft \| top \| topright \| left \| center \| right \| botleft \| bot \| botright
# [AnchorComp](#AnchorComp):
The anchor`anchor()` component.
# [anchor](#AnchorComp-anchor): Anchor \| Vec2
Anchor point for render.
# [AnimateComp](#AnimateComp):
# [animate](#AnimateComp-animate)\<T\>(name: string, keys: T\[\], opts: AnimateOpt): void
Animates a property on this object.
`param`nameName of the property to animate.
`param`keysKeys determining the value at a certain point in time.
`param`optsOptions.
# [unanimate](#AnimateComp-unanimate)(name: string): void
Removes the animation from the given property.
`param`nameName of the property to remove the animation from.
# [unanimateAll](#AnimateComp-unanimateAll)(): void
Removes the animations from all properties
# [onAnimateFinished](#AnimateComp-onAnimateFinished)(cb: ()=\>void): KEventController
Attaches an event handler which is called when all the animation channels have finished.
`param`cbThe event handler called when the animation finishes.
# [onAnimateChannelFinished](#AnimateComp-onAnimateChannelFinished)(cb: (name: string)=\>void): KEventController
Attaches an event handler which is called when an animation channels has finished.
`param`cbThe event handler called when an animation channel finishes.
# [base](#AnimateComp-base): BaseValues
Base values for relative animation
[animation](#AnimateComp-animation):
# [paused](#undefined-paused): boolean
Pauses playing
# [seek](#undefined-seek)(time: number): void
Move the animation to a specific point in time
# [duration](#undefined-duration): number
Returns the duration of the animation
# [serializeAnimationChannels](#AnimateComp-serializeAnimationChannels)(): Record\<string, AnimationChannel\>
[serializeAnimationOptions](#AnimateComp-serializeAnimationOptions)():
# [followMotion](#undefined-followMotion)?: boolean
# [relative](#undefined-relative)?: boolean
Serializes the options of this object to plain Javascript types
# [AnimateCompOpt](#AnimateCompOpt):
# [followMotion](#AnimateCompOpt-followMotion)?: boolean
Changes the angle so it follows the motion, requires the rotate component
# [relative](#AnimateCompOpt-relative)?: boolean
The animation is added to the base values of pos, angle, scale and opacity instead of replacing them
# [AnimateOpt](#AnimateOpt):
# [duration](#AnimateOpt-duration): number
Duration of the animation in seconds
# [loops](#AnimateOpt-loops)?: number
Loops, Default is undefined aka infinite
# [direction](#AnimateOpt-direction)?: TimeDirection
Behavior when reaching the end of the animation. Default is forward.
# [easing](#AnimateOpt-easing)?: EaseFunc
Easing function. Default is linear time.
# [interpolation](#AnimateOpt-interpolation)?: Interpolation
Interpolation function. Default is linear interpolation.
# [timing](#AnimateOpt-timing)?: number\[\]
Timestamps in percent for the given keys, if omitted, keys are equally spaced.
# [easings](#AnimateOpt-easings)?: EaseFunc\[\]
Easings for the given keys, if omitted, easing is used.
[AnimationChannel](#AnimationChannel):
# [keys](#undefined-keys): AnimationChannelKeys
& AnimationOptions
# [AnimationChannelKeys](#AnimationChannelKeys): number\[\] \| number\[\]\[\]
[AnimationOptions](#AnimationOptions):
# [duration](#undefined-duration): number
# [loops](#undefined-loops)?: number
# [direction](#undefined-direction)?: TimeDirection
# [easing](#undefined-easing)?: string
# [interpolation](#undefined-interpolation)?: Interpolation
# [timing](#undefined-timing)?: number\[\]
# [easings](#undefined-easings)?: string\[\]
# [App](#App): ReturnType\<initApp\>
[AppEventMap](#AppEventMap):
# [mouseMove](#undefined-mouseMove): \[\]
# [mouseDown](#undefined-mouseDown): \[MouseButton\]
# [mousePress](#undefined-mousePress): \[MouseButton\]
# [mouseRelease](#undefined-mouseRelease): \[MouseButton\]
# [charInput](#undefined-charInput): \[string\]
# [keyPress](#undefined-keyPress): \[Key\]
# [keyDown](#undefined-keyDown): \[Key\]
# [keyPressRepeat](#undefined-keyPressRepeat): \[Key\]
# [keyRelease](#undefined-keyRelease): \[Key\]
# [touchStart](#undefined-touchStart): \[Vec2, Touch\]
# [touchMove](#undefined-touchMove): \[Vec2, Touch\]
# [touchEnd](#undefined-touchEnd): \[Vec2, Touch\]
# [gamepadButtonDown](#undefined-gamepadButtonDown): \[KGamepadButton, KGamepad\]
# [gamepadButtonPress](#undefined-gamepadButtonPress): \[KGamepadButton, KGamepad\]
# [gamepadButtonRelease](#undefined-gamepadButtonRelease): \[KGamepadButton, KGamepad\]
# [gamepadStick](#undefined-gamepadStick): \[string, Vec2, KGamepad\]
# [gamepadConnect](#undefined-gamepadConnect): \[KGamepad\]
# [gamepadDisconnect](#undefined-gamepadDisconnect): \[KGamepad\]
# [buttonDown](#undefined-buttonDown): \[string\]
# [buttonPress](#undefined-buttonPress): \[string\]
# [buttonRelease](#undefined-buttonRelease): \[string\]
# [scroll](#undefined-scroll): \[Vec2\]
# [hide](#undefined-hide): \[\]
# [show](#undefined-show): \[\]
# [resize](#undefined-resize): \[\]
# [input](#undefined-input): \[\]
App events with their arguments
# [AppEvents](#AppEvents): MappedType
The App method names that will have a helper in GameObjRaw
[AppGfxCtx](#AppGfxCtx):
# [lastDrawCalls](#undefined-lastDrawCalls): number
How many draw calls we're doing last frame
# [ggl](#undefined-ggl): GfxCtx
# [defShader](#undefined-defShader): Shader
Default shader
# [defTex](#undefined-defTex): Texture
Default texture
# [frameBuffer](#undefined-frameBuffer): FrameBuffer
FrameBuffer
# [postShader](#undefined-postShader): string \| null
Post Shader, used in postEffect()
# [postShaderUniform](#undefined-postShaderUniform): Uniform \| ()=\>Uniform \| null
# [renderer](#undefined-renderer): BatchRenderer
# [pixelDensity](#undefined-pixelDensity): number
# [gscale](#undefined-gscale): number
This is the scale factor that scales pixel \"kaplay({ scale })\"
# [transform](#undefined-transform): Mat23
# [transformStack](#undefined-transformStack): Mat23\[\]
# [transformStackIndex](#undefined-transformStackIndex): number
# [bgTex](#undefined-bgTex): Texture
The background texture
# [bgColor](#undefined-bgColor): Color \| null
# [bgAlpha](#undefined-bgAlpha): number
# [width](#undefined-width): number
The
# [height](#undefined-height): number
# [viewport](#undefined-viewport): Viewport
Where the game is rendered.
# [fixed](#undefined-fixed): boolean
# [gl](#undefined-gl): WebGLRenderingContext
# [AppState](#AppState): ReturnType\<initAppState\>
# [AreaComp](#AreaComp):
The area`area()` component.
[area](#AreaComp-area):
# [shape](#undefined-shape): Shape \| null
If we use a custom shape over render shape.
# [scale](#undefined-scale): Vec2
Area scale.
# [offset](#undefined-offset): Vec2
Area offset.
# [cursor](#undefined-cursor): Cursor \| null
Cursor on hover.
Collider area info.
# [collisionIgnore](#AreaComp-collisionIgnore): Tag\[\]
If this object should ignore collisions against certain other objects.
`since`v3000.0
# [restitution](#AreaComp-restitution)?: number
Restitution (\"bounciness\") of the object.
# [friction](#AreaComp-friction)?: number
Friction of the object.
# [isClicked](#AreaComp-isClicked)(): boolean
If was just clicked on last frame.
# [isHovering](#AreaComp-isHovering)(): boolean
If is being hovered on.
# [checkCollision](#AreaComp-checkCollision)(other: GameObj): Collision \| null
Check collision with another game obj.
`since`v3000.0
# [getCollisions](#AreaComp-getCollisions)(): Collision\[\]
Get all collisions currently happening.
`since`v3000.0
# [isColliding](#AreaComp-isColliding)(o: GameObj): boolean
If is currently colliding with another game obj.
# [isOverlapping](#AreaComp-isOverlapping)(o: GameObj): boolean
If is currently overlapping with another game obj (like isColliding, but will return false if the objects are just touching edges).
# [onClick](#AreaComp-onClick)(f: ()=\>void, btn?: MouseButton): KEventController
Register an event runs when clicked.
`since`v2000.1
# [onHover](#AreaComp-onHover)(action: ()=\>void): KEventController
Register an event runs once when hovered.
`since`v3000.0
# [onHoverUpdate](#AreaComp-onHoverUpdate)(action: ()=\>void): KEventController
Register an event runs every frame when hovered.
`since`v3000.0
# [onHoverEnd](#AreaComp-onHoverEnd)(action: ()=\>void): KEventController
Register an event runs once when unhovered.
`since`v3000.0
# [onCollide](#AreaComp-onCollide)(tag: Tag, f: (obj: GameObj, col?: Collision)=\>void): KEventController
Register an event runs once when collide with another game obj with certain tag.
`since`v2001.0
# [onCollide](#AreaComp-onCollide)(f: (obj: GameObj, col?: Collision)=\>void): KEventController
Register an event runs once when collide with another game obj.
`since`v2000.1
# [onCollideUpdate](#AreaComp-onCollideUpdate)(tag: Tag, f: (obj: GameObj, col?: Collision)=\>void): KEventController
Register an event runs every frame when collide with another game obj with certain tag.
`since`v3000.0
# [onCollideUpdate](#AreaComp-onCollideUpdate)(f: (obj: GameObj, col?: Collision)=\>void): KEventController
Register an event runs every frame when collide with another game obj.
`since`v3000.0
# [onCollideEnd](#AreaComp-onCollideEnd)(tag: Tag, f: (obj: GameObj)=\>void): KEventController
Register an event runs once when stopped colliding with another game obj with certain tag.
`since`v3000.0
# [onCollideEnd](#AreaComp-onCollideEnd)(f: (obj: GameObj)=\>void): void
Register an event runs once when stopped colliding with another game obj.
`since`v3000.0
# [hasPoint](#AreaComp-hasPoint)(p: Vec2): boolean
If has a certain point inside collider.
# [resolveCollision](#AreaComp-resolveCollision)(obj: GameObj): void
Push out from another solid game obj if currently overlapping.
# [localArea](#AreaComp-localArea)(): Shape
Get the geometry data for the collider in local coordinate space.
`since`v3000.0
# [worldArea](#AreaComp-worldArea)(): Shape
Get the geometry data for the collider in world coordinate space.
# [screenArea](#AreaComp-screenArea)(): Shape
Get the geometry data for the collider in screen coordinate space.
# [AreaCompOpt](#AreaCompOpt):
Options for the area`area()` component.
# [shape](#AreaCompOpt-shape)?: Shape
The shape of the area (currently only Rect and Polygon is supported).
``` js
add([
sprite("butterfly"),
pos(100, 200),
// a triangle shape!
area({ shape: new Polygon([vec2(0), vec2(100), vec2(-100, 100)]) }),
])
```
# [scale](#AreaCompOpt-scale)?: number \| Vec2
Area scale.
# [offset](#AreaCompOpt-offset)?: Vec2
Area offset.
# [cursor](#AreaCompOpt-cursor)?: Cursor
Cursor on hover.
# [collisionIgnore](#AreaCompOpt-collisionIgnore)?: Tag\[\]
If this object should ignore collisions against certain other objects.
`since`v3000.0
# [restitution](#AreaCompOpt-restitution)?: number
Bounciness factor between 0 and 1.
`since`v4000.0
# [friction](#AreaCompOpt-friction)?: number
Friction factor between 0 and 1.
`since`v4000.0
# [AreaEffectorComp](#AreaEffectorComp):
# [useGlobalAngle](#AreaEffectorComp-useGlobalAngle): boolean
# [force](#AreaEffectorComp-force): Vec2
# [linearDrag](#AreaEffectorComp-linearDrag): number
[AreaEffectorCompOpt](#AreaEffectorCompOpt):
# [useGlobalAngle](#undefined-useGlobalAngle)?: boolean
# [force](#undefined-force): Vec2
# [linearDrag](#undefined-linearDrag)?: number
[AsepriteData](#AsepriteData):
[frames](#undefined-frames): Array\<
[frame](#undefined-frame):
# [x](#undefined-x): number
# [y](#undefined-y): number
# [w](#undefined-w): number
# [h](#undefined-h): number
\>
[meta](#undefined-meta):
[size](#undefined-size):
# [w](#undefined-w): number
# [h](#undefined-h): number
[frameTags](#undefined-frameTags): Array\<
# [from](#undefined-from): number
# [to](#undefined-to): number
# [direction](#undefined-direction): forward \| reverse \| pingpong
\>
# [Asset](#Asset)\<D\>:
An asset is a resource that is loaded asynchronously. It can be a sprite, a sound, a font, a shader, etc.
# [loaded](#Asset-loaded): boolean
# [loaded](#Asset-loaded)\<D\>(data: D): Asset\<D\>
# [data](#Asset-data): D \| null
# [error](#Asset-error): Error \| null
# [onLoadEvents](#Asset-onLoadEvents):
# [onErrorEvents](#Asset-onErrorEvents):
# [onFinishEvents](#Asset-onFinishEvents):
# [onLoad](#Asset-onLoad)(action: (data: D)=\>void): this
# [onError](#Asset-onError)(action: (err: Error)=\>void): this
# [onFinish](#Asset-onFinish)(action: ()=\>void): this
# [then](#Asset-then)(action: (data: D)=\>void): Asset\<D\>
# [catch](#Asset-catch)(action: (err: Error)=\>void): Asset\<D\>
# [finally](#Asset-finally)(action: ()=\>void): Asset\<D\>
# [AssetBucket](#AssetBucket)\<D\>:
# [assets](#AssetBucket-assets): Map\<string, Asset\>
# [lastUID](#AssetBucket-lastUID): number
# [add](#AssetBucket-add)(name: string \| null, loader: Promise): Asset\<D\>
# [addLoaded](#AssetBucket-addLoaded)(name: string \| null, data: D): Asset\<D\>
# [get](#AssetBucket-get)(handle: string): Asset \| undefined
# [progress](#AssetBucket-progress)(): number
# [getFailedAssets](#AssetBucket-getFailedAssets)(): \[string, Asset\]\[\]
# [AssetsCtx](#AssetsCtx): ReturnType\<initAssets\>
# [Attributes](#Attributes):
# [pos](#Attributes-pos): number\[\]
# [uv](#Attributes-uv): number\[\]
# [color](#Attributes-color): number\[\]
# [opacity](#Attributes-opacity): number\[\]
# [AudioCtx](#AudioCtx): ReturnType\<initAudio\>
# [AudioPlay](#AudioPlay):
# [play](#AudioPlay-play)(time?: number): void
Start playing audio.
`since`v3000.0
# [seek](#AudioPlay-seek)(time: number): void
Seek time.
`since`v3000.0
# [stop](#AudioPlay-stop)(): void
Stop the sound.
`since`v3001.0
# [paused](#AudioPlay-paused): boolean
If the sound is paused.
`since`v2000.1
# [speed](#AudioPlay-speed): number
Playback speed of the sound. 1.0 means normal playback speed, 2.0 means twice as fast.
# [detune](#AudioPlay-detune): number
Detune the sound. Every 100 means a semitone.
``` js
// tune down a semitone
music.detune = -100
// tune up an octave
music.detune = 1200
```
# [volume](#AudioPlay-volume): number
Volume of the sound. 1.0 means full volume, 0.5 means half volume.
# [pan](#AudioPlay-pan)?: number
The stereo pan of the sound. -1.0 means fully from the left channel, 0.0 means centered, 1.0 means fully right. Defaults to 0.0.
# [loop](#AudioPlay-loop): boolean
If the audio should start again when it ends.
# [time](#AudioPlay-time)(): number
The current playing time (not accurate if speed is changed).
# [duration](#AudioPlay-duration)(): number
The total duration.
# [onEnd](#AudioPlay-onEnd)(action: ()=\>void): KEventController
Register an event that runs when audio ends.
`since`v3000.0
# [then](#AudioPlay-then)(action: ()=\>void): KEventController
# [connect](#AudioPlay-connect)(node?: AudioNode): void
Disconnect the audio node from whatever it is currently connected to and connect it to the passed-in audio node, or to Kaplay's default volume node if no node is passed.
# [AudioPlayOpt](#AudioPlayOpt):
Audio play configurations.
# [paused](#AudioPlayOpt-paused)?: boolean
If audio should start out paused.
`since`v3000.0
# [loop](#AudioPlayOpt-loop)?: boolean
If audio should be played again from start when its ended.
# [volume](#AudioPlayOpt-volume)?: number
Volume of audio. 1.0 means full volume, 0.5 means half volume.
# [speed](#AudioPlayOpt-speed)?: number
Playback speed. 1.0 means normal playback speed, 2.0 means twice as fast.
# [detune](#AudioPlayOpt-detune)?: number
Detune the sound. Every 100 means a semitone.
``` js
// play a random note in the octave
play("noteC", {
detune: randi(0, 12) * 100,
})
```
# [seek](#AudioPlayOpt-seek)?: number
The start time, in seconds.
# [pan](#AudioPlayOpt-pan)?: number
The stereo pan of the sound. -1.0 means fully from the left channel, 0.0 means centered, 1.0 means fully right. Defaults to 0.0.
# [connectTo](#AudioPlayOpt-connectTo)?: AudioNode
If the audio node should start out connected to another audio node rather than KAPLAY's default volume node. Defaults to undefined, i.e. use KAPLAY's volume node.
# [BaseValues](#BaseValues):
# [pos](#BaseValues-pos): Vec2
# [angle](#BaseValues-angle): number
# [scale](#BaseValues-scale): Vec2
# [opacity](#BaseValues-opacity): number
# [BatchRenderer](#BatchRenderer):
# [ctx](#BatchRenderer-ctx): GfxCtx
# [glVBuf](#BatchRenderer-glVBuf): WebGLBuffer
# [glIBuf](#BatchRenderer-glIBuf): WebGLBuffer
# [vqueue](#BatchRenderer-vqueue): number\[\]
# [iqueue](#BatchRenderer-iqueue): number\[\]
# [stride](#BatchRenderer-stride): number
# [maxVertices](#BatchRenderer-maxVertices): number
# [maxIndices](#BatchRenderer-maxIndices): number
# [vertexFormat](#BatchRenderer-vertexFormat): VertexFormat
# [numDraws](#BatchRenderer-numDraws): number
# [curPrimitive](#BatchRenderer-curPrimitive): GLenum \| null
# [curTex](#BatchRenderer-curTex): Texture \| null
# [curShader](#BatchRenderer-curShader): Shader \| null
# [curUniform](#BatchRenderer-curUniform): Uniform \| null
# [curBlend](#BatchRenderer-curBlend): BlendMode
# [curFixed](#BatchRenderer-curFixed): boolean \| undefined
# [picture](#BatchRenderer-picture): Picture \| null
# [push](#BatchRenderer-push)(primitive: GLenum, vertices: number\[\], indices: number\[\], shader: Shader, tex: Texture \| null \| undefined, uniform: Uniform \| null \| undefined, blend: BlendMode, width: number, height: number, fixed: boolean): void
# [flush](#BatchRenderer-flush)(width: number, height: number): void
# [free](#BatchRenderer-free)(): void
# [setBlend](#BatchRenderer-setBlend)(blend: BlendMode): void
# [BinaryHeap](#BinaryHeap)\<T\>:
# [\_items](#BinaryHeap-_items): T\[\]
# [\_compareFn](#BinaryHeap-_compareFn)(a: T, b: T): boolean
# [insert](#BinaryHeap-insert)(item: T): void
Insert an item into the binary heap
# [remove](#BinaryHeap-remove)(): T \| null
Remove the smallest item from the binary heap in case of a min heap or the greatest item from the binary heap in case of a max heap
# [clear](#BinaryHeap-clear)(): void
Remove all items
# [moveUp](#BinaryHeap-moveUp)(pos: number): void
# [moveDown](#BinaryHeap-moveDown)(pos: number): void
# [swap](#BinaryHeap-swap)(index1: number, index2: number): void
# [length](#BinaryHeap-length)(): number
Returns the amount of items
# [BitmapFontData](#BitmapFontData): GfxFont
# [BlendComp](#BlendComp):
The blend`blend()` component.
# [blend](#BlendComp-blend): BlendMode
# [BlendMode](#BlendMode):
# [Normal](#BlendMode-Normal):
# [Add](#BlendMode-Add):
# [Multiply](#BlendMode-Multiply):
# [Screen](#BlendMode-Screen):
# [Overlay](#BlendMode-Overlay):
# [BodyComp](#BodyComp):
The body`body()` component.
# [vel](#BodyComp-vel): Vec2
Object current velocity.
`since`v3001.0
# [damping](#BodyComp-damping): number
How much velocity decays (velocity \*= 1 / (1 + damping \* dt) every frame).
`since`v3001.0
# [isStatic](#BodyComp-isStatic): boolean
If object is static, it won't move, all non static objects won't move past it, and all calls to addForce(), applyImpulse(), or jump() on this body will do absolutely nothing.
# [jumpForce](#BodyComp-jumpForce): number
Initial speed in pixels per second for jump().
# [gravityScale](#BodyComp-gravityScale): number
Gravity multiplier.
# [mass](#BodyComp-mass): number
Mass of the body, decides how much a non-static body should move when resolves with another non-static body. (default 1).
`since`v3000.0
# [stickToPlatform](#BodyComp-stickToPlatform)?: boolean
If object should move with moving platform (default true).
`since`v3000.0
# [curPlatform](#BodyComp-curPlatform)(): GameObj \| null
Current platform landing on.
# [isGrounded](#BodyComp-isGrounded)(): boolean
If currently landing on a platform.
`since`v2000.1
# [isFalling](#BodyComp-isFalling)(): boolean
If currently falling.
`since`v2000.1
# [isJumping](#BodyComp-isJumping)(): boolean
If currently rising.
`since`v3000.0
# [applyImpulse](#BodyComp-applyImpulse)(impulse: Vec2): void
Applies an impulse
`param`impulseThe impulse vector, applied directly
# [addForce](#BodyComp-addForce)(force: Vec2): void
Applies a force
`param`forceThe force vector, applied after scaled by the inverse mass
# [jump](#BodyComp-jump)(force?: number): void
Upward thrust.
# [onPhysicsResolve](#BodyComp-onPhysicsResolve)(action: (col: Collision)=\>void): KEventController
Register an event that runs when a collision is resolved.
`since`v3000.0
# [onBeforePhysicsResolve](#BodyComp-onBeforePhysicsResolve)(action: (col: Collision)=\>void): KEventController
Register an event that runs before a collision would be resolved.
`since`v3000.0
# [onGround](#BodyComp-onGround)(action: ()=\>void): KEventController
Register an event that runs when the object is grounded.
`since`v2000.1
# [onFall](#BodyComp-onFall)(action: ()=\>void): KEventController
Register an event that runs when the object starts falling.
`since`v2000.1
# [onFallOff](#BodyComp-onFallOff)(action: ()=\>void): KEventController
Register an event that runs when the object falls off platform.
`since`v3000.0
# [onHeadbutt](#BodyComp-onHeadbutt)(action: ()=\>void): KEventController
Register an event that runs when the object bumps into something on the head.
`since`v2000.1
# [onLand](#BodyComp-onLand)(action: (obj: GameObj)=\>void): KEventController
Register an event that runs when an object lands on this object.
`since`v3001.0
# [onHeadbutted](#BodyComp-onHeadbutted)(action: (obj: GameObj)=\>void): KEventController
Register an event that runs when the object is bumped by another object head.
# [BodyCompOpt](#BodyCompOpt):
Options for the body`body()` component.
# [damping](#BodyCompOpt-damping)?: number
How much velocity decays (velocity \*= 1 / (1 + damping \* dt) every frame).
`since`v3001.0
# [jumpForce](#BodyCompOpt-jumpForce)?: number
Initial speed in pixels per second for jump().
# [maxVelocity](#BodyCompOpt-maxVelocity)?: number
Maximum velocity when falling.
# [gravityScale](#BodyCompOpt-gravityScale)?: number
Gravity multiplier.
# [isStatic](#BodyCompOpt-isStatic)?: boolean
If object is static, it won't move, all non static objects won't move past it, and all calls to addForce(), applyImpulse(), or jump() on this body will do absolutely nothing.
`since`v3000.0
# [stickToPlatform](#BodyCompOpt-stickToPlatform)?: boolean
If object should move with moving platform (default true).
`since`v3000.0
# [mass](#BodyCompOpt-mass)?: number
Mass of the body, decides how much a non-static body should move when resolves with another non-static body. (default 1).
`since`v3000.0
# [BoomOpt](#BoomOpt):
# [speed](#BoomOpt-speed)?: number
Animation speed.
# [scale](#BoomOpt-scale)?: number
Scale.
# [comps](#BoomOpt-comps)?: CompList\<any\>
Additional components.
`since`v3000.0
# [BuoyancyEffectorComp](#BuoyancyEffectorComp):
# [surfaceLevel](#BuoyancyEffectorComp-surfaceLevel): number
# [density](#BuoyancyEffectorComp-density): number
# [linearDrag](#BuoyancyEffectorComp-linearDrag): number
# [angularDrag](#BuoyancyEffectorComp-angularDrag): number
# [flowAngle](#BuoyancyEffectorComp-flowAngle): number
# [flowMagnitude](#BuoyancyEffectorComp-flowMagnitude): number
# [flowVariation](#BuoyancyEffectorComp-flowVariation): number
# [applyBuoyancy](#BuoyancyEffectorComp-applyBuoyancy)(body: GameObj, submergedArea: Polygon): void
# [applyDrag](#BuoyancyEffectorComp-applyDrag)(body: GameObj, submergedArea: Polygon): void
[BuoyancyEffectorCompOpt](#BuoyancyEffectorCompOpt):
# [surfaceLevel](#undefined-surfaceLevel): number
# [density](#undefined-density)?: number
# [linearDrag](#undefined-linearDrag)?: number
# [angularDrag](#undefined-angularDrag)?: number
# [flowAngle](#undefined-flowAngle)?: number
# [flowMagnitude](#undefined-flowMagnitude)?: number
# [flowVariation](#undefined-flowVariation)?: number
[ButtonBinding](#ButtonBinding):
# [keyboard](#undefined-keyboard)?: Key \| Key\[\]
# [keyboardCode](#undefined-keyboardCode)?: string \| string\[\]
# [gamepad](#undefined-gamepad)?: KGamepadButton \| KGamepadButton\[\]
# [mouse](#undefined-mouse)?: MouseButton \| MouseButton\[\]
A button binding.
# [ButtonBindingDevice](#ButtonBindingDevice): keyboard \| gamepad \| mouse
A button binding device
# [ButtonState](#ButtonState)\<T\>:
# [pressed](#ButtonState-pressed): Set\<T\>
# [pressedRepeat](#ButtonState-pressedRepeat): Set\<T\>
# [released](#ButtonState-released): Set\<T\>
# [down](#ButtonState-down): Set\<T\>
# [update](#ButtonState-update)(): void
# [press](#ButtonState-press)(btn: T): void
# [pressRepeat](#ButtonState-pressRepeat)(btn: T): void
# [release](#ButtonState-release)(btn: T): void
# [ButtonsDef](#ButtonsDef): Record\<string, ButtonBinding\>
A buttons definition for an action (jump, walk-left, run).
# [CSSColor](#CSSColor): CSS_COLOR_MAP
[CSS_COLOR_MAP](#CSS_COLOR_MAP):
# [black](#undefined-black): string
# [silver](#undefined-silver): string
# [gray](#undefined-gray): string
# [white](#undefined-white): string
# [maroon](#undefined-maroon): string
# [red](#undefined-red): string
# [purple](#undefined-purple): string
# [fuchsia](#undefined-fuchsia): string
# [green](#undefined-green): string
# [lime](#undefined-lime): string
# [olive](#undefined-olive): string
# [yellow](#undefined-yellow): string
# [navy](#undefined-navy): string
# [blue](#undefined-blue): string
# [teal](#undefined-teal): string
# [aqua](#undefined-aqua): string
# [aliceblue](#undefined-aliceblue): string
# [antiquewhite](#undefined-antiquewhite): string
# [aquamarine](#undefined-aquamarine): string
# [azure](#undefined-azure): string
# [beige](#undefined-beige): string
# [bisque](#undefined-bisque): string
# [blanchedalmond](#undefined-blanchedalmond): string
# [blueviolet](#undefined-blueviolet): string
# [brown](#undefined-brown): string
# [burlywood](#undefined-burlywood): string
# [cadetblue](#undefined-cadetblue): string
# [chartreuse](#undefined-chartreuse): string
# [chocolate](#undefined-chocolate): string
# [coral](#undefined-coral): string
# [cornflowerblue](#undefined-cornflowerblue): string
# [cornsilk](#undefined-cornsilk): string
# [crimson](#undefined-crimson): string
# [cyan](#undefined-cyan): string
# [darkblue](#undefined-darkblue): string
# [darkcyan](#undefined-darkcyan): string
# [darkgoldenrod](#undefined-darkgoldenrod): string
# [darkgray](#undefined-darkgray): string
# [darkgreen](#undefined-darkgreen): string
# [darkkhaki](#undefined-darkkhaki): string
# [darkmagenta](#undefined-darkmagenta): string
# [darkolivegreen](#undefined-darkolivegreen): string
# [darkorange](#undefined-darkorange): string
# [darkorchid](#undefined-darkorchid): string
# [darkred](#undefined-darkred): string
# [darksalmon](#undefined-darksalmon): string
# [darkseagreen](#undefined-darkseagreen): string
# [darkslateblue](#undefined-darkslateblue): string
# [darkslategray](#undefined-darkslategray): string
# [darkturquoise](#undefined-darkturquoise): string
# [darkviolet](#undefined-darkviolet): string
# [deeppink](#undefined-deeppink): string
# [deepskyblue](#undefined-deepskyblue): string
# [dimgray](#undefined-dimgray): string
# [dodgerblue](#undefined-dodgerblue): string
# [firebrick](#undefined-firebrick): string
# [floralwhite](#undefined-floralwhite): string
# [forestgreen](#undefined-forestgreen): string
# [gainsboro](#undefined-gainsboro): string
# [ghostwhite](#undefined-ghostwhite): string
# [gold](#undefined-gold): string
# [goldenrod](#undefined-goldenrod): string
# [greenyellow](#undefined-greenyellow): string
# [honeydew](#undefined-honeydew): string
# [hotpink](#undefined-hotpink): string
# [indianred](#undefined-indianred): string
# [indigo](#undefined-indigo): string
# [ivory](#undefined-ivory): string
# [khaki](#undefined-khaki): string
# [lavender](#undefined-lavender): string
# [lavenderblush](#undefined-lavenderblush): string
# [lawngreen](#undefined-lawngreen): string
# [lemonchiffon](#undefined-lemonchiffon): string
# [lightblue](#undefined-lightblue): string
# [lightcoral](#undefined-lightcoral): string
# [lightcyan](#undefined-lightcyan): string
# [lightgoldenrodyellow](#undefined-lightgoldenrodyellow): string
# [lightgray](#undefined-lightgray): string
# [lightgreen](#undefined-lightgreen): string
# [lightpink](#undefined-lightpink): string
# [lightsalmon](#undefined-lightsalmon): string
# [lightseagreen](#undefined-lightseagreen): string
# [lightskyblue](#undefined-lightskyblue): string
# [lightslategray](#undefined-lightslategray): string
# [lightsteelblue](#undefined-lightsteelblue): string
# [lightyellow](#undefined-lightyellow): string
# [limegreen](#undefined-limegreen): string
# [linen](#undefined-linen): string
# [mediumaquamarine](#undefined-mediumaquamarine): string
# [mediumblue](#undefined-mediumblue): string
# [mediumorchid](#undefined-mediumorchid): string
# [mediumpurple](#undefined-mediumpurple): string
# [mediumseagreen](#undefined-mediumseagreen): string
# [mediumslateblue](#undefined-mediumslateblue): string
# [mediumspringgreen](#undefined-mediumspringgreen): string
# [mediumturquoise](#undefined-mediumturquoise): string
# [mediumvioletred](#undefined-mediumvioletred): string
# [midnightblue](#undefined-midnightblue): string
# [mintcream](#undefined-mintcream): string
# [mistyrose](#undefined-mistyrose): string
# [moccasin](#undefined-moccasin): string
# [navajowhite](#undefined-navajowhite): string
# [oldlace](#undefined-oldlace): string
# [olivedrab](#undefined-olivedrab): string
# [orange](#undefined-orange): string
# [orangered](#undefined-orangered): string
# [orchid](#undefined-orchid): string
# [palegoldenrod](#undefined-palegoldenrod): string
# [palegreen](#undefined-palegreen): string
# [paleturquoise](#undefined-paleturquoise): string
# [palevioletred](#undefined-palevioletred): string
# [papayawhip](#undefined-papayawhip): string
# [peachpuff](#undefined-peachpuff): string
# [peru](#undefined-peru): string
# [pink](#undefined-pink): string
# [plum](#undefined-plum): string
# [powderblue](#undefined-powderblue): string
# [rebeccapurple](#undefined-rebeccapurple): string
# [rosybrown](#undefined-rosybrown): string
# [royalblue](#undefined-royalblue): string
# [saddlebrown](#undefined-saddlebrown): string
# [salmon](#undefined-salmon): string
# [sandybrown](#undefined-sandybrown): string
# [seagreen](#undefined-seagreen): string
# [seashell](#undefined-seashell): string
# [sienna](#undefined-sienna): string
# [skyblue](#undefined-skyblue): string
# [slateblue](#undefined-slateblue): string
# [slategray](#undefined-slategray): string
# [snow](#undefined-snow): string
# [springgreen](#undefined-springgreen): string
# [steelblue](#undefined-steelblue): string
# [tan](#undefined-tan): string
# [thistle](#undefined-thistle): string
# [tomato](#undefined-tomato): string
# [turquoise](#undefined-turquoise): string
# [violet](#undefined-violet): string
# [wheat](#undefined-wheat): string
# [whitesmoke](#undefined-whitesmoke): string
# [yellowgreen](#undefined-yellowgreen): string
[CamData](#CamData):
# [pos](#undefined-pos): Vec2 \| null
# [scale](#undefined-scale): Vec2
# [angle](#undefined-angle): number
# [shake](#undefined-shake): number
# [transform](#undefined-transform): Mat23
[Canvas](#Canvas):
# [width](#undefined-width): number
# [height](#undefined-height): number
# [toImageData](#undefined-toImageData)(): ImageData
# [toDataURL](#undefined-toDataURL)(): string
# [clear](#undefined-clear)(): void
# [draw](#undefined-draw)(action: ()=\>void): void
# [free](#undefined-free)(): void
# [fb](#undefined-fb): FrameBuffer
# [CharTransform](#CharTransform):
Describes how to transform each character.
# [pos](#CharTransform-pos)?: Vec2
Offset to apply to the position of the text character. Shifts the character's position by the specified 2D vector.
# [scale](#CharTransform-scale)?: Vec2 \| number
Scale transformation to apply to the text character's current scale. When a number, it is scaled uniformly. Given a 2D vector, it is scaled independently along the X and Y axis.
# [angle](#CharTransform-angle)?: number
Increases the amount of degrees to rotate the text character.
# [color](#CharTransform-color)?: Color
Color transformation applied to the text character. Multiplies the current color with this color.
# [opacity](#CharTransform-opacity)?: number
Opacity multiplication applied to the text character. For example, an opacity of 0.4 with 2 set in the transformation, the resulting opacity will be 0.8 (0.4 × 2).
# [override](#CharTransform-override)?: boolean
If true, the styles applied by this specific entry transform will override, rather than compose with, the default styles given in and by other components' styles.
# [font](#CharTransform-font)?: string \| FontData
If the font for this character should be different from the default font or the one specified in . Because the font can't be composed like the other properties, this will override the font even if is false.
# [stretchInPlace](#CharTransform-stretchInPlace)?: boolean
If true, characters that have a X scale that is not 1 won't have the bounding box stretched to fit the character, and may end up overlapping with adjacent characters.
`default`true
# [shader](#CharTransform-shader)?: string
A name for a shader that will be applied to this character only.
# [uniform](#CharTransform-uniform)?: Uniform
Values to use for the shader's uniform inputs. If there is no shader set (by this character's transform or an entire-text transform), this is not used.
# [CharTransformFunc](#CharTransformFunc)(idx: number, ch: string): CharTransform
A function that returns a character transform config. Useful if you're generating dynamic styles.
# [Circle](#Circle):
# [center](#Circle-center): Vec2
# [radius](#Circle-radius): number
# [transform](#Circle-transform)(tr: Mat23, s?: Shape): Ellipse
# [bbox](#Circle-bbox)(): Rect
# [area](#Circle-area)(): number
# [clone](#Circle-clone)(): Circle
# [collides](#Circle-collides)(shape: ShapeType \| Vec2): boolean
# [contains](#Circle-contains)(point: Vec2): boolean
# [raycast](#Circle-raycast)(origin: Vec2, direction: Vec2): RaycastResult
# [random](#Circle-random)(): Vec2
# [CircleComp](#CircleComp):
The circle`circle()` component.
# [draw](#CircleComp-draw): Comp\[draw\]
# [radius](#CircleComp-radius): number
Radius of circle.
# [renderArea](#CircleComp-renderArea)(): Circle
Render area of the circle.
`since`v3000.0
# [CircleCompOpt](#CircleCompOpt):
Options for the circle\`circle()\`\` component.
# [fill](#CircleCompOpt-fill)?: boolean
If fill the circle (useful if you only want to render outline with outline`outline()` component).
# [Collision](#Collision):
Collision resolution data.
# [source](#Collision-source): GameObj
The first game object in the collision.
# [target](#Collision-target): GameObj
The second game object in the collision.
# [normal](#Collision-normal): Vec2
The contact normal.
# [distance](#Collision-distance): Vec2
The length of the displacement.
# [displacement](#Collision-displacement): Vec2
The displacement source game object have to make to avoid the collision.
# [resolved](#Collision-resolved): boolean
If the collision is resolved.
# [preventResolution](#Collision-preventResolution)(): void
Prevent collision resolution if not yet resolved.
`since`v3000.0
# [hasOverlap](#Collision-hasOverlap)(): boolean
If the 2 objects have any overlap, or they're just touching edges.
`since`v3000.0
# [reverse](#Collision-reverse)(): Collision
Get a new collision with reversed source and target relationship.
# [isTop](#Collision-isTop)(): boolean
If the collision happened (roughly) on the top side.
# [isBottom](#Collision-isBottom)(): boolean
If the collision happened (roughly) on the bottom side.
# [isLeft](#Collision-isLeft)(): boolean
If the collision happened (roughly) on the left side.
# [isRight](#Collision-isRight)(): boolean
If the collision happened (roughly) on the right side.
# [Color](#Color):
0-255 RGBA color.
# [r](#Color-r): number
Red (0-255.
# [g](#Color-g): number
Green (0-255).
# [b](#Color-b): number
Blue (0-255).
# [fromArray](#Color-fromArray)(arr: \[number, number, number\]): Color
# [fromHex](#Color-fromHex)(hex: string \| number): Color
Create color from hex string or literal.
``` js
Color.fromHex(0xfcef8d)
Color.fromHex("#5ba675")
Color.fromHex("d46eb3")
```
`since`v3000.0
# [fromHSL](#Color-fromHSL)(h: number, s: number, l: number): Color
# [fromCSS](#Color-fromCSS)(cssColor: CSSColor): Color
Create a color from a CSS color name
`param`cssColor- The color name.
``` js
loadHappy();
add([
rect(512, 512, {
radius: [0, 96, 96, 96]
}),
color("#663399"),
pos(40, 40),
]);
add([
text("css", { size: 192, font: "happy" }),
pos(90, 310)
]);
```
`static`
`returns`The color.
`experimental`This feature is in experimental phase, it will be fully released in v3001.1.0
# [RED](#Color-RED): Color
# [GREEN](#Color-GREEN): Color
# [BLUE](#Color-BLUE): Color
# [YELLOW](#Color-YELLOW): Color
# [MAGENTA](#Color-MAGENTA): Color
# [CYAN](#Color-CYAN): Color
# [WHITE](#Color-WHITE): Color
# [BLACK](#Color-BLACK): Color
# [clone](#Color-clone)(): Color
# [lighten](#Color-lighten)(a: number): Color
Lighten the color (adds RGB by n).
# [darken](#Color-darken)(a: number): Color
Darkens the color (subtracts RGB by n).
# [invert](#Color-invert)(): Color
# [mult](#Color-mult)(other: Color): Color
# [lerp](#Color-lerp)(dest: Color, t: number): Color
Linear interpolate to a destination color.
`since`v3000.0
# [toHSL](#Color-toHSL)(): \[number, number, number\]
Convert color into HSL format.
`since`v3001.0
# [eq](#Color-eq)(other: Color): boolean
# [toHex](#Color-toHex)(): string
Return the hex string of color.
`since`v3000.0
# [toArray](#Color-toArray)(): Array\<number\>
Return the color converted to an array.
`since`v3001.0
# [ColorArgs](#ColorArgs): \[Color\] \| \[Color, number\] \| RGBValue \| RGBAValue \| \[string\] \| \[number\[\]\] \| \[\] \| \[CSSColor & string & \]
# [ColorComp](#ColorComp):
The color`color()` component.
# [color](#ColorComp-color): Color
# [Comp](#Comp):
# [id](#Comp-id)?: Tag
Component ID (if left out won't be treated as a comp).
# [require](#Comp-require)?: Tag\[\]
What other comps this comp depends on.
# [add](#Comp-add)?(): void
Event that runs when host game obj is added to scene.
# [fixedUpdate](#Comp-fixedUpdate)?(): void
Event that runs at a fixed frame rate.
# [update](#Comp-update)?(): void
Event that runs every frame.
# [draw](#Comp-draw)?(): void
Event that runs every frame after update.
# [destroy](#Comp-destroy)?(): void
Event that runs when obj is removed from scene.
# [inspect](#Comp-inspect)?(): string \| null
Debug info for inspect mode.
# [drawInspect](#Comp-drawInspect)?(): void
Draw debug info in inspect mode
`since`v3000.0
# [CompList](#CompList)\<T\>: T \| Tag\[\]
A component list.
# [ConstantForceComp](#ConstantForceComp):
# [force](#ConstantForceComp-force): Vec2 \| undefined
# [useGlobalAngle](#ConstantForceComp-useGlobalAngle): boolean
[ConstantForceCompOpt](#ConstantForceCompOpt):
# [force](#undefined-force)?: Vec2
# [useGlobalAngle](#undefined-useGlobalAngle)?: boolean
# [Cursor](#Cursor): string \| auto \| default \| none \| context-menu \| help \| pointer \| progress \| wait \| cell \| crosshair \| text \| vertical-text \| alias \| copy \| move \| no-drop \| not-allowed \| grab \| grabbing \| all-scroll \| col-resize \| row-resize \| n-resize \| e-resize \| s-resize \| w-resize \| ne-resize \| nw-resize \| se-resize \| sw-resize \| ew-resize \| ns-resize \| nesw-resize \| nwse-resize \| zoom-int \| zoom-out
# [Debug](#Debug):
# [paused](#Debug-paused): boolean
Pause the whole game.
# [inspect](#Debug-inspect): boolean
Draw bounding boxes of all objects with \`area()\` component, hover to inspect their states.
# [timeScale](#Debug-timeScale): number
Global time scale.
# [showLog](#Debug-showLog): boolean
Show the debug log or not.
# [fps](#Debug-fps)(): number
Current frames per second.
# [numFrames](#Debug-numFrames)(): number
Total number of frames elapsed.
`since`v3000.0
# [drawCalls](#Debug-drawCalls)(): number
Number of draw calls made last frame.
# [stepFrame](#Debug-stepFrame)(): void
Step to the next frame. Useful with pausing.
# [clearLog](#Debug-clearLog)(): void
Clear the debug log.
# [log](#Debug-log)(msg: any): void
Log some text to on screen debug log.
# [error](#Debug-error)(msg: any): void
Log an error message to on screen debug log.
# [curRecording](#Debug-curRecording): Recording \| null
The recording handle if currently in recording mode.
`since`v2000.1
# [numObjects](#Debug-numObjects)(): number
Get total number of objects.
`since`v3001.0
# [Defined](#Defined)\<T\>: ConditionalType
# [DoubleJumpComp](#DoubleJumpComp):
The doubleJump`doubleJump()` component.
# [numJumps](#DoubleJumpComp-numJumps): number
Number of jumps allowed.
# [doubleJump](#DoubleJumpComp-doubleJump)(force?: number): void
Performs double jump (the initial jump only happens if player is grounded).
# [onDoubleJump](#DoubleJumpComp-onDoubleJump)(action: ()=\>void): KEventController
Register an event that runs when the object performs the second jump when double jumping.
[DrawBezierOpt](#DrawBezierOpt): DrawCurveOpt &
# [pt1](#undefined-pt1): Vec2
The first point.
# [pt2](#undefined-pt2): Vec2
The the first control point.
# [pt3](#undefined-pt3): Vec2
The the second control point.
# [pt4](#undefined-pt4): Vec2
The second point.
[DrawCanvasOpt](#DrawCanvasOpt): DrawUVQuadOpt &
# [canvas](#undefined-canvas): Canvas
[DrawCircleOpt](#DrawCircleOpt): Omit &
# [radius](#undefined-radius): number
Radius of the circle.
# [start](#undefined-start)?: number
Starting angle.
# [fill](#undefined-fill)?: boolean
If fill the shape with color (set this to false if you only want an outline).
# [gradient](#undefined-gradient)?: \[Color, Color\]
Use gradient instead of solid color.
`since`v3000.0
# [resolution](#undefined-resolution)?: number
Multiplier for circle vertices resolution (default 1)
# [anchor](#undefined-anchor)?: Anchor \| Vec2
The anchor point, or the pivot point. Default to \"topleft\".
How the circle should look like.
[DrawCurveOpt](#DrawCurveOpt): RenderProps &
# [segments](#undefined-segments)?: number
The amount of line segments to draw.
# [width](#undefined-width)?: number
The width of the line.
[DrawEllipseOpt](#DrawEllipseOpt): RenderProps &
# [radiusX](#undefined-radiusX): number
The horizontal radius.
# [radiusY](#undefined-radiusY): number
The vertical radius.
# [start](#undefined-start)?: number
Starting angle.
# [fill](#undefined-fill)?: boolean
If fill the shape with color (set this to false if you only want an outline).
# [gradient](#undefined-gradient)?: \[Color, Color\]
Use gradient instead of solid color.
`since`v3000.0
# [resolution](#undefined-resolution)?: number
Multiplier for circle vertices resolution (default 1)
# [anchor](#undefined-anchor)?: Anchor \| Vec2
The anchor point, or the pivot point. Default to \"topleft\".
How the ellipse should look like.
[DrawLineOpt](#DrawLineOpt): Omit &
# [p1](#undefined-p1): Vec2
Starting point of the line.
# [p2](#undefined-p2): Vec2
Ending point of the line.
# [width](#undefined-width)?: number
The width, or thickness of the line,
How the line should look like.
[DrawLinesOpt](#DrawLinesOpt): Omit &
# [pts](#undefined-pts): Vec2\[\]
The points that should be connected with a line.
# [width](#undefined-width)?: number
The width, or thickness of the lines,
# [radius](#undefined-radius)?: number \| number\[\]
The radius of each corner.
# [join](#undefined-join)?: LineJoin
Line join style (default \"none\").
# [cap](#undefined-cap)?: LineCap
Line cap style (default \"none\").
# [miterLimit](#undefined-miterLimit)?: number
Maximum miter length, anything longer becomes bevel.
How the lines should look like.
# [DrawPictureOpt](#DrawPictureOpt): RenderProps &
Drawing options for drawPicture
[DrawPolygonOpt](#DrawPolygonOpt): RenderProps &
# [pts](#undefined-pts): Vec2\[\]
The points that make up the polygon
# [fill](#undefined-fill)?: boolean
If fill the shape with color (set this to false if you only want an outline).
# [indices](#undefined-indices)?: number\[\]
Manual triangulation.
# [offset](#undefined-offset)?: Vec2
The center point of transformation in relation to the position.
# [radius](#undefined-radius)?: number \| number\[\]
The radius of each corner.
# [colors](#undefined-colors)?: Color\[\]
The color of each vertex.
`since`v3000.0
# [uv](#undefined-uv)?: Vec2\[\]
The uv of each vertex.
`since`v3001.0
# [tex](#undefined-tex)?: Texture
The texture if uv are supplied.
`since`v3001.0
# [triangulate](#undefined-triangulate)?: boolean
Triangulate concave polygons.
`since`v3001.0
How the polygon should look like.
[DrawRectOpt](#DrawRectOpt): RenderProps &
# [width](#undefined-width): number
Width of the rectangle.
# [height](#undefined-height): number
Height of the rectangle.
# [gradient](#undefined-gradient)?: \[Color, Color\]
Use gradient instead of solid color.
`since`v3000.0
# [horizontal](#undefined-horizontal)?: boolean
If the gradient should be horizontal.
`since`v3000.0
# [fill](#undefined-fill)?: boolean
If fill the shape with color (set this to false if you only want an outline).
# [radius](#undefined-radius)?: number \| number\[\]
The radius of each corner.
# [anchor](#undefined-anchor)?: Anchor \| Vec2
The anchor point, or the pivot point. Default to \"topleft\".
How the rectangle should look like.
[DrawSpriteOpt](#DrawSpriteOpt): RenderProps &
# [sprite](#undefined-sprite): string \| SpriteData \| Asset
The sprite name in the asset manager, or the raw sprite data.
# [frame](#undefined-frame)?: number
If the sprite is loaded with multiple frames, or sliced, use the frame option to specify which frame to draw.
# [width](#undefined-width)?: number
Width of sprite. If \`height\` is not specified it'll stretch with aspect ratio. If \`tiled\` is set to true it'll tiled to the specified width horizontally.
# [height](#undefined-height)?: number
Height of sprite. If \`width\` is not specified it'll stretch with aspect ratio. If \`tiled\` is set to true it'll tiled to the specified width vertically.
# [tiled](#undefined-tiled)?: boolean
When set to true, \`width\` and \`height\` will not scale the sprite but instead render multiple tiled copies of them until the specified width and height. Useful for background texture pattern etc.
# [flipX](#undefined-flipX)?: boolean
If flip the texture horizontally.
# [flipY](#undefined-flipY)?: boolean
If flip the texture vertically.
# [quad](#undefined-quad)?: Quad
The sub-area to render from the texture, by default it'll render the whole \`quad(0, 0, 1, 1)\`
# [anchor](#undefined-anchor)?: Anchor \| Vec2
The anchor point, or the pivot point. Default to \"topleft\".
# [pos](#undefined-pos)?: Vec2
The position
How the sprite should look like.
[DrawTextOpt](#DrawTextOpt): RenderProps &
# [text](#undefined-text): string
The text to render.
# [font](#undefined-font)?: string \| FontData \| Asset \| BitmapFontData \| Asset
The name of font to use.
# [size](#undefined-size)?: number
The size of text (the height of each character).
# [align](#undefined-align)?: TextAlign
Text alignment (default \"left\")
`since`v3000.0
# [width](#undefined-width)?: number
The maximum width. Will wrap word around if exceed.
# [lineSpacing](#undefined-lineSpacing)?: number
The gap between each line (only available for bitmap fonts).
`since`v2000.2
# [letterSpacing](#undefined-letterSpacing)?: number
The gap between each character (only available for bitmap fonts).
`since`v2000.2
# [anchor](#undefined-anchor)?: Anchor \| Vec2
The anchor point, or the pivot point. Default to \"topleft\".
# [transform](#undefined-transform)?: CharTransform \| CharTransformFunc
Transform the pos, scale, rotation or color for each character based on the index or char (only available for bitmap fonts).
`since`v2000.1
# [styles](#undefined-styles)?: Record\<string, CharTransform \| CharTransformFunc\>
Stylesheet for styled chunks, in the syntax of \"this is a \[stylename\]styled\[/stylename\] word\" (only available for bitmap fonts).
`since`v2000.2
# [indentAll](#undefined-indentAll)?: boolean
If true, any (whitespace) indent on the first line of the paragraph will be copied to all of the lines for those parts that text-wrap.
How the text should look like.
[DrawTextureOpt](#DrawTextureOpt): RenderProps &
# [tex](#undefined-tex): Texture
# [width](#undefined-width)?: number
# [height](#undefined-height)?: number
# [tiled](#undefined-tiled)?: boolean
# [flipX](#undefined-flipX)?: boolean
# [flipY](#undefined-flipY)?: boolean
# [quad](#undefined-quad)?: Quad
# [anchor](#undefined-anchor)?: Anchor \| Vec2
[DrawTriangleOpt](#DrawTriangleOpt): RenderProps &
# [p1](#undefined-p1): Vec2
First point of triangle.
# [p2](#undefined-p2): Vec2
Second point of triangle.
# [p3](#undefined-p3): Vec2
Third point of triangle.
# [fill](#undefined-fill)?: boolean
If fill the shape with color (set this to false if you only want an outline).
# [radius](#undefined-radius)?: number
The radius of each corner.
How the triangle should look like.
[DrawUVQuadOpt](#DrawUVQuadOpt): RenderProps &
# [width](#undefined-width): number
Width of the UV quad.
# [height](#undefined-height): number
Height of the UV quad.
# [flipX](#undefined-flipX)?: boolean
If flip the texture horizontally.
# [flipY](#undefined-flipY)?: boolean
If flip the texture vertically.
# [tex](#undefined-tex)?: Texture
The texture to sample for this quad.
# [quad](#undefined-quad)?: Quad
The texture sampling area.
# [anchor](#undefined-anchor)?: Anchor \| Vec2
The anchor point, or the pivot point. Default to \"topleft\".
# [DrawonComp](#DrawonComp):
# [refresh](#DrawonComp-refresh)(): void
[DrawonOpt](#DrawonOpt):
# [childrenOnly](#undefined-childrenOnly)?: boolean
# [refreshOnly](#undefined-refreshOnly)?: boolean
# [EaseFunc](#EaseFunc)(t: number): number
A function that takes a time value and returns a new time value.
# [EaseFuncs](#EaseFuncs): linear \| easeInSine \| easeOutSine \| easeInOutSine \| easeInQuad \| easeOutQuad \| easeInOutQuad \| easeInCubic \| easeOutCubic \| easeInOutCubic \| easeInQuart \| easeOutQuart \| easeInOutQuart \| easeInQuint \| easeOutQuint \| easeInOutQuint \| easeInExpo \| easeOutExpo \| easeInOutExpo \| easeInCirc \| easeOutCirc \| easeInOutCirc \| easeInBack \| easeOutBack \| easeInOutBack \| easeInElastic \| easeOutElastic \| easeInOutElastic \| easeInBounce \| easeOutBounce \| easeInOutBounce
The list of easing functions available.
# [Edge\$1](#Edge$1):
# [obj](#Edge$1-obj): GameObj\<AreaComp\>
# [x](#Edge$1-x): number
# [isLeft](#Edge$1-isLeft): boolean
# [Edge](#Edge): left \| right \| top \| bottom
# [EdgeMask](#EdgeMask):
# [None](#EdgeMask-None):
# [Left](#EdgeMask-Left):
# [Top](#EdgeMask-Top):
# [LeftTop](#EdgeMask-LeftTop):
# [Right](#EdgeMask-Right):
# [Horizontal](#EdgeMask-Horizontal):
# [RightTop](#EdgeMask-RightTop):
# [HorizontalTop](#EdgeMask-HorizontalTop):
# [Bottom](#EdgeMask-Bottom):
# [LeftBottom](#EdgeMask-LeftBottom):
# [Vertical](#EdgeMask-Vertical):
# [LeftVertical](#EdgeMask-LeftVertical):
# [RightBottom](#EdgeMask-RightBottom):
# [HorizontalBottom](#EdgeMask-HorizontalBottom):
# [RightVertical](#EdgeMask-RightVertical):
# [All](#EdgeMask-All):
# [Ellipse](#Ellipse):
# [center](#Ellipse-center): Vec2
# [radiusX](#Ellipse-radiusX): number
# [radiusY](#Ellipse-radiusY): number
# [angle](#Ellipse-angle): number
# [fromMat2](#Ellipse-fromMat2)(tr: Mat2): Ellipse
# [toMat2](#Ellipse-toMat2)(): Mat2
# [transform](#Ellipse-transform)(tr: Mat23): Ellipse
# [bbox](#Ellipse-bbox)(): Rect
# [area](#Ellipse-area)(): number
# [clone](#Ellipse-clone)(): Ellipse
# [collides](#Ellipse-collides)(shape: ShapeType): boolean
# [contains](#Ellipse-contains)(point: Vec2): boolean
# [raycast](#Ellipse-raycast)(origin: Vec2, direction: Vec2): RaycastResult
# [random](#Ellipse-random)(): Vec2
# [EllipseComp](#EllipseComp):
The ellipse`ellipse()` component.
# [draw](#EllipseComp-draw): Comp\[draw\]
# [radiusX](#EllipseComp-radiusX): number
Semi-major axis of ellipse.
# [radiusY](#EllipseComp-radiusY): number
Semi-minor axis of ellipse.
# [renderArea](#EllipseComp-renderArea)(): Ellipse
Render area of the ellipse.
# [EllipseCompOpt](#EllipseCompOpt):
Options for the ellipse\`ellipse()\`\` component.
# [fill](#EllipseCompOpt-fill)?: boolean
If fill is false, the ellipse is not filled (useful if you only want to render outline with outline`outline()` component).
[EmitterOpt](#EmitterOpt):
# [shape](#undefined-shape)?: ShapeType
Shape of the emitter. If given, particles spawn within this shape.
# [lifetime](#undefined-lifetime)?: number
Lifetime of the emitter.
# [rate](#undefined-rate)?: number
Rate of emission in particles per second if the emitter should emit out of itself.
# [position](#undefined-position): Vec2
Position (relative) of emission.
# [direction](#undefined-direction): number
Direction of emission.
# [spread](#undefined-spread): number
Spread (cone) of emission around the direction.
Options for the particles`particles()`'s component
[EmptyComp](#EmptyComp):
# [id](#undefined-id): string
& Comp
A component without own properties.
# [Engine](#Engine): ReturnType\<createEngine\>
# [FPSCounter](#FPSCounter):
# [dts](#FPSCounter-dts): number\[\]
# [timer](#FPSCounter-timer): number
# [fps](#FPSCounter-fps): number
# [tick](#FPSCounter-tick)(dt: number): void
# [FakeMouseComp](#FakeMouseComp):
The fakeMouse`fakeMouse()` component.
# [isPressed](#FakeMouseComp-isPressed)(): boolean
Whether the fake mouse is pressed.
# [press](#FakeMouseComp-press)(): void
Trigger press (onClick).
# [release](#FakeMouseComp-release)(): void
Trigger release.
# [onPress](#FakeMouseComp-onPress)(action: ()=\>void): void
Register an event that runs when the fake mouse performs a click.
# [onRelease](#FakeMouseComp-onRelease)(action: ()=\>void): void
Register an event that runs when the fake mouse releases.
[FakeMouseOpt](#FakeMouseOpt):
# [followMouse](#undefined-followMouse)?: boolean
Whether the fake mouse should follow the real mouse. Defaults to \`true\`.
Options for the fakeMouse`fakeMouse()` component.
# [FixedComp](#FixedComp):
The fixed`fixed()` component.
# [fixed](#FixedComp-fixed): boolean
If the obj is unaffected by camera
# [FollowComp](#FollowComp):
The follow`follow()` component.
[follow](#FollowComp-follow):
# [obj](#undefined-obj): GameObj
The object to follow.
# [offset](#undefined-offset): Vec2
The offset to follow the object by.
# [FontData](#FontData):
# [fontface](#FontData-fontface): FontFace
# [filter](#FontData-filter): TexFilter
# [outline](#FontData-outline): Outline \| null
# [size](#FontData-size): number
# [ForceMode](#ForceMode): constant \| inverseLinear \| inverseSquared
# [FormattedChar](#FormattedChar):
One formated character.
# [ch](#FormattedChar-ch): string
# [tex](#FormattedChar-tex): Texture
# [width](#FormattedChar-width): number
# [height](#FormattedChar-height): number
# [quad](#FormattedChar-quad): Quad
# [pos](#FormattedChar-pos): Vec2
# [scale](#FormattedChar-scale): Vec2
# [angle](#FormattedChar-angle): number
# [color](#FormattedChar-color): Color
# [opacity](#FormattedChar-opacity): number
# [font](#FormattedChar-font)?: string \| FontData
# [stretchInPlace](#FormattedChar-stretchInPlace): boolean
# [shader](#FormattedChar-shader)?: string
# [uniform](#FormattedChar-uniform)?: Uniform
[FormattedText](#FormattedText):
# [width](#undefined-width): number
# [height](#undefined-height): number
# [chars](#undefined-chars): FormattedChar\[\]
# [opt](#undefined-opt): DrawTextOpt
# [renderedText](#undefined-renderedText): string
Formatted text with info on how and where to render each character.
# [FrameBuffer](#FrameBuffer):
# [ctx](#FrameBuffer-ctx): GfxCtx
# [tex](#FrameBuffer-tex): Texture
# [glFramebuffer](#FrameBuffer-glFramebuffer): WebGLFramebuffer
# [glRenderbuffer](#FrameBuffer-glRenderbuffer): WebGLRenderbuffer
# [width](#FrameBuffer-width)(): number
# [height](#FrameBuffer-height)(): number
# [toImageData](#FrameBuffer-toImageData)(): ImageData
# [toDataURL](#FrameBuffer-toDataURL)(): string
# [clear](#FrameBuffer-clear)(): void
# [draw](#FrameBuffer-draw)(action: ()=\>void): void
# [bind](#FrameBuffer-bind)(): void
# [unbind](#FrameBuffer-unbind)(): void
# [free](#FrameBuffer-free)(): void
# [FrameRenderer](#FrameRenderer): ReturnType\<createFrameRenderer\>
[Game](#Game):
# [events](#undefined-events): KEventHandler\<GameEventMap & GameObjEventMap\>
Where game object global events are stored.
# [root](#undefined-root): GameObj\<TimerComp\>
The root game object, parent of all game objects.
# [gravity](#undefined-gravity): Vec2 \| null
# [scenes](#undefined-scenes): Record\<SceneName, SceneDef\>
# [currentScene](#undefined-currentScene): string \| null
# [layers](#undefined-layers): string\[\] \| null
# [defaultLayerIndex](#undefined-defaultLayerIndex): number
# [systems](#undefined-systems): System\[\]
# [systemsByEvent](#undefined-systemsByEvent): \[System\[\], System\[\], System\[\], System\[\], System\[\], System\[\]\]
# [kaSprite](#undefined-kaSprite): Asset \| null
# [boomSprite](#undefined-boomSprite): Asset \| null
# [logs](#undefined-logs): Log\[\]
# [cam](#undefined-cam): CamData
The \"Game\" it's all the state related to the game running
[GameEventMap](#GameEventMap):
# [load](#undefined-load): \[\]
# [loadError](#undefined-loadError): \[string, Asset\]
# [loading](#undefined-loading): \[number\]
# [error](#undefined-error): \[Error\]
# [input](#undefined-input): \[\]
# [frameEnd](#undefined-frameEnd): \[\]
# [resize](#undefined-resize): \[\]
# [sceneLeave](#undefined-sceneLeave): \[string\]
# [sceneEnter](#undefined-sceneEnter): \[string\]
All Game State events with their arguments
# [GameObj](#GameObj)\<T\>: GameObjRaw & MergeComps
The basic unit of object in KAPLAY. The player, a butterfly, a tree, or even a piece of text.
[GameObjEventMap](#GameObjEventMap):
# [update](#undefined-update): \[GameObj\]
Triggered every frame
# [fixedUpdate](#undefined-fixedUpdate): \[GameObj\]
Triggered every frame at a fixed 50fps rate
# [draw](#undefined-draw): \[GameObj\]
Triggered every frame before update
# [add](#undefined-add): \[GameObj\]
Triggered when object is added
# [destroy](#undefined-destroy): \[GameObj\]
Triggered when object is destroyed
# [use](#undefined-use): \[GameObj, string\]
Triggered when component is used
# [unuse](#undefined-unuse): \[GameObj, string\]
Triggered when component is unused
# [tag](#undefined-tag): \[GameObj, string\]
Triggered when tag is added
# [untag](#undefined-untag): \[GameObj, string\]
Triggered when tag is removed
# [collide](#undefined-collide): \[GameObj, GameObj, Collision\]
Triggered when object collides with another object From area`area()` component
# [collideUpdate](#undefined-collideUpdate): \[GameObj, GameObj, Collision\]
Triggered every frame when object collides with another object From area`area()` component
# [collideEnd](#undefined-collideEnd): \[GameObj, GameObj, Collision\]
Triggered when object stops colliding with another object From area`area()` component
# [hurt](#undefined-hurt): \[GameObj, NamedTupleMember\]
Triggered when object is hurted From health`health()` component
# [heal](#undefined-heal): \[GameObj, NamedTupleMember\]
Triggered when object is healed From health`health()` component
# [death](#undefined-death): \[GameObj\]
Triggered when object dies From health`health()` component
# [beforePhysicsResolve](#undefined-beforePhysicsResolve): \[GameObj, NamedTupleMember\]
Triggered before physics resolves From body`body()` component
# [physicsResolve](#undefined-physicsResolve): \[GameObj, NamedTupleMember\]
Triggered after physics resolves From body`body()` component
# [ground](#undefined-ground): \[GameObj\]
Triggered when object is on the ground From body`body()` component
# [fall](#undefined-fall): \[GameObj\]
Triggered when object is falling From body`body()` component
# [fallOff](#undefined-fallOff): \[GameObj\]
Triggered when object stops falling From body`body()` component
# [headbutt](#undefined-headbutt): \[GameObj\]
Triggered when object head butt something (like Mario with brick) From body`body()` component
# [land](#undefined-land): \[GameObj\]
Triggered when an object lands on this object From body`body()` component
# [headbutted](#undefined-headbutted): \[GameObj\]
Triggered when object is headbutted by another object From body`body()` component
# [doubleJump](#undefined-doubleJump): \[GameObj\]
Triggered when object double jumps From doubleJump`doubleJump()` component
# [exitView](#undefined-exitView): \[GameObj\]
Triggered when object goes out of view From offscreen`offscreen()` component
# [enterView](#undefined-enterView): \[GameObj\]
Triggered when object enters view From offscreen`offscreen()` component
# [animStart](#undefined-animStart): \[GameObj, NamedTupleMember\]
Triggered when a sprite animation starts From sprite`sprite()` component
# [animEnd](#undefined-animEnd): \[GameObj, NamedTupleMember\]
Triggered when a sprite animation ends From sprite`sprite()` component
# [navigationNext](#undefined-navigationNext): \[GameObj, GameObj, Vec2\]
From agent`agent()` component
# [navigationEnded](#undefined-navigationEnded): \[GameObj, GameObj\]
From agent`agent()` component
# [navigationStarted](#undefined-navigationStarted): \[GameObj, GameObj\]
From agent`agent()` component
# [targetReached](#undefined-targetReached): \[GameObj, GameObj\]
From agent`agent()` component
# [patrolFinished](#undefined-patrolFinished): \[GameObj\]
From patrol`patrol()` component
# [objectSpotted](#undefined-objectSpotted): \[GameObj, GameObj\[\]\]
From sentry`sentry()` component
# [animateChannelFinished](#undefined-animateChannelFinished): \[GameObj, NamedTupleMember\]
From animate`animate()` component
# [animateFinished](#undefined-animateFinished): \[GameObj\]
From animate`animate()` component
# [spatialMapChanged](#undefined-spatialMapChanged): \[GameObj\]
From level of addLevel`addLevel()` function
# [navigationMapInvalid](#undefined-navigationMapInvalid): \[GameObj\]
From level of addLevel`addLevel()` function
# [navigationMapChanged](#undefined-navigationMapChanged): \[GameObj\]
From level of addLevel`addLevel()` function
Game Object events with their arguments. If looking for use it with \`obj.on()\`, ignore first parameter (Game Obj)
# [GameObjEventNames](#GameObjEventNames): GameObjEventMap
# [GameObjEvents](#GameObjEvents): GameObjEventMap &
# [GameObjID](#GameObjID): number
# [GameObjInspect](#GameObjInspect): Record\<Tag, string \| null\>
Inspect info for a game object.
# [GameObjRaw](#GameObjRaw):
Base interface of all game objects.
`since`v2000.0
# [id](#GameObjRaw-id): GameObjID
The unique id of the game obj.
# [children](#GameObjRaw-children): GameObj\[\]
Get all children game objects.
`readonly`
`since`v3000.0
# [tags](#GameObjRaw-tags): string\[\]
Get the tags of a game object. For update it, use \`tag()\` and \`untag()\`.
`readonly`
`since`v3001.0
# [transform](#GameObjRaw-transform): Mat23
Calculated transform matrix of a game object.
`since`v3000.0
# [hidden](#GameObjRaw-hidden): boolean
If draw the game obj (run \"draw\" event or not).
`since`v2000.0
# [paused](#GameObjRaw-paused): boolean
If update the game obj (run \"update\" event or not).
`since`v2000.0
# [target](#GameObjRaw-target)?: RenderTarget
The canvas to draw this game object on
`since`v3001.0
# [setParent](#GameObjRaw-setParent)(p: GameObj, opt: SetParentOpt): void
Set the parent game obj with additional options.
`since`v4000.0
# [add](#GameObjRaw-add)\<T\>(comps?: \[RestType\]): GameObj\<T\[number\]\>
Add a child.
`param`comps- The components to add.
`returns`The added game object.
`since`v3000.0
# [readd](#GameObjRaw-readd)\<T\>(obj: GameObj): GameObj\<T\>
Remove and re-add the game obj, without triggering add / destroy events.
`param`obj- The game object to re-add.
`returns`The re-added game object.
`since`v3000.0
# [remove](#GameObjRaw-remove)(obj: GameObj): void
Remove a child.
`param`obj- The game object to remove.
`since`v3000.0
# [removeAll](#GameObjRaw-removeAll)(tag: Tag): void
Remove all children with a certain tag.
`param`tag- The tag to remove.
`since`v3000.0
# [removeAll](#GameObjRaw-removeAll)(): void
Remove all children.
`since`v3000.0
# [destroy](#GameObjRaw-destroy)(): void
Remove this game obj from scene.
`since`v2000.0
# [exists](#GameObjRaw-exists)(): boolean
If game obj is attached to the scene graph.
`returns`true if attached, false otherwise.
`since`v2000.0
# [isAncestorOf](#GameObjRaw-isAncestorOf)(obj: GameObj): boolean
Check if is an ancestor (recursive parent) of another game object
`returns`true if is ancestor, false otherwise.
`since`v3000.0
# [get](#GameObjRaw-get)\<T\>(tag: Tag \| Tag\[\], opts?: GetOpt): GameObj\[\]
Get a list of all game objs with certain tag.
`param`tag- The tag to get.
`since`v3000.0
# [query](#GameObjRaw-query)(opt: QueryOpt): GameObj\[\]
Get a list of all game objs with certain properties.
`param`opt- The properties to get.
`since`v3001.0
# [update](#GameObjRaw-update)(): void
Update this game object and all children game objects.
`since`v3000.0
# [fixedUpdate](#GameObjRaw-fixedUpdate)(): void
Update this game object and all children game objects.
`since`v3001.0
# [draw](#GameObjRaw-draw)(): void
Draw this game object and all children game objects.
`since`v3000.0
# [drawTree](#GameObjRaw-drawTree)(): void
# [inspect](#GameObjRaw-inspect)(): GameObjInspect
Gather debug info of all comps.
`since`v2000.0
# [drawInspect](#GameObjRaw-drawInspect)(): void
Draw debug info in inspect mode
`since`v3000.0
# [collectAndTransform](#GameObjRaw-collectAndTransform)(objects: GameObj\[\]): void
This method is called to transform and collect objects which should be drawn layered
# [use](#GameObjRaw-use)(comp: Comp): void
Add a component.
``` js
const obj = add([
sprite("bean"),
]);
// Add opacity
obj.use(opacity(0.5));
```
`since`v2000.0
# [unuse](#GameObjRaw-unuse)(comp: string): void
Remove a component with its id (the component name)
`param`comp- The component id to remove. It means the name, if sprite, then it's \"sprite\".
``` js
// Remove sprite component
obj.unuse("sprite");
```
`since`v2000.0
# [has](#GameObjRaw-has)(compId: string \| string\[\], op?: and \| or): boolean
Check if game object has a certain component.
`param`compId- The component id(s) to check.
`param`op- The operator to use when searching for multiple components. Default is \"and\".
``` js
// Check if game object has sprite component
if(obj.has("sprite")) {
debug.log("has sprite component");
}
// Check if game object has tags
obj.has(["tag1", "tag2"]); // AND, it has both tags
obj.has(["tag1", "tag2"], "or"); // OR, it has either tag1 or tag2
```
`returns`true if has the component(s), false otherwise.
`since`v3001.0.5
`experimental`This feature is in experimental phase, it will be fully released in v3001.1.0
# [c](#GameObjRaw-c)(id: string): Comp \| null
Get state for a specific comp.
`param`id- The component id.
`since`v2000.0
# [tag](#GameObjRaw-tag)(tag: Tag \| Tag\[\]): void
Add a tag(s) to the game obj.
`param`tag- The tag(s) to add.
``` js
// add enemy tag
obj.tag("enemy");
// add multiple tags
obj.tag(["enemy", "boss"]);
```
`since`v3001.0.5
`experimental`This feature is in experimental phase, it will be fully released in v3001.1.0
# [untag](#GameObjRaw-untag)(tag: Tag \| Tag\[\]): void
Remove a tag(s) from the game obj.
`param`tag- The tag(s) to remove.
``` js
// remove enemy tag
obj.untag("enemy");
// remove multiple tags
obj.untag(["enemy", "boss"]);
```
`since`v3001.0.5
`experimental`This feature is in experimental phase, it will be fully released in v3001.1.0
# [is](#GameObjRaw-is)(tag: Tag \| Tag\[\], op?: and \| or): boolean
If there's certain tag(s) on the game obj.
`param`tag- The tag(s) for checking.
`param`op- The operator to use when searching for multiple tags. Default is \"and\".
`since`v3001.0.5
`experimental`This feature is in experimental phase, it will be fully released in v3001.1.0
# [on](#GameObjRaw-on)(event: GameObjEventNames \| string & , action: (args: any)=\>void): KEventController
Register an event.
`param`event- The event name.
`param`action- The action to run when event is triggered.
`returns`The event controller.
`since`v2000.0
# [trigger](#GameObjRaw-trigger)(event: string, args: any): void
Trigger an event.
`param`event- The event name.
`parm`args - The arguments to pass to the event action.
`since`v2000.0
# [clearEvents](#GameObjRaw-clearEvents)(): void
Clear all events.
# [onAdd](#GameObjRaw-onAdd)(action: ()=\>void): KEventController
Register an event that runs when the game obj is added to the scene.
`returns`The event controller.
`since`v2000.0
# [onUpdate](#GameObjRaw-onUpdate)(action: ()=\>void): KEventController
Register an event that runs every frame as long as the game obj exists.
`returns`The event controller.
`since`v2000.1
# [onFixedUpdate](#GameObjRaw-onFixedUpdate)(action: ()=\>void): KEventController
Register an event that runs every frame as long as the game obj exists.
`returns`The event controller.
`since`v2000.1
# [onDraw](#GameObjRaw-onDraw)(action: ()=\>void): KEventController
Register an event that runs every frame as long as the game obj exists (this is the same as \`onUpdate()\`, but all draw events are run after all update events).
`returns`The event controller.
`since`v2000.1
# [onDestroy](#GameObjRaw-onDestroy)(action: ()=\>void): KEventController
Register an event that runs when the game obj is destroyed.
`returns`The event controller.
`since`v2000.1
# [onUse](#GameObjRaw-onUse)(action: (id: string)=\>void): KEventController
Register an event that runs when a component is used.
`returns`The event controller.
`since`v4000.0
# [onUnuse](#GameObjRaw-onUnuse)(action: (id: string)=\>void): KEventController
Register an event that runs when a component is unused.
`returns`The event controller.
`since`v4000.0
# [onTag](#GameObjRaw-onTag)(action: (tag: string)=\>void): KEventController
Register an event that runs when a tag is added.
`returns`The event controller.
`since`v4000.0
# [onUntag](#GameObjRaw-onUntag)(action: (tag: string)=\>void): KEventController
Register an event that runs when a tag is removed.
`returns`The event controller.
`since`v4000.0
# [onKeyDown](#GameObjRaw-onKeyDown): KAPLAYCtx\[onKeyDown\]
# [onKeyPress](#GameObjRaw-onKeyPress): KAPLAYCtx\[onKeyPress\]
# [onKeyPressRepeat](#GameObjRaw-onKeyPressRepeat): KAPLAYCtx\[onKeyPressRepeat\]
# [onKeyRelease](#GameObjRaw-onKeyRelease): KAPLAYCtx\[onKeyRelease\]
# [onCharInput](#GameObjRaw-onCharInput): KAPLAYCtx\[onCharInput\]
# [onMouseDown](#GameObjRaw-onMouseDown): KAPLAYCtx\[onMouseDown\]
# [onMousePress](#GameObjRaw-onMousePress): KAPLAYCtx\[onMousePress\]
# [onMouseRelease](#GameObjRaw-onMouseRelease): KAPLAYCtx\[onMouseRelease\]
# [onMouseMove](#GameObjRaw-onMouseMove): KAPLAYCtx\[onMouseMove\]
# [onTouchStart](#GameObjRaw-onTouchStart): KAPLAYCtx\[onTouchStart\]
# [onTouchMove](#GameObjRaw-onTouchMove): KAPLAYCtx\[onTouchMove\]
# [onTouchEnd](#GameObjRaw-onTouchEnd): KAPLAYCtx\[onTouchEnd\]
# [onScroll](#GameObjRaw-onScroll): KAPLAYCtx\[onScroll\]
# [onGamepadButtonDown](#GameObjRaw-onGamepadButtonDown): KAPLAYCtx\[onGamepadButtonDown\]
# [onGamepadButtonPress](#GameObjRaw-onGamepadButtonPress): KAPLAYCtx\[onGamepadButtonPress\]
# [onGamepadButtonRelease](#GameObjRaw-onGamepadButtonRelease): KAPLAYCtx\[onGamepadButtonRelease\]
# [onGamepadStick](#GameObjRaw-onGamepadStick): KAPLAYCtx\[onGamepadStick\]
# [onButtonDown](#GameObjRaw-onButtonDown): KAPLAYCtx\[onButtonDown\]
# [onButtonPress](#GameObjRaw-onButtonPress): KAPLAYCtx\[onButtonPress\]
# [onButtonRelease](#GameObjRaw-onButtonRelease): KAPLAYCtx\[onButtonRelease\]
# [\_parent](#GameObjRaw-_parent): GameObj
`readonly`
# [\_compsIds](#GameObjRaw-_compsIds): Set\<string\>
# [\_compStates](#GameObjRaw-_compStates): Map\<string, Comp\>
# [\_anonymousCompStates](#GameObjRaw-_anonymousCompStates): Comp\[\]
# [\_cleanups](#GameObjRaw-_cleanups): Record\<string, ()=\>any\[\]\>
# [\_events](#GameObjRaw-_events): KEventHandler\<any\>
# [\_fixedUpdateEvents](#GameObjRaw-_fixedUpdateEvents): KEvent\<\[\]\>
# [\_updateEvents](#GameObjRaw-_updateEvents): KEvent\<\[\]\>
# [\_drawEvents](#GameObjRaw-_drawEvents): KEvent\<\[\]\>
# [\_inputEvents](#GameObjRaw-_inputEvents): KEventController\[\]
# [\_onCurCompCleanup](#GameObjRaw-_onCurCompCleanup): Function \| null
# [\_tags](#GameObjRaw-_tags): Set\<Tag\>
[GamepadDef](#GamepadDef):
# [buttons](#undefined-buttons): Record\<string, KGamepadButton\>
# [sticks](#undefined-sticks): Partial\<Record\>
A gamepad definition.
# [GamepadState](#GamepadState):
# [buttonState](#GamepadState-buttonState): ButtonState\<KGamepadButton\>
# [stickState](#GamepadState-stickState): Map\<GamepadStick, Vec2\>
# [GamepadStick](#GamepadStick): left \| right
A gamepad stick.
[GetOpt](#GetOpt):
# [recursive](#undefined-recursive)?: boolean
Recursively get all children and their descendants.
# [liveUpdate](#undefined-liveUpdate)?: boolean
Live update the returned list every time object is added / removed.
# [only](#undefined-only)?: tags \| comps
Get only by tags or components.
# [GfxCtx](#GfxCtx): ReturnType\<initGfx\>
# [GfxFont](#GfxFont):
# [tex](#GfxFont-tex): Texture
# [map](#GfxFont-map): Record\<string, Quad\>
# [size](#GfxFont-size): number
[GjkCollisionResult](#GjkCollisionResult):
# [normal](#undefined-normal): Vec2
The direction the first shape needs to be moved to resolve the collision
# [distance](#undefined-distance): number
The distance the first shape needs to be moved to resolve the collision
# [Graph](#Graph):
# [getNeighbours](#Graph-getNeighbours)(node: number): number\[\]
# [getCost](#Graph-getCost)(node: number, neighbor: number): number
# [getHeuristic](#Graph-getHeuristic)(node: number, goal: number): number
# [getPath](#Graph-getPath)(from: number, to: number): number\[\]
# [getWaypointPath](#Graph-getWaypointPath)(from: Vec2, to: Vec2, opt: any): Vec2\[\]
# [Grid](#Grid):
A grid is a graph consisting of connected grid cells
# [\_columns](#Grid-_columns):
# [\_rows](#Grid-_rows):
# [\_tileWidth](#Grid-_tileWidth):
# [\_tileHeight](#Grid-_tileHeight):
# [\_data](#Grid-_data):
# [\_diagonals](#Grid-_diagonals):
# [\_connMap](#Grid-_connMap):
# [\_buildConnectivityMap](#Grid-_buildConnectivityMap):
# [\_getTile](#Grid-_getTile):
# [\_getTileX](#Grid-_getTileX):
# [\_getTileY](#Grid-_getTileY):
# [getNeighbours](#Grid-getNeighbours)(tile: number): number\[\]
# [getCost](#Grid-getCost)(a: number, b: number): number
# [getHeuristic](#Grid-getHeuristic)(a: number, b: number): number
# [getPath](#Grid-getPath)(start: number, goal: number): number\[\]
# [getWaypointPath](#Grid-getWaypointPath)(start: Vec2, goal: Vec2): Vec2\[\]
# [HealthComp](#HealthComp):
The health`health()` component.
# [hurt](#HealthComp-hurt)(n?: number): void
Decrease HP by n (defaults to 1).
# [heal](#HealthComp-heal)(n?: number): void
Increase HP by n (defaults to 1).
# [hp](#HealthComp-hp)(): number
Current health points.
# [setHP](#HealthComp-setHP)(hp: number): void
Set current health points.
# [maxHP](#HealthComp-maxHP)(): number \| null
Max amount of HP.
# [setMaxHP](#HealthComp-setMaxHP)(hp: number): void
Set max amount of HP.
# [onHurt](#HealthComp-onHurt)(action: (amount?: number)=\>void): KEventController
Register an event that runs when hurt() is called upon the object.
`since`v2000.1
# [onHeal](#HealthComp-onHeal)(action: (amount?: number)=\>void): KEventController
Register an event that runs when heal() is called upon the object.
`since`v2000.1
# [onDeath](#HealthComp-onDeath)(action: ()=\>void): KEventController
Register an event that runs when object's HP is equal or below 0.
`since`v2000.1
# [ImageSource](#ImageSource): Exclude\<TexImageSource, VideoFrame\>
# [Interpolation](#Interpolation): none \| linear \| slerp \| spline
# [KAPLAYOpt](#KAPLAYOpt)\<TPlugin, TButtonDef\>:
KAPLAY configurations.
# [width](#KAPLAYOpt-width)?: number
Width of game.
# [height](#KAPLAYOpt-height)?: number
Height of game.
# [scale](#KAPLAYOpt-scale)?: number
Pixel scale / size.
# [letterbox](#KAPLAYOpt-letterbox)?: boolean
Keep aspect ratio and leave black bars on remaining spaces.
# [debug](#KAPLAYOpt-debug)?: boolean
If register debug buttons (default true)
# [debugKey](#KAPLAYOpt-debugKey)?: Key
Key that toggles debug mode
# [font](#KAPLAYOpt-font)?: string
Default font (defaults to \"monospace\").
# [pixelDensity](#KAPLAYOpt-pixelDensity)?: number
Device pixel scale (defaults to 1, high pixel density will hurt performance).
`since`v3000.0
# [crisp](#KAPLAYOpt-crisp)?: boolean
Disable antialias and enable sharp pixel display.
# [canvas](#KAPLAYOpt-canvas)?: HTMLCanvasElement
The canvas DOM element to use. If empty will create one.
# [root](#KAPLAYOpt-root)?: HTMLElement
The container DOM element to insert the canvas if created. Defaults to document.body.
# [background](#KAPLAYOpt-background)?: RGBValue \| RGBAValue \| string
Background color. E.g. \[ 0, 0, 255 \] for solid blue background, or \[ 0, 0, 0, 0 \] for transparent background. Accepts RGB value array or string hex codes.
# [texFilter](#KAPLAYOpt-texFilter)?: TexFilter
Default texture filter.
# [logMax](#KAPLAYOpt-logMax)?: number
How many log messages can there be on one screen (default 8).
# [logTime](#KAPLAYOpt-logTime)?: number
How many seconds log messages stay on screen (default 4).
`since`v3000.1
# [hashGridSize](#KAPLAYOpt-hashGridSize)?: number
Size of the spatial hash grid for collision detection (default 64).
`since`v3000.0
# [touchToMouse](#KAPLAYOpt-touchToMouse)?: boolean
If translate touch events as mouse clicks (default true).
# [loadingScreen](#KAPLAYOpt-loadingScreen)?: boolean
If KAPLAY should render a default loading screen when assets are not fully ready (default true).
`since`v3000.0
# [backgroundAudio](#KAPLAYOpt-backgroundAudio)?: boolean
If pause audio when tab is not active (default false).
`since`v3000.0
# [gamepads](#KAPLAYOpt-gamepads)?: Record\<string, GamepadDef\>
Custom gamepad definitions (see gamepad.json for reference of the format).
`since`v3000.0
# [buttons](#KAPLAYOpt-buttons)?: TButtonDef
Defined buttons for input binding.
`since`v30010
# [maxFPS](#KAPLAYOpt-maxFPS)?: number
Limit framerate to an amount per second.
`since`v3000.0
# [focus](#KAPLAYOpt-focus)?: boolean
If focus on the canvas on start (default true).
`since`v3001.0
# [global](#KAPLAYOpt-global)?: boolean
If import all KAPLAY functions to global (default true).
# [plugins](#KAPLAYOpt-plugins)?: TPlugin
List of plugins to import.
# [burp](#KAPLAYOpt-burp)?: boolean
Enter burp mode.
# [tagsAsComponents](#KAPLAYOpt-tagsAsComponents)?: boolean
Make component's id (\"sprite\" for sprite() comp) be added as tags. That means .is() will return true for components with that id.
`default`true
`experimental`This feature is in experimental phase, it will be fully released in v3001.1.0
# [spriteAtlasPadding](#KAPLAYOpt-spriteAtlasPadding)?: number
Padding used when adding sprites to texture atlas.
`default`0
# [inspectOnlyActive](#KAPLAYOpt-inspectOnlyActive)?: boolean
If the debug inspect view should ignore objects that are paused when choosing the object to show the inspect view on.
`default`false
`experimental`
# [KAPLAYPlugin](#KAPLAYPlugin)\<T\>(k: KAPLAYCtx): T \| (args: any)=\>(k: KAPLAYCtx)=\>T
A plugin for KAPLAY.
``` js
// a plugin that adds a new function to KAPLAY
const myPlugin = (k) => ({
myFunc: () => {
k.debug.log("hello from my plugin")
}
})
// use the plugin
kaplay({
plugins: [ myPlugin ]
})
// now you can use the new function
myFunc()
```
# [KEvent](#KEvent)\<Args\>:
# [cancellers](#KEvent-cancellers):
# [handlers](#KEvent-handlers):
# [add](#KEvent-add)(action: (args: Args)=\>unknown): KEventController
# [addOnce](#KEvent-addOnce)(action: (args: Args \| PromiseLike\[\])=\>void): KEventController
# [next](#KEvent-next)(): Promise\<Args\>
# [trigger](#KEvent-trigger)(args: Args): void
# [numListeners](#KEvent-numListeners)(): number
# [clear](#KEvent-clear)(): void
# [KEventController](#KEventController):
A controller for all events in KAPLAY.
``` js
// Create a new event
const logHi = onUpdate(() => {
debug.log("hi");
});
// Pause the event
logHi.paused = true;
// Cancel the event
logHi.cancel();
```
# [paused](#KEventController-paused): boolean
If the event is paused
# [cancel](#KEventController-cancel)(): void
Cancel the event
# [join](#KEventController-join)(events: KEventController\[\]): KEventController
# [replace](#KEventController-replace)(oldEv: KEventController, newEv: KEventController): KEventController
# [KEventHandler](#KEventHandler)\<EventMap\>:
# [handlers](#KEventHandler-handlers):
# [registers](#KEventHandler-registers): Partial\<MappedType\>
# [on](#KEventHandler-on)\<Name\>(name: Name, action: (args: EventMap\[Name\])=\>void): KEventController
# [onOnce](#KEventHandler-onOnce)\<Name\>(name: Name, action: (args: EventMap\[Name\])=\>void): KEventController
# [next](#KEventHandler-next)\<Name\>(name: Name): Promise\<unknown\>
# [trigger](#KEventHandler-trigger)\<Name\>(name: Name, args: EventMap\[Name\]): void
# [remove](#KEventHandler-remove)\<Name\>(name: Name): void
# [clear](#KEventHandler-clear)(): void
# [numListeners](#KEventHandler-numListeners)\<Name\>(name: Name): number
[KGamepad](#KGamepad):
# [index](#undefined-index): number
The order of the gamepad in the gamepad list.
# [isPressed](#undefined-isPressed)(b: KGamepadButton): boolean
If certain button is pressed.
# [isDown](#undefined-isDown)(b: KGamepadButton): boolean
If certain button is held down.
# [isReleased](#undefined-isReleased)(b: KGamepadButton): boolean
If certain button is released.
# [getStick](#undefined-getStick)(stick: GamepadStick): Vec2
Get the value of a stick.
A KAPLAY gamepad
# [KGamepadButton](#KGamepadButton): north \| east \| south \| west \| ltrigger \| rtrigger \| lshoulder \| rshoulder \| select \| start \| lstick \| rstick \| dpad-up \| dpad-right \| dpad-down \| dpad-left \| home \| capture
A gamepad button.
# [KeepFlags](#KeepFlags):
# [Pos](#KeepFlags-Pos):
# [Angle](#KeepFlags-Angle):
# [Scale](#KeepFlags-Scale):
# [All](#KeepFlags-All):
# [Key](#Key): f1 \| f2 \| f3 \| f4 \| f5 \| f6 \| f7 \| f8 \| f9 \| f10 \| f11 \| f12 \| \` \| 1 \| 2 \| 3 \| 4 \| 5 \| 6 \| 7 \| 8 \| 9 \| 0 \| - \| + \| = \| q \| w \| e \| r \| t \| y \| u \| i \| o \| p \| \[ \| \] \| \\ \| a \| s \| d \| f \| g \| h \| j \| k \| l \| ; \| ' \| z \| x \| c \| v \| b \| n \| m \| , \| . \| / \| escape \| backspace \| enter \| tab \| control \| alt \| meta \| space \| \| left \| right \| up \| down \| shift \| string &
A key.
# [LCEvents](#LCEvents):
# [LayerComp](#LayerComp):
The layer`layer()` component.
# [layerIndex](#LayerComp-layerIndex)(): number \| null
Get the index of the current layer the object is assigned to.
`returns`The index of the layer the object is assigned to, or \`null\` if the layer does not exist.
# [layer](#LayerComp-layer)(): string \| null
Get the name of the current layer the object is assigned to.
`returns`The name of the layer the object is assigned to.
# [layer](#LayerComp-layer)(name: string):
Set the name of the layer the object should be assigned to.
# [LerpValue](#LerpValue): number \| Vec2 \| Color
# [LevelComp](#LevelComp):
The level`level()` component.
# [tileWidth](#LevelComp-tileWidth)(): number
# [tileHeight](#LevelComp-tileHeight)(): number
# [numRows](#LevelComp-numRows)(): number
# [numColumns](#LevelComp-numColumns)(): number
# [spawn](#LevelComp-spawn)(sym: string, p: Vec2): GameObj \| null
Spawn a tile from a symbol defined previously.
# [spawn](#LevelComp-spawn)(sym: string, x: number, y: number): GameObj \| null
# [spawn](#LevelComp-spawn)\<T\>(obj: CompList, p: Vec2): GameObj \| null
Spawn a tile from a component list.
`returns`The spawned game object, or null if the obj hasn't components.
# [spawn](#LevelComp-spawn)\<T\>(sym: CompList, x: number, y: number): GameObj \| null
# [levelWidth](#LevelComp-levelWidth)(): number
Total width of level in pixels.
# [levelHeight](#LevelComp-levelHeight)(): number
Total height of level in pixels.
# [getAt](#LevelComp-getAt)(tilePos: Vec2): GameObj\[\]
Get all game objects that's currently inside a given tile.
# [raycast](#LevelComp-raycast)(origin: Vec2, direction: Vec2): RaycastResult
Raycast all game objects on the given path.
# [tile2Pos](#LevelComp-tile2Pos)(tilePos: Vec2): Vec2
Convert tile position to pixel position.
# [tile2Pos](#LevelComp-tile2Pos)(x: number, y: number): Vec2
# [pos2Tile](#LevelComp-pos2Tile)(pos: Vec2): Vec2
Convert pixel position to tile position.
# [pos2Tile](#LevelComp-pos2Tile)(x: number, y: number): Vec2
# [getTilePath](#LevelComp-getTilePath)(from: Vec2, to: Vec2, opts?: PathFindOpt): Vec2\[\] \| null
Find the path to navigate from one tile to another tile.
`returns`A list of traverse points in tile positions.
# [getPath](#LevelComp-getPath)(from: Vec2, to: Vec2, opts?: PathFindOpt): Vec2\[\] \| null
Find the path to navigate from one tile to another tile.
`returns`A list of traverse points in pixel positions.
# [getSpatialMap](#LevelComp-getSpatialMap)(): GameObj\[\]\[\]
# [removeFromSpatialMap](#LevelComp-removeFromSpatialMap)(obj: GameObj): void
# [insertIntoSpatialMap](#LevelComp-insertIntoSpatialMap)(obj: GameObj): void
# [onSpatialMapChanged](#LevelComp-onSpatialMapChanged)(cb: ()=\>void): KEventController
# [onNavigationMapInvalid](#LevelComp-onNavigationMapInvalid)(cb: ()=\>void): KEventController
# [invalidateNavigationMap](#LevelComp-invalidateNavigationMap)(): void
# [onNavigationMapChanged](#LevelComp-onNavigationMapChanged)(cb: ()=\>void): KEventController
# [LevelOpt](#LevelOpt):
Options for the level`level()` component.
# [tileWidth](#LevelOpt-tileWidth): number
Width of each block.
# [tileHeight](#LevelOpt-tileHeight): number
Height of each block.
# [tiles](#LevelOpt-tiles):
Definition of each tile.
# [wildcardTile](#LevelOpt-wildcardTile)?(sym: string, pos: Vec2): CompList \| null \| undefined
Called when encountered a symbol not defined in \"tiles\".
# [LifespanCompOpt](#LifespanCompOpt):
The lifespan`lifespan()` component.
# [fade](#LifespanCompOpt-fade)?: number
Fade out duration (default 0 which is no fade out).
# [Line](#Line):
# [p1](#Line-p1): Vec2
# [p2](#Line-p2): Vec2
# [transform](#Line-transform)(m: Mat23, s?: Shape): Line
# [bbox](#Line-bbox)(): Rect
# [area](#Line-area)(): number
# [clone](#Line-clone)(): Line
# [collides](#Line-collides)(shape: ShapeType \| Vec2): boolean
# [contains](#Line-contains)(point: Vec2): boolean
# [raycast](#Line-raycast)(origin: Vec2, direction: Vec2): RaycastResult
# [random](#Line-random)(): Vec2
# [LineCap](#LineCap): butt \| round \| square
# [LineJoin](#LineJoin): none \| round \| bevel \| miter
# [LoadBitmapFontOpt](#LoadBitmapFontOpt):
# [chars](#LoadBitmapFontOpt-chars)?: string
# [filter](#LoadBitmapFontOpt-filter)?: TexFilter
# [outline](#LoadBitmapFontOpt-outline)?: number
# [LoadFontOpt](#LoadFontOpt):
# [filter](#LoadFontOpt-filter)?: TexFilter
# [outline](#LoadFontOpt-outline)?: number \| Outline
# [size](#LoadFontOpt-size)?: number
The size to load the font in (default 64).
`since`v3001.0
# [LoadSpriteOpt](#LoadSpriteOpt):
Sprite loading configuration.
# [sliceX](#LoadSpriteOpt-sliceX)?: number
If the defined area contains multiple sprites, how many frames are in the area horizontally.
# [sliceY](#LoadSpriteOpt-sliceY)?: number
If the defined area contains multiple sprites, how many frames are in the area vertically.
# [slice9](#LoadSpriteOpt-slice9)?: NineSlice
9 slice sprite for proportional scaling.
`since`v3000.0
# [frames](#LoadSpriteOpt-frames)?: Quad\[\]
Individual frames.
`since`v3000.0
# [anims](#LoadSpriteOpt-anims)?: SpriteAnims
Animation configuration.
# [singular](#LoadSpriteOpt-singular)?: boolean
If the sprite is a single image.
# [LoadSpriteSrc](#LoadSpriteSrc): string \| ImageSource
[Log](#Log):
# [msg](#undefined-msg): string \|
# [time](#undefined-time): number
# [Mask](#Mask): intersect \| subtract
# [MaskComp](#MaskComp):
The mask`mask()` component.
# [mask](#MaskComp-mask): Mask
# [Mat2](#Mat2):
# [a](#Mat2-a): number
# [b](#Mat2-b): number
# [c](#Mat2-c): number
# [d](#Mat2-d): number
# [mul](#Mat2-mul)(other: Mat2): Mat2
# [transform](#Mat2-transform)(point: Vec2): Vec2
# [inverse](#Mat2-inverse)(): Mat2
# [transpose](#Mat2-transpose)(): Mat2
# [eigenvalues](#Mat2-eigenvalues)(): number\[\]
# [eigenvectors](#Mat2-eigenvectors)(e1: number, e2: number): number\[\]\[\]
# [det](#Mat2-det)(): number
# [trace](#Mat2-trace)(): number
# [rotation](#Mat2-rotation)(radians: number): Mat2
# [scale](#Mat2-scale)(x: number, y: number): Mat2
# [Mat23](#Mat23):
# [a](#Mat23-a): number
# [b](#Mat23-b): number
# [c](#Mat23-c): number
# [d](#Mat23-d): number
# [e](#Mat23-e): number
# [f](#Mat23-f): number
# [fromMat2](#Mat23-fromMat2)(m: Mat2): Mat23
# [toMat2](#Mat23-toMat2)(): Mat2
# [fromTranslation](#Mat23-fromTranslation)(t: Vec2): Mat23
# [fromRotation](#Mat23-fromRotation)(radians: number): Mat23
# [fromScale](#Mat23-fromScale)(s: Vec2): Mat23
# [clone](#Mat23-clone)(): Mat23
# [setMat23](#Mat23-setMat23)(m: Mat23): this
# [setIdentity](#Mat23-setIdentity)(): this
# [mul](#Mat23-mul)(other: Mat23): Mat23
# [translateSelfV](#Mat23-translateSelfV)(t: Vec2): Mat23
# [translateSelf](#Mat23-translateSelf)(x: number, y: number): Mat23
# [rotateSelf](#Mat23-rotateSelf)(degrees: number): Mat23
# [scaleSelfV](#Mat23-scaleSelfV)(s: Vec2): Mat23
# [scaleSelf](#Mat23-scaleSelf)(x: number, y: number): Mat23
# [mulSelf](#Mat23-mulSelf)(other: Mat23): void
# [transform](#Mat23-transform)(p: Vec2): Vec2
# [transformPointV](#Mat23-transformPointV)(p: Vec2, o: Vec2): Vec2
# [transformVectorV](#Mat23-transformVectorV)(v: Vec2, o: Vec2): Vec2
# [transformPoint](#Mat23-transformPoint)(x: number, y: number, o: Vec2): Vec2
# [transformVector](#Mat23-transformVector)(x: number, y: number, o: Vec2): Vec2
# [det](#Mat23-det)(): number
# [inverse](#Mat23-inverse)(): Mat23
# [getTranslation](#Mat23-getTranslation)(): Vec2
# [getRotation](#Mat23-getRotation)(): number
# [getScale](#Mat23-getScale)(): Vec2
# [Mat4](#Mat4):
# [m](#Mat4-m): number\[\]
# [translate](#Mat4-translate)(p: Vec2): Mat4
# [translate](#Mat4-translate)(p: Vec2): this
# [scale](#Mat4-scale)(s: Vec2): Mat4
# [scale](#Mat4-scale)(p: Vec2): this
# [rotateX](#Mat4-rotateX)(a: number): Mat4
# [rotateY](#Mat4-rotateY)(a: number): Mat4
# [rotateZ](#Mat4-rotateZ)(a: number): Mat4
# [rotate](#Mat4-rotate)(a: number): Mat4
# [mult](#Mat4-mult)(other: Mat4): Mat4
# [multVec2](#Mat4-multVec2)(p: Vec2): Vec2
# [getTranslation](#Mat4-getTranslation)(): Vec2
# [getScale](#Mat4-getScale)(): Vec2
# [getRotation](#Mat4-getRotation)(): number
# [getSkew](#Mat4-getSkew)(): Vec2
# [invert](#Mat4-invert)(): Mat4
# [clone](#Mat4-clone)(): Mat4
[Material](#Material):
# [tex](#undefined-tex)?: Texture
# [shader](#undefined-shader)?: Shader
# [uniform](#undefined-uniform)?: Uniform
# [blend](#undefined-blend)?: BlendMode
# [MergeComps](#MergeComps)\<T\>: MergeObj\<RemoveCompProps\>
A type to merge the components of a game object, omitting the default component properties.
# [MergeObj](#MergeObj)\<T\>: Prettify\<UnionToIntersection\>
# [MergePlugins](#MergePlugins)\<T\>: MergeObj\<ReturnType\>
# [Mesh](#Mesh):
# [ctx](#Mesh-ctx): GfxCtx
# [glVBuf](#Mesh-glVBuf): WebGLBuffer
# [glIBuf](#Mesh-glIBuf): WebGLBuffer
# [vertexFormat](#Mesh-vertexFormat): VertexFormat
# [count](#Mesh-count): number
# [draw](#Mesh-draw)(primitive?: GLenum, index?: GLuint, count?: GLuint): void
# [free](#Mesh-free)(): void
# [MouseButton](#MouseButton): left \| right \| middle \| back \| forward
A mouse button.
# [MusicData](#MusicData): string
# [NamedComp](#NamedComp):
The named`named()` component.
# [NavEdge](#NavEdge):
# [a](#NavEdge-a): Vec2
# [b](#NavEdge-b): Vec2
# [polygon](#NavEdge-polygon): WeakRef\<NavPolygon\>
# [isLeft](#NavEdge-isLeft)(x: number, y: number): number
# [middle](#NavEdge-middle)(): Vec2
# [NavMesh](#NavMesh):
# [\_polygons](#NavMesh-_polygons):
# [\_pointCache](#NavMesh-_pointCache):
# [\_edgeCache](#NavMesh-_edgeCache):
# [\_addPoint](#NavMesh-_addPoint):
# [\_addEdge](#NavMesh-_addEdge):
# [\_findEdge](#NavMesh-_findEdge):
# [\_findCommonEdge](#NavMesh-_findCommonEdge):
# [addPolygon](#NavMesh-addPolygon)(vertices: Vec2\[\]): NavPolygon
# [addRect](#NavMesh-addRect)(pos: Vec2, size: Vec2): NavPolygon
# [\_getLocation](#NavMesh-_getLocation):
# [getNeighbours](#NavMesh-getNeighbours)(index: number): number\[\]
# [getCost](#NavMesh-getCost)(a: number, b: number): number
# [getHeuristic](#NavMesh-getHeuristic)(indexA: number, indexB: number): number
# [getPath](#NavMesh-getPath)(start: number, goal: number): number\[\]
# [getWaypointPath](#NavMesh-getWaypointPath)(start: Vec2, goal: Vec2, opt: any): Vec2\[\]
# [NavPolygon](#NavPolygon):
# [\_edges](#NavPolygon-_edges):
# [\_centroid](#NavPolygon-_centroid):
# [\_id](#NavPolygon-_id):
# [id](#NavPolygon-id)(): number
# [edges](#NavPolygon-edges)(edges: NavEdge\[\]):
# [edges](#NavPolygon-edges)(): NavEdge\[\]
# [centroid](#NavPolygon-centroid)(): Vec2
# [contains](#NavPolygon-contains)(p: Vec2): boolean
[NineSlice](#NineSlice):
# [left](#undefined-left): number
The width of the 9-slice's left column.
# [right](#undefined-right): number
The width of the 9-slice's right column.
# [top](#undefined-top): number
The height of the 9-slice's top row.
# [bottom](#undefined-bottom): number
The height of the 9-slice's bottom row.
# [OffScreenComp](#OffScreenComp):
The offscreen`offscreen()` component.
# [offscreenDistance](#OffScreenComp-offscreenDistance): number \| undefined
The minimum distance that the object must be off the screen by to be considered \"offscreen\". If it is undefined, it means that the object will be considered to be offscreen when its bounding rectangle (defined by width and height) is not intersecting with the screen rectangle.
# [isOffScreen](#OffScreenComp-isOffScreen)(): boolean
If object is currently out of view.
# [onExitScreen](#OffScreenComp-onExitScreen)(action: ()=\>void): KEventController
Register an event that runs when object goes out of view.
# [onEnterScreen](#OffScreenComp-onEnterScreen)(action: ()=\>void): KEventController
Register an event that runs when object enters view.
# [OffScreenCompOpt](#OffScreenCompOpt):
Options for offscreen`offscreen()` component.
# [hide](#OffScreenCompOpt-hide)?: boolean
If hide object when out of view.
# [pause](#OffScreenCompOpt-pause)?: boolean
If pause object when out of view.
# [unpause](#OffScreenCompOpt-unpause)?: boolean
If unpause object when back in view.
# [destroy](#OffScreenCompOpt-destroy)?: boolean
If destroy object when out of view.
# [distance](#OffScreenCompOpt-distance)?: number
The distance when out of view is triggered (default 200).
`since`v3000.0
# [OpacityComp](#OpacityComp):
The opacity`opacity()` component.
# [opacity](#OpacityComp-opacity): number
Opacity of the current object.
# [fadeIn](#OpacityComp-fadeIn)(time?: number, easeFunc?: EaseFunc): TweenController
Fade in at the start.
# [fadeOut](#OpacityComp-fadeOut)(time?: number, easeFunc?: EaseFunc): TweenController
Fade out at the start.
# [Outline](#Outline):
# [width](#Outline-width)?: number
The width, or thickness of the line.
# [color](#Outline-color)?: Color
The color of the line.
# [opacity](#Outline-opacity)?: number
Opacity (overrides fill opacity).
`since`v3001.0
# [join](#Outline-join)?: LineJoin
Line join.
`since`v3000.0
# [miterLimit](#Outline-miterLimit)?: number
Miter limit. If the length of the miter divided by the line width exceeds this limit, the style is converted to a bevel.
`since`v3001.0
# [cap](#Outline-cap)?: LineCap
Line cap.
`since`v3001.0
# [OutlineComp](#OutlineComp):
The outline`outline()` component.
# [outline](#OutlineComp-outline): Outline
# [ParticlesComp](#ParticlesComp):
The particles`particles()` component.
[emitter](#ParticlesComp-emitter):
# [position](#undefined-position): Vec2
Relative position of the emitter
# [direction](#undefined-direction): number
Relative direction of the emitter
# [emit](#ParticlesComp-emit)(n: number): void
Emit a number of particles
# [onEnd](#ParticlesComp-onEnd)(cb: ()=\>void): void
Called when the emitter expires
[ParticlesOpt](#ParticlesOpt):
# [max](#undefined-max): number
Maximum number of simultaneously rendered particles.
# [lifeTime](#undefined-lifeTime)?: \[number, number\]
Minimum and maximum lifetime of a particle in seconds.
# [speed](#undefined-speed)?: \[number, number\]
Minimum and maximum speed of a particle in pixels per second.
# [acceleration](#undefined-acceleration)?: \[Vec2, Vec2\]
Minimum and maximum acceleration of a particle in pixels per second\^2.
# [damping](#undefined-damping)?: \[number, number\]
Minimum and maximum damping of a particle.
# [angle](#undefined-angle)?: \[number, number\]
Minimum and maximum start angle of a particle.
# [angularVelocity](#undefined-angularVelocity)?: \[number, number\]
Minimum and maximum angular velocity of a particle.
# [scales](#undefined-scales)?: number\[\]
Scale from start to end for a particle.
# [colors](#undefined-colors)?: Color\[\]
Colors from start to end for a particle.
# [opacities](#undefined-opacities)?: number\[\]
Opacity from start to end for a particle.
# [quads](#undefined-quads)?: Quad\[\]
Quads from start to end for a particle.
# [texture](#undefined-texture): Texture
Texture used for the particle.
Options for the particles`particles()`'s component
[PathFindOpt](#PathFindOpt):
# [allowDiagonals](#undefined-allowDiagonals)?: boolean
# [PathfinderComp](#PathfinderComp):
# [navigateTo](#PathfinderComp-navigateTo)(target: Vec2): Vec2\[\] \| undefined
Get navigation waypoints to reach the given target from the current position.
# [graph](#PathfinderComp-graph): Graph \| undefined
Get the graph used for navigastion if any.
# [PathfinderCompOpt](#PathfinderCompOpt):
# [graph](#PathfinderCompOpt-graph)?: Graph
The graph to use for navigation. If null, the ancestors are queried for a pathfinderMap component.
# [navigationOpt](#PathfinderCompOpt-navigationOpt)?: any
The navigation options depending on the kind of graph used.
# [PathfinderMapComp](#PathfinderMapComp):
# [navigate](#PathfinderMapComp-navigate)(origin: Vec2, target: Vec2, navigationOpt: any): Vec2\[\] \| undefined
Get navigation waypoints to reach the given target from the given origin.
# [graph](#PathfinderMapComp-graph): Graph \| undefined
The graph to use for navigation.
# [PathfinderMapCompOpt](#PathfinderMapCompOpt):
# [graph](#PathfinderMapCompOpt-graph)?: Graph
The graph to use for navigation. If null, the ancestors are queried for a pathfinderMap component.
# [PatrolComp](#PatrolComp):
# [waypoints](#PatrolComp-waypoints): Vec2\[\] \| undefined
Path to follow. If null, doesn't move.
# [patrolSpeed](#PatrolComp-patrolSpeed): number
Speed of the movement during patrol.
# [nextLocation](#PatrolComp-nextLocation): Vec2 \| undefined
Current subgoal, if any.
# [onPatrolFinished](#PatrolComp-onPatrolFinished)(cb: (objects: GameObj\[\])=\>void): KEventController
Attaches an event handler which is called when using \"stop\" and the end of the path is reached.
`param`cbThe event handler called when the patrol finishes.
# [PatrolCompOpt](#PatrolCompOpt):
# [waypoints](#PatrolCompOpt-waypoints)?: Vec2\[\]
Path to follow. If null, starts suspended.
# [speed](#PatrolCompOpt-speed)?: number
Speed of the movement during patrol.
# [endBehavior](#PatrolCompOpt-endBehavior)?: PatrolEndBehavior
What to do after the last waypoint has been reached.
# [PatrolEndBehavior](#PatrolEndBehavior): loop \| ping-pong \| stop
# [PeditFile](#PeditFile):
# [width](#PeditFile-width): number
# [height](#PeditFile-height): number
# [frames](#PeditFile-frames): string\[\]
# [anims](#PeditFile-anims): SpriteAnims
# [Picture](#Picture):
A picture holding drawing data
# [vertices](#Picture-vertices): number\[\]
# [indices](#Picture-indices): number\[\]
# [commands](#Picture-commands): PictureCommand\[\]
# [mesh](#Picture-mesh)?: Mesh
# [archive](#Picture-archive)(): string
Serializes this picture to a JSON string
`returns`a string containing JSON picture data
# [free](#Picture-free)(): void
[PictureCommand](#PictureCommand):
# [material](#undefined-material): Material
# [index](#undefined-index): number
# [count](#undefined-count): number
# [PictureComp](#PictureComp):
# [picture](#PictureComp-picture): Picture
[PictureCompOpt](#PictureCompOpt):
# [picture](#undefined-picture): Picture
# [PlatformEffectorComp](#PlatformEffectorComp):
# [platformIgnore](#PlatformEffectorComp-platformIgnore): Set\<GameObj\>
A set of the objects that should not collide with this, because \`shouldCollide\` returned true. Objects in here are automatically removed when they stop colliding, so the casual user shouldn't need to touch this much. However, if an object is added to this set before the object collides with the platform effector, it won't collide even if \`shouldCollide\` returns true.
[PlatformEffectorCompOpt](#PlatformEffectorCompOpt):
# [ignoreSides](#undefined-ignoreSides)?: Vec2\[\]
If the object is about to collide and the collision normal direction is in here (i.e. the object is moving roughly in this direction), the object won't collide. Should be a list of unit vectors \`LEFT\`, \`RIGHT\`, \`UP\`, or \`DOWN\`. Defaults to \`\[UP\]\`, i.e. the object will only be able to pass through when it is jumping upwards, but will collide when it is moving downwards or sideways.
# [shouldCollide](#undefined-shouldCollide)?(this: GameObj, obj: GameObj, normal: Vec2): boolean
A function that determines whether the object should collide. If present, it overrides the \`ignoreSides\`; if absent, it is automatically created from \`ignoreSides\`.
# [PluginList](#PluginList)\<T\>: Array\<T \| KAPLAYPlugin\>
# [Point](#Point):
# [pt](#Point-pt): Vec2
# [transform](#Point-transform)(m: Mat23, s?: Shape): Point
# [bbox](#Point-bbox)(): Rect
# [area](#Point-area)(): number
# [clone](#Point-clone)(): Point
# [collides](#Point-collides)(shape: ShapeType): boolean
# [contains](#Point-contains)(point: Vec2): boolean
# [raycast](#Point-raycast)(origin: Vec2, direction: Vec2): RaycastResult
# [random](#Point-random)(): Vec2
# [PointEffectorComp](#PointEffectorComp):
# [forceMagnitude](#PointEffectorComp-forceMagnitude): number
# [distanceScale](#PointEffectorComp-distanceScale): number
# [forceMode](#PointEffectorComp-forceMode): ForceMode
# [linearDrag](#PointEffectorComp-linearDrag): number
[PointEffectorCompOpt](#PointEffectorCompOpt):
# [forceMagnitude](#undefined-forceMagnitude): number
# [distanceScale](#undefined-distanceScale)?: number
# [forceMode](#undefined-forceMode)?: ForceMode
# [linearDrag](#undefined-linearDrag)?: number
# [Polygon](#Polygon):
# [pts](#Polygon-pts): Vec2\[\]
# [transform](#Polygon-transform)(m: Mat23, s?: Shape): Polygon
# [bbox](#Polygon-bbox)(): Rect
# [area](#Polygon-area)(): number
# [clone](#Polygon-clone)(): Polygon
# [collides](#Polygon-collides)(shape: ShapeType \| Vec2): boolean
# [contains](#Polygon-contains)(point: Vec2): boolean
# [raycast](#Polygon-raycast)(origin: Vec2, direction: Vec2): RaycastResult
# [random](#Polygon-random)(): Vec2
# [cut](#Polygon-cut)(a: Vec2, b: Vec2, srcUv?: Vec2\[\], dstUv?: \[Vec2\[\], Vec2\[\]\]): \[Polygon \| null, Polygon \| null\]
# [PolygonComp](#PolygonComp):
The polygon`polygon()` component.
`since`v3001.0
# [draw](#PolygonComp-draw): Comp\[draw\]
# [pts](#PolygonComp-pts): Vec2\[\]
Points in the polygon.
# [radius](#PolygonComp-radius)?: number \| number\[\]
The radius of each corner.
# [colors](#PolygonComp-colors)?: Color\[\]
The color of each vertex.
# [uv](#PolygonComp-uv)?: Vec2\[\]
The uv of each vertex.
`since`v3001.0
# [tex](#PolygonComp-tex)?: Texture
The texture used when uv coordinates are present.
`since`v3001.0
# [renderArea](#PolygonComp-renderArea)(): Polygon
# [PolygonCompOpt](#PolygonCompOpt): Omit\<DrawPolygonOpt, pts\>
Options for the polygon`polygon()` component.
# [PosComp](#PosComp):
The pos`pos()` component.
# [pos](#PosComp-pos): Vec2
Object's current world position.
# [move](#PosComp-move)(xVel: number, yVel: number): void
Move how many pixels per second. If object is 'solid', it won't move into other 'solid' objects.
# [move](#PosComp-move)(vel: Vec2): void
# [moveBy](#PosComp-moveBy)(dx: number, dy: number): void
Move how many pixels, without multiplying dt, but still checking for 'solid'.
# [moveBy](#PosComp-moveBy)(d: Vec2): void
# [moveTo](#PosComp-moveTo)(dest: Vec2, speed?: number): void
Move to a spot with a speed (pixels per second), teleports if speed is not given.
# [moveTo](#PosComp-moveTo)(x: number, y: number, speed?: number): void
# [screenPos](#PosComp-screenPos)(newPos?: Vec2): Vec2 \| null
Get / Set the position of the object on the screen.
`since`v2000.0
# [worldPos](#PosComp-worldPos)(newPos?: Vec2): Vec2 \| null
Get / Set the position of the object relative to the root.
`since`v2000.0
# [toScreen](#PosComp-toScreen)(this: GameObj, p: Vec2): Vec2
Transform a local point (relative to this) to a screen point (relative to the camera)
# [toWorld](#PosComp-toWorld)(this: GameObj, p: Vec2): Vec2
Transform a local point (relative to this) to a world point (relative to the root)
`since`v3001.0
# [fromScreen](#PosComp-fromScreen)(this: GameObj, p: Vec2): Vec2
Transform a screen point (relative to the camera) to a local point (relative to this)
`since`v3001.0
# [fromWorld](#PosComp-fromWorld)(this: GameObj, p: Vec2): Vec2
Transform a world point (relative to the root) to a local point (relative to this)
`since`v3001.0
# [toOther](#PosComp-toOther)(this: GameObj, other: GameObj, p: Vec2): Vec2
Transform a point relative to this to a point relative to other
`since`v3001.0
# [fromOther](#PosComp-fromOther)(this: GameObj, other: GameObj, p: Vec2): Vec2
Transform a point relative to other to a point relative to this
`since`v3001.0
# [Prettify](#Prettify)\<T\>: ConditionalType
It obligates to TypeScript to Expand the type. Instead of being \`{ id: 1 } \| { name: \"hi\" }\` makes It's \`{ id: 1, name: \"hi\" }\` https://www.totaltypescript.com/concepts/the-prettify-helper Previously Expand\<T\>
# [Quad](#Quad):
# [x](#Quad-x): number
# [y](#Quad-y): number
# [w](#Quad-w): number
# [h](#Quad-h): number
# [scale](#Quad-scale)(other: Quad): Quad
# [pos](#Quad-pos)(): Vec2
# [clone](#Quad-clone)(): Quad
# [eq](#Quad-eq)(other: Quad): boolean
[QueryOpt](#QueryOpt):
# [include](#undefined-include)?: string \| string\[\]
All objects which include all or any of these tags, depending on includeOp.
# [includeOp](#undefined-includeOp)?: and \| or
Selects the operator to use. Defaults to and.
# [exclude](#undefined-exclude)?: string \| string\[\]
All objects which do not have all or any of these tags, depending on excludeOp.
# [excludeOp](#undefined-excludeOp)?: and \| or
Selects the operator to use. Defaults to and.
# [distance](#undefined-distance)?: number
All objects which are near or far to the position of this, depending on distanceOp.
# [distanceOp](#undefined-distanceOp)?: near \| far
Selects the operator to use. Defaults to near.
# [visible](#undefined-visible)?: boolean
All objects visible from this standpoint.
# [hierarchy](#undefined-hierarchy)?: children \| siblings \| ancestors \| descendants
All objects in the given group. Defaults to children.
# [RGBAValue](#RGBAValue): \[number, number, number, number\]
# [RGBValue](#RGBValue): \[number, number, number\]
# [RNG](#RNG):
A random number generator using the linear congruential generator algorithm.
# [seed](#RNG-seed): number
The current seed value used by the random number generator.
# [gen](#RNG-gen)(): number
Generate a random number between 0 and 1.
``` js
const rng = new RNG(Date.now())
const value = rng.gen() // Returns number between 0-1
```
`returns`A number between 0 and 1.
# [genNumber](#RNG-genNumber)(a: number, b: number): number
Generate a random number between two values.
`param`a- The minimum value.
`param`b- The maximum value.
``` js
const rng = new RNG(Date.now())
const value = rng.genNumber(10, 20) // Returns number between 10-20
```
`returns`A number between a and b.
# [genVec2](#RNG-genVec2)(a: Vec2, b: Vec2): Vec2
Generate a random 2D vector between two vectors.
`param`a- The minimum vector.
`param`b- The maximum vector.
``` js
const rng = new RNG(Date.now())
const vec = rng.genVec2(vec2(0,0), vec2(100,100))
```
`returns`A vector between vectors a and b.
# [genColor](#RNG-genColor)(a: Color, b: Color): Color
Generate a random color between two colors.
`param`a- The first color.
`param`b- The second color.
``` js
const rng = new RNG(Date.now())
const color = rng.genColor(rgb(0,0,0), rgb(255,255,255))
```
`returns`A color between colors a and b.
# [genAny](#RNG-genAny)\<T\>(args: \[\] \| \[T\] \| \[T, T\]): T
Generate a random value of a specific type.
`param`args- No args for \[0-1\], one arg for \[0-arg\], or two args for \[arg1-arg2\].
``` js
const rng = new RNG(Date.now())
const val = rng.genAny(0, 100) // Number between 0-100
const vec = rng.genAny(vec2(0,0), vec2(100,100)) // Vec2
const col = rng.genAny(rgb(0,0,0), rgb(255,255,255)) // Color
```
`returns`A random value.
# [RNGValue](#RNGValue): number \| Vec2 \| Color
[RaycastHit](#RaycastHit):
# [fraction](#undefined-fraction): number
# [normal](#undefined-normal): Vec2
# [point](#undefined-point): Vec2
# [gridPos](#undefined-gridPos)?: Vec2
# [object](#undefined-object)?: GameObj
# [RaycastResult](#RaycastResult): RaycastHit \| null
# [Recording](#Recording):
Screen recording control handle.
# [pause](#Recording-pause)(): void
Pause the recording.
# [resume](#Recording-resume)(): void
Resume the recording.
# [stop](#Recording-stop)(): Promise\<Blob\>
Stop the recording and get the video data as mp4 Blob.
`since`v3000.0
# [download](#Recording-download)(filename?: string): void
Stop the recording and downloads the file as mp4. Trying to resume later will lead to error.
# [Rect](#Rect):
# [pos](#Rect-pos): Vec2
# [width](#Rect-width): number
# [height](#Rect-height): number
# [fromPoints](#Rect-fromPoints)(p1: Vec2, p2: Vec2): Rect
# [center](#Rect-center)(): Vec2
# [points](#Rect-points)(): \[Vec2, Vec2, Vec2, Vec2\]
# [transform](#Rect-transform)(m: Mat23, s?: Shape): Polygon
# [bbox](#Rect-bbox)(): Rect
# [area](#Rect-area)(): number
# [clone](#Rect-clone)(): Rect
# [distToPoint](#Rect-distToPoint)(p: Vec2): number
# [sdistToPoint](#Rect-sdistToPoint)(p: Vec2): number
# [collides](#Rect-collides)(shape: ShapeType \| Vec2): boolean
# [contains](#Rect-contains)(point: Vec2): boolean
# [raycast](#Rect-raycast)(origin: Vec2, direction: Vec2): RaycastResult
# [random](#Rect-random)(): Vec2
# [RectComp](#RectComp):
The rect`rect()` component.
# [draw](#RectComp-draw): Comp\[draw\]
# [width](#RectComp-width): number
Width of rectangle.
# [height](#RectComp-height): number
Height of rectangle.
# [radius](#RectComp-radius)?: number \| \[number, number, number, number\]
The radius of each corner.
# [renderArea](#RectComp-renderArea)(): Rect
`since`v3000.0
# [RectCompOpt](#RectCompOpt):
Options for the rect`rect()` component.
# [radius](#RectCompOpt-radius)?: number \| \[number, number, number, number\]
Radius of the rectangle corners.
# [fill](#RectCompOpt-fill)?: boolean
If fill the rectangle (useful if you only want to render outline with outline() component).
# [Registry](#Registry)\<T\>:
# [lastID](#Registry-lastID):
# [push](#Registry-push)(v: T): number
# [pushd](#Registry-pushd)(v: T): void
# [RemoveCompProps](#RemoveCompProps)\<T\>: Defined\<MappedType\>
# [RenderProps](#RenderProps):
Common render properties.
# [pos](#RenderProps-pos)?: Vec2
# [scale](#RenderProps-scale)?: Vec2
# [angle](#RenderProps-angle)?: number
# [color](#RenderProps-color)?: Color
# [opacity](#RenderProps-opacity)?: number
# [fixed](#RenderProps-fixed)?: boolean
# [shader](#RenderProps-shader)?: string \| ShaderData \| Asset \| null
# [uniform](#RenderProps-uniform)?: Uniform \| null
# [blend](#RenderProps-blend)?: BlendMode
# [outline](#RenderProps-outline)?: Outline
[RenderTarget](#RenderTarget):
# [destination](#undefined-destination): FrameBuffer \| Picture \| null
# [childrenOnly](#undefined-childrenOnly)?: boolean
# [refreshOnly](#undefined-refreshOnly)?: boolean
# [isFresh](#undefined-isFresh)?: boolean
# [RotateComp](#RotateComp):
The rotate`rotate()` component.
# [angle](#RotateComp-angle): number
Angle in degrees.
# [rotateBy](#RotateComp-rotateBy)(angle: number): void
Rotate in degrees.
# [rotateTo](#RotateComp-rotateTo)(s: number): void
Rotate to a degree (like directly assign to .angle)
`since`v3000.0
[SatResult](#SatResult):
# [normal](#undefined-normal): Vec2
# [distance](#undefined-distance): number
# [ScaleComp](#ScaleComp):
The scale`scale()` component.
# [scale](#ScaleComp-scale): Vec2
The current scale of the object
`returns`The current scale of the object as a
# [scaleTo](#ScaleComp-scaleTo)(s: number): void
Set the scale of the object to a number
# [scaleTo](#ScaleComp-scaleTo)(s: Vec2): void
Set the scale of the object to a Vec2
# [scaleTo](#ScaleComp-scaleTo)(sx: number, sy: number): void
Set the scale of the object to a number for x and y
# [scaleBy](#ScaleComp-scaleBy)(s: number): void
Scale the object by a number
# [scaleBy](#ScaleComp-scaleBy)(s: Vec2): void
Scale the object by a Vec2
# [scaleBy](#ScaleComp-scaleBy)(sx: number, sy: number): void
Scale the object by a number for x and y
# [SceneDef](#SceneDef)(args: any): void
# [SceneName](#SceneName): string
The name of a scene.
# [SentryCandidates](#SentryCandidates): SentryCandidatesCb \| QueryOpt
# [SentryCandidatesCb](#SentryCandidatesCb)(): GameObj\[\]
# [SentryComp](#SentryComp):
The sentry`sentry()` component.
# [direction](#SentryComp-direction)?: Vec2
The direction the sentry is pointing to.
# [directionAngle](#SentryComp-directionAngle)?: number
The direction of the sentry as an angle in degrees.
# [fieldOfView](#SentryComp-fieldOfView)?: number
The field of view of the sentry in degrees.
# [spotted](#SentryComp-spotted): GameObj\[\]
The objects spotted most recently.
# [onObjectsSpotted](#SentryComp-onObjectsSpotted)(cb: (objects: GameObj\[\])=\>void): KEventController
Attaches an event handler which is called when objects of interest are spotted.
`param`cbThe event handler called when objects are spotted.
# [isWithinFieldOfView](#SentryComp-isWithinFieldOfView)(obj: GameObj, direction?: Vec2, fieldOfView?: number): boolean
Returns true if the object is within the field of view.
`param`objThe object to test.
`param`directionThe direction to look at.
`param`fieldOfViewThe field of view in degrees.
# [hasLineOfSight](#SentryComp-hasLineOfSight)(obj: GameObj): boolean
Returns true if there is a line of sight to the object.
`param`objThe object to test.
# [SentryCompOpt](#SentryCompOpt):
Options for the sentry`sentry()` component.
# [direction](#SentryCompOpt-direction)?: Vec2 \| number
The direction the sentry is pointing to. If undefined, direction has no influence.
# [fieldOfView](#SentryCompOpt-fieldOfView)?: number
The field of view of the sentry in degrees. If undefined, defaults to human fov of 200 degrees.
# [lineOfSight](#SentryCompOpt-lineOfSight)?: boolean
If true, line of sight matters. This means that objects which are blocked from view by areas are invisible.
# [raycastExclude](#SentryCompOpt-raycastExclude)?: string\[\]
When using line of sight, the objects which are transparent for the ray. Include at least a tag identifying the sentry.
# [checkFrequency](#SentryCompOpt-checkFrequency)?: number
The frequency of checking, defaults to every second.
[SetParentOpt](#SetParentOpt):
# [keep](#undefined-keep): KeepFlags
# [Shader](#Shader):
# [ctx](#Shader-ctx): GfxCtx
# [glProgram](#Shader-glProgram): WebGLProgram
# [bind](#Shader-bind)(): void
# [unbind](#Shader-unbind)(): void
# [send](#Shader-send)(uniform: Uniform): void
# [free](#Shader-free)(): void
# [ShaderComp](#ShaderComp):
The shader`shader()` component.
# [uniform](#ShaderComp-uniform)?: Uniform
Uniform values to pass to the shader.
# [shader](#ShaderComp-shader): string
The shader ID.
# [ShaderData](#ShaderData): Shader
# [Shape](#Shape): Rect \| Line \| Point \| Circle \| Ellipse \| Polygon
# [ShapeType](#ShapeType): Point \| Circle \| Line \| Rect \| Polygon \| Ellipse
# [SoundData](#SoundData):
# [buf](#SoundData-buf): AudioBuffer
# [fromAudioBuffer](#SoundData-fromAudioBuffer)(buf: AudioBuffer): SoundData
# [fromArrayBuffer](#SoundData-fromArrayBuffer)(buf: ArrayBuffer): Promise\<SoundData\>
# [fromURL](#SoundData-fromURL)(url: string): Promise\<SoundData\>
[SpriteAnim](#SpriteAnim): number \|
# [from](#undefined-from)?: number
The starting frame.
# [to](#undefined-to)?: number
The end frame.
# [loop](#undefined-loop)?: boolean
If this anim should be played in loop.
# [pingpong](#undefined-pingpong)?: boolean
When looping should it move back instead of go to start frame again.
# [speed](#undefined-speed)?: number
This anim's speed in frames per second.
# [frames](#undefined-frames)?: number\[\]
List of frames for the animation. If this property exists, \*\*from, to, and pingpong will be ignored\*\*.
Frame-based animation configuration.
# [SpriteAnimPlayOpt](#SpriteAnimPlayOpt):
Sprite animation configuration when playing.
# [loop](#SpriteAnimPlayOpt-loop)?: boolean
If this anim should be played in loop.
# [pingpong](#SpriteAnimPlayOpt-pingpong)?: boolean
When looping should it move back instead of go to start frame again.
# [speed](#SpriteAnimPlayOpt-speed)?: number
This anim's speed in frames per second.
# [onEnd](#SpriteAnimPlayOpt-onEnd)?(): void
Runs when this animation ends.
# [SpriteAnims](#SpriteAnims): Record\<string, SpriteAnim\>
A dict of name \<-\> animation.
# [SpriteAtlasData](#SpriteAtlasData): Record\<string, SpriteAtlasEntry\>
[SpriteAtlasEntry](#SpriteAtlasEntry): LoadSpriteOpt &
# [x](#undefined-x): number
X position of the top left corner.
# [y](#undefined-y): number
Y position of the top left corner.
# [width](#undefined-width): number
Sprite area width.
# [height](#undefined-height): number
Sprite area height.
A sprite in a sprite atlas.
# [SpriteComp](#SpriteComp):
The sprite`sprite()` component.
# [draw](#SpriteComp-draw): Comp\[draw\]
# [sprite](#SpriteComp-sprite): string
Name of the sprite.
# [width](#SpriteComp-width): number
Width for sprite.
# [height](#SpriteComp-height): number
Height for sprite.
# [frame](#SpriteComp-frame): number
Current frame in the entire spritesheet.
# [animFrame](#SpriteComp-animFrame): number
Current frame in relative to the animation that is currently playing.
# [quad](#SpriteComp-quad): Quad
The rectangular area of the texture to render.
# [play](#SpriteComp-play)(anim: string, options?: SpriteAnimPlayOpt): void
Play a piece of anim.
# [stop](#SpriteComp-stop)(): void
Stop current anim.
# [numFrames](#SpriteComp-numFrames)(): number
Get total number of frames.
# [getCurAnim](#SpriteComp-getCurAnim)(): SpriteCurAnim \| null
Get the current animation data.
`since`v3001.0
# [curAnim](#SpriteComp-curAnim)(): string \| undefined
Get current anim name.
`deprecated`Use \`getCurAnim().name\` instead.
# [hasAnim](#SpriteComp-hasAnim)(name: string): boolean
Check if object's sprite has an animation.
# [getAnim](#SpriteComp-getAnim)(name: string): SpriteAnim \| null
Get an animation.
# [animSpeed](#SpriteComp-animSpeed): number
Speed multiplier for all animations (for the actual fps for an anim use .play(\"anim\", { speed: 10 })).
# [flipX](#SpriteComp-flipX): boolean
Flip texture horizontally.
# [flipY](#SpriteComp-flipY): boolean
Flip texture vertically.
# [onAnimStart](#SpriteComp-onAnimStart)(action: (anim: string)=\>void): KEventController
Register an event that runs when an animation is played.
# [onAnimEnd](#SpriteComp-onAnimEnd)(action: (anim: string)=\>void): KEventController
Register an event that runs when an animation is ended.
# [renderArea](#SpriteComp-renderArea)(): Rect
`since`v3000.0
# [SpriteCompOpt](#SpriteCompOpt):
Options for the sprite`sprite()` component.
# [frame](#SpriteCompOpt-frame)?: number
If the sprite is loaded with multiple frames, or sliced, use the frame option to specify which frame to draw.
# [tiled](#SpriteCompOpt-tiled)?: boolean
If provided width and height, don't stretch but instead render tiled.
# [width](#SpriteCompOpt-width)?: number
Stretch sprite to a certain width.
# [height](#SpriteCompOpt-height)?: number
Stretch sprite to a certain height.
# [anim](#SpriteCompOpt-anim)?: string
Play an animation on start.
# [animSpeed](#SpriteCompOpt-animSpeed)?: number
Speed multiplier for all animations (for the actual fps for an anim use .play(\"anim\", { speed: 10 })).
# [flipX](#SpriteCompOpt-flipX)?: boolean
Flip texture horizontally.
# [flipY](#SpriteCompOpt-flipY)?: boolean
Flip texture vertically.
# [quad](#SpriteCompOpt-quad)?: Quad
The rectangular sub-area of the texture to render, default to full texture \`quad(0, 0, 1, 1)\`.
# [fill](#SpriteCompOpt-fill)?: boolean
If fill the sprite (useful if you only want to render outline with outline() component).
# [SpriteCurAnim](#SpriteCurAnim):
# [timer](#SpriteCurAnim-timer): number
# [loop](#SpriteCurAnim-loop): boolean
# [speed](#SpriteCurAnim-speed): number
# [frameIndex](#SpriteCurAnim-frameIndex): number
The current index relative to the start of the associated \`frames\` array for this animation. This may be greater than the number of frames in the sprite.
# [pingpong](#SpriteCurAnim-pingpong): boolean
# [onEnd](#SpriteCurAnim-onEnd)(): void
# [SpriteData](#SpriteData):
# [tex](#SpriteData-tex): Texture
# [frames](#SpriteData-frames): Quad\[\]
# [anims](#SpriteData-anims): SpriteAnims
# [slice9](#SpriteData-slice9): NineSlice \| null
# [packerId](#SpriteData-packerId): number \| null
# [width](#SpriteData-width)(): number
`since`v3001.0
# [height](#SpriteData-height)(): number
# [from](#SpriteData-from)(src: LoadSpriteSrc, opt?: LoadSpriteOpt): Promise\<SpriteData\>
# [fromImage](#SpriteData-fromImage)(data: ImageSource, opt?: LoadSpriteOpt): SpriteData
# [fromURL](#SpriteData-fromURL)(url: string, opt?: LoadSpriteOpt): Promise\<SpriteData\>
# [StateComp](#StateComp):
The state`state()` component.
# [state](#StateComp-state): string
Current state.
# [enterState](#StateComp-enterState)(state: string, args: any): void
Enter a state, trigger onStateEnd for previous state and onStateEnter for the new State state.
# [onStateTransition](#StateComp-onStateTransition)(from: string, to: string, action: ()=\>void): KEventController
Register event that runs once when a specific state transition happens. Accepts arguments passed from \`enterState(name, \...args)\`.
`since`v2000.2
# [onStateEnter](#StateComp-onStateEnter)(state: string, action: (args: any)=\>void): KEventController
Register event that runs once when enters a specific state. Accepts arguments passed from \`enterState(name, \...args)\`.
# [onStateEnd](#StateComp-onStateEnd)(state: string, action: ()=\>void): KEventController
Register an event that runs once when leaves a specific state.
# [onStateUpdate](#StateComp-onStateUpdate)(state: string, action: ()=\>void): KEventController
Register an event that runs every frame when in a specific state.
# [onStateDraw](#StateComp-onStateDraw)(state: string, action: ()=\>void): KEventController
Register an event that runs every frame when in a specific state.
# [StayComp](#StayComp):
The stay`stay()` component.
# [stay](#StayComp-stay): boolean
If the obj should not be destroyed on scene switch.
# [scenesToStay](#StayComp-scenesToStay)?: string\[\]
Array of scenes that the obj will stay on.
# [StepPosition](#StepPosition): jump-start \| jump-end \| jump-none \| jump-both
[StyledTextInfo](#StyledTextInfo):
# [charStyleMap](#undefined-charStyleMap): Record\<number, string\[\]\>
# [text](#undefined-text): string
# [SurfaceEffectorComp](#SurfaceEffectorComp):
# [speed](#SurfaceEffectorComp-speed): number
# [speedVariation](#SurfaceEffectorComp-speedVariation): number
# [forceScale](#SurfaceEffectorComp-forceScale): number
[SurfaceEffectorCompOpt](#SurfaceEffectorCompOpt):
# [speed](#undefined-speed): number
# [speedVariation](#undefined-speedVariation)?: number
# [forceScale](#undefined-forceScale)?: number
# [SweepAndPrune](#SweepAndPrune):
One dimensional sweep and prune
# [edges](#SweepAndPrune-edges): Array\<Edge\$1\>
# [objects](#SweepAndPrune-objects): Map\<GameObj, \[Edge\$1, Edge\$1\]\>
# [add](#SweepAndPrune-add)(obj: GameObj): void
Add the object and its edges to the list
`param`objThe object to add
# [remove](#SweepAndPrune-remove)(obj: GameObj): void
Remove the object and its edges from the list
`param`objThe object to remove
# [clear](#SweepAndPrune-clear)(): void
# [update](#SweepAndPrune-update)(): void
Update edges and sort
[System](#System):
# [run](#undefined-run)(): void
# [when](#undefined-when): LCEvents\[\]
# [Tag](#Tag): string
# [TexFilter](#TexFilter): nearest \| linear
Texture scaling filter. \"nearest\" is mainly for sharp pixelated scaling, \"linear\" means linear interpolation.
# [TexPacker](#TexPacker):
# [lastTextureId](#TexPacker-lastTextureId):
# [textures](#TexPacker-textures):
# [bigTextures](#TexPacker-bigTextures):
# [texturesPosition](#TexPacker-texturesPosition):
# [canvas](#TexPacker-canvas):
# [c2d](#TexPacker-c2d):
# [x](#TexPacker-x):
# [y](#TexPacker-y):
# [curHeight](#TexPacker-curHeight):
# [gfx](#TexPacker-gfx):
# [padding](#TexPacker-padding):
# [add_single](#TexPacker-add_single)(img: ImageSource): \[Texture, Quad, number\]
# [add](#TexPacker-add)(img: ImageSource): \[Texture, Quad, number\]
# [free](#TexPacker-free)(): void
# [remove](#TexPacker-remove)(packerId: number): void
# [TexWrap](#TexWrap): repeat \| clampToEdge
# [TextAlign](#TextAlign): center \| left \| right
How the text should be aligned.
# [TextComp](#TextComp):
The text`text()` component.
# [draw](#TextComp-draw): Comp\[draw\]
# [text](#TextComp-text): string
The text to render.
# [textSize](#TextComp-textSize): number
The text size.
# [font](#TextComp-font): string \| BitmapFontData
The font to use.
# [width](#TextComp-width): number
Width of text.
# [height](#TextComp-height): number
Height of text.
# [align](#TextComp-align): TextAlign
Text alignment (\"left\", \"center\" or \"right\", default \"left\").
`since`v3000.0
# [lineSpacing](#TextComp-lineSpacing): number
The gap between each line.
`since`v2000.2
# [letterSpacing](#TextComp-letterSpacing): number
The gap between each character.
`since`v2000.2
# [textTransform](#TextComp-textTransform): CharTransform \| CharTransformFunc
Transform the pos, scale, rotation or color for each character based on the index or char.
`since`v2000.1
# [textStyles](#TextComp-textStyles): Record\<string, CharTransform \| CharTransformFunc\>
Stylesheet for styled chunks, in the syntax of \"this is a \[style\]text\[/style\] word\".
`since`v2000.2
# [renderArea](#TextComp-renderArea)(): Rect
`since`v3000.0
# [formattedText](#TextComp-formattedText)(): FormattedText
The text data object after formatting, that contains the renering info as well as the parse data of the formatting tags.
# [TextCompOpt](#TextCompOpt):
Options for the text`text()` component.
# [size](#TextCompOpt-size)?: number
Height of text.
# [font](#TextCompOpt-font)?: string \| BitmapFontData
The font to use.
# [width](#TextCompOpt-width)?: number
Wrap text to a certain width.
# [align](#TextCompOpt-align)?: TextAlign
Text alignment (\"left\", \"center\" or \"right\", default \"left\").
`since`v3000.0
# [lineSpacing](#TextCompOpt-lineSpacing)?: number
The gap between each line.
`since`v2000.2
# [letterSpacing](#TextCompOpt-letterSpacing)?: number
The gap between each character.
`since`v2000.2
# [transform](#TextCompOpt-transform)?: CharTransform \| CharTransformFunc
Transform the pos, scale, rotation or color for each character based on the index or char.
`since`v2000.1
# [styles](#TextCompOpt-styles)?: Record\<string, CharTransform \| CharTransformFunc\>
Stylesheet for styled chunks, in the syntax of \"this is a \[style\]text\[/style\] word\".
`since`v2000.2
# [indentAll](#TextCompOpt-indentAll)?: boolean
If true, any (whitespace) indent on the first line of the paragraph will be copied to all of the lines for those parts that text-wrap.
# [TextInputComp](#TextInputComp):
The textInput`textInput()` component.
# [hasFocus](#TextInputComp-hasFocus): boolean
Enable the text input array to be modified by user input. Setting this to true is the same as calling focus(), and will clear focus on all other active textInput objects.
# [typedText](#TextInputComp-typedText): string
The \"real\" text that the user typed, without any escaping.
# [focus](#TextInputComp-focus)(): void
Focuses this text input so that it will receive input, and removes focus from all other text inputs.
# [onFocus](#TextInputComp-onFocus)(cb: ()=\>void): KEventController
Event that runs when the text input gains focus.
# [onBlur](#TextInputComp-onBlur)(cb: ()=\>void): KEventController
Event that runs when the text input loses focus.
# [onInput](#TextInputComp-onInput)(cb: ()=\>void): KEventController
Event that runs when the user types any character in the text input and causes its value to change. This runs \*after\* the display text is updated with the escaped version of the typed text, so in the event handler you can override the displayed text with another version (like if you want to add syntax highlighting or something). See also .
# [onChange](#TextInputComp-onChange)(cb: ()=\>void): KEventController
Runs immediately after onBlur if the value has changed while the text input has been focused.
# [Texture](#Texture):
# [ctx](#Texture-ctx): GfxCtx
# [src](#Texture-src): null \| ImageSource
# [glTex](#Texture-glTex): WebGLTexture
# [width](#Texture-width): number
# [height](#Texture-height): number
# [fromImage](#Texture-fromImage)(ctx: GfxCtx, img: ImageSource, opt?: TextureOpt): Texture
# [update](#Texture-update)(img: ImageSource, x?: number, y?: number): void
# [bind](#Texture-bind)(): void
# [unbind](#Texture-unbind)(): void
# [free](#Texture-free)(): void
Frees up texture memory. Call this once the texture is no longer being used to avoid memory leaks.
[TextureOpt](#TextureOpt):
# [filter](#undefined-filter)?: TexFilter
# [wrap](#undefined-wrap)?: TexWrap
# [TileComp](#TileComp):
The tile`tile()` component.
# [tilePos](#TileComp-tilePos): Vec2
The tile position inside the level.
# [isObstacle](#TileComp-isObstacle): boolean
If the tile is an obstacle in pathfinding.
# [cost](#TileComp-cost): number
How much a tile is cost to traverse in pathfinding (default 0).
# [edges](#TileComp-edges): Edge\[\]
If the tile has hard edges that cannot pass in pathfinding.
# [tilePosOffset](#TileComp-tilePosOffset): Vec2
Position offset when setting \`tilePos\`.
# [edgeMask](#TileComp-edgeMask): EdgeMask
# [getLevel](#TileComp-getLevel)(): GameObj\<LevelComp\>
# [tileMove](#TileComp-tileMove)(dir: Vec2): void
# [moveLeft](#TileComp-moveLeft)(): void
# [moveRight](#TileComp-moveRight)(): void
# [moveUp](#TileComp-moveUp)(): void
# [moveDown](#TileComp-moveDown)(): void
[TileCompOpt](#TileCompOpt):
# [isObstacle](#undefined-isObstacle)?: boolean
If the tile is an obstacle in pathfinding.
# [cost](#undefined-cost)?: number
How much a tile is cost to traverse in pathfinding (default 0).
# [edges](#undefined-edges)?: Edge\[\]
If the tile has hard edges that cannot pass in pathfinding.
# [offset](#undefined-offset)?: Vec2
Position offset when setting \`tilePos\`.
Options for the tile`tile()` component.
# [TimeDirection](#TimeDirection): forward \| reverse \| ping-pong
# [TimerComp](#TimerComp):
The timer`timer()` component.
# [maxLoopsPerFrame](#TimerComp-maxLoopsPerFrame): number
The maximum number of loops per frame allowed, to keep loops with sub-frame intervals from freezing the game.
# [wait](#TimerComp-wait)(time: number, action?: ()=\>void): TimerController
Run the callback after n seconds.
# [loop](#TimerComp-loop)(time: number, action: ()=\>void, maxLoops?: number, waitFirst?: boolean): TimerController
Run the callback every n seconds. If waitFirst is false (the default), the function will be called once on the very next frame, and then loop like normal.
`since`v3000.0
# [tween](#TimerComp-tween)\<V\>(from: V, to: V, duration: number, setValue: (value: V)=\>void, easeFunc?: (t: number)=\>number): TweenController
Tweeeeen! Note that this doesn't specifically mean tweening on this object's property, this just registers the timer on this object, so the tween will cancel with the object gets destroyed, or paused when obj.paused is true.
`since`v3000.0
[TimerController](#TimerController):
# [paused](#undefined-paused): boolean
If the event handler is paused.
# [cancel](#undefined-cancel)(): void
Cancel the event handler.
# [onEnd](#undefined-onEnd)(action: ()=\>void): void
Register an event when finished.
# [then](#undefined-then)(action: ()=\>void): TimerController
# [TupleWithoutFirst](#TupleWithoutFirst)\<T\>: ConditionalType
[TweenController](#TweenController): TimerController &
# [finish](#undefined-finish)(): void
Finish the tween now and cancel.
Event controller for tween.
# [UVQuadComp](#UVQuadComp):
The uvquad`uvquad()` component.
# [draw](#UVQuadComp-draw): Comp\[draw\]
# [width](#UVQuadComp-width): number
Width of rect.
# [height](#UVQuadComp-height): number
Height of height.
# [renderArea](#UVQuadComp-renderArea)(): Rect
`since`v3000.0
# [Uniform](#Uniform): Record\<UniformKey, UniformValue\>
# [UniformKey](#UniformKey): Exclude\<string, u_tex\>
# [UniformValue](#UniformValue): number \| Vec2 \| Color \| Mat4 \| Mat23 \| number\[\] \| Vec2\[\] \| Color\[\]
# [UnionToIntersection](#UnionToIntersection)\<U\>: ConditionalType
# [Vec2](#Vec2):
A 2D vector.
# [x](#Vec2-x): number
The x coordinate
# [y](#Vec2-y): number
The y coordinate
# [set](#Vec2-set)(x: number, y: number): Vec2
Set the X and Y of this vector
# [fromAngle](#Vec2-fromAngle)(deg: number): Vec2
Create a new Vec2 from an angle in degrees
# [fromArray](#Vec2-fromArray)(arr: Array): Vec2
Create a new Vec2 from an array
# [ZERO](#Vec2-ZERO): Vec2
An empty vector. (0, 0)
# [ONE](#Vec2-ONE): Vec2
A vector with both components of 1. (1, 1)
# [LEFT](#Vec2-LEFT): Vec2
A vector signaling to the left. (-1, 0)
# [RIGHT](#Vec2-RIGHT): Vec2
A vector signaling to the right. (1, 0)
# [UP](#Vec2-UP): Vec2
A vector signaling up. (0, -1)
# [DOWN](#Vec2-DOWN): Vec2
A vector signaling down. (0, 1)
# [toAxis](#Vec2-toAxis)(): Vec2
Closest orthogonal direction: LEFT, RIGHT, UP, or DOWN
# [clone](#Vec2-clone)(): Vec2
Clone the vector
# [copy](#Vec2-copy)(v: Vec2, out: Vec2): Vec2
# [add](#Vec2-add)(args: Vec2Args): Vec2
Returns the sum with another vector.
# [add](#Vec2-add)(v: Vec2, other: Vec2, out: Vec2): Vec2
Calculates the sum of the vectors
`param`vThe first term
`param`otherThe second term
`param`outThe vector sum
`returns`The sum of the vectors
# [addScaled](#Vec2-addScaled)(v: Vec2, other: Vec2, s: number, out: Vec2): Vec2
# [addc](#Vec2-addc)(v: Vec2, x: number, y: number, out: Vec2): Vec2
Calculates the sum of the vectors
`param`vThe first term
`param`xThe x of the second term
`param`yThe y of the second term
`param`outThe vector sum
`returns`The sum of the vectors
# [sub](#Vec2-sub)(args: Vec2Args): Vec2
Returns the difference with another vector.
# [sub](#Vec2-sub)(v: Vec2, other: Vec2, out: Vec2): Vec2
Calculates the difference of the vectors
`param`vThe first term
`param`otherThe second term
`param`outThe vector difference
`returns`The difference of the vectors
# [subc](#Vec2-subc)(v: Vec2, x: number, y: number, out: Vec2): Vec2
Calculates the difference of the vectors
`param`vThe first term
`param`xThe x of the second term
`param`yThe y of the second term
`param`outThe vector difference
`returns`The difference of the vectors
# [scale](#Vec2-scale)(args: Vec2Args): Vec2
Scale by another vector. or a single number
# [scale](#Vec2-scale)(v: Vec2, s: number, out: Vec2): Vec2
Calculates the scale of the vector
`param`vThe vector
`param`sThe x scale
`param`outThe y scale
`param`unknownThe scaled vector
`returns`The scale of the vector
# [scalec](#Vec2-scalec)(v: Vec2, x: number, y: number, out: Vec2): Vec2
Calculates the scale of the vector
`param`vThe vector
`param`xThe x scale
`param`yThe y scale
`param`outThe scaled vector
`returns`The scale of the vector
# [scalev](#Vec2-scalev)(v: Vec2, other: Vec2, out: Vec2): Vec2
Calculates the scale of the vector
`param`vThe vector
`param`otherThe scale
`param`outThe scaled vector
`returns`The scale of the vector
# [invScale](#Vec2-invScale)(args: Vec2Args): Vec2
Scale by the inverse of another vector. or a single number
# [dist](#Vec2-dist)(args: Vec2Args): number
Get distance between another vector
# [dist](#Vec2-dist)(v: Vec2, other: Vec2): number
Calculates the distance between the vectors
`param`vThe vector
`param`otherThe other vector
`returns`The between the vectors
# [sdist](#Vec2-sdist)(args: Vec2Args): number
Get squared distance between another vector
# [sdist](#Vec2-sdist)(v: Vec2, other: Vec2): number
Calculates the squared distance between the vectors
`param`vThe vector
`param`otherThe other vector
`returns`The distance between the vectors
# [len](#Vec2-len)(): number
Get length of the vector
`since`v3000.0
# [len](#Vec2-len)(v: Vec2): number
Calculates the length of the vector
`param`vThe vector
`returns`The length of the vector
# [slen](#Vec2-slen)(): number
Get squared length of the vector
`since`v3000.0
# [slen](#Vec2-slen)(v: Vec2): number
Calculates the squared length of the vector
`param`vThe vector
`returns`The squared length of the vector
# [unit](#Vec2-unit)(): Vec2
Get the unit vector (length of 1).
# [unit](#Vec2-unit)(v: Vec2, out: Vec2): Vec2
# [normal](#Vec2-normal)(): Vec2
Get the perpendicular vector.
# [normal](#Vec2-normal)(v: Vec2, out: Vec2): Vec2
# [reflect](#Vec2-reflect)(normal: Vec2): Vec2
Get the reflection of a vector with a normal.
`since`v3000.0
# [project](#Vec2-project)(on: Vec2): Vec2
Get the projection of a vector onto another vector.
`since`v3000.0
# [reject](#Vec2-reject)(on: Vec2): Vec2
Get the rejection of a vector onto another vector.
`since`v3000.0
# [rotate](#Vec2-rotate)(vecOrAngle: Vec2 \| number): Vec2
# [rotate](#Vec2-rotate)(v: Vec2, dir: Vec2, out: Vec2): Vec2
Calculates the rotated vector
`param`vThe vector
`param`dirThe rotation vector
`param`outThe rotated vector
`returns`The rotated vector
# [rotateByAngle](#Vec2-rotateByAngle)(v: Vec2, angle: number, out: Vec2): Vec2
Calculates the rotated vector
`param`vThe vector
`param`angleThe angle in radians
`param`outThe rotated vector
`returns`The rotated vector
# [invRotate](#Vec2-invRotate)(vecOrAngle: Vec2 \| number): Vec2
# [inverseRotate](#Vec2-inverseRotate)(v: Vec2, dir: Vec2, out: Vec2): Vec2
Calculates the inverse rotated vector
`param`vThe vector
`param`dirThe rotation vector
`param`outThe rotated vector
`returns`The rotated vector
# [dot](#Vec2-dot)(p2: Vec2): number
Get the dot product with another vector.
# [dot](#Vec2-dot)(v: Vec2, other: Vec2): number
Get the dot product between 2 vectors.
`since`v3000.0
# [cross](#Vec2-cross)(p2: Vec2): number
Get the cross product with another vector.
`since`v3000.0
# [cross](#Vec2-cross)(v: Vec2, other: Vec2): number
Get the cross product between 2 vectors.
`since`v3000.0
# [angle](#Vec2-angle)(args: Vec2Args): number
Get the angle of the vector in degrees.
# [toAngle](#Vec2-toAngle)(v: Vec2): number
Calculates the angle represented by the vector in radians
`param`vThe vector
`returns`Angle represented by the vector in radians
# [angleBetween](#Vec2-angleBetween)(args: Vec2Args): number
Get the angle between this vector and another vector.
`since`v3000.0
# [angleBetween](#Vec2-angleBetween)(v: Vec2, other: Vec2): number
Calculates the angle between the vectors in radians
`param`vFirst vector
`param`otherSecond vector
`returns`Angle between the vectors in radians
# [lerp](#Vec2-lerp)(dest: Vec2, t: number): Vec2
Linear interpolate to a destination vector (for positions).
# [lerp](#Vec2-lerp)(src: Vec2, dst: Vec2, t: number, out: Vec2): Vec2
Linear interpolate src and dst by t
`param`srcFirst vector
`param`dstSecond vector
`param`tPercentage
`param`outThe linear interpolation between src and dst by t
`returns`The linear interpolation between src and dst by t
# [slerp](#Vec2-slerp)(dest: Vec2, t: number): Vec2
Spherical linear interpolate to a destination vector (for rotations).
`since`v3000.0
# [slerp](#Vec2-slerp)(src: Vec2, dst: Vec2, t: number, out: Vec2): Vec2
Spherical interpolate src and dst by t
`param`srcFirst vector
`param`dstSecond vector
`param`tPercentage
`param`outThe spherical interpolation between src and dst by t
`returns`The spherical interpolation between src and dst by t
# [isZero](#Vec2-isZero)(): boolean
If the vector (x, y) is zero.
`since`v3000.0
# [toFixed](#Vec2-toFixed)(n: number): Vec2
To n precision floating point.
# [transform](#Vec2-transform)(m: Mat4): Vec2
Multiply by a Mat4.
`since`v3000.0
# [eq](#Vec2-eq)(other: Vec2): boolean
See if one vector is equal to another.
`since`v3000.0
# [bbox](#Vec2-bbox)(): Rect
Converts the vector to a Rect`Rect()` with the vector as the origin.
`since`v3000.0.
# [toArray](#Vec2-toArray)(): Array\<number\>
Converts the vector to an array.
`since`v3001.0
# [Vec2Args](#Vec2Args): \[number, number\] \| \[number\] \| \[Vec2\] \| \[number \| Vec2\] \| \[\]
Possible arguments for a Vec2.
# [Vec3](#Vec3):
# [x](#Vec3-x): number
# [y](#Vec3-y): number
# [z](#Vec3-z): number
# [dot](#Vec3-dot)(other: Vec3): number
# [cross](#Vec3-cross)(other: Vec3): Vec3
# [Vertex](#Vertex):
# [pos](#Vertex-pos): Vec2
# [uv](#Vertex-uv): Vec2
# [color](#Vertex-color): Color
# [opacity](#Vertex-opacity): number
[VertexFormat](#VertexFormat):
# [size](#undefined-size): number
\[\]
# [VideoComp](#VideoComp):
# [width](#VideoComp-width): number
# [height](#VideoComp-height): number
# [currentTime](#VideoComp-currentTime): number
# [duration](#VideoComp-duration): number
# [play](#VideoComp-play)(): void
# [pause](#VideoComp-pause)(): void
# [mute](#VideoComp-mute): boolean
# [renderArea](#VideoComp-renderArea)(): Rect
[VideoCompOpt](#VideoCompOpt):
# [width](#undefined-width): number
# [height](#undefined-height): number
[Viewport](#Viewport):
# [x](#undefined-x): number
# [y](#undefined-y): number
# [width](#undefined-width): number
# [height](#undefined-height): number
# [scale](#undefined-scale): number
# [ZComp](#ZComp):
The z`z()` component.
# [z](#ZComp-z): number
Defines the z-index of this game obj
[createEngine](#createEngine)(gopt: KAPLAYOpt):
# [globalOpt](#undefined-globalOpt): KAPLAYOpt\<any, any\>
# [canvas](#undefined-canvas): HTMLCanvasElement
[app](#undefined-app):
[state](#undefined-state):
# [canvas](#undefined-canvas): HTMLCanvasElement
# [buttons](#undefined-buttons): ButtonsDef
# [buttonsByKey](#undefined-buttonsByKey): Map\<Key, string\[\]\>
# [buttonsByMouse](#undefined-buttonsByMouse): Map\<MouseButton, string\[\]\>
# [buttonsByGamepad](#undefined-buttonsByGamepad): Map\<KGamepadButton, string\[\]\>
# [buttonsByKeyCode](#undefined-buttonsByKeyCode): Map\<string, string\[\]\>
# [loopID](#undefined-loopID): null \| number
# [stopped](#undefined-stopped): boolean
# [dt](#undefined-dt): number
# [fixedDt](#undefined-fixedDt): number
# [restDt](#undefined-restDt): number
# [time](#undefined-time): number
# [realTime](#undefined-realTime): number
[fpsCounter](#undefined-fpsCounter):
# [dts](#undefined-dts): number\[\]
# [timer](#undefined-timer): number
# [fps](#undefined-fps): number
# [tick](#undefined-tick)(dt: number): void
# [timeScale](#undefined-timeScale): number
# [skipTime](#undefined-skipTime): boolean
# [isHidden](#undefined-isHidden): boolean
# [numFrames](#undefined-numFrames): number
# [capsOn](#undefined-capsOn): boolean
# [mousePos](#undefined-mousePos): Vec2
# [mouseDeltaPos](#undefined-mouseDeltaPos): Vec2
# [keyState](#undefined-keyState): ButtonState\<Key\>
# [mouseState](#undefined-mouseState): ButtonState\<MouseButton\>
[mergedGamepadState](#undefined-mergedGamepadState):
# [buttonState](#undefined-buttonState): ButtonState\<KGamepadButton\>
# [stickState](#undefined-stickState): Map\<GamepadStick, Vec2\>
[gamepadStates](#undefined-gamepadStates): Map\<number,
# [buttonState](#undefined-buttonState): ButtonState\<KGamepadButton\>
# [stickState](#undefined-stickState): Map\<GamepadStick, Vec2\>
\>
# [lastInputDevice](#undefined-lastInputDevice): mouse \| keyboard \| gamepad \| null
# [buttonState](#undefined-buttonState): ButtonState\<string\>
# [gamepads](#undefined-gamepads): KGamepad\[\]
# [charInputted](#undefined-charInputted): string\[\]
# [isMouseMoved](#undefined-isMouseMoved): boolean
# [lastWidth](#undefined-lastWidth): number
# [lastHeight](#undefined-lastHeight): number
# [events](#undefined-events): KEventHandler\<AppEventMap\>
# [dt](#undefined-dt)(): number
# [fixedDt](#undefined-fixedDt)(): number
# [restDt](#undefined-restDt)(): number
# [time](#undefined-time)(): number
# [run](#undefined-run)(fixedUpdate: ()=\>void, update: (processInput: ()=\>void, resetInput: ()=\>void)=\>void): void
# [canvas](#undefined-canvas): HTMLCanvasElement
# [fps](#undefined-fps)(): number
# [numFrames](#undefined-numFrames)(): number
# [quit](#undefined-quit)(): void
# [isHidden](#undefined-isHidden)(): boolean
# [setFullscreen](#undefined-setFullscreen)(f?: boolean): void
# [isFullscreen](#undefined-isFullscreen)(): boolean
# [setCursor](#undefined-setCursor)(c: Cursor): void
# [screenshot](#undefined-screenshot)(): string
# [getGamepads](#undefined-getGamepads)(): KGamepad\[\]
# [getCursor](#undefined-getCursor)(): Cursor
# [setCursorLocked](#undefined-setCursorLocked)(b: boolean): void
# [isCursorLocked](#undefined-isCursorLocked)(): boolean
# [isTouchscreen](#undefined-isTouchscreen)(): boolean
# [mousePos](#undefined-mousePos)(): Vec2
# [mouseDeltaPos](#undefined-mouseDeltaPos)(): Vec2
# [isKeyDown](#undefined-isKeyDown)(k?: Key \| Key\[\]): boolean
# [isKeyPressed](#undefined-isKeyPressed)(k?: Key \| Key\[\]): boolean
# [isKeyPressedRepeat](#undefined-isKeyPressedRepeat)(k?: Key \| Key\[\]): boolean
# [isKeyReleased](#undefined-isKeyReleased)(k?: Key \| Key\[\]): boolean
# [isMouseDown](#undefined-isMouseDown)(m?: MouseButton): boolean
# [isMousePressed](#undefined-isMousePressed)(m?: MouseButton): boolean
# [isMouseReleased](#undefined-isMouseReleased)(m?: MouseButton): boolean
# [isMouseMoved](#undefined-isMouseMoved)(): boolean
# [isGamepadButtonPressed](#undefined-isGamepadButtonPressed)(btn?: KGamepadButton \| KGamepadButton\[\]): boolean
# [isGamepadButtonDown](#undefined-isGamepadButtonDown)(btn?: KGamepadButton \| KGamepadButton\[\]): boolean
# [isGamepadButtonReleased](#undefined-isGamepadButtonReleased)(btn?: KGamepadButton \| KGamepadButton\[\]): boolean
# [getGamepadStick](#undefined-getGamepadStick)(stick: GamepadStick): Vec2
# [isButtonPressed](#undefined-isButtonPressed)(btn?: string \| string\[\]): boolean
# [isButtonDown](#undefined-isButtonDown)(btn?: string \| string\[\]): boolean
# [isButtonReleased](#undefined-isButtonReleased)(btn?: string \| string\[\]): boolean
# [setButton](#undefined-setButton)(btn: string, binding: ButtonBinding): void
# [getButton](#undefined-getButton)(btn: string): ButtonBinding
# [pressButton](#undefined-pressButton)(btn: string): void
# [releaseButton](#undefined-releaseButton)(btn: string): void
# [charInputted](#undefined-charInputted)(): string\[\]
# [onResize](#undefined-onResize)(action: ()=\>void): KEventController
# [onKeyDown](#undefined-onKeyDown): (action: (key: Key)=\>void)=\>KEventController & (key: Key \| Key\[\], action: (key: Key)=\>void)=\>KEventController
# [onKeyPress](#undefined-onKeyPress): (action: (key: Key)=\>void)=\>KEventController & (key: Key \| Key\[\], action: (key: Key)=\>void)=\>KEventController
# [onKeyPressRepeat](#undefined-onKeyPressRepeat): (action: (key: Key)=\>void)=\>KEventController & (key: Key \| Key\[\], action: (key: Key)=\>void)=\>KEventController
# [onKeyRelease](#undefined-onKeyRelease): (action: (key: Key)=\>void)=\>KEventController & (key: Key \| Key\[\], action: (key: Key)=\>void)=\>KEventController
# [onMouseDown](#undefined-onMouseDown): (action: (m: MouseButton)=\>void)=\>KEventController & (mouse: MouseButton \| MouseButton\[\], action: (m: MouseButton)=\>void)=\>KEventController
# [onMousePress](#undefined-onMousePress): (action: (m: MouseButton)=\>void)=\>KEventController & (mouse: MouseButton \| MouseButton\[\], action: (m: MouseButton)=\>void)=\>KEventController
# [onMouseRelease](#undefined-onMouseRelease): (action: (m: MouseButton)=\>void)=\>KEventController & (mouse: MouseButton \| MouseButton\[\], action: (m: MouseButton)=\>void)=\>KEventController
# [onMouseMove](#undefined-onMouseMove)(f: (pos: Vec2, dpos: Vec2)=\>void): KEventController
# [onCharInput](#undefined-onCharInput)(action: (ch: string)=\>void): KEventController
# [onTouchStart](#undefined-onTouchStart)(f: (pos: Vec2, t: Touch)=\>void): KEventController
# [onTouchMove](#undefined-onTouchMove)(f: (pos: Vec2, t: Touch)=\>void): KEventController
# [onTouchEnd](#undefined-onTouchEnd)(f: (pos: Vec2, t: Touch)=\>void): KEventController
# [onScroll](#undefined-onScroll)(action: (delta: Vec2)=\>void): KEventController
# [onHide](#undefined-onHide)(action: ()=\>void): KEventController
# [onShow](#undefined-onShow)(action: ()=\>void): KEventController
# [onGamepadButtonDown](#undefined-onGamepadButtonDown): (action: (btn: KGamepadButton, gamepad: KGamepad)=\>void)=\>KEventController & (btn: KGamepadButton, action: (btn: KGamepadButton, gamepad: KGamepad)=\>void)=\>KEventController
# [onGamepadButtonPress](#undefined-onGamepadButtonPress): (action: (btn: KGamepadButton, gamepad: KGamepad)=\>void)=\>KEventController & (btn: KGamepadButton \| KGamepadButton\[\], action: (btn: KGamepadButton, gamepad: KGamepad)=\>void)=\>KEventController
# [onGamepadButtonRelease](#undefined-onGamepadButtonRelease): (action: (btn: KGamepadButton, gamepad: KGamepad)=\>void)=\>KEventController & (btn: KGamepadButton \| KGamepadButton\[\], action: (btn: KGamepadButton, gamepad: KGamepad)=\>void)=\>KEventController
# [onGamepadStick](#undefined-onGamepadStick)(stick: GamepadStick, action: (value: Vec2, gp: KGamepad)=\>void): KEventController
# [onGamepadConnect](#undefined-onGamepadConnect)(action: (gamepad: KGamepad)=\>void): KEventController
# [onGamepadDisconnect](#undefined-onGamepadDisconnect)(action: (gamepad: KGamepad)=\>void): KEventController
# [onButtonPress](#undefined-onButtonPress): (action: (btn: string)=\>void)=\>KEventController & (btn: string \| string, action: (btn: string)=\>void)=\>KEventController
# [onButtonDown](#undefined-onButtonDown): (action: (btn: string)=\>void)=\>KEventController & (btn: string \| string, action: (btn: string)=\>void)=\>KEventController
# [onButtonRelease](#undefined-onButtonRelease): (action: (btn: string)=\>void)=\>KEventController & (btn: string \| string, action: (btn: string)=\>void)=\>KEventController
# [getLastInputDeviceType](#undefined-getLastInputDeviceType)(): ButtonBindingDevice \| null
# [events](#undefined-events): KEventHandler\<AppEventMap\>
[ggl](#undefined-ggl):
# [gl](#undefined-gl): WebGLRenderingContext
# [opts](#undefined-opts): KAPLAYOpt\<any, any\>
# [onDestroy](#undefined-onDestroy)(action: ()=\>unknown): void
# [destroy](#undefined-destroy)(): void
# [pushTexture2D](#undefined-pushTexture2D)(item: WebGLTexture): void
# [popTexture2D](#undefined-popTexture2D)(): void
# [pushArrayBuffer](#undefined-pushArrayBuffer)(item: WebGLBuffer): void
# [popArrayBuffer](#undefined-popArrayBuffer)(): void
# [pushElementArrayBuffer](#undefined-pushElementArrayBuffer)(item: WebGLBuffer): void
# [popElementArrayBuffer](#undefined-popElementArrayBuffer)(): void
# [pushFramebuffer](#undefined-pushFramebuffer)(item: WebGLFramebuffer): void
# [popFramebuffer](#undefined-popFramebuffer)(): void
# [pushRenderbuffer](#undefined-pushRenderbuffer)(item: WebGLRenderbuffer): void
# [popRenderbuffer](#undefined-popRenderbuffer)(): void
[pushViewport](#undefined-pushViewport)(item:
# [x](#undefined-x): number
# [y](#undefined-y): number
# [w](#undefined-w): number
# [h](#undefined-h): number
): void
# [popViewport](#undefined-popViewport)(): void
# [pushProgram](#undefined-pushProgram)(item: WebGLProgram): void
# [popProgram](#undefined-popProgram)(): void
# [setVertexFormat](#undefined-setVertexFormat)(fmt: VertexFormat): void
# [gfx](#undefined-gfx): AppGfxCtx
[audio](#undefined-audio):
# [ctx](#undefined-ctx): AudioContext
# [masterNode](#undefined-masterNode): GainNode
# [burpSnd](#undefined-burpSnd): SoundData
[assets](#undefined-assets):
# [urlPrefix](#undefined-urlPrefix): string
# [sprites](#undefined-sprites): AssetBucket\<SpriteData\>
# [fonts](#undefined-fonts): AssetBucket\<FontData\>
# [bitmapFonts](#undefined-bitmapFonts): AssetBucket\<GfxFont\>
# [sounds](#undefined-sounds): AssetBucket\<SoundData\>
# [shaders](#undefined-shaders): AssetBucket\<Shader\>
# [custom](#undefined-custom): AssetBucket\<any\>
# [music](#undefined-music): Record\<string, string\>
# [packer](#undefined-packer): TexPacker
# [loaded](#undefined-loaded): boolean
[frameRenderer](#undefined-frameRenderer):
# [frameStart](#undefined-frameStart)(): void
# [frameEnd](#undefined-frameEnd)(): void
# [fixedUpdateFrame](#undefined-fixedUpdateFrame)(): void
# [updateFrame](#undefined-updateFrame)(): void
# [fontCacheC2d](#undefined-fontCacheC2d): CanvasRenderingContext2D \| null
# [fontCacheCanvas](#undefined-fontCacheCanvas): HTMLCanvasElement
# [game](#undefined-game): Game
# [debug](#undefined-debug): Debug
# [k](#undefined-k): KAPLAYCtx
[createFrameRenderer](#createFrameRenderer)(gfx: AppGfxCtx, game: Game, pixelDensity: number):
# [frameStart](#undefined-frameStart)(): void
# [frameEnd](#undefined-frameEnd)(): void
# [fixedUpdateFrame](#undefined-fixedUpdateFrame)(): void
# [updateFrame](#undefined-updateFrame)(): void
# [ASCII_CHARS](#ASCII_CHARS): string
All chars in ASCII.
`since`v2000.0
# [Asset](#Asset): Asset
The asset data.
# [BLACK](#BLACK): Color
Black color.
`since`v2000.0
# [BLUE](#BLUE): Color
Blue color.
`since`v2000.0
# [BlendMode](#BlendMode): BlendMode
BlendMode.Normal Normal alpha blending BlendMode.Add Additive blending BlendMode.Multiply multiplicative blending BlendMode.Screen Screen blending
`since`v4000.0
# [CYAN](#CYAN): Color
Cyan color.
`since`v2000.0
# [DOWN](#DOWN): Vec2
Down directional vector vec2(0, 1).
`since`v2000.0
# [GREEN](#GREEN): Color
Green color.
`since`v2000.0
# [KEvent](#KEvent): KEvent
EventHandler for one single event.
`since`v3000.0
# [KEventController](#KEventController): KEventController
The object that can pause or cancel an event.
`since`v3000.0
# [KEventHandler](#KEventHandler): KEventHandler
EventHandler for multiple events.
`since`v3000.0
# [KeepFlags](#KeepFlags): KeepFlags
Flags indicating which transform components to keep. When used, the aspect of the transform will not change visually even if the parent transform is different. For example a sprite pointing west, will keep pointing west, even if the parent transform applies a rotation with an angle different from 0. This is only applied once, during switching parents.
`since`v3000.0
# [LEFT](#LEFT): Vec2
Left directional vector vec2(-1, 0).
`since`v2000.0
# [Line](#Line): Line
A line shape.
`since`v2000.0
# [MAGENTA](#MAGENTA): Color
Cyan color.
`since`v2000.0
# [Mat23](#Mat23): Mat23
`since`v4000.0
# [Mat4](#Mat4): Mat4
`since`v3001.0
# [NavMesh](#NavMesh): NavMesh
A Navigation Mesh.
`since`v3001.0
# [Point](#Point): Point
A point.
`since`v3001.0
# [RED](#RED): Color
Red color.
`since`v2000.0
# [RIGHT](#RIGHT): Vec2
Right directional vector vec2(1, 0).
`since`v2000.0
# [RNG](#RNG): RNG
The Random Number Generator.
`since`v2000.0
# [SoundData](#SoundData): SoundData
# [SpriteData](#SpriteData): SpriteData
The sprite data.
# [UP](#UP): Vec2
Up directional vector vec2(0, -1).
`since`v2000.0
# [VERSION](#VERSION): string
Current KAPLAY library version.
`since`v3000.0
# [WHITE](#WHITE): Color
White color.
`since`v2000.0
# [YELLOW](#YELLOW): Color
Yellow color.
`since`v2000.0
[\_k](#_k): Engine &
# [k](#undefined-k): KAPLAYCtx
Internal data that should not be accessed directly.
`readonly`
# [add](#add)\<T\>(comps?: \[RestType\]): GameObj\<T\[number\]\>
Assemble a game object from a list of components, and add it to the game,
`param`comps- List of components to add to the game object.
``` js
const player = add([
// List of components, each offers a set of functionalities
sprite("mark"),
pos(100, 200),
area(),
body(),
health(8),
// Plain strings are tags, a quicker way to let us define behaviors for a group
"player",
"friendly",
// Components are just plain objects, you can pass an object literal as a component.
{
dir: LEFT,
dead: false,
speed: 240,
},
]);
// .jump is provided by body()
player.jump();
// .moveTo is provided by pos()
player.moveTo(300, 200);
// .onUpdate() is on every game object, it registers an event that runs every frame
player.onUpdate(() => {
// .move() is provided by pos()
player.move(player.dir.scale(player.speed));
});
// .onCollide is provided by area()
player.onCollide("tree", () => {
destroy(player);
});
```
`returns`The added game object that contains all properties and methods each component offers.
# [addKaboom](#addKaboom)(pos: Vec2, opt?: BoomOpt): GameObj
Add an explosion effect.
`param`pos- The position of the explosion.
`param`opt- The options for the explosion.
``` js
onMousePress(() => {
addKaboom(mousePos());
});
```
`returns`The explosion object.
`since`v2000.0
# [addLevel](#addLevel)(map: string\[\], opt: AddLevelOpt, parent?: GameObj): GameObj\<PosComp \| LevelComp\>
Construct a level based on symbols.
`param`map- The map data.
`param`opt- The level options.
`param`parent- The parent object of the level. Defaults to root.
``` js
addLevel([
" $",
" $",
" $$ = $",
" % ==== = $",
" = ",
" ^^ = > = &",
"===========================",
], {
// define the size of tile block
tileWidth: 32,
tileHeight: 32,
// define what each symbol means, by a function returning a component list (what will be passed to add())
tiles: {
"=": () => [
sprite("floor"),
area(),
body({ isStatic: true }),
],
"$": () => [
sprite("coin"),
area(),
pos(0, -9),
],
"^": () => [
sprite("spike"),
area(),
"danger",
],
}
})
```
`returns`A game obj with the level.
`since`v2000.0
# [agent](#agent)(opt?: AgentCompOpt): AgentComp
An agent which can finds it way on a tilemap.
`param`opt- Options for the agent component. See
`returns`The agent comp.
`since`v3000.0
# [anchor](#anchor)(o: Anchor \| Vec2): AnchorComp
Anchor point for render (default \"topleft\").
`param`o- The anchor point to set.
``` js
// set anchor to "center" so it'll rotate from center
add([
rect(40, 10),
rotate(45),
anchor("center"),
])
```
`returns`The anchor comp.
`since`v2000.0
# [animate](#animate)(opt?: AnimateCompOpt): AnimateComp
A component to animate properties.
`param`opt- Options for the animate component. See
``` js
let movingBean = add([
sprite("bean"),
pos(50, 150),
anchor("center"),
animate(),
]);
// Moving right to left using ping-pong
movingBean.animate("pos", [vec2(50, 150), vec2(150, 150)], {
duration: 2,
direction: "ping-pong",
});
```
`returns`The animate comp.
`since`v3001.0
# [appendToPicture](#appendToPicture)(picture?: Picture): void
Selects the picture for drawing, keeps existing data.
`param`pictureThe picture to write drawing data to.
# [area](#area)(opt?: AreaCompOpt): AreaComp
Attach a collider area from shape and enables collision detection in a Game Object.
`param`opt- Options for the area component. See
``` js
// Automatically generate area information from the shape of render
const player = add([
sprite("bean"),
area(),
])
// Die if player collides with another game obj with tag "tree"
player.onCollide("tree", () => {
destroy(player)
go("lose")
})
// Check for collision manually every frame instead of registering an event
player.onUpdate(() => {
if (player.isColliding(bomb)) {
score += 1
}
})
```
`returns`The area comp.
`since`v2000.0
# [areaEffector](#areaEffector)(opt: AreaEffectorCompOpt): AreaEffectorComp
Applies a force on a colliding object. Good to apply anti-gravity, wind or water flow.
`param`opt- Options for the area effector component. See
`returns`The area effector comp.
`since`v3001.0
# [audioCtx](#audioCtx): AudioContext
Get the underlying browser AudioContext.
`since`v2000.0
# [beginPicture](#beginPicture)(picture?: Picture): void
Selects the picture for drawing, erases existing data.
`param`pictureThe picture to write drawing data to.
# [bezier](#bezier)(pt1: Vec2, pt2: Vec2, pt3: Vec2, pt4: Vec2): Vec2
A second order function returning an evaluator for the given 2D quadratic Bezier curve
`param`pt1- First point
`param`pt2- First control point
`param`pt3- Second control point
`param`pt4- Second point
`returns`A function which gives the value on the 2D quadratic Bezier curve at t
# [blend](#blend)(blend: BlendMode): BlendComp
Sets the blend mode of a Game Object.
``` js
// light
add([
sprite("light"),
blend(BlendMode.Add),
]);
```
`returns`The blend comp.
`since`v4000.0
# [body](#body)(opt?: BodyCompOpt): BodyComp
Physical body that responds to gravity. Requires \"area\" and \"pos\" comp. This also makes the object \"solid\".
`param`opt- Options for the body component. See
``` js
// bean jumpy
const bean = add([
sprite("bean"),
// body() requires "pos" and "area" component
pos(),
area(),
body(),
])
// when bean is grounded, press space to jump
// check out #BodyComp for more methods
onKeyPress("space", () => {
if (bean.isGrounded()) {
bean.jump()
}
})
// run something when bean falls and hits a ground
bean.onGround(() => {
debug.log("oh no!")
})
```
`returns`The body comp.
`since`v2000.0
# [buoyancyEffector](#buoyancyEffector)(opt: BuoyancyEffectorCompOpt): BuoyancyEffectorComp
Applies an upwards force (force against gravity) to colliding objects depending on the fluid density and submerged area. Good to apply constant thrust.
`param`opt- Options for the buoyancy effector component. See
`returns`The buoyancy effector comp.
`since`v3001.0
# [burp](#burp)(options?: AudioPlayOpt): AudioPlay
Yep. Plays a burp sound.
`returns`A control handle.
`since`v2000.0
# [camFlash](#camFlash)(flashColor: Color, fadeOutTime: number): TimerController
`param`flashColor- The color of the flash.
`param`fadeOutTime- The time it takes for the flash to fade out.
`deprecated`use
``` js
onClick(() => {
// flashed
camFlash(WHITE, 0.5)
})
```
`returns`A timer controller.
`since`v3001.0
# [camPos](#camPos)(pos: Vec2): Vec2
`param`pos- The position to set the camera to.
`deprecated`Use
``` js
// camera follows player
player.onUpdate(() => {
camPos(player.pos)
})
```
`returns`The current camera position.
`since`v2000.0
# [camPos](#camPos)(x: number, y: number): Vec2
`deprecated`
# [camPos](#camPos)(xy: number): Vec2
`deprecated`
# [camPos](#camPos)(): Vec2
`deprecated`
# [camRot](#camRot)(angle?: number): number
`param`angle- The angle to rotate the camera.
`deprecated`Use
`returns`The current camera rotation.
`since`v2000.0
# [camScale](#camScale)(scale: Vec2): Vec2
`param`scale- The scale to set the camera to.
`deprecated`Use
`returns`The current camera scale.
`since`v2000.0
# [camScale](#camScale)(x: number, y: number): Vec2
`deprecated`
# [camScale](#camScale)(xy: number): Vec2
`deprecated`
# [camScale](#camScale)(): Vec2
`deprecated`
# [camTransform](#camTransform)(): Mat23
`deprecated`use
# [cancel](#cancel)(): Symbol
Cancels the event by returning the cancel symbol.
``` js
onKeyPress((key) => {
if (key === "q") return cancel();
});
```
`returns`The cancel event symbol.
`since`v3001.0.5
`experimental`This feature is in experimental phase, it will be fully released in v3001.1.0
# [canvas](#canvas): HTMLCanvasElement
The canvas DOM KAPLAY is currently using.
`since`v2000.0
# [cardinal](#cardinal)(pt1: Vec2, m1: Vec2, m2: Vec2, pt2: Vec2, tension: number): Vec2
A second order function returning an evaluator for the given 2D Cardinal curve
`param`pt1- Previous point
`param`m1- First point
`param`m2- Second point
`param`pt2- Next point
`param`tensionThe tension of the curve, \[0..1\] from round to tight.
`returns`A function which gives the value on the 2D Cardinal curve at t
# [catmullRom](#catmullRom)(pt1: Vec2, m1: Vec2, m2: Vec2, pt2: Vec2): Vec2
A second order function returning an evaluator for the given 2D Catmull-Rom curve
`param`pt1- Previous point
`param`m1- First point
`param`m2- Second point
`param`pt2- Next point
`returns`A function which gives the value on the 2D Catmull-Rom curve at t
# [center](#center)(): Vec2
Get the center point of view.
``` js
// add bean to the center of the screen
add([
sprite("bean"),
pos(center()),
// ...
])
```
`returns`The center point of the view.
`since`v2000.0
# [chance](#chance)(p: number): boolean
rand(1) \<= p
``` js
// every frame all objs with tag "unlucky" have 50% chance die
onUpdate("unlucky", (o) => {
if (chance(0.5)) {
destroy(o)
}
})
```
# [charInputted](#charInputted)(): string\[\]
List of characters inputted since last frame.
`returnns`An array of characters inputted.
`since`v3000.0
# [choose](#choose)\<T\>(lst: T\[\]): T
Choose a random item from a list.
`param`lst- The list to choose from.
``` js
// decide the best fruit randomly
const bestFruit = choose(["apple", "banana", "pear", "watermelon"]);
```
`returns`A random item from the list.
`since`v3001.0
# [chooseMultiple](#chooseMultiple)\<T\>(lst: T\[\], count: number): T\[\]
Choose multiple random items from a list.
`param`lst- The list to choose from.
`param`count- The number of items to choose.
`returns`An array of random items from the list.
`since`v3001.0
# [Circle](#Circle): Circle
A circle shape.
`since`v2000.0
# [clamp](#clamp)(n: number, min: number, max: number): number
Return a value clamped to an inclusive range of min and max.
# [clipLineToCircle](#clipLineToCircle)(c: Circle, l: Line, result: Line): boolean
`since`v4000.0
# [clipLineToRect](#clipLineToRect)(r: Rect, l: Line, result: Line): boolean
`since`v4000.0
# [Color](#Color): Color
A color.
`since`v2000.0
# [compileStyledText](#compileStyledText)(text: any): StyledTextInfo
Parses the text that has formatting tags, and returns the unstyled text (the actual characters that will be displayed) as well as which styles are active on each character.
`since`v4000
# [constantForce](#constantForce)(opt: ConstantForceCompOpt): ConstantForceComp
Applies a constant force to the object. Good to apply constant thrust.
`param`opt- Options for the constant force component. See
`returns`The constant force comp.
`since`v3001.0
# [curveLengthApproximation](#curveLengthApproximation)(curve: (t: number)=\>Vec2, entries: number, detail: number): number
Returns a function. entries is the amount of entries in the LUT. detail is the sampling granularity of each segment recorded in the LUT. This new function either returns the length for a given t, or t for a given length, depending on the inverse parameter.
`since`v3001.0
# [debug](#debug): Debug
The Debug interface for debugging stuff.
``` js
// pause the whole game
debug.paused = true
// enter inspect mode
debug.inspect = true
```
`returns`The debug interface.
`since`v2000.0
# [deg2rad](#deg2rad)(deg: number): number
Convert degrees to radians.
# [destroy](#destroy)(obj: GameObj): void
Remove the game obj.
`param`obj- The game object to remove.
``` js
// every time bean collides with anything with tag "fruit", remove it
bean.onCollide("fruit", (fruit) => {
destroy(fruit);
});
```
# [destroyAll](#destroyAll)(tag: Tag): void
Remove all game objs with certain tag.
`param`tag- The tag to search for.
``` js
// destroy all objects with tag "bomb" when you click one
onClick("bomb", () => {
destroyAll("bomb");
});
```
# [doubleJump](#doubleJump)(numJumps?: number): DoubleJumpComp
Enables double jump.
`param`numJumps- The number of jumps allowed. Defaults to 1.
`requires`
`returns`The double jump comp.
`since`v3000.0
# [download](#download)(filename: string, dataurl: string): void
Trigger a file download from a url.
`since`v3000.0
# [downloadBlob](#downloadBlob)(filename: string, blob: Blob): void
Trigger a file download from a blob.
`since`v3000.0
# [downloadJSON](#downloadJSON)(filename: string, data: any): void
Trigger a json download from a .
`since`v3000.0
# [downloadText](#downloadText)(filename: string, text: string): void
Trigger a text file download.
`since`v3000.0
# [drawBezier](#drawBezier)(opt: DrawBezierOpt): void
Draw a cubic Bezier curve.
`param`opt- The draw cubic bezier options.
``` js
drawBezier({
pt1: vec2(100, 100),
pt2: vec2(200, 100),
pt3: vec2(200, 200),
pt4: vec2(100, 200),
width: 2,
color: GREEN
});
```
`since`v3001.0
# [drawCanvas](#drawCanvas)(opt: DrawCanvasOpt): void
Draw a canvas.
`param`optThe canvas object.
`since`v4000.0
# [drawCircle](#drawCircle)(opt: DrawCircleOpt): void
Draw a circle.
`param`opt- The draw circle options.
``` js
drawCircle({
pos: vec2(100, 200),
radius: 120,
color: rgb(255, 255, 0),
});
```
`since`v2000.0
# [drawCurve](#drawCurve)(curve: (t: number)=\>Vec2, opt: DrawCurveOpt): void
Draw a curve.
``` js
drawCurve(t => evaluateBezier(a, b, c, d, t)
{
width: 2,
color: rgb(0, 0, 255),
});
```
`since`v3001.0
# [drawEllipse](#drawEllipse)(opt: DrawEllipseOpt): void
Draw an ellipse.
`param`opt- The draw ellipse options.
``` js
drawEllipse({
pos: vec2(100, 200),
radiusX: 120,
radiusY: 120,
color: rgb(255, 255, 0),
});
```
`since`v3000.0
# [drawFormattedText](#drawFormattedText)(text: FormattedText): void
Draw a piece of formatted text from formatText().
`param`text- The formatted text object.
``` js
// text background
const txt = formatText({
text: "oh hi",
});
drawRect({
width: txt.width,
height: txt.height,
});
drawFormattedText(txt);
```
`since`v2000.2
# [drawLine](#drawLine)(opt: DrawLineOpt): void
Draw a line.
`param`opt- The draw line options.
``` js
drawLine({
p1: vec2(0),
p2: mousePos(),
width: 4,
color: rgb(0, 0, 255),
});
```
`since`v3000.0
# [drawLines](#drawLines)(opt: DrawLinesOpt): void
Draw lines.
`param`opt- The draw lines options.
``` js
drawLines({
pts: [ vec2(0), vec2(0, height()), mousePos() ],
width: 4,
pos: vec2(100, 200),
color: rgb(0, 0, 255),
});
```
`since`v3000.0
# [drawMasked](#drawMasked)(content: ()=\>void, mask: ()=\>void): void
Whatever drawn in content will only be drawn if it's also drawn in mask (mask will not be rendered).
`since`v3000.0
# [drawPicture](#drawPicture)(picture: Picture, opt: DrawPictureOpt): void
Draws a picture to the screen. This function can not be used to draw recursively to a picture.
`param`pictureThe picture to draw
`param`optDrawing options
# [drawPolygon](#drawPolygon)(opt: DrawPolygonOpt): void
Draw a convex polygon from a list of vertices.
`param`opt- The draw polygon options.
``` js
drawPolygon({
pts: [
vec2(-12),
vec2(0, 16),
vec2(12, 4),
vec2(0, -2),
vec2(-8),
],
pos: vec2(100, 200),
color: rgb(0, 0, 255),
});
```
`since`v3000.0
# [drawRect](#drawRect)(opt: DrawRectOpt): void
Draw a rectangle.
`param`opt- The draw rect options.
``` js
drawRect({
width: 120,
height: 240,
pos: vec2(20, 20),
color: YELLOW,
outline: { color: BLACK, width: 4 },
});
```
`since`v2000.0
# [drawSprite](#drawSprite)(opt: DrawSpriteOpt): void
Draw a sprite.
`param`opt- The draw sprite options.
``` js
drawSprite({
sprite: "bean",
pos: vec2(100, 200),
frame: 3,
});
```
`since`v2000.0
# [drawSubtracted](#drawSubtracted)(content: ()=\>void, mask: ()=\>void): void
Subtract whatever drawn in content by whatever drawn in mask (mask will not be rendered).
`since`v3000.0
# [drawText](#drawText)(opt: DrawTextOpt): void
Draw a piece of text.
`param`opt- The draw text options.
``` js
drawText({
text: "oh hi",
size: 48,
font: "sans-serif",
width: 120,
pos: vec2(100, 200),
color: rgb(0, 0, 255),
});
```
`since`v2000.0
# [drawTriangle](#drawTriangle)(opt: DrawTriangleOpt): void
Draw a triangle.
`param`opt- The draw triangle options.
``` js
drawTriangle({
p1: vec2(0),
p2: vec2(0, height()),
p3: mousePos(),
pos: vec2(100, 200),
color: rgb(0, 0, 255),
});
```
`since`v3001.0
# [drawUVQuad](#drawUVQuad)(opt: DrawUVQuadOpt): void
Draw a rectangle with UV data.
`param`opt- The draw rect with UV options.
`since`v2000.0
# [drawon](#drawon)(canvas: FrameBuffer \| Picture, opt?: DrawonOpt): DrawonComp
Specifies the FrameBuffer the object should be drawn on.
`param`canvas- The FrameBuffer to draw on.
``` js
// Draw on another canvas
let canvas = makeCanvas(width(), height());
let beanOnCanvas = add([
sprite("bean"),
drawon(canvas.fb),
]);
```
`returns`The drawon comp.
`since`v3000.0
# [dt](#dt)(): number
Get the delta time since last frame.
``` js
// rotate bean 100 deg per second
bean.onUpdate(() => {
bean.angle += 100 * dt()
})
```
`since`v2000.0
# [easingCubicBezier](#easingCubicBezier)(p1: Vec2, p2: Vec2): number
Bezier easing. Both control points need x to be within 0 and 1.
`since`v3001.0
# [easingLinear](#easingLinear)(keys: Vec2\[\]): number
Linear easing with keyframes
`since`v3001.0
# [easingSteps](#easingSteps)(steps: number, position: StepPosition): number
Steps easing. Eases in discontinious steps.
`since`v3001.0
# [easings](#easings): Record\<EaseFuncs, EaseFunc\>
A collection of easing functions for tweening.
`since`v3000.0
# [Ellipse](#Ellipse): Ellipse
A ellipse shape.
`since`v3001.0
# [endPicture](#endPicture)(): Picture
Deselects the current picture for drawing, returning the picture.
`returns`The picture which was previously selected.
# [evaluateBezier](#evaluateBezier)(pt1: Vec2, pt2: Vec2, pt3: Vec2, pt4: Vec2, t: number): Vec2
Evaluate the cubic Bezier at the given t
`since`v3001.0
# [evaluateBezierFirstDerivative](#evaluateBezierFirstDerivative)(pt1: Vec2, pt2: Vec2, pt3: Vec2, pt4: Vec2, t: number): Vec2
Evaluate the first derivative of a cubic Bezier at the given t
# [evaluateBezierSecondDerivative](#evaluateBezierSecondDerivative)(pt1: Vec2, pt2: Vec2, pt3: Vec2, pt4: Vec2, t: number): Vec2
Evaluate the second derivative of a cubic bezier at the given t
`since`v3001.0
# [evaluateCatmullRom](#evaluateCatmullRom)(pt1: Vec2, pt2: Vec2, pt3: Vec2, pt4: Vec2, t: number): Vec2
Evaluate the Catmull-Rom spline at the given t
`since`v3001.0
# [evaluateCatmullRomFirstDerivative](#evaluateCatmullRomFirstDerivative)(pt1: Vec2, pt2: Vec2, pt3: Vec2, pt4: Vec2, t: number): Vec2
Evaluate the first derivative of a Catmull-Rom spline at the given t
`since`v3001.0
# [evaluateQuadratic](#evaluateQuadratic)(pt1: Vec2, pt2: Vec2, pt3: Vec2, t: number): Vec2
Evaluate the quadratic Bezier at the given t
# [evaluateQuadraticFirstDerivative](#evaluateQuadraticFirstDerivative)(pt1: Vec2, pt2: Vec2, pt3: Vec2, t: number): Vec2
Evaluate the first derivative of a quadratic bezier at the given t
`since`v3001.0
# [evaluateQuadraticSecondDerivative](#evaluateQuadraticSecondDerivative)(pt1: Vec2, pt2: Vec2, pt3: Vec2, t: number): Vec2
Evaluate the second derivative of a quadratic bezier at the given t
`since`v3001.0
# [fadeIn](#fadeIn)(time: number): Comp
`deprecated`since v3001.0
`requires`
`returns`An empty comp.
`since`v3000.0
# [fakeMouse](#fakeMouse)(opt?: FakeMouseOpt): FakeMouseComp
A fake mouse that follows the mouse position and triggers events. \[Guide about fake mouse\](https://v4000.kaplayjs.com/guides/fake_mouse/)
`param`opt- Options for the fake mouse comp. See
`returns`The fake mouse comp.
`since`v3001.0
# [fixed](#fixed)(): FixedComp
Make a game obj unaffected by camera or parent object transforms, and render at last. Useful for UI elements.
``` js
// this will be be fixed on top left and not affected by camera
const score = add([
text(0),
pos(12, 12),
fixed(),
])
```
`returns`The fixed comp.
`since`v2000.0
# [fixedDt](#fixedDt)(): number
Get the fixed delta time since last frame.
`since`v3000.0
# [flash](#flash)(flashColor: Color, fadeOutTime: number): TimerController
Camera flash.
`param`flashColor- The color of the flash.
`param`fadeOutTime- The time it takes for the flash to fade out.
``` js
onClick(() => {
// flashed
flash(WHITE, 0.5);
});
```
`returns`A timer controller.
`since`v3001.0
# [follow](#follow)(obj: GameObj \| null, offset?: Vec2): FollowComp
Follow another game obj's position.
`param`obj- The game obj to follow.
`param`offset- The offset to follow at.
``` js
const bean = add(...)
add([
sprite("bag"),
pos(),
follow(bean) // Follow bean's position
]);
// Using offset
const target = add(...)
const mark = add([
sprite("mark"),
pos(),
follow(target, vec2(32, 32)) // Follow target's position with an offset
])
mark.follow.offset = vec2(64, 64) // Change the offset
```
`returns`The follow comp.
`since`v2000.0
# [formatText](#formatText)(options: DrawTextOpt): FormattedText
Format a piece of text without drawing (for getting dimensions, etc).
``` js
// text background
const txt = formatText({
text: "oh hi",
});
drawRect({
width: txt.width,
height: txt.height,
});
drawFormattedText(txt);
```
`returns`The formatted text object.
`since`v2000.2
# [get](#get)\<T\>(tag: Tag \| Tag\[\], opts?: GetOpt): GameObj\[\]
Get a list of all game objs with certain tag.
`param`tag- The tag to search for. Use \"\*\" to get all objects.
`param`opts- Additional options.
``` js
// get a list of all game objs with tag "bomb"
const allBombs = get("bomb");
// To get all objects use "*"
const allObjs = get("*");
// Recursively get all children and descendents
const allObjs = get("*", { recursive: true });
// Get a live query which updates in real-time
const allObjs = get("*", { liveUpdate: true });
```
`returns`A list of game objects that have the tag.
`since`v2000.0
# [getAsset](#getAsset)(name: string): Asset \| null
Get custom data from name.
`param`name- The asset name.
`returns`The asset data.
`since`v3000.0
# [getBackground](#getBackground)(): Color \| null
Get background color.
`returns`The background color.
`since`v3000.0
# [getBitmapFont](#getBitmapFont)(name: string): Asset \| null
Get BitmapFontData from name.
`param`name- The asset name.
`returns`The asset data.
`since`v3000.0
# [getButton](#getButton)(btn: TypeOperator): ButtonBinding
Get a input binding from a button name.
`param`btn- The button to get binding for.
`since`v3001.0
# [getCamPos](#getCamPos)(): Vec2
Get camera position.
`returns`The current camera position.
`since`v3001.1
# [getCamRot](#getCamRot)(): number
Get camera rotation.
`returns`The current camera rotation.
`since`v3001.1
# [getCamScale](#getCamScale)(): Vec2
Get camera scale.
`returns`The current camera scale.
`since`v3001.1
# [getCamTransform](#getCamTransform)(): Mat23
Get camera transform.
`returns`The current camera transform.
`since`v3001.1
# [getCursor](#getCursor)(): Cursor
Get current cursor style.
`returns`The current cursor style.
`since`v2000.0
# [getData](#getData)\<T\>(key: string, def?: T): T \| null
Get data from local storage, if not present can set to a default value.
`param`key- The key to get data from.
`param`def- The default value to set if not found.
`returns`The data or null if not found.
`since`v2000.0
# [getDefaultLayer](#getDefaultLayer)(): string \| null
Get the default layer name.
`returns`The default layer name or null if not set.
`since`v3001.0.5
`experimental`This feature is in experimental phase, it will be fully released in v3001.1
# [getFont](#getFont)(name: string): Asset \| null
Get FontData from name.
`param`name- The asset name.
`returns`The asset data.
`since`v3000.0
# [getGamepadStick](#getGamepadStick)(stick: GamepadStick): Vec2
Get stick axis values from a gamepad.
`param`stick- The stick to get values from.
`returns`The stick axis Vec2.
`since`v3001.0
# [getGamepads](#getGamepads)(): KGamepad\[\]
Get connected gamepads.
`returns`An array of connected gamepads.
`since`v3000.0
# [getGravity](#getGravity)(): number
Get gravity.
`since`v3001.0
# [getGravityDirection](#getGravityDirection)(): Vec2
Get gravity direction.
`returns`The gravity direction.
`since`v3001.0
# [getLastInputDeviceType](#getLastInputDeviceType)(): ButtonBindingDevice \| null
Get the latest input device type that triggered the input event.
`returns`The last input device type, or null if no input event has been triggered.
`since`v3001.0
# [getLayers](#getLayers)(): string\[\] \| null
Get the layer names.
`returns`The layer names or null if not set.
`since`v3001.1
`experimental`This feature is in experimental phase, it will be fully released in v3001.1
# [getSceneName](#getSceneName)(): string \| null
Gets the name of the current scene. Returns null if no scene is active.
`since`v3001.0
# [getShader](#getShader)(name: string): Asset \| null
Get ShaderData from name.
`param`name- The asset name.
`returns`The asset data.
`since`v3000.0
# [getSound](#getSound)(name: string): Asset \| null
Get SoundData from name.
`param`name- The asset name.
`returns`The asset data.
`since`v3000.0
# [getSprite](#getSprite)(name: string): Asset \| null
Get SpriteData from name.
`param`name- The asset name.
`returns`The asset data.
`since`v3000.0
# [getTreeRoot](#getTreeRoot)(): GameObj
Get the root of all objects.
`returns`The root object.
`since`v2000.0
# [getVolume](#getVolume)(): number
Get the global volume.
`returns`The current volume.
`since`v3001.1
# [gjkShapeIntersection](#gjkShapeIntersection)(shapeA: Shape, shapeB: Shape): GjkCollisionResult \| null
`since`v4000.0
# [gjkShapeIntersects](#gjkShapeIntersects)(shapeA: Shape, shapeB: Shape): boolean
`since`v4000.0
# [go](#go)(name: SceneName, args: any): void
Go to a scene, passing all rest args to scene callback.
`param`name- The scene name.
`param`args- The rest args to pass to the scene callback.
``` js
// go to "game" scene
go("game");
// go with options
go("game", { level: 1 });
```
`since`v2000.0
# [health](#health)(hp: number, maxHP?: number): HealthComp
Handles health related logic and events.
`param`hp- The initial health points.
`param`maxHP- The maximum health points.
``` js
const player = add([
health(3),
])
player.onCollide("bad", (bad) => {
player.hurt(1)
bad.hurt(1)
})
player.onCollide("apple", () => {
player.heal(1)
})
player.on("hurt", () => {
play("ouch")
})
// triggers when hp reaches 0
player.on("death", () => {
destroy(player)
go("lose")
})
```
`returns`The health comp.
`since`v2000.0
# [height](#height)(): number
Get the height of game.
`returns`The height of the game.
`since`v2000.0
# [hermite](#hermite)(pt1: number, m1: number, m2: number, pt2: number): number
A second order function returning an evaluator for the given 1D Hermite curve
`param`pt1- First point
`param`m1- First control point (tangent)
`param`m2- Second control point (tangent)
`param`pt2- Second point
`returns`A function which gives the value on the 1D Hermite curve at t
# [hsl2rgb](#hsl2rgb)(hue: number, saturation: number, lightness: number): Color
Convert HSL color (all values in 0.0 - 1.0 range) to RGB color.
`param`hue- The hue value.
`param`saturation- The saturation value.
`param`lightness- The lightness value.
``` js
// animate rainbow color
onUpdate("rainbow", (obj) => {
obj.color = hsl2rgb(wave(0, 1, time()), 0.6, 0.6);
});
```
`returns`The color.
`since`v2000.1
# [isButtonDown](#isButtonDown)(btn?: TButton \| TButton\[\]): boolean
If any or certain bound button(s) are currently held down on any input (keyboard, gamepad).
`param`btn- The button(s) to check.
``` js
onUpdate(() => {
if (!isButtonDown()) return // early return as no button is held down
if (isButtonDown("jump")) debug.log("Player is jumping")
if (isButtonDown(["left", "right"])) debug.log("Player is moving")
})
```
`since`v3001.0
# [isButtonPressed](#isButtonPressed)(btn?: TButton \| TButton\[\]): boolean
If any or certain bound button(s) are just pressed last frame on any input (keyboard, gamepad).
`param`btn- The button(s) to check.
``` js
onUpdate(() => {
if (!isButtonPressed()) return // early return as no button was pressed
if (isButtonPressed("jump")) debug.log("Player jumped")
if (isButtonPressed(["left", "right"])) debug.log("Player moved")
})
```
`since`v3001.0
# [isButtonReleased](#isButtonReleased)(btn?: TButton \| TButton\[\]): boolean
If any or certain bound button(s) are just released last frame on any input (keyboard, gamepad).
`param`btn- The button(s) to check.
``` js
onUpdate(() => {
if (!isButtonReleased()) return // early return as no button was released
if (isButtonReleased("jump")) debug.log("Player stopped jumping")
if (isButtonReleased(["left", "right"])) debug.log("Player stopped moving")
})
```
`since`v3001.0
# [isConvex](#isConvex)(pts: Vec2\[\]): boolean
`returns`true if the given polygon is convex
`since`v3001.0
# [isCursorLocked](#isCursorLocked)(): boolean
Get if cursor is currently locked.
`returns`true if locked, false otherwise.
`since`v2000.0
# [isFocused](#isFocused)(): boolean
If the game canvas is currently focused.
`returns`true if focused.
`since`v2000.1
# [isFullscreen](#isFullscreen)(): boolean
If currently in fullscreen mode.
`returns`true if fullscreen, false otherwise.
`since`v2000.0
# [isGamepadButtonDown](#isGamepadButtonDown)(btn?: KGamepadButton \| KGamepadButton): boolean
If certain gamepad buttons are currently held down.
`param`btn- The button(s) to check.
`since`v3000.0
# [isGamepadButtonPressed](#isGamepadButtonPressed)(btn?: KGamepadButton \| KGamepadButton\[\]): boolean
If certain gamepad buttons are just pressed last frame
`param`btn- The button(s) to check.
`since`v3000.0
# [isGamepadButtonReleased](#isGamepadButtonReleased)(btn?: KGamepadButton \| KGamepadButton\[\]): boolean
If certain gamepad buttons are just released last frame.
`param`btn- The button(s) to check.
`since`v3000.0
# [isKeyDown](#isKeyDown)(k?: Key \| Key\[\]): boolean
If any or certain key(s) are currently down.
`param`k- The key(s) to check.
``` js
// Any key down
let lastKeyTime = time()
let triedToWakeUp = false
onUpdate(() => {
if (isKeyDown()) {
lastKeyTime = time()
triedToWakeUp = false
return
}
if (triedToWakeUp || time() - lastKeyTime < 5) return
debug.log("Wake up!")
triedToWakeUp = true
})
// Certain key down
// equivalent to the calling bean.move() in an onKeyDown("left")
onUpdate(() => {
if (isKeyDown("left")) {
bean.move(-SPEED, 0)
}
})
// Certain keys down
let isMoving = false
onUpdate(() => {
isMoving = isKeyDown(["left", "right"])
})
```
`since`v2000.0
# [isKeyPressed](#isKeyPressed)(k?: Key \| Key\[\]): boolean
If any or certain key(s) are just pressed last frame.
`param`k- The key(s) to check.
``` js
onUpdate(() => {
if (!isKeyPressed()) return // early return as no key was pressed
if (isKeyPressed("space")) debug.log("Pressed the jump key")
if (isKeyPressed(["left", "right"])) debug.log("Pressed any of the move keys")
})
```
`since`v2000.0
# [isKeyPressedRepeat](#isKeyPressedRepeat)(k?: Key \| Key\[\]): boolean
If any or certain key(s) are just pressed last frame (also fires repeatedly when the keys are being held down).
`param`k- The key(s) to check.
``` js
let heldKeys = new Set()
onUpdate(() => {
if (isKeyPressedRepeat("space")) {
pressedOrHeld(["space"], 'the jump key')
} else if (isKeyPressedRepeat(["left", "right"])) {
pressedOrHeld(["left", "right"], 'any of the move keys')
} else if (isKeyPressedRepeat()) {
pressedOrHeld(["any"], 'any key')
}
})
onKeyRelease((key) => wait(0.1, () => {
heldKeys.delete(key)
heldKeys.delete("any")
}))
// log message if pressed only or held as well
function pressedOrHeld(keys, string) {
debug.log(`Pressed${keys.some(key => heldKeys.has(key)) ? ' and held' : ''} ${string}`)
keys.forEach((key) => {
if (key == "any" || isKeyDown(key)) heldKeys.add(key)
})
}
```
`since`v2000.0
# [isKeyReleased](#isKeyReleased)(k?: Key \| Key\[\]): boolean
If any or certain key(s) are just released last frame.
`param`k- The key(s) to check.
``` js
onUpdate(() => {
if (!isKeyReleased()) return // early return as no key was released
if (isKeyReleased("space")) debug.log("Released the jump key")
if (isKeyReleased(["left", "right"])) debug.log("Released any of the move keys")
})
```
`since`v2000.0
# [isMouseDown](#isMouseDown)(btn?: MouseButton \| MouseButton\[\]): boolean
If mouse buttons are currently down.
`param`btn- The button(s) to check.
`since`v2000.0
# [isMouseMoved](#isMouseMoved)(): boolean
If mouse moved last frame.
`since`v2000.1
# [isMousePressed](#isMousePressed)(btn?: MouseButton \| MouseButton\[\]): boolean
If mouse buttons are just clicked last frame
`param`btn- The button(s) to check.
`since`v2000.0
# [isMouseReleased](#isMouseReleased)(btn?: MouseButton \| MouseButton\[\]): boolean
If mouse buttons are just released last frame.
`param`btn- The button(s) to check.
`since`v2000.0
# [isTouchscreen](#isTouchscreen)(): boolean
Is currently on a touch screen device.
`returns`true if on a touch screen device.
`since`v3000.0
# [kochanekBartels](#kochanekBartels)(pt1: Vec2, pt2: Vec2, pt3: Vec2, pt4: Vec2, tension: number, continuity: number, bias: number): Vec2
A second order function returning an evaluator for the given 2D Kochanek--Bartels curve
`param`pt1- Previous point
`param`pt2- First point
`param`pt3- Second point
`param`pt4- Next point
`param`tension- The tension of the curve, \[-1..1\] from round to tight.
`param`continuity- The continuity of the curve, \[-1..1\] from box corners to inverted corners.
`param`bias- The bias of the curve, \[-1..1\] from pre-shoot to post-shoot.
`returns`A function which gives the value on the 2D Kochanek--Bartels curve at t
# [layer](#layer)(name: string): LayerComp
Determines the layer for objects. Object will be drawn on top if the layer index is higher.
`param`name- The layer name to set.
``` js
// Define layers
layers(["background", "game", "foreground"], "game")
const bean = add([
sprite("bean"),
pos(100, 100),
layer("background"),
])
// Mark is in a higher layer, so he will be drawn on top of bean
const mark = add([
sprite("mark"),
pos(100, 100),
layer("game"),
])
bean.layer("foreground") // Bean is now in the foreground layer and will be drawn on top of mark
```
`returns`The layer comp.
`since`v3001.0
# [layers](#layers)(layers: string\[\], defaultLayer: string): void
`param`layers- The layer names.
`param`defaultLayer- The default layer name.
`deprecated`Use
``` js
setLayers(["bg", "obj", "ui"], "obj")
// no layer specified, will be added to "obj"
add([
sprite("bean"),
]);
// add to "bg" layer
add([
sprite("bg"),
layer("bg"),
]);
```
`since`v3001.0
# [lerp](#lerp)\<V\>(from: V, to: V, t: number): V
Linear interpolation. Can take a number, vector, or color.
# [level](#level)(map: string\[\], opt?: LevelOpt): LevelComp
Construct a level based on symbols.
`param`map- The map data.
`param`opt- The level options.
`param`unknown- The parent object of the level. Defaults to root.
``` js
const myLevel = add([
level([
" $",
" $",
" $$ = $",
" % ==== = $",
" = ",
" ^^ = > = &",
"===========================",
], {
// define the size of tile block
tileWidth: 32,
tileHeight: 32,
// define what each symbol means, by a function returning a component list (what will be passed to add())
tiles: {
"=": () => [
sprite("floor"),
area(),
body({ isStatic: true }),
],
"$": () => [
sprite("coin"),
area(),
pos(0, -9),
],
"^": () => [
sprite("spike"),
area(),
"danger",
],
}
})
])
```
`returns`A game obj with the level.
`since`v4000.0
# [lifespan](#lifespan)(time: number, options?: LifespanCompOpt): EmptyComp
Destroy the game obj after certain amount of time
`param`time- The time to live.
`param`options- Options for the lifespan component. See
``` js
// spawn an explosion, destroy after 1.5 seconds (time + fade)
add([
sprite("explosion", { anim: "burst", }),
lifespan(1, {
fade: 0.5 // it start fading 0.5 second after time
}),
]);
```
`returns`The lifespan comp.
`since`v2000.0
# [load](#load)\<T\>(l: Promise): Asset\<T\>
Add a new loader to wait for before starting the game.
`param`l- The loader to wait for.
``` js
load(new Promise((resolve, reject) => {
// anything you want to do that stalls the game in loading state
resolve("ok")
}))
```
`returns`The asset data.
`since`v3000.0
# [loadAseprite](#loadAseprite)(name: string \| null, imgSrc: LoadSpriteSrc, jsonSrc: string \| AsepriteData): Asset\<SpriteData\>
Load a sprite with aseprite spritesheet json (should use \"array\" in the export options and have tags enabled, that way kaplay can load tagged frames as animations).
`param`name- The asset name.
`param`imgSrc- The image resource url.
``` js
loadAseprite("car", "sprites/car.png", "sprites/car.json")
```
`returns`The asset data.
`since`v2000.0
# [loadBean](#loadBean)(name?: string): Asset\<SpriteData\>
Load default sprite \"bean\".
`param`name- An optional name for bean.
``` js
loadBean();
// use it right away
add([
sprite("bean"),
]);
```
`returns`The asset data.
`since`v2000.0
# [loadBitmapFont](#loadBitmapFont)(name: string \| null, src: string, gridW: number, gridH: number, opt?: LoadBitmapFontOpt): Asset\<BitmapFontData\>
Load a bitmap font into asset manager, with name and resource url and information on the layout of the bitmap.
`param`name- The asset name.
`param`src- The resource url.
`param`gridW- The width of each character on the bitmap.
`param`gridH- The height of each character on the bitmap.
`param`opt- The options for the bitmap font.
``` js
// load a bitmap font called "04b03", with bitmap "fonts/04b03.png"
// each character on bitmap has a size of (6, 8), and contains default ASCII_CHARS
loadBitmapFont("04b03", "fonts/04b03.png", 6, 8);
// load a font with custom characters
loadBitmapFont("myfont", "myfont.png", 6, 8, { chars: "☺☻♥♦♣♠" });
```
`returns`The asset data.
`since`v3000.0
# [loadFont](#loadFont)(name: string, src: string \| ArrayBuffer \| ArrayBufferView, opt?: LoadFontOpt): Asset\<FontData\>
Load a font (any format supported by the browser, e.g. ttf, otf, woff).
`param`name- The asset name.
``` js
// load a font from a .ttf file
loadFont("frogblock", "fonts/frogblock.ttf");
```
`returns`The asset data.
`since`v3000.0
# [loadHappy](#loadHappy)(name?: string, opt?: LoadBitmapFontOpt): Asset\<BitmapFontData\>
Load default font \"happy\".
`param`name- An optional name for happy.
``` js
loadHappy();
add([
text("ohhi", { font: "happy" }),
]);
```
# [loadJSON](#loadJSON)(name: string \| null, url: string): Asset\<any\>
Load custom JSON data from url.
`param`name- The asset name.
`param`url- The resource url.
`returns`The asset data.
`since`v3000.0
# [loadMusic](#loadMusic)(name: string \| null, url: string): void
Like loadSound(), but the audio is streamed and won't block loading. Use this for big audio files like background music.
`param`name- The asset name.
`param`url- The resource url.
``` js
loadMusic("shoot", "/music/bossfight.mp3");
```
`returns`The asset data.
`since`v3001.0
# [loadPedit](#loadPedit)(name: string \| null, src: string): Asset\<SpriteData\>
`param`name- The asset name.
`param`src- The resource url. Load .pedit file.
`deprecated`The format is not supported anymore.
`returns`The asset data.
`since`v2000.0
# [loadProgress](#loadProgress)(): number
Get the global asset loading progress (0.0 - 1.0).
`returns`The loading progress.
`since`v3000.0
# [loadRoot](#loadRoot)(path?: string): string
Sets the root for all subsequent resource urls. This is useful when you want to load assets from a different domain, or setup a base path for all assets.
`param`path- The root path.
``` js
loadRoot("https://myassets.com/");
loadSprite("bean", "sprites/bean.png"); // will resolve to "https://myassets.com/sprites/bean.png"
loadRoot("./"); // useful for Itch.io
```
# [loadShader](#loadShader)(name: string \| null, vert?: string \| null, frag?: string \| null): Asset\<ShaderData\>
Load a shader with vertex and fragment code.
`param`name- The asset name.
`param`vert- The vertex shader code. Null if not needed.
`param`frag- The fragment shader code. Null if not needed.
``` js
// default shaders and custom shader format
loadShader("outline",
`vec4 vert(vec2 pos, vec2 uv, vec4 color) {
// predefined functions to get the default value by KAPLAY
return def_vert();
}`,
`vec4 frag(vec2 pos, vec2 uv, vec4 color, sampler2D tex) {
// turn everything blue-ish
return def_frag() * vec4(0, 0, 1, 1);
}`, false)
```
`returns`The asset data.
`since`v2000.0
# [loadShaderURL](#loadShaderURL)(name: string \| null, vert?: string \| null, frag?: string \| null): Asset\<ShaderData\>
Load a shader with vertex and fragment code file url.
`param`name- The name of the asset.
`param`vert- The vertex shader code. Null if not needed.
`param`frag- The fragment shader code. Null if not needed.
``` js
// load only a fragment shader from URL
loadShaderURL("outline", null, "/shaders/outline.glsl")
```
`retunrs`The asset data.
`since`v3000.0
# [loadSound](#loadSound)(name: string \| null, src: string \| ArrayBuffer \| AudioBuffer): Asset\<SoundData\>
Load a sound into asset manager, with name and resource url. Supported formats: mp3, ogg, wav.
`param`name- The asset name.
`param`src- The resource url.
``` js
loadSound("shoot", "/sounds/horse.ogg");
loadSound("shoot", "/sounds/squeeze.mp3");
loadSound("shoot", "/sounds/shoot.wav");
```
`returns`The asset data.
`since`v2000.0
# [loadSprite](#loadSprite)(name: string \| null, src: LoadSpriteSrc \| LoadSpriteSrc\[\], opt?: LoadSpriteOpt): Asset\<SpriteData\>
Load a sprite into asset manager, with name and resource url and optional config.
`param`name- The asset name.
`param`src- The resource url.
`param`opt- The optional config.
``` js
// due to browser policies you'll need a static file server to load local files
loadSprite("bean", "bean.png");
loadSprite("apple", "https://play.kaplayjs.com/sprites/apple.png");
// slice a spritesheet and add anims manually
loadSprite("bean", "bean.png", {
sliceX: 4,
sliceY: 1,
anims: {
run: {
from: 0,
to: 3,
},
jump: {
from: 3,
to: 3,
},
},
});
```
`returns`The asset data.
`since`v2000.0
# [loadSpriteAtlas](#loadSpriteAtlas)(src: LoadSpriteSrc, data: SpriteAtlasData): Asset\<Record\>
Load sprites from a sprite atlas.
`param`src- The image resource url.
`param`data- The sprite atlas data.
``` js
// See #SpriteAtlasData type for format spec
loadSpriteAtlas("sprites/dungeon.png", {
"hero": {
x: 128,
y: 68,
width: 144,
height: 28,
sliceX: 9,
anims: {
idle: { from: 0, to: 3 },
run: { from: 4, to: 7 },
hit: 8,
},
},
});
const player = add([
sprite("hero"),
]);
player.play("run");
```
`returns`The asset data.
`since`v2000.0
# [loadSpriteAtlas](#loadSpriteAtlas)(src: LoadSpriteSrc, url: string): Asset\<Record\>
Load sprites from a sprite atlas with URL.
`param`src- The image resource url.
`param`url- The json resource url.
``` js
// Load from json file, see #SpriteAtlasData type for format spec
loadSpriteAtlas("sprites/dungeon.png", "sprites/dungeon.json")
const player = add([
sprite("hero"),
])
player.play("run")
```
`returns`The asset data.
`since`v2000.0
# [loop](#loop)(t: number, action: ()=\>void, maxLoops?: number, waitFirst?: boolean): TimerController
Run the function every n seconds.
`param`t- The time to wait in seconds.
`param`action- The function to run.
`param`maxLoops- The maximum number of loops to run. If not provided, it will run forever.
`param`waitFirst- Whether to wait for the first loop to start.
``` js
// spawn a butterfly at random position every 1 second
loop(1, () => {
add([
sprite("butterfly"),
pos(rand(vec2(width(), height()))),
area(),
"friend",
])
})
```
`returns`A timer controller.
`since`v2000.0
# [makeCanvas](#makeCanvas)(w: number, h: number): Canvas
Create a canvas to draw stuff offscreen.
`returns`The canvas object.
`since`v3001.0
# [map](#map)(v: number, l1: number, h1: number, l2: number, h2: number): number
Map a value from one range to another range. If the value overshoots, the source range, the result values will also do. For clamping check mapc
`param`vThe value the function will depend on.
`param`l1The minimum value of the source range.
`param`h1The minimum result value.
`param`l2The maximum value of the source range.
`param`h2The maximum result value.
``` js
onUpdate(() => {
// Redness will be 0 when the mouse is at the left edge and 255 when the mouse is at the right edge
const redness = map(mousePos().x, 0, width(), 0, 255)
setBackground(rgb(redness, 0, 0))
})
```
`returns`The result value based on the source value.
`since`v2000.0
# [mapc](#mapc)(v: number, l1: number, h1: number, l2: number, h2: number): number
Map a value from one range to another range, and clamp to the dest range.
`param`vThe value the function will depend on.
`param`l1The minimum value of the source range.
`param`h1The minimum result value.
`param`l2The maximum value of the source range.
`param`h2The maximum result value.
``` js
onUpdate(() => {
// This variable will be 0 when the mouse is at the left edge and 255 when the mouse is at the right edge
const redness = mapc(mousePos().x, 0, width(), 0, 255)
setBackground(rgb(redness, 0, 0))
})
```
`returns`The clamped result value based on the source value.
`since`v2000.0
# [mask](#mask)(maskType?: Mask): MaskComp
Mask all children object render.
`param`maskType- The type of mask to use.
`returns`The mask comp.
`since`v3001.0
# [mouseDeltaPos](#mouseDeltaPos)(): Vec2
How much mouse moved last frame.
`returns`The delta mouse position.
`since`v2000.0
# [mousePos](#mousePos)(): Vec2
Get current mouse position (without camera transform).
`returns`The current mouse position.
`since`v2000.0
# [move](#move)(dir: number \| Vec2, speed: number): EmptyComp
Move towards a direction infinitely, and destroys when it leaves game view.
`param`dir- The direction to move towards.
`param`speed- The speed to move at.
`requires`
``` js
// enemy throwing feces at player
const projectile = add([
sprite("feces"),
pos(enemy.pos),
area(),
move(player.pos.angle(enemy.pos), 1200),
offscreen({ destroy: true }),
])
```
`returns`The move comp.
`since`v2000.0
# [named](#named)(name: string): NamedComp
Names an game obj.
`param`name- The name to set.
`returns`The named comp.
`since`v3001.0
# [normalizedCurve](#normalizedCurve)(curve: (t: number)=\>Vec2): Vec2
Returns a new curve which is normalized. This new curve has constant speed curve is any curve in t (non-constant between 0 and 1) returns a curve in s (constant between 0 and 1)
`since`v3001.0
# [offscreen](#offscreen)(opt?: OffScreenCompOpt): OffScreenComp
Control the behavior of object when it goes out of view.
`param`opt- Options for the offscreen component. See
``` js
add([
pos(player.pos),
sprite("bullet"),
offscreen({ destroy: true }),
"projectile",
]);
```
`returns`The offscreen comp.
`since`v2000.2
# [on](#on)\<Ev\>(event: Ev, tag: Tag, action: (obj: GameObj, args: TupleWithoutFirst)=\>void): KEventController
Register an event on all game objs with certain tag.
`param`event- The tag to listen for.
`param`tag- The function to run when the event is triggered.
``` js
// a custom event defined by body() comp
// every time an obj with tag "bomb" hits the floor, destroy it and addKaboom()
on("ground", "bomb", (bomb) => {
destroy(bomb)
addKaboom(bomb.pos)
})
// a custom event can be defined manually
// by passing an event name, a tag, and a callback function
// if you want any tag, use a tag of "*"
on("talk", "npc", (npc, message) => {
npc.add([
text(message),
pos(0, -50),
lifespan(2),
opacity(),
])
});
onKeyPress("space", () => {
// the trigger method on game objs can be used to trigger a custom event
npc.trigger("talk", "Hello, KAPLAY!");
});
```
`returns`The event controller.
`since`v2000.0
# [onAdd](#onAdd)(tag: Tag, action: (obj: GameObj)=\>void): KEventController
Register an event that runs when an object with the provided tag is added.
`param`tag- The tag to listen for.
`param`action- The function that runs when an object is added.
``` js
// This will run when the object is added.
onAdd("player", () => {
debug.log("ohhi");
});
add([
pos(),
"player"
]);
```
`returns`The event controller.
`since`v2000.0
# [onAdd](#onAdd)(action: (obj: GameObj)=\>void): KEventController
Register an event that runs when an object is added
`param`action- The tag to match, only called for objects with a matching tag.
`param`unknown- The function that runs when an object is added.
``` js
// This will run when the object is added.
onAdd(() => {
debug.log("ohhi");
});
add([
pos(),
]);
```
`returns`The event controller.
`since`v2000.0
# [onButtonDown](#onButtonDown)(btn: TButton \| TButton\[\], action: (btn: TButton)=\>void): KEventController
Register an event that runs when user press a defined button (like \"jump\") on any input (keyboard, gamepad).
`param`btn- The button(s) to listen for.
`param`action- The function to run when the event is triggered.
`returns`The event controller.
`since`v3001.0
# [onButtonDown](#onButtonDown)(action: (btn: TButton)=\>void): KEventController
# [onButtonPress](#onButtonPress)(btn: TButton \| TButton\[\], action: (btn: TButton)=\>void): KEventController
Register an event that runs when user press a defined button (like \"jump\") on any input (keyboard, gamepad).
`param`btn- The button(s) to listen for.
`param`action- The function to run when the event is triggered.
`returns`The event controller.
`since`v3001.0
# [onButtonRelease](#onButtonRelease)(btn: TButton \| TButton\[\], action: (btn: TButton)=\>void): KEventController
Register an event that runs when user release a defined button (like \"jump\") on any input (keyboard, gamepad).
`param`btn- The button(s) to listen for.
`param`action- The function to run when the event is triggered.
`returns`The event controller.
`since`v3001.0
# [onButtonRelease](#onButtonRelease)(action: (btn: TButton)=\>void): KEventController
# [onCharInput](#onCharInput)(action: (ch: string)=\>void): KEventController
Register an event that runs when user inputs text.
`param`action- The function to run when the event is triggered.
``` js
// type into input
onCharInput((ch) => {
input.text += ch
})
```
`returns`The event controller.
`since`v2000.1
# [onCleanup](#onCleanup)(action: ()=\>void): void
Cleanup function to run when quit() is called.
`param`action- The function that runs when quit() is called.
``` js
// useful externally from KAPLAY
onCleanup(() => {
console.log(`ohbye :(`);
});
quit();
```
`returns`The event controller.
`since`v3000.0
# [onClick](#onClick)(tag: Tag, action: (a: GameObj)=\>void): KEventController
Register an event that runs when game objs with certain tags are clicked (required to have the area() component).
`param`tag- The tag to listen for.
`param`action- The function to run when the event is triggered.
``` js
// click on any "chest" to open
onClick("chest", (chest) => chest.open())
```
`returns`The event controller.
`since`v2000.1
# [onClick](#onClick)(action: ()=\>void): KEventController
Register an event that runs when users clicks.
`param`action- The function to run when the event is triggered.
``` js
// click on anywhere to go to "game" scene
onClick(() => go("game"));
```
`returns`The event controller.
`since`v2000.1
# [onCollide](#onCollide)(t1: Tag, t2: Tag, action: (a: GameObj, b: GameObj, col?: Collision)=\>void): KEventController
Register an event that runs once when 2 game objs with certain tags collides (required to have area() component).
`param`t1- The tag of the first game obj.
`param`t2- The tag of the second game obj.
`param`action- The function to run when the event is triggered.
``` js
onCollide("sun", "earth", () => {
addExplosion()
})
```
`returns`The event controller.
`since`v2000.1
# [onCollideEnd](#onCollideEnd)(t1: Tag, t2: Tag, action: (a: GameObj, b: GameObj, col?: Collision)=\>void): KEventController
Register an event that runs once frame when 2 game objs with certain tags stops colliding (required to have area() component).
`param`t1- The tag of the first game obj.
`param`t2- The tag of the second game obj.
`param`action- The function to run when the event is triggered.
``` js
onCollideEnd("bean", "earth", () => {
debug.log("destroying world in 3... 2... 1...")
});
```
`returns`The event controller.
`since`v3000.0
# [onCollideUpdate](#onCollideUpdate)(t1: Tag, t2: Tag, action: (a: GameObj, b: GameObj, col?: Collision)=\>void): KEventController
Register an event that runs every frame when 2 game objs with certain tags collides (required to have area() component).
`param`t1- The tag of the first game obj.
`param`t2- The tag of the second game obj.
`param`action- The function to run when the event is triggered.
``` js
onCollideUpdate("sun", "earth", () => {
debug.log("okay this is so hot");
})l
```
`returns`The event controller.
`since`v3000.0
# [onDestroy](#onDestroy)(tag: Tag, action: (obj: GameObj)=\>void): KEventController
Register an event that runs when an object with the provided tag is destroyed.
`param`tag- The function that runs when an object is destroyed.
``` js
// This will run when the tagged object is destroyed.
onDestroy("bean", () => {
debug.log("ohbye");
});
let player = add([
pos(),
"bean"
])
// Destroy the tagged object
destroy(player);
```
`returns`The event controller.
`since`v2000.0
# [onDestroy](#onDestroy)(action: (obj: GameObj)=\>void): KEventController
Register an event that runs when an object is destroyed.
`param`action- The tag to match, only called for objects with a matching tag.
`param`unknown- The function that runs when an object is destroyed.
``` js
// This will run when the object is destroyed.
onDestroy(() => {
debug.log("ohbye");
});
let ghosty = add([
pos(),
]);
// Destroy the object
destroy(ghosty);
```
`returns`The event controller.
# [onDraw](#onDraw)(tag: Tag, action: (obj: GameObj)=\>void): KEventController
Register an event that runs every frame (\~60 times per second) for all game objs with certain tag (this is the same as onUpdate but all draw events are run after update events, drawXXX() functions only work in this phase).
`param`tag- The tag to listen for.
`param`action- The function to run when the event is triggered.
`returns`The event controller.
`since`v2000.1
# [onDraw](#onDraw)(action: ()=\>void): KEventController
Register an event that runs every frame (\~60 times per second) (this is the same as onUpdate but all draw events are run after update events, drawXXX() functions only work in this phase).
``` js
onDraw(() => {
drawLine({
p1: vec2(0),
p2: mousePos(),
color: rgb(0, 0, 255),
})
})
```
`returns`The event controller.
`since`v2000.1
# [onError](#onError)(action: (err: Error)=\>void): KEventController
Register a custom error handler. Can be used to draw a custom error screen.
`param`action- The function that runs when the program errors.
``` js
// Create custom error handler
onError((err) => {
drawRect({
width: width(),
height: height(),
pos: center(),
color: RED,
anchor: `center,
});
drawText({
text: err.message,
size: 48,
width: width()/2,
anchor: `center`,
align: `center`,
pos: center(),
color: BLACK
});
});
// cause common error
let pos = add([
pos()
]);
```
`returns`The event controller.
`since`v3000.0
# [onFixedUpdate](#onFixedUpdate)(action: ()=\>void): KEventController
Register an event that runs at a fixed framerate.
`param`action- The function to run when the event is triggered.
`returns`The event controller.
`since`v3001.0
# [onFixedUpdate](#onFixedUpdate)(tag: Tag, action: (obj: GameObj)=\>void): KEventController
# [onGamepadButtonDown](#onGamepadButtonDown)(btn: KGamepadButton \| KGamepadButton\[\], action: (btn: KGamepadButton, gamepad: KGamepad)=\>void): KEventController
Register an event that runs every frame when certain gamepad buttons are held down.
`param`btn- The button(s) to listen for. See
`param`action- The function that is run while certain gamepad buttons are held down.
``` js
// when button is being held down
onGamepadButtonDown("rtrigger", (gp) => {
car.addForce(Vec2.fromAngle(car.angle).scale(10));
});
```
`returns`The event controller.
`since`v3001.0
# [onGamepadButtonDown](#onGamepadButtonDown)(action: (btn: KGamepadButton, gamepad: KGamepad)=\>void): KEventController
Register an event that runs every frame when any gamepad buttons are held down.
`param`action- The function that is run while any gamepad buttons are held down.
``` js
// when button is being held down
onGamepadButtonDown((btn, gp) => {
if (btn == "rtrigger") {
car.addForce(Vec2.fromAngle(car.angle).scale(10));
} else if (btn == "ltrigger") {
car.addForce(Vec2.fromAngle(car.angle).scale(-5));
}
});
```
`returns`The event controller.
`since`v3001.0
# [onGamepadButtonPress](#onGamepadButtonPress)(btn: KGamepadButton \| KGamepadButton\[\], action: (btn: KGamepadButton, gamepad: KGamepad)=\>void): KEventController
Register an event that runs when user presses certain gamepad button.
`param`btn- The button(s) to listen for. See
`param`action- The function that is run when certain gamepad buttons are pressed.
``` js
// when user presses button
onGamepadButtonPress("south", (btn, gp) => {
player.jump(200);
});
```
`returns`The event controller.
`since`v3001.0
# [onGamepadButtonPress](#onGamepadButtonPress)(action: (btn: KGamepadButton, gamepad: KGamepad)=\>void): KEventController
Register an event that runs when user presses any gamepad button.
`param`action- The function that is run when any gamepad buttons is pressed.
``` js
// when user presses button
onGamepadButtonPress((btn, gp) => {
if (btn == "south") {
player.jump(200); // jump
}
});
```
`returns`The event controller.
`since`v3001.0
# [onGamepadButtonRelease](#onGamepadButtonRelease)(btn: KGamepadButton \| KGamepadButton\[\], action: (btn: KGamepadButton, gamepad: KGamepad)=\>void): KEventController
Register an event that runs when user releases certain gamepad button
`param`btn- The button(s) to listen for. See
`param`action- The function that is run when certain gamepad buttons are released.
``` js
// charged attack
let chargeTime = 0
onGamepadButtonPress("west", (btn, gp) => {
chargeTime = time();
});
// when a gamepad button is released, this is run
onGamepadButtonRelease("west", (btn, gp) => {
let chargedt = time() - chargeTime;
debug.log(`Used ${chargedt * 1000} power!`);
});
```
`returns`The event controller.
`since`v3001.0
# [onGamepadButtonRelease](#onGamepadButtonRelease)(action: (btn: KGamepadButton, gamepad: KGamepad)=\>void): KEventController
Register an event that runs when user releases any gamepad button.
`param`action- The function that is run when any gamepad buttons are released.
``` js
// when a gamepad button is released, this is run
onGamepadButtonRelease((btn, gp) => {
if (btn == "north") {
player.jump(500);
}
});
```
`returns`The event controller.
`since`v3000.0
# [onGamepadConnect](#onGamepadConnect)(action: (gamepad: KGamepad)=\>void): KEventController
Register an event that runs when a gamepad is connected.
`param`action- The function that runs when quit() is called.
``` js
// watch for a controller connecting
onGamepadConnect((gp) => {
debug.log(`ohhi player ${gp.index + 1}`);
});
```
`returns`The event controller.
`since`v3000.0
# [onGamepadDisconnect](#onGamepadDisconnect)(action: (gamepad: KGamepad)=\>void): KEventController
Register an event that runs when a gamepad is disconnected.
`param`action- The function that runs when quit() is called.
``` js
// watch for a controller disconnecting
onGamepadDisconnect((gp) => {
debug.log(`ohbye player ${gp.index + 1}`);
});
```
`returns`The event controller.
`since`v3000.0
# [onGamepadStick](#onGamepadStick)(stick: GamepadStick, action: (value: Vec2, gameepad: KGamepad)=\>void): KEventController
Register an event that runs when the gamepad axis exists.
`param`stick- The stick to listen for. See
`param`action- The function that is run when a specific gamepad stick is moved.
``` js
// player move
let player = add([
pos(center()),
sprite(`bean`),
]);
// when left stick is moved
onGamepadStick("left", (stickVector, gp) => {
player.move(stickVector.x, 0);
});
```
`returns`The event controller.
`since`v3000.0
# [onHide](#onHide)(action: ()=\>void): KEventController
Register an event that runs when tab is hidden.
`param`action- The function that is run what the tab is hidden.
``` js
// spooky ghost
let ghosty = add([
pos(center()),
sprite("ghosty"),
anchor("center"),
]);
// when switching tabs, this runs
onHide(() => {
destroy(ghosty);
add([
text("There was never aa ghosttttt"),
pos(center()),
anchor("center")
]);
});
```
`returns`The event controller.
`since`v3001.0
# [onHover](#onHover)(tag: Tag, action: (a: GameObj)=\>void): KEventController
Register an event that runs once when game objs with certain tags are hovered (required to have area() component).
`param`tag- The tag to listen for.
`param`action- The function to run when the event is triggered.
`returns`The event controller.
`since`v3000.0
# [onHoverEnd](#onHoverEnd)(tag: Tag, action: (a: GameObj)=\>void): KEventController
Register an event that runs once when game objs with certain tags are unhovered (required to have area() component).
`param`tag- The tag to listen for.
`param`action- The function to run when the event is triggered.
`returns`The event controller.
`since`v3000.0
# [onHoverUpdate](#onHoverUpdate)(tag: Tag, action: (a: GameObj)=\>void): KEventController
Register an event that runs every frame when game objs with certain tags are hovered (required to have area() component).
`param`tag- The tag to listen for.
`param`action- The function to run when the event is triggered.
``` js
// Rotate bean 90 degrees per second when hovered
onHoverUpdate("bean", (bean) => {
bean.angle += dt() * 90
});
```
`returns`The event controller.
`since`v3000.0
# [onKeyDown](#onKeyDown)(key: Key \| Key\[\], action: (key: Key)=\>void): KEventController
Register an event that runs every frame when a key is held down.
`param`key- The key(s) to listen for.
`param`action- The function to run when the event is triggered.
``` js
// move left by SPEED pixels per frame every frame when left arrow key is being held down
onKeyDown("left", () => {
bean.move(-SPEED, 0)
});
```
`returns`The event controller.
`since`v2000.1
# [onKeyDown](#onKeyDown)(action: (key: Key)=\>void): KEventController
Register an event that runs every frame when any key is held down.
`param`action- The function to run when the event is triggered.
`returns`The event controller.
`since`v2000.1
# [onKeyPress](#onKeyPress)(key: Key \| Key\[\], action: (key: Key)=\>void): KEventController
Register an event that runs when user presses certain keys.
`param`key- The key(s) to listen for.
`param`action- The function to run when the event is triggered.
``` js
// .jump() once when "space" is just being pressed
onKeyPress("space", () => {
bean.jump();
});
onKeyPress(["up", "space"], () => {
bean.jump();
});
```
`returns`The event controller.
`since`v2000.1
# [onKeyPress](#onKeyPress)(action: (key: Key)=\>void): KEventController
Register an event that runs when user presses any key.
`param`action- The function to run when the event is triggered.
``` js
// Call restart() when player presses any key
onKeyPress((key) => {
debug.log(`key pressed ${key}`);
restart();
});
```
`returns`The event controller.
`since`v3001.0
# [onKeyPressRepeat](#onKeyPressRepeat)(k: Key \| Key\[\], action: (k: Key)=\>void): KEventController
Register an event that runs when user presses certain keys (also fires repeatedly when the keys are being held down).
`param`k- The key(s) to listen for.
`param`action- The function to run when the event is triggered.
``` js
// delete last character when "backspace" is being pressed and held
onKeyPressRepeat("backspace", () => {
input.text = input.text.substring(0, input.text.length - 1);
});
```
`returns`The event controller.
`since`v3000.1
# [onKeyPressRepeat](#onKeyPressRepeat)(action: (k: Key)=\>void): KEventController
# [onKeyRelease](#onKeyRelease)(k: Key \| Key\[\], action: (k: Key)=\>void): KEventController
Register an event that runs when user release certain keys.
`param`k= The key(s) to listen for. See
`param`action- The function that runs when a user releases certain keys
``` js
// release `a` or `b` keys
onKeyRelease([`a`, `b`], (k) => {
debug.log(`Released the ${k} key...`);
});
```
`returns`The event controller.
`since`v2000.1
# [onKeyRelease](#onKeyRelease)(action: (k: Key)=\>void): KEventController
Register an event that runs when user releases a key.
`param`action- The function that runs when a user releases a
``` js
// release a key
onKeyRelease((k) => {
debug.log(`Released the ${k} key...`);
});
```
`returns`The event controller.
`since`v2000.1
# [onLoad](#onLoad)(action: ()=\>void): KEventController \| undefined
Register an event that runs when all assets finished loading.
`param`action- The function to run when the event is triggered.
``` js
const bean = add([
sprite("bean"),
]);
// certain assets related data are only available when the game finishes loading
onLoad(() => {
debug.log(bean.width)
});
```
`returns`The event controller.
`since`v2000.1
# [onLoadError](#onLoadError)(action: (name: string, failedAsset: Asset)=\>void): KEventController \| undefined
Register an event that runs once for each asset that failed to load, after all others have completed.
`param`actionThe function to run when the event is triggered.
``` js
// this will not load
loadSprite("bobo", "notavalidURL");
// process the error
// you decide whether to ignore it, or throw an error and halt the game
onLoadError((name, asset) => {
debug.error(`${name} failed to load: ${asset.error}`);
});
```
`returns`The event controller.
`since`v3001.0
# [onLoading](#onLoading)(action: (progress: number)=\>void): KEventController
Register an event that runs every frame when assets are initially loading. Can be used to draw a custom loading screen.
`param`action- The function that runs when assets are loading.
```` js
```
// progress bar
onLoading((progress) => {
// Background of the bar
drawRect({
width: 240,
height: 40,
pos: center().add(-120,0),
color: BLACK,
anchor: `left,
});
// Progress of the bar
drawRect({
width: map(progress, 0, 1, 0, 220),
height: 32,
pos: center().add(-116, 0),
color: BLUE,
anchor: `left
});
});
````
`returns`The event controller.
`since`v3000.0
# [onMouseDown](#onMouseDown)(btn: MouseButton \| MouseButton\[\], action: (m: MouseButton)=\>void): KEventController
Register an event that runs every frame when certain mouse buttons are being held down.
`param`btn- The mouse button(s) to listen for. See
`param`action- The function that is run when certain mouse buttons are being held down.
``` js
// count time with left mouse button down
let mouseTime = 0;
onMouseDown("left", () => {
mouseTime += dt();
debug.log(`Time with mouse down: ${mouseTime});
});
```
`returns`The event controller.
`since`v3001.0
# [onMouseDown](#onMouseDown)(action: (m: MouseButton)=\>void): KEventController
Register an event that runs every frame when any mouse button is being held down.
`param`action- The function that is run when any mouse button is being held down.
``` js
// count time with any mouse button down
let mouseTime = 0;
onMouseDown((m) => {
mouseTime += dt();
});
```
`returns`The event controller.
`since`v3001.0
# [onMouseMove](#onMouseMove)(action: (pos: Vec2, delta: Vec2)=\>void): KEventController
Register an event that runs whenever user moves the mouse.
`param`action- The function that is run what the user moves the mouse.
``` js
// runs when the mouse has moved
onMouseMove((p, d) => {
bean.pos = p; // set bean position to mouse position
});
```
`returns`The event controller.
`since`v2000.1
# [onMousePress](#onMousePress)(action: (m: MouseButton)=\>void): KEventController
Register an event that runs when user clicks mouse.
`param`action- The function that is run when user clicks a mouse button.
``` js
// gives cookies on left press, remove on right press
let cookies = 0;
onMousePress(["left", "right"], (m) => {
if (m == "left") {
cookies++;
} else {
cookies--;
}
});
```
`returns`The event controller.
`since`v3001.0
# [onMousePress](#onMousePress)(btn: MouseButton \| MouseButton\[\], action: (m: MouseButton)=\>void): KEventController
Register an event that runs when user clicks mouse.
`param`btn- The mouse button(s) to listen for. See
`param`action- The function that is run what the user clicks cetain mouse buttons.
``` js
// gives cookies on any mouse press
let cookies = 0;
onMousePress((m) => {
cookies++;
debug.log(`Cookies: ${cookies}`);
});
```
`returns`The event controller.
`since`v3001.0
# [onMouseRelease](#onMouseRelease)(action: (m: MouseButton)=\>void): KEventController
Register an event that runs when user releases mouse.
`param`action- The function that is run what the user clicks a provided mouse button.
``` js
// spawn bean where right mouse is released
onMouseRelease("right", (m) => {
debug.log(`${m} released, spawning bean...`);
add([
pos(mousePos()),
sprite("bean"),
anchor("center"),
]);
});
```
`returns`The event controller.
`since`v3001.0
# [onMouseRelease](#onMouseRelease)(btn: MouseButton \| MouseButton\[\], action: (m: MouseButton)=\>void): KEventController
Register an event that runs when user releases mouse.
`param`btn- The button(s) to listen for. See
`param`action- The function that is run what the user clicks a provided mouse button.
``` js
// spawn bean where right mouse is released
onMouseRelease((m) => {
if (m == "right") {
debug.log(`${m} released, spawning bean...`);
add([
pos(mousePos()),
sprite("bean"),
anchor("center"),
]);
});
});
```
`returns`The event controller.
`since`v3001.0
# [onResize](#onResize)(action: ()=\>void): KEventController
Register an event that runs when the canvas resizes.
`param`action- The function that runs when the canvas resizes.
``` js
// create a rectangle with screen size
let rectangle = add([
rect(width(), height()),
color(GREEN),
]);
// resize the rectangle to screen size
onResize(() => {
debug.log(`Old Size: ${rectangle.width}x${rectangle.height}`);
rectangle.width = width();
rectangle.height = height();
debug.log(`New Size: ${rectangle.width}x${rectangle.height}`);
});
```
`returns`The event controller.
`since`v3000.0
# [onSceneLeave](#onSceneLeave)(action: (newScene?: string)=\>void): KEventController
Register an event that runs when current scene ends.
`param`action- The function to run when the event is triggered.
`returns`The event controller.
`since`v3000.0
# [onScroll](#onScroll)(action: (delta: Vec2)=\>void): KEventController
Register an event that runs when mouse wheel scrolled.
`param`action- The function to run when the event is triggered.
``` js
// Zoom camera on scroll
onScroll((delta) => {
const zoom = delta.y / 500;
camScale(camScale().add(zoom));
});
```
`returns`The event controller.
`since`v3000.0
# [onShow](#onShow)(action: ()=\>void): KEventController
Register an event that runs when tab is shown.
`param`action- The function that is run when the tab is shown.
``` js
// user has returned to this tab
onShow(() => {
burp();
});
```
`returns`The event controller.
`since`v3001.0
# [onTag](#onTag)(action: (obj: GameObj, tag: string)=\>void): KEventController
Register an event that runs when an object gains a tag.
`param`action- The function that runs when an object gains a tag.
`param`unknown- The tag which was added.
`returns`The event controller.
`since`v3001.1
# [onTouchEnd](#onTouchEnd)(action: (pos: Vec2, t: Touch)=\>void): KEventController
Register an event that runs when a touch ends.
`param`action- The function to run when the event is triggered.
`returns`The event controller.
`since`v2000.1
# [onTouchMove](#onTouchMove)(action: (pos: Vec2, t: Touch)=\>void): KEventController
Register an event that runs whenever touch moves.
`param`action- The function to run when the event is triggered.
`returns`The event controller.
`since`v2000.1
# [onTouchStart](#onTouchStart)(action: (pos: Vec2, t: Touch)=\>void): KEventController
Register an event that runs when a touch starts.
`param`action- The function to run when the event is triggered.
`returns`The event controller.
`since`v2000.1
# [onUntag](#onUntag)(action: (obj: GameObj, tag: string)=\>void): KEventController
Register an event that runs when an object loses a tag.
`param`action- The function that runs when an object loses a tag.
`param`unknown- The tag which was removed.
`returns`The event controller.
`since`v3001.1
# [onUnuse](#onUnuse)(action: (obj: GameObj, id: string)=\>void): KEventController
Register an event that runs when an object stops using a component.
`param`action- The function that runs when an object stops using a component.
`param`unknown- The id of the component that was removed.d
`returns`The event controller.
`since`v3001.1
# [onUpdate](#onUpdate)(tag: Tag, action: (obj: GameObj)=\>void): KEventController
Register an event that runs every frame (\~60 times per second) for all game objs with certain tag.
`param`tag- The tag to listen for.
`param`action- The function to run when the event is triggered.
``` js
// move every "tree" 120 pixels per second to the left, destroy it when it leaves screen
// there'll be nothing to run if there's no "tree" obj in the scene
onUpdate("tree", (tree) => {
tree.move(-120, 0)
if (tree.pos.x < 0) {
destroy(tree)
}
})
```
`returns`The event controller.
`since`v2000.1
# [onUpdate](#onUpdate)(action: ()=\>void): KEventController
Register an event that runs every frame (\~60 times per second).
`param`action- The function to run when the event is triggered.
``` js
// This will run every frame
onUpdate(() => {
debug.log("ohhi")
})
```
`returns`The event controller.
`since`v2000.1
# [onUse](#onUse)(action: (obj: GameObj, id: string)=\>void): KEventController
Register an event that runs when an object starts using a component.
`param`action- The function that runs when an object starts using component.
`param`unknown- The id of the component that was added.
`returns`The event controller.
`since`v3001.1
# [opacity](#opacity)(o?: number): OpacityComp
Sets the opacity of a Game Object (0.0 - 1.0).
`param`o- The opacity value to set.
``` js
const bean = add([
sprite("bean"),
opacity(0.5) // Make bean 50% transparent
])
// Make bean invisible
bean.opacity = 0
// Make bean fully visible
bean.opacity = 1
```
`returns`The opacity comp.
`since`v2000.0
# [outline](#outline)(width?: number, color?: Color, opacity?: number, join?: LineJoin, miterLimit?: number, cap?: LineCap): OutlineComp
Give an object an outline. Doesn't support sprite or text components.
`param`width- The width of the outline.
`param`color- The color of the outline.
`param`opacity- The opacity of the outline.
`param`join- -The line join style.
`param`miterLimit- The miter limit ratio.
`param`cap-The line cap style.
``` js
// Add an outline to a rectangle
add([
rect(40, 40),
outline(4),
]);
```
`returns`The outline comp.
`since`v2000.0
# [particles](#particles)(popt: ParticlesOpt, eopt: EmitterOpt): ParticlesComp
Attach a particle emitter to a Game Object.
`param`popt- The options for the particles.
`param`eopt- The options for the emitter.
``` js
// beansplosion
// create the emitter
const emitter = add([
pos(center()),
particles({
max: 100,
speed: [75, 100],
lifeTime: [0.75,1.0],
angle: [0, 360],
opacities: [1.0, 0.0],
texture: getSprite("bean").tex, // texture of a sprite
quads: getSprite("bean").frames, // frames of a sprite
}, {
direction: 0,
spread: 360,
}),
])
onUpdate(() => {
emitter.emit(1)
})
```
`returns`The particles comp.
`since`v3001.0
# [pathfinder](#pathfinder)(opts: PathfinderCompOpt): PathfinderComp
A navigator pathfinder which can calculate waypoints to a goal.
`since`v3001.0
# [patrol](#patrol)(opts: PatrolCompOpt): PatrolComp
A patrol which can follow waypoints to a goal.
`param`opts- Options for the patrol component. See
``` js
const bean = add([
sprite("bean"),
pos(40, 30),
patrol({
waypoints: [
vec2(100, 100),
vec2(120, 170),
vec2(50, 50),
vec2(300, 100),
],
}),
]);
bean.onPatrolFinished(gb => {
// Note that the position doesn't exactly match the last waypoint,
// this is an approximation.
debug.log(`Bean reached the end of the patrol at ${gb.pos.x}, ${gb.pos.y}`);
});
```
`returns`The patrol comp.
`since`v3001.0
# [Picture](#Picture): Picture
A picture holding drawing data
# [platformEffector](#platformEffector)(opt?: PlatformEffectorCompOpt): PlatformEffectorComp
The platform effector makes it easier to implement one way platforms or walls. This effector is typically used with a static body, and it will only be solid depending on the direction the object is traveling from.
`param`opt- Options for the platform effector component. See
`returns`The platform effector comp.
`since`v3001.0
# [play](#play)(src: string \| SoundData \| Asset \| MusicData \| Asset, options?: AudioPlayOpt): AudioPlay
Play a piece of audio.
``` js
// play a one off sound
play("wooosh")
// play a looping soundtrack (check out AudioPlayOpt for more options)
const music = play("OverworldlyFoe", {
volume: 0.8,
loop: true
})
// using the handle to control (check out AudioPlay for more controls / info)
music.paused = true
music.speed = 1.2
```
`returns`A control handle.
`since`v2000.0
# [plug](#plug)\<T\>(plugin: KAPLAYPlugin): KAPLAYCtx & T
Import a plugin.
`param`plugin- The plugin to import.
`returns`The updated context with the plugin.
`since`v2000.0
# [pointEffector](#pointEffector)(opt: PointEffectorCompOpt): PointEffectorComp
Applies a force on a colliding object directed towards this object's origin. Good to apply magnetic attraction or repulsion.
`param`opt- Options for the point effector component. See
`returns`The point effector comp.
`since`v3001.0
# [Polygon](#Polygon): Polygon
A polygon shape.
`since`v2000.0
# [popTransform](#popTransform)(): void
Pop the topmost transform matrix from the transform stack.
`since`v2000.0
# [pos](#pos)(x: number, y: number): PosComp
Set the position of a Game Object.
`param`x- The x position to set.
`param`y- The y position to set.
``` js
// This game object will draw a "bean" sprite at (100, 200)
add([
pos(100, 200),
sprite("bean"),
]);
```
`returns`The position comp.
`since`v2000.0
# [pos](#pos)(xy: number): PosComp
# [pos](#pos)(p: Vec2): PosComp
# [pos](#pos)(): PosComp
# [pressButton](#pressButton)(btn: TButton): void
Press a button virtually.
`param`btn- The button to press.
``` js
// press "jump" button
pressButton("jump"); // triggers onButtonPress, starts onButtonDown
releaseButton("jump"); // triggers onButtonRelease, stops onButtonDown
```
`since`v3001.0
# [pushMatrix](#pushMatrix)(mat?: Mat23): void
Apply a transform matrix, ignore all prior transforms.
`since`v3000.0
# [pushRotate](#pushRotate)(angle?: number): void
Rotate all subsequent draws.
`since`v2000.0
# [pushScale](#pushScale)(s?: Vec2): void
Scale all subsequent draws.
`since`v2000.0
# [pushTransform](#pushTransform)(): void
Push current transform matrix to the transform stack.
``` js
pushTransform();
// These transforms will affect every render until popTransform()
pushTranslate(120, 200);
pushRotate(time() * 120);
pushScale(6);
drawSprite("bean");
drawCircle(vec2(0), 120);
// Restore the transformation stack to when last pushed
popTransform();
```
`since`v2000.0
# [pushTranslate](#pushTranslate)(t?: Vec2): void
Translate all subsequent draws.
``` js
pushTranslate(100, 100)
// this will be drawn at (120, 120)
drawText({
text: "oh hi",
pos: vec2(20, 20),
})
```
`since`v2000.0
# [Quad](#Quad): Quad
A 2D quad.
`since`v3001.0
# [query](#query)(opt: QueryOpt): GameObj\[\]
Get a list of game objects in an advanced way.
`param`opt- The query options.
``` js
const bean = k.add(["friend", "bean"]);
const bean2 = k.add(["friend", "bean"]);
const bag = k.add(["friend", "bag"]);
// get bean
query({
include: "bean",
}) // will return [bean, bean2];
// get all friends excluding bean
query({
include: "friend",
exclude: "bean",
}); // will return [bag]
// get all visible friends
query({
include: "friend",
visible: true,
});
// get all friends less than 150 pixels from bean
bean.query({
include: "friend",
distance: 150,
});
```
# [quit](#quit)(): void
End everything.
`since`v2000.0
# [rad2deg](#rad2deg)(rad: number): number
Convert radians to degrees.
# [rand](#rand)\<T\>(a?: T, b?: T): T
Get a random value between the given bound.
`param`a- The lower bound. If not upper bound, this is the upper bound and the lower bound is 0.
`param`b- The upper bound.
``` js
// a random number between 0 - 8
rand(8)
// a random point on screen
rand(vec2(width(), height()))
// a random color
rand(rgb(255, 255, 255))
// a random number between 50 - 100
rand(50, 100);
// a random point on screen with x between 20 - 100 and y between 20 - 100
rand(vec2(20), vec2(100));
// spawn something on the right side of the screen but with random y value within screen height
add([
pos(width(), rand(0, height())),
]);
```
`since`v2000.0
# [randSeed](#randSeed)(seed?: number): number
Get / set the random number generator seed.
`param`seed- The seed to set.
``` js
randSeed(Date.now())
```
`returns`The new seed.
`since`v2000.0
# [randi](#randi)(a?: number, b?: number): number
rand() but floored to integer. If not arguments, returns 0 or 1.
`param`a- The lower bound. If not upper bound, this is the upper bound.
`param`b- The upper bound.
``` js
randi(); // returns either 0 or 1
randi(10); // returns a random integer between 0 and 9
randi(10, 20); // returns a random integer between 10 and 19
```
`returns`A random integer between 0 and 1.
`since`v2000.0
# [raycast](#raycast)(origin: Vec2, direction: Vec2, exclude?: string\[\]): RaycastResult
Create a raycast.
`since`v3001.0
# [readd](#readd)(obj: GameObj): GameObj
Remove and re-add the game obj, without triggering add / destroy events.
`param`obj- The game object to re-add.
``` js
// Common way to use this is to have one sprite overlap another sprite, and use readd() to have the bottom sprite on top of the other.
// Create two sprites.
const greenBean = add([
sprite("bean"),
pos(200,140),
color(255, 255, 255),
area(),
]);
// This bean will overlap the green bean.
const purpleBean = add([
sprite("bean"),
pos(230,140),
color(255, 0, 255),
area(),
]);
// Example 1: simply call readd() on the target you want on top.
readd(greenBean);
// Example 2: using onClick() or other functions with readd().
// If you comment out the first example, and use this readd() with a function like onClick(), you
can keep switching which sprite is above the other ( click on edge of face ).
purpleBean.onClick(() => {
readd(greenBean);
});
greenBean.onClick(() => {
readd(purpleBean);
});
```
`returns`The re-added game object.
`since`v3001.0
# [record](#record)(frameRate?: number): Recording
Start recording the canvas into a video. If framerate is not specified, a new frame will be captured each time the canvas changes.
`returns`A control handle.
`since`v2000.1
# [Rect](#Rect): Rect
A rectangle shape.
`since`v2000.0
# [releaseButton](#releaseButton)(btn: TButton): void
Release a button virtually.
`param`btn- The button to release.
``` js
// press "jump" button
pressButton("jump"); // triggers onButtonPress, starts onButtonDown
releaseButton("jump"); // triggers onButtonRelease, stops onButtonDown
```
`since`v3001.0
# [restDt](#restDt)(): number
Get the rest delta time since last frame.
`since`v3000.0
# [rgb](#rgb)(r: number, g: number, b: number): Color
Create a color from RGB values (0 - 255).
`param`r- The red value.
`param`g- The green value.
`param`b- The blue value.
``` js
// update the color of the sky to light blue
sky.color = rgb(0, 128, 255)
```
`returns`The color.
`since`v2000.0
# [rgb](#rgb)(hex: string): Color
Create a color from hex string.
`param`hex- The hex string.
``` js
sky.color = rgb("#ef6360")
```
`returns`The color.
`since`v2000.0
# [rgb](#rgb)(cssColor: CSSColor): Color
Create a color from CSS name.
`param`cssColor- The CSS name.
``` js
sea.color = rgb("slateblue");
```
`returns`The color.
`since`v3001.0.10
`experimental`This feature is in experimental phase, it will be fully released in v3001.1.0
# [rgb](#rgb)(): Color
Same as rgb(255, 255, 255).
# [rotate](#rotate)(a?: number): RotateComp
Rotates a Game Object (in degrees).
`param`a- The angle to rotate by. Defaults to 0.
``` js
let bean = add([
sprite("bean"),
rotate(),
])
// bean will be upside down!
bean.angle = 180
```
`returns`The rotate comp.
`since`v2000.0
# [scale](#scale)(x: number, y: number): ScaleComp
Set the scale of a Game Object.
`param`x- The x scale to set.
`param`y- The y scale to set.
``` js
// scale uniformly with one value
add([
sprite("bean"),
scale(3),
]);
// scale with x & y values. In this case, scales more horizontally.
add([
sprite("bean"),
scale(3, 1),
]);
// scale with vec2(x,y).
bean.scale = vec2(2,4);
```
`returns`The scale comp.
`since`v2000.0
# [scale](#scale)(xy: number): ScaleComp
# [scale](#scale)(s: Vec2): ScaleComp
# [scale](#scale)(): ScaleComp
# [scene](#scene)(name: SceneName, def: SceneDef): void
Define a scene.
`param`name- The scene name.
`param`def- The scene definition.
``` js
// define a scene
scene("game", () => {
// ...
});
// get options
scene("game", (opts) => {
debug.log(opts.level);
});
```
# [screenshot](#screenshot)(): string
Take a screenshot and get the data url of the image.
`returns`The dataURL of the image.
`since`v2000.0
# [sentry](#sentry)(candidates: SentryCandidates, opt?: SentryCompOpt): SentryComp
A sentry which reacts to objects coming into view.
`returns`The sentry comp.
`since`v3001.0
# [serializeAnimation](#serializeAnimation)(obj: GameObj, name: string): Animation
Serializes the animation to plain objects
`param`obj- The game obj to serialize.
`returns`The serialized animation.
`since`v3001.0
# [setBackground](#setBackground)(color: Color): void
Set background color.
`since`v3000.0
# [setBackground](#setBackground)(color: Color, alpha: number): void
# [setBackground](#setBackground)(r: number, g: number, b: number): void
# [setBackground](#setBackground)(r: number, g: number, b: number, alpha: number): void
# [setButton](#setButton)(btn: string, def: ButtonBinding): void
Set a input binding for a button name.
`param`btn- The button to set binding for.
`since`v3001.0
# [setCamPos](#setCamPos)(pos: Vec2): void
Set camera position.
`param`pos- The position to set the camera to.
``` js
// move camera to (100, 100)
setCamPos(100, 100);
setCamPos(vec2(100, 100));
setCamPos(100); // x and y are the same
```
`since`v3001.1
# [setCamPos](#setCamPos)(x: number, y: number): void
# [setCamPos](#setCamPos)(xy: number): void
# [setCamRot](#setCamRot)(angle: number): void
Set camera rotation.
`param`angle- The angle to rotate the camera.
``` js
// rotate camera 90 degrees
setCamRot(90);
```
`since`v3001.1
# [setCamScale](#setCamScale)(scale: Vec2): void
Set camera scale.
`param`scale- The scale to set the camera to.
``` js
// set camera scale to (2, 2)
setCamScale(2, 2);
setCamScale(vec2(2, 2));
setCamScale(2); // x and y are the same
```
`since`v3001.1
# [setCamScale](#setCamScale)(x: number, y: number): void
# [setCamScale](#setCamScale)(xy: number): void
# [setCursor](#setCursor)(style: Cursor): void
Set cursor style.
`param`style- The cursor style.
``` js
// Change between cursor styles
// Reset cursor to default at start of every frame
onUpdate(() => setCursor("default"));
button.onHover((c) => {
// change cursor to pointer when hovering over button
setCursor("pointer")
})
// Hide the only cursor at start (useful for fakeMouse)
setCursor("none");
```
`since`v2000.0
# [setCursorLocked](#setCursorLocked)(locked: boolean): void
Lock / unlock cursor. Note that you cannot lock cursor within 1 second after user unlocking the cursor with the default unlock gesture (typically the esc key) due to browser policy.
`since`v2000.0
# [setData](#setData)(key: string, data: any): void
Set data from local storage.
`param`key- The key to set data to.
`param`data- The data to set.
`since`v2000.0
# [setFullscreen](#setFullscreen)(f?: boolean): void
Enter / exit fullscreen mode. (note: mouse position is not working in fullscreen mode at the moment)
``` js
// toggle fullscreen mode on "f"
onKeyPress("f", (c) => {
setFullscreen(!isFullscreen());
});
```
`since`v2000.0
# [setGravity](#setGravity)(g: number): void
Set gravity.
`param`g- The gravity to set.
`since`v2000.0
# [setGravityDirection](#setGravityDirection)(d: Vec2): void
Set gravity direction.
`since`v3001.0
# [setLayers](#setLayers)(layers: string\[\], defaultLayer: string): void
Define the layer names. Should be called before any objects are made.
`param`layers- The layer names.
`param`defaultLayer- The default layer name.
``` js
layers(["bg", "obj", "ui"], "obj")
// no layer specified, will be added to "obj"
add([
sprite("bean"),
]);
// add to "bg" layer
add([
sprite("bg"),
layer("bg"),
]);
```
`since`v3001.1
# [setVolume](#setVolume)(v: number): void
Set the global volume.
`param`v- The volume to set.
``` js
setVolume(0.5)
```
`since`v3001.1
# [shader](#shader)(id: string, uniform?: Uniform \| ()=\>Uniform): ShaderComp
Custom shader to manipulate sprite.
`param`id- The shader id.
`param`uniform- The uniform to pass to the shader.
`returns`The shader comp.
`since`v2000.0
# [shake](#shake)(intensity?: number): void
Camera shake.
`param`intensity- The intensity of the shake. Default to 12.
``` js
// shake intensively when bean collides with a "bomb"
bean.onCollide("bomb", () => {
shake(120)
})
```
`since`v3000.0
# [shuffle](#shuffle)\<T\>(lst: T\[\]): T\[\]
Shuffle an array.
`param`lst- The list to shuffle.
`returns`A shuffled array.
`since`v3001.0
# [smoothstep](#smoothstep)(edge0: number, edge1: number, x: number): number
`returns`1 if over edge1, 0 if under edge0, a smooth hermite curve value otherwise
`since`v3001.0
# [sprite](#sprite)(spr: string \| SpriteData \| Asset, opt?: SpriteCompOpt): SpriteComp
Attach and render a sprite to a Game Object.
`param`spr- The sprite to render.
`param`opt- Options for the sprite component. See
``` js
// minimal setup
add([
sprite("bean"),
])
// with options
const bean = add([
sprite("bean", {
// start with animation "idle"
anim: "idle",
}),
])
// play / stop an anim
bean.play("jump")
bean.stop()
// manually setting a frame
bean.frame = 3
```
`returns`The sprite comp.
`since`v2000.0
# [state](#state)(initialState: string, stateList?: string\[\]): StateComp
Finite state machine.
`param`initialState- The initial state.
`param`stateList- The list of states.
``` js
const enemy = add([
pos(80, 100),
sprite("robot"),
state("idle", ["idle", "attack", "move"]),
])
// this callback will run once when enters "attack" state
enemy.onStateEnter("attack", () => {
// enter "idle" state when the attack animation ends
enemy.play("attackAnim", {
// any additional arguments will be passed into the onStateEnter() callback
onEnd: () => enemy.enterState("idle", rand(1, 3)),
})
checkHit(enemy, player)
})
// this will run once when enters "idle" state
enemy.onStateEnter("idle", (time) => {
enemy.play("idleAnim")
wait(time, () => enemy.enterState("move"))
})
// this will run every frame when current state is "move"
enemy.onStateUpdate("move", () => {
enemy.follow(player)
if (enemy.pos.dist(player.pos) < 16) {
enemy.enterState("attack")
}
})
```
`returns`The state comp.
`since`v2000.1
# [state](#state)(initialState: string, stateList: string\[\], transitions: Record): StateComp
state() with pre-defined transitions.
`param`initialState- The initial state.
`param`stateList- The list of states.
`param`transitions- The transitions between states.
``` js
const enemy = add([
pos(80, 100),
sprite("robot"),
state("idle", ["idle", "attack", "move"], {
"idle": "attack",
"attack": "move",
"move": [ "idle", "attack" ],
}),
])
// this callback will only run once when enter "attack" state from "idle"
enemy.onStateTransition("idle", "attack", () => {
checkHit(enemy, player)
})
```
`returns`The state comp.
`since`v2000.2
# [stay](#stay)(scenesToStay?: string\[\]): StayComp
Don't get destroyed on scene switch. Only works in objects attached to root.
`param`scenesToStay- The scenes to stay in. By default it stays in all scenes.
``` js
player.onCollide("bomb", () => {
// spawn an explosion and switch scene, but don't destroy the explosion game obj on scene switch
add([
sprite("explosion", { anim: "burst", }),
stay(),
lifespan(1),
])
go("lose", score)
})
```
`returns`The stay comp.
`since`v2000.0
# [step](#step)(edge: number, x: number): number
`returns`1 if over the edge, 0 otherwise
`since`v3001.0
# [surfaceEffector](#surfaceEffector)(opt: SurfaceEffectorCompOpt): SurfaceEffectorComp
Applies a force on a colliding object in order to make it move along the collision tangent vector. Good for conveyor belts.
`param`opt- Options for the surface effector component. See
``` js
loadSprite("belt", "/sprites/jumpy.png")
// conveyor belt
add([
pos(center()),
sprite("belt"),
rotate(90),
area(),
body({ isStatic: true }),
surfaceEffector({
speed: 50,
})
])
```
`returns`The surface effector comp.
`since`v3001.0
# [system](#system)(name: string, cb: ()=\>void, when: LCEvents\[\]): void
Runs a system at the specified events in the pipeline
`param`nameThe name of the system. Overwrites an existing system if the name has been used before.
`param`cbThe function to run.
`param`whenWhen to run the function.
`since`v4000.0
# [testCirclePolygon](#testCirclePolygon)(c: Circle, p: Polygon): boolean
Check if a circle and polygon intersect linewise.
`param`c- The circle.
`param`p- The polygon.
`returns`true if the circle and polygon intersect linewise.
`since`v2000.0
# [testLineCircle](#testLineCircle)(l: Line, c: Circle): boolean
Check if a line and a circle intersect.
`param`l- The line.
`param`c- The circle.
`returns`true if the line and circle intersects.
`since`v2000.0
# [testLineLine](#testLineLine)(l1: Line, l2: Line): Vec2 \| null
Check if 2 lines intersects, if yes returns the intersection point.
`param`l1- The first line.
`param`l2- The second line.
`return`The intersection point, or null if the lines are parallel.
`since`v2000.0
# [testLinePoint](#testLinePoint)(l: Line, pt: Vec2): boolean
Check if a line and a point intersect.
`param`l- The line.
`param`pt- The point.
`returns`true if the line and point intersects.
`since`v2000.0
# [testRectLine](#testRectLine)(r: Rect, l: Line): boolean
Check if a line and a rectangle overlaps.
`param`r- The line.
`param`l- The rectangle.
`returns`true if the line and rectangle overlaps.
`since`v2000.0
# [testRectPoint](#testRectPoint)(r: Rect, pt: Vec2): boolean
Check if a point is inside a rectangle.
`param`r- The rectangle.
`param`pt- The point.
`returns`true if the point is inside the rectangle.
`since`v2000.0
# [testRectRect](#testRectRect)(r1: Rect, r2: Rect): boolean
Check if 2 rectangle overlaps.
`param`r1- The first rectangle.
`param`r2- The second rectangle.
`returns`true if the rectangles overlap.
`since`v2000.0
# [text](#text)(txt?: string, opt?: TextCompOpt): TextComp
Attach and render a text to a Game Object.
`param`txt- The text to display.
`param`opt- Options for the text component. See
``` js
// a simple score counter
const score = add([
text("Score: 0"),
pos(24, 24),
{ value: 0 },
])
player.onCollide("coin", () => {
score.value += 1
score.text = "Score:" + score.value
})
// with options
add([
pos(24, 24),
text("ohhi", {
size: 48, // 48 pixels tall
width: 320, // it'll wrap to next line when width exceeds this value
font: "sans-serif", // specify any font you loaded or browser built-in
}),
])
```
`returns`The text comp.
`since`v2000.0
# [textInput](#textInput)(hasFocus?: boolean, maxInputLength?: number): TextInputComp
Get input from the user and store it in the nodes text property, displaying it with the text component and allowing other functions to access it.
`param`hasFocus- Whether the text input should have focus.
`param`maxInputLength- The maximum length of the input.
``` js
const obj = add([
text(""),
textInput(),
])
obj.hasFocus = false
debug.log(obj.text) // oh no i cant see my new text since it was disabled
```
`returns`The text input comp.
`since`v3001.0
# [tile](#tile)(opt?: TileCompOpt): TileComp
A tile on a tile map.
`param`opt- Options for the tile component. See
`returns`The tile comp.
`since`v3000.0
# [time](#time)(): number
Get the total time since beginning.
`since`v3001
# [timer](#timer)(maxLoopsPerFrame?: number): TimerComp
Enable timer related functions like wait(), loop(), tween() on the game object.
`param`maxLoopsPerFrame- The maximum number of loops per frame.
``` js
const obj = add([
timer(),
])
obj.wait(2, () => { ... })
obj.loop(0.5, () => { ... })
obj.tween(obj.pos, mousePos(), 0.5, (p) => obj.pos = p, easings.easeOutElastic)
```
`returns`The timer comp.
`since`v2000.0
# [toScreen](#toScreen)(p: Vec2): Vec2
Transform a point from world position (relative to the root) to screen position (relative to the screen).
`param`p- The point to transform.
`since`v3001.0
# [toWorld](#toWorld)(p: Vec2): Vec2
Transform a point from screen position (relative to the screen) to world position (relative to the root).
`param`p- The point to transform.
`since`v3001.0
# [triangulate](#triangulate)(pts: Vec2\[\]): Vec2\[\]\[\]
`since`v3001.0
# [trigger](#trigger)(event: string, tag: string, args: any): void
Trigger an event on all game objs with certain tag.
`param`event- The tag to trigger to.
`param`tag- Arguments to pass to the \`on()\` functions
``` js
trigger("shoot", "target", 140);
on("shoot", "target", (obj, score) => {
obj.destroy();
debug.log(140); // every bomb was 140 score points!
});
```
`since`v3001.0.6
`experimental`This feature is in experimental phase, it will be fully released in v3001.1.0
# [tween](#tween)\<V\>(from: V, to: V, duration: number, setValue: (value: V)=\>void, easeFunc?: (t: number)=\>number): TweenController
Tweeeeeeeening!
`since`v3000.0
``` js
// tween bean to mouse position
tween(bean.pos, mousePos(), 1, (p) => bean.pos = p, easings.easeOutBounce)
```
# [usePostEffect](#usePostEffect)(name: string, uniform?: Uniform \| ()=\>Uniform): void
Apply a post process effect from a shader name.
``` js
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")
```
`since`v3000.0
# [uvquad](#uvquad)(w: number, h: number): UVQuadComp
Attach and render a UV quad to a Game Object.
`param`w- The width of the quad.
`param`h- The height of the quad.
``` js
add([
uvquad(width(), height()),
shader("spiral"),
])
```
`returns`The UV quad comp.
`since`v2000.0
# [Vec2](#Vec2): Vec2
A 2D vector.
`since`v2000.0
# [video](#video)(url: string, opt?: VideoCompOpt): VideoComp
Draws a video.
`param`urlThe video to play. Needs to be on the same webserver due to CORS.
`param`optThe video component options
`returns`The video comp.
`since`v4000.0
# [volume](#volume)(v?: number): number
`deprecated`Use
``` js
// makes everything quieter
volume(0.5)
```
`returns`The new volume or the current volume.
`since`v2000.0
# [wait](#wait)(n: number, action?: ()=\>void): TimerController
Run the function after n seconds.
`param`n- The time to wait in seconds.
`param`action- The function to run.
``` js
// 3 seconds until explosion! Runnn!
wait(3, () => {
explode()
})
// wait() returns a PromiseLike that can be used with await
await wait(1)
```
`returns`A timer controller.
`since`v2000.0
# [wave](#wave)\<V\>(lo: V, hi: V, t: number, func?: (x: number)=\>number): V
Interpolate back and forth between 2 values. (Optionally takes a custom periodic function, which default to a sine wave.).
``` js
// bounce color between 2 values as time goes on
onUpdate("colorful", (c) => {
c.color.r = wave(0, 255, time())
c.color.g = wave(0, 255, time() + 1)
c.color.b = wave(0, 255, time() + 2)
})
```
# [width](#width)(): number
Get the width of game.
`returns`The width of the game.
`since`v2000.0
# [z](#z)(z: number): ZComp
Determines the draw order for objects on the same layer. Object will be drawn on top if z value is bigger.
`param`z- The z value to set.
``` js
const bean = add([
sprite("bean"),
pos(100, 100),
z(10), // Bean has a z value of 10
])
// Mark has a z value of 20, so he will always be drawn on top of bean
const mark = add([
sprite("mark"),
pos(100, 100),
z(20),
])
bean.z = 30 // Bean now has a higher z value, so it will be drawn on top of mark
```
`returns`The z comp.
`since`v2000.0
[initApp](#initApp)(opt:
# [canvas](#undefined-canvas): HTMLCanvasElement
& KAPLAYOpt):
[state](#undefined-state):
# [canvas](#undefined-canvas): HTMLCanvasElement
# [buttons](#undefined-buttons): ButtonsDef
# [buttonsByKey](#undefined-buttonsByKey): Map\<Key, string\[\]\>
# [buttonsByMouse](#undefined-buttonsByMouse): Map\<MouseButton, string\[\]\>
# [buttonsByGamepad](#undefined-buttonsByGamepad): Map\<KGamepadButton, string\[\]\>
# [buttonsByKeyCode](#undefined-buttonsByKeyCode): Map\<string, string\[\]\>
# [loopID](#undefined-loopID): null \| number
# [stopped](#undefined-stopped): boolean
# [dt](#undefined-dt): number
# [fixedDt](#undefined-fixedDt): number
# [restDt](#undefined-restDt): number
# [time](#undefined-time): number
# [realTime](#undefined-realTime): number
# [fpsCounter](#undefined-fpsCounter): FPSCounter
# [timeScale](#undefined-timeScale): number
# [skipTime](#undefined-skipTime): boolean
# [isHidden](#undefined-isHidden): boolean
# [numFrames](#undefined-numFrames): number
# [capsOn](#undefined-capsOn): boolean
# [mousePos](#undefined-mousePos): Vec2
# [mouseDeltaPos](#undefined-mouseDeltaPos): Vec2
# [keyState](#undefined-keyState): ButtonState\<Key\>
# [mouseState](#undefined-mouseState): ButtonState\<MouseButton\>
# [mergedGamepadState](#undefined-mergedGamepadState): GamepadState
# [gamepadStates](#undefined-gamepadStates): Map\<number, GamepadState\>
# [lastInputDevice](#undefined-lastInputDevice): mouse \| keyboard \| gamepad \| null
# [buttonState](#undefined-buttonState): ButtonState\<string\>
# [gamepads](#undefined-gamepads): KGamepad\[\]
# [charInputted](#undefined-charInputted): string\[\]
# [isMouseMoved](#undefined-isMouseMoved): boolean
# [lastWidth](#undefined-lastWidth): number
# [lastHeight](#undefined-lastHeight): number
# [events](#undefined-events): KEventHandler\<AppEventMap\>
# [dt](#undefined-dt)(): number
# [fixedDt](#undefined-fixedDt)(): number
# [restDt](#undefined-restDt)(): number
# [time](#undefined-time)(): number
# [run](#undefined-run)(fixedUpdate: ()=\>void, update: (processInput: ()=\>void, resetInput: ()=\>void)=\>void): void
# [canvas](#undefined-canvas): HTMLCanvasElement
# [fps](#undefined-fps)(): number
# [numFrames](#undefined-numFrames)(): number
# [quit](#undefined-quit)(): void
# [isHidden](#undefined-isHidden)(): boolean
# [setFullscreen](#undefined-setFullscreen)(f?: boolean): void
# [isFullscreen](#undefined-isFullscreen)(): boolean
# [setCursor](#undefined-setCursor)(c: Cursor): void
# [screenshot](#undefined-screenshot)(): string
# [getGamepads](#undefined-getGamepads)(): KGamepad\[\]
# [getCursor](#undefined-getCursor)(): Cursor
# [setCursorLocked](#undefined-setCursorLocked)(b: boolean): void
# [isCursorLocked](#undefined-isCursorLocked)(): boolean
# [isTouchscreen](#undefined-isTouchscreen)(): boolean
# [mousePos](#undefined-mousePos)(): Vec2
# [mouseDeltaPos](#undefined-mouseDeltaPos)(): Vec2
# [isKeyDown](#undefined-isKeyDown)(k?: Key \| Key\[\]): boolean
# [isKeyPressed](#undefined-isKeyPressed)(k?: Key \| Key\[\]): boolean
# [isKeyPressedRepeat](#undefined-isKeyPressedRepeat)(k?: Key \| Key\[\]): boolean
# [isKeyReleased](#undefined-isKeyReleased)(k?: Key \| Key\[\]): boolean
# [isMouseDown](#undefined-isMouseDown)(m?: MouseButton): boolean
# [isMousePressed](#undefined-isMousePressed)(m?: MouseButton): boolean
# [isMouseReleased](#undefined-isMouseReleased)(m?: MouseButton): boolean
# [isMouseMoved](#undefined-isMouseMoved)(): boolean
# [isGamepadButtonPressed](#undefined-isGamepadButtonPressed)(btn?: KGamepadButton \| KGamepadButton\[\]): boolean
# [isGamepadButtonDown](#undefined-isGamepadButtonDown)(btn?: KGamepadButton \| KGamepadButton\[\]): boolean
# [isGamepadButtonReleased](#undefined-isGamepadButtonReleased)(btn?: KGamepadButton \| KGamepadButton\[\]): boolean
# [getGamepadStick](#undefined-getGamepadStick)(stick: GamepadStick): Vec2
# [isButtonPressed](#undefined-isButtonPressed)(btn?: string \| string\[\]): boolean
# [isButtonDown](#undefined-isButtonDown)(btn?: string \| string\[\]): boolean
# [isButtonReleased](#undefined-isButtonReleased)(btn?: string \| string\[\]): boolean
# [setButton](#undefined-setButton)(btn: string, binding: ButtonBinding): void
# [getButton](#undefined-getButton)(btn: string): ButtonBinding
# [pressButton](#undefined-pressButton)(btn: string): void
# [releaseButton](#undefined-releaseButton)(btn: string): void
# [charInputted](#undefined-charInputted)(): string\[\]
# [onResize](#undefined-onResize)(action: ()=\>void): KEventController
# [onKeyDown](#undefined-onKeyDown): (action: (key: Key)=\>void)=\>KEventController & (key: Key \| Key\[\], action: (key: Key)=\>void)=\>KEventController
# [onKeyPress](#undefined-onKeyPress): (action: (key: Key)=\>void)=\>KEventController & (key: Key \| Key\[\], action: (key: Key)=\>void)=\>KEventController
# [onKeyPressRepeat](#undefined-onKeyPressRepeat): (action: (key: Key)=\>void)=\>KEventController & (key: Key \| Key\[\], action: (key: Key)=\>void)=\>KEventController
# [onKeyRelease](#undefined-onKeyRelease): (action: (key: Key)=\>void)=\>KEventController & (key: Key \| Key\[\], action: (key: Key)=\>void)=\>KEventController
# [onMouseDown](#undefined-onMouseDown): (action: (m: MouseButton)=\>void)=\>KEventController & (mouse: MouseButton \| MouseButton\[\], action: (m: MouseButton)=\>void)=\>KEventController
# [onMousePress](#undefined-onMousePress): (action: (m: MouseButton)=\>void)=\>KEventController & (mouse: MouseButton \| MouseButton\[\], action: (m: MouseButton)=\>void)=\>KEventController
# [onMouseRelease](#undefined-onMouseRelease): (action: (m: MouseButton)=\>void)=\>KEventController & (mouse: MouseButton \| MouseButton\[\], action: (m: MouseButton)=\>void)=\>KEventController
# [onMouseMove](#undefined-onMouseMove)(f: (pos: Vec2, dpos: Vec2)=\>void): KEventController
# [onCharInput](#undefined-onCharInput)(action: (ch: string)=\>void): KEventController
# [onTouchStart](#undefined-onTouchStart)(f: (pos: Vec2, t: Touch)=\>void): KEventController
# [onTouchMove](#undefined-onTouchMove)(f: (pos: Vec2, t: Touch)=\>void): KEventController
# [onTouchEnd](#undefined-onTouchEnd)(f: (pos: Vec2, t: Touch)=\>void): KEventController
# [onScroll](#undefined-onScroll)(action: (delta: Vec2)=\>void): KEventController
# [onHide](#undefined-onHide)(action: ()=\>void): KEventController
# [onShow](#undefined-onShow)(action: ()=\>void): KEventController
# [onGamepadButtonDown](#undefined-onGamepadButtonDown): (action: (btn: KGamepadButton, gamepad: KGamepad)=\>void)=\>KEventController & (btn: KGamepadButton, action: (btn: KGamepadButton, gamepad: KGamepad)=\>void)=\>KEventController
# [onGamepadButtonPress](#undefined-onGamepadButtonPress): (action: (btn: KGamepadButton, gamepad: KGamepad)=\>void)=\>KEventController & (btn: KGamepadButton \| KGamepadButton\[\], action: (btn: KGamepadButton, gamepad: KGamepad)=\>void)=\>KEventController
# [onGamepadButtonRelease](#undefined-onGamepadButtonRelease): (action: (btn: KGamepadButton, gamepad: KGamepad)=\>void)=\>KEventController & (btn: KGamepadButton \| KGamepadButton\[\], action: (btn: KGamepadButton, gamepad: KGamepad)=\>void)=\>KEventController
# [onGamepadStick](#undefined-onGamepadStick)(stick: GamepadStick, action: (value: Vec2, gp: KGamepad)=\>void): KEventController
# [onGamepadConnect](#undefined-onGamepadConnect)(action: (gamepad: KGamepad)=\>void): KEventController
# [onGamepadDisconnect](#undefined-onGamepadDisconnect)(action: (gamepad: KGamepad)=\>void): KEventController
# [onButtonPress](#undefined-onButtonPress): (action: (btn: string)=\>void)=\>KEventController & (btn: string \| string, action: (btn: string)=\>void)=\>KEventController
# [onButtonDown](#undefined-onButtonDown): (action: (btn: string)=\>void)=\>KEventController & (btn: string \| string, action: (btn: string)=\>void)=\>KEventController
# [onButtonRelease](#undefined-onButtonRelease): (action: (btn: string)=\>void)=\>KEventController & (btn: string \| string, action: (btn: string)=\>void)=\>KEventController
# [getLastInputDeviceType](#undefined-getLastInputDeviceType)(): ButtonBindingDevice \| null
# [events](#undefined-events): KEventHandler\<AppEventMap\>
[initAppState](#initAppState)(opt:
# [canvas](#undefined-canvas): HTMLCanvasElement
# [touchToMouse](#undefined-touchToMouse)?: boolean
# [gamepads](#undefined-gamepads)?: Record\<string, GamepadDef\>
# [pixelDensity](#undefined-pixelDensity)?: number
# [maxFPS](#undefined-maxFPS)?: number
# [buttons](#undefined-buttons)?: ButtonsDef
):
# [canvas](#undefined-canvas): HTMLCanvasElement
# [buttons](#undefined-buttons): ButtonsDef
# [buttonsByKey](#undefined-buttonsByKey): Map\<Key, string\[\]\>
# [buttonsByMouse](#undefined-buttonsByMouse): Map\<MouseButton, string\[\]\>
# [buttonsByGamepad](#undefined-buttonsByGamepad): Map\<KGamepadButton, string\[\]\>
# [buttonsByKeyCode](#undefined-buttonsByKeyCode): Map\<string, string\[\]\>
# [loopID](#undefined-loopID): null \| number
# [stopped](#undefined-stopped): boolean
# [dt](#undefined-dt): number
# [fixedDt](#undefined-fixedDt): number
# [restDt](#undefined-restDt): number
# [time](#undefined-time): number
# [realTime](#undefined-realTime): number
# [fpsCounter](#undefined-fpsCounter): FPSCounter
# [timeScale](#undefined-timeScale): number
# [skipTime](#undefined-skipTime): boolean
# [isHidden](#undefined-isHidden): boolean
# [numFrames](#undefined-numFrames): number
# [capsOn](#undefined-capsOn): boolean
# [mousePos](#undefined-mousePos): Vec2
# [mouseDeltaPos](#undefined-mouseDeltaPos): Vec2
# [keyState](#undefined-keyState): ButtonState\<Key\>
# [mouseState](#undefined-mouseState): ButtonState\<MouseButton\>
# [mergedGamepadState](#undefined-mergedGamepadState): GamepadState
# [gamepadStates](#undefined-gamepadStates): Map\<number, GamepadState\>
# [lastInputDevice](#undefined-lastInputDevice): mouse \| keyboard \| gamepad \| null
# [buttonState](#undefined-buttonState): ButtonState\<string\>
# [gamepads](#undefined-gamepads): KGamepad\[\]
# [charInputted](#undefined-charInputted): string\[\]
# [isMouseMoved](#undefined-isMouseMoved): boolean
# [lastWidth](#undefined-lastWidth): number
# [lastHeight](#undefined-lastHeight): number
# [events](#undefined-events): KEventHandler\<AppEventMap\>
[initAssets](#initAssets)(ggl: GfxCtx, spriteAtlasPadding: number):
# [urlPrefix](#undefined-urlPrefix): string
# [sprites](#undefined-sprites): AssetBucket\<SpriteData\>
# [fonts](#undefined-fonts): AssetBucket\<FontData\>
# [bitmapFonts](#undefined-bitmapFonts): AssetBucket\<GfxFont\>
# [sounds](#undefined-sounds): AssetBucket\<SoundData\>
# [shaders](#undefined-shaders): AssetBucket\<Shader\>
# [custom](#undefined-custom): AssetBucket\<any\>
# [music](#undefined-music): Record\<string, string\>
# [packer](#undefined-packer): TexPacker
# [loaded](#undefined-loaded): boolean
[initAudio](#initAudio)():
# [ctx](#undefined-ctx): AudioContext
# [masterNode](#undefined-masterNode): GainNode
# [burpSnd](#undefined-burpSnd): SoundData
[initGfx](#initGfx)(gl: WebGLRenderingContext, opts?: KAPLAYOpt):
# [gl](#undefined-gl): WebGLRenderingContext
# [opts](#undefined-opts): KAPLAYOpt\<any, any\>
# [onDestroy](#undefined-onDestroy)(action: ()=\>unknown): void
# [destroy](#undefined-destroy)(): void
# [pushTexture2D](#undefined-pushTexture2D)(item: WebGLTexture): void
# [popTexture2D](#undefined-popTexture2D)(): void
# [pushArrayBuffer](#undefined-pushArrayBuffer)(item: WebGLBuffer): void
# [popArrayBuffer](#undefined-popArrayBuffer)(): void
# [pushElementArrayBuffer](#undefined-pushElementArrayBuffer)(item: WebGLBuffer): void
# [popElementArrayBuffer](#undefined-popElementArrayBuffer)(): void
# [pushFramebuffer](#undefined-pushFramebuffer)(item: WebGLFramebuffer): void
# [popFramebuffer](#undefined-popFramebuffer)(): void
# [pushRenderbuffer](#undefined-pushRenderbuffer)(item: WebGLRenderbuffer): void
# [popRenderbuffer](#undefined-popRenderbuffer)(): void
[pushViewport](#undefined-pushViewport)(item:
# [x](#undefined-x): number
# [y](#undefined-y): number
# [w](#undefined-w): number
# [h](#undefined-h): number
): void
# [popViewport](#undefined-popViewport)(): void
# [pushProgram](#undefined-pushProgram)(item: WebGLProgram): void
# [popProgram](#undefined-popProgram)(): void
# [setVertexFormat](#undefined-setVertexFormat)(fmt: VertexFormat): void
# [kaplay](#kaplay)(gopt?: KAPLAYOpt)
Initialize KAPLAY context. The starting point of all KAPLAY games.
``` js
// Start KAPLAY with default options (will create a fullscreen canvas under <body>)
kaplay()
// Init with some options
kaplay({
width: 320,
height: 240,
font: "sans-serif",
canvas: document.querySelector("#mycanvas"),
background: [ 0, 0, 255, ],
})
// All KAPLAY functions are imported to global after calling kaplay()
add()
onUpdate()
onKeyPress()
vec2()
// If you want to prevent KAPLAY from importing all functions to global and use a context handle for all KAPLAY functions
const k = kaplay({ global: false })
k.add(...)
k.onUpdate(...)
k.onKeyPress(...)
k.vec2(...)
```
## Games
## Reference
# [kaplay](#kaplay)(gopt?: KAPLAYOpt)
Initialize KAPLAY context. The starting point of all KAPLAY games.
``` js
// Start KAPLAY with default options (will create a fullscreen canvas under <body>)
kaplay()
// Init with some options
kaplay({
width: 320,
height: 240,
font: "sans-serif",
canvas: document.querySelector("#mycanvas"),
background: [ 0, 0, 255, ],
})
// All KAPLAY functions are imported to global after calling kaplay()
add()
onUpdate()
onKeyPress()
vec2()
// If you want to prevent KAPLAY from importing all functions to global and use a context handle for all KAPLAY functions
const k = kaplay({ global: false })
k.add(...)
k.onUpdate(...)
k.onKeyPress(...)
k.vec2(...)
```
# [quit](#quit)(): void
End everything.
`since`v2000.0
# [KAPLAYOpt](#KAPLAYOpt)\<TPlugin, TButtonDef\>:
KAPLAY configurations.
# [width](#KAPLAYOpt-width)?: number
Width of game.
# [height](#KAPLAYOpt-height)?: number
Height of game.
# [scale](#KAPLAYOpt-scale)?: number
Pixel scale / size.
# [letterbox](#KAPLAYOpt-letterbox)?: boolean
Keep aspect ratio and leave black bars on remaining spaces.
# [debug](#KAPLAYOpt-debug)?: boolean
If register debug buttons (default true)
# [debugKey](#KAPLAYOpt-debugKey)?: Key
Key that toggles debug mode
# [font](#KAPLAYOpt-font)?: string
Default font (defaults to \"monospace\").
# [pixelDensity](#KAPLAYOpt-pixelDensity)?: number
Device pixel scale (defaults to 1, high pixel density will hurt performance).
`since`v3000.0
# [crisp](#KAPLAYOpt-crisp)?: boolean
Disable antialias and enable sharp pixel display.
# [canvas](#KAPLAYOpt-canvas)?: HTMLCanvasElement
The canvas DOM element to use. If empty will create one.
# [root](#KAPLAYOpt-root)?: HTMLElement
The container DOM element to insert the canvas if created. Defaults to document.body.
# [background](#KAPLAYOpt-background)?: RGBValue \| RGBAValue \| string
Background color. E.g. \[ 0, 0, 255 \] for solid blue background, or \[ 0, 0, 0, 0 \] for transparent background. Accepts RGB value array or string hex codes.
# [texFilter](#KAPLAYOpt-texFilter)?: TexFilter
Default texture filter.
# [logMax](#KAPLAYOpt-logMax)?: number
How many log messages can there be on one screen (default 8).
# [logTime](#KAPLAYOpt-logTime)?: number
How many seconds log messages stay on screen (default 4).
`since`v3000.1
# [hashGridSize](#KAPLAYOpt-hashGridSize)?: number
Size of the spatial hash grid for collision detection (default 64).
`since`v3000.0
# [touchToMouse](#KAPLAYOpt-touchToMouse)?: boolean
If translate touch events as mouse clicks (default true).
# [loadingScreen](#KAPLAYOpt-loadingScreen)?: boolean
If KAPLAY should render a default loading screen when assets are not fully ready (default true).
`since`v3000.0
# [backgroundAudio](#KAPLAYOpt-backgroundAudio)?: boolean
If pause audio when tab is not active (default false).
`since`v3000.0
# [gamepads](#KAPLAYOpt-gamepads)?: Record\<string, GamepadDef\>
Custom gamepad definitions (see gamepad.json for reference of the format).
`since`v3000.0
# [buttons](#KAPLAYOpt-buttons)?: TButtonDef
Defined buttons for input binding.
`since`v30010
# [maxFPS](#KAPLAYOpt-maxFPS)?: number
Limit framerate to an amount per second.
`since`v3000.0
# [focus](#KAPLAYOpt-focus)?: boolean
If focus on the canvas on start (default true).
`since`v3001.0
# [global](#KAPLAYOpt-global)?: boolean
If import all KAPLAY functions to global (default true).
# [plugins](#KAPLAYOpt-plugins)?: TPlugin
List of plugins to import.
# [burp](#KAPLAYOpt-burp)?: boolean
Enter burp mode.
# [tagsAsComponents](#KAPLAYOpt-tagsAsComponents)?: boolean
Make component's id (\"sprite\" for sprite() comp) be added as tags. That means .is() will return true for components with that id.
`default`true
`experimental`This feature is in experimental phase, it will be fully released in v3001.1.0
# [spriteAtlasPadding](#KAPLAYOpt-spriteAtlasPadding)?: number
Padding used when adding sprites to texture atlas.
`default`0
# [inspectOnlyActive](#KAPLAYOpt-inspectOnlyActive)?: boolean
If the debug inspect view should ignore objects that are paused when choosing the object to show the inspect view on.
`default`false
`experimental`
# [loadRoot](#loadRoot)(path?: string): string
Sets the root for all subsequent resource urls. This is useful when you want to load assets from a different domain, or setup a base path for all assets.
`param`path- The root path.
``` js
loadRoot("https://myassets.com/");
loadSprite("bean", "sprites/bean.png"); // will resolve to "https://myassets.com/sprites/bean.png"
loadRoot("./"); // useful for Itch.io
```
# [loadSprite](#loadSprite)(name: string \| null, src: LoadSpriteSrc \| LoadSpriteSrc\[\], opt?: LoadSpriteOpt): Asset\<SpriteData\>
Load a sprite into asset manager, with name and resource url and optional config.
`param`name- The asset name.
`param`src- The resource url.
`param`opt- The optional config.
``` js
// due to browser policies you'll need a static file server to load local files
loadSprite("bean", "bean.png");
loadSprite("apple", "https://play.kaplayjs.com/sprites/apple.png");
// slice a spritesheet and add anims manually
loadSprite("bean", "bean.png", {
sliceX: 4,
sliceY: 1,
anims: {
run: {
from: 0,
to: 3,
},
jump: {
from: 3,
to: 3,
},
},
});
```
`returns`The asset data.
`since`v2000.0
# [loadSpriteAtlas](#loadSpriteAtlas)(src: LoadSpriteSrc, data: SpriteAtlasData): Asset\<Record\>
Load sprites from a sprite atlas.
`param`src- The image resource url.
`param`data- The sprite atlas data.
``` js
// See #SpriteAtlasData type for format spec
loadSpriteAtlas("sprites/dungeon.png", {
"hero": {
x: 128,
y: 68,
width: 144,
height: 28,
sliceX: 9,
anims: {
idle: { from: 0, to: 3 },
run: { from: 4, to: 7 },
hit: 8,
},
},
});
const player = add([
sprite("hero"),
]);
player.play("run");
```
`returns`The asset data.
`since`v2000.0
# [loadSpriteAtlas](#loadSpriteAtlas)(src: LoadSpriteSrc, url: string): Asset\<Record\>
Load sprites from a sprite atlas with URL.
`param`src- The image resource url.
`param`url- The json resource url.
``` js
// Load from json file, see #SpriteAtlasData type for format spec
loadSpriteAtlas("sprites/dungeon.png", "sprites/dungeon.json")
const player = add([
sprite("hero"),
])
player.play("run")
```
`returns`The asset data.
`since`v2000.0
# [loadAseprite](#loadAseprite)(name: string \| null, imgSrc: LoadSpriteSrc, jsonSrc: string \| AsepriteData): Asset\<SpriteData\>
Load a sprite with aseprite spritesheet json (should use \"array\" in the export options and have tags enabled, that way kaplay can load tagged frames as animations).
`param`name- The asset name.
`param`imgSrc- The image resource url.
``` js
loadAseprite("car", "sprites/car.png", "sprites/car.json")
```
`returns`The asset data.
`since`v2000.0
# [loadPedit](#loadPedit)(name: string \| null, src: string): Asset\<SpriteData\>
`param`name- The asset name.
`param`src- The resource url. Load .pedit file.
`deprecated`The format is not supported anymore.
`returns`The asset data.
`since`v2000.0
# [loadBean](#loadBean)(name?: string): Asset\<SpriteData\>
Load default sprite \"bean\".
`param`name- An optional name for bean.
``` js
loadBean();
// use it right away
add([
sprite("bean"),
]);
```
`returns`The asset data.
`since`v2000.0
# [loadJSON](#loadJSON)(name: string \| null, url: string): Asset\<any\>
Load custom JSON data from url.
`param`name- The asset name.
`param`url- The resource url.
`returns`The asset data.
`since`v3000.0
# [loadSound](#loadSound)(name: string \| null, src: string \| ArrayBuffer \| AudioBuffer): Asset\<SoundData\>
Load a sound into asset manager, with name and resource url. Supported formats: mp3, ogg, wav.
`param`name- The asset name.
`param`src- The resource url.
``` js
loadSound("shoot", "/sounds/horse.ogg");
loadSound("shoot", "/sounds/squeeze.mp3");
loadSound("shoot", "/sounds/shoot.wav");
```
`returns`The asset data.
`since`v2000.0
# [loadMusic](#loadMusic)(name: string \| null, url: string): void
Like loadSound(), but the audio is streamed and won't block loading. Use this for big audio files like background music.
`param`name- The asset name.
`param`url- The resource url.
``` js
loadMusic("shoot", "/music/bossfight.mp3");
```
`returns`The asset data.
`since`v3001.0
# [loadFont](#loadFont)(name: string, src: string \| ArrayBuffer \| ArrayBufferView, opt?: LoadFontOpt): Asset\<FontData\>
Load a font (any format supported by the browser, e.g. ttf, otf, woff).
`param`name- The asset name.
``` js
// load a font from a .ttf file
loadFont("frogblock", "fonts/frogblock.ttf");
```
`returns`The asset data.
`since`v3000.0
# [loadBitmapFont](#loadBitmapFont)(name: string \| null, src: string, gridW: number, gridH: number, opt?: LoadBitmapFontOpt): Asset\<BitmapFontData\>
Load a bitmap font into asset manager, with name and resource url and information on the layout of the bitmap.
`param`name- The asset name.
`param`src- The resource url.
`param`gridW- The width of each character on the bitmap.
`param`gridH- The height of each character on the bitmap.
`param`opt- The options for the bitmap font.
``` js
// load a bitmap font called "04b03", with bitmap "fonts/04b03.png"
// each character on bitmap has a size of (6, 8), and contains default ASCII_CHARS
loadBitmapFont("04b03", "fonts/04b03.png", 6, 8);
// load a font with custom characters
loadBitmapFont("myfont", "myfont.png", 6, 8, { chars: "☺☻♥♦♣♠" });
```
`returns`The asset data.
`since`v3000.0
# [loadShader](#loadShader)(name: string \| null, vert?: string \| null, frag?: string \| null): Asset\<ShaderData\>
Load a shader with vertex and fragment code.
`param`name- The asset name.
`param`vert- The vertex shader code. Null if not needed.
`param`frag- The fragment shader code. Null if not needed.
``` js
// default shaders and custom shader format
loadShader("outline",
`vec4 vert(vec2 pos, vec2 uv, vec4 color) {
// predefined functions to get the default value by KAPLAY
return def_vert();
}`,
`vec4 frag(vec2 pos, vec2 uv, vec4 color, sampler2D tex) {
// turn everything blue-ish
return def_frag() * vec4(0, 0, 1, 1);
}`, false)
```
`returns`The asset data.
`since`v2000.0
# [loadShaderURL](#loadShaderURL)(name: string \| null, vert?: string \| null, frag?: string \| null): Asset\<ShaderData\>
Load a shader with vertex and fragment code file url.
`param`name- The name of the asset.
`param`vert- The vertex shader code. Null if not needed.
`param`frag- The fragment shader code. Null if not needed.
``` js
// load only a fragment shader from URL
loadShaderURL("outline", null, "/shaders/outline.glsl")
```
`retunrs`The asset data.
`since`v3000.0
# [load](#load)\<T\>(l: Promise): Asset\<T\>
Add a new loader to wait for before starting the game.
`param`l- The loader to wait for.
``` js
load(new Promise((resolve, reject) => {
// anything you want to do that stalls the game in loading state
resolve("ok")
}))
```
`returns`The asset data.
`since`v3000.0
# [loadProgress](#loadProgress)(): number
Get the global asset loading progress (0.0 - 1.0).
`returns`The loading progress.
`since`v3000.0
# [getSprite](#getSprite)(name: string): Asset \| null
Get SpriteData from name.
`param`name- The asset name.
`returns`The asset data.
`since`v3000.0
# [getSound](#getSound)(name: string): Asset \| null
Get SoundData from name.
`param`name- The asset name.
`returns`The asset data.
`since`v3000.0
# [getFont](#getFont)(name: string): Asset \| null
Get FontData from name.
`param`name- The asset name.
`returns`The asset data.
`since`v3000.0
# [getBitmapFont](#getBitmapFont)(name: string): Asset \| null
Get BitmapFontData from name.
`param`name- The asset name.
`returns`The asset data.
`since`v3000.0
# [getShader](#getShader)(name: string): Asset \| null
Get ShaderData from name.
`param`name- The asset name.
`returns`The asset data.
`since`v3000.0
# [getAsset](#getAsset)(name: string): Asset \| null
Get custom data from name.
`param`name- The asset name.
`returns`The asset data.
`since`v3000.0
# [Asset](#Asset)\<D\>:
An asset is a resource that is loaded asynchronously. It can be a sprite, a sound, a font, a shader, etc.
# [loaded](#Asset-loaded): boolean
# [loaded](#Asset-loaded)\<D\>(data: D): Asset\<D\>
# [data](#Asset-data): D \| null
# [error](#Asset-error): Error \| null
# [onLoadEvents](#Asset-onLoadEvents):
# [onErrorEvents](#Asset-onErrorEvents):
# [onFinishEvents](#Asset-onFinishEvents):
# [onLoad](#Asset-onLoad)(action: (data: D)=\>void): this
# [onError](#Asset-onError)(action: (err: Error)=\>void): this
# [onFinish](#Asset-onFinish)(action: ()=\>void): this
# [then](#Asset-then)(action: (data: D)=\>void): Asset\<D\>
# [catch](#Asset-catch)(action: (err: Error)=\>void): Asset\<D\>
# [finally](#Asset-finally)(action: ()=\>void): Asset\<D\>
# [SpriteData](#SpriteData):
# [tex](#SpriteData-tex): Texture
# [frames](#SpriteData-frames): Quad\[\]
# [anims](#SpriteData-anims): SpriteAnims
# [slice9](#SpriteData-slice9): NineSlice \| null
# [packerId](#SpriteData-packerId): number \| null
# [width](#SpriteData-width)(): number
`since`v3001.0
# [height](#SpriteData-height)(): number
# [from](#SpriteData-from)(src: LoadSpriteSrc, opt?: LoadSpriteOpt): Promise\<SpriteData\>
# [fromImage](#SpriteData-fromImage)(data: ImageSource, opt?: LoadSpriteOpt): SpriteData
# [fromURL](#SpriteData-fromURL)(url: string, opt?: LoadSpriteOpt): Promise\<SpriteData\>
# [SoundData](#SoundData):
# [buf](#SoundData-buf): AudioBuffer
# [fromAudioBuffer](#SoundData-fromAudioBuffer)(buf: AudioBuffer): SoundData
# [fromArrayBuffer](#SoundData-fromArrayBuffer)(buf: ArrayBuffer): Promise\<SoundData\>
# [fromURL](#SoundData-fromURL)(url: string): Promise\<SoundData\>
# [GameObjRaw](#GameObjRaw):
Base interface of all game objects.
`since`v2000.0
# [id](#GameObjRaw-id): GameObjID
The unique id of the game obj.
# [children](#GameObjRaw-children): GameObj\[\]
Get all children game objects.
`readonly`
`since`v3000.0
# [tags](#GameObjRaw-tags): string\[\]
Get the tags of a game object. For update it, use \`tag()\` and \`untag()\`.
`readonly`
`since`v3001.0
# [transform](#GameObjRaw-transform): Mat23
Calculated transform matrix of a game object.
`since`v3000.0
# [hidden](#GameObjRaw-hidden): boolean
If draw the game obj (run \"draw\" event or not).
`since`v2000.0
# [paused](#GameObjRaw-paused): boolean
If update the game obj (run \"update\" event or not).
`since`v2000.0
# [target](#GameObjRaw-target)?: RenderTarget
The canvas to draw this game object on
`since`v3001.0
# [setParent](#GameObjRaw-setParent)(p: GameObj, opt: SetParentOpt): void
Set the parent game obj with additional options.
`since`v4000.0
# [add](#GameObjRaw-add)\<T\>(comps?: \[RestType\]): GameObj\<T\[number\]\>
Add a child.
`param`comps- The components to add.
`returns`The added game object.
`since`v3000.0
# [readd](#GameObjRaw-readd)\<T\>(obj: GameObj): GameObj\<T\>
Remove and re-add the game obj, without triggering add / destroy events.
`param`obj- The game object to re-add.
`returns`The re-added game object.
`since`v3000.0
# [remove](#GameObjRaw-remove)(obj: GameObj): void
Remove a child.
`param`obj- The game object to remove.
`since`v3000.0
# [removeAll](#GameObjRaw-removeAll)(tag: Tag): void
Remove all children with a certain tag.
`param`tag- The tag to remove.
`since`v3000.0
# [removeAll](#GameObjRaw-removeAll)(): void
Remove all children.
`since`v3000.0
# [destroy](#GameObjRaw-destroy)(): void
Remove this game obj from scene.
`since`v2000.0
# [exists](#GameObjRaw-exists)(): boolean
If game obj is attached to the scene graph.
`returns`true if attached, false otherwise.
`since`v2000.0
# [isAncestorOf](#GameObjRaw-isAncestorOf)(obj: GameObj): boolean
Check if is an ancestor (recursive parent) of another game object
`returns`true if is ancestor, false otherwise.
`since`v3000.0
# [get](#GameObjRaw-get)\<T\>(tag: Tag \| Tag\[\], opts?: GetOpt): GameObj\[\]
Get a list of all game objs with certain tag.
`param`tag- The tag to get.
`since`v3000.0
# [query](#GameObjRaw-query)(opt: QueryOpt): GameObj\[\]
Get a list of all game objs with certain properties.
`param`opt- The properties to get.
`since`v3001.0
# [update](#GameObjRaw-update)(): void
Update this game object and all children game objects.
`since`v3000.0
# [fixedUpdate](#GameObjRaw-fixedUpdate)(): void
Update this game object and all children game objects.
`since`v3001.0
# [draw](#GameObjRaw-draw)(): void
Draw this game object and all children game objects.
`since`v3000.0
# [drawTree](#GameObjRaw-drawTree)(): void
# [inspect](#GameObjRaw-inspect)(): GameObjInspect
Gather debug info of all comps.
`since`v2000.0
# [drawInspect](#GameObjRaw-drawInspect)(): void
Draw debug info in inspect mode
`since`v3000.0
# [collectAndTransform](#GameObjRaw-collectAndTransform)(objects: GameObj\[\]): void
This method is called to transform and collect objects which should be drawn layered
# [use](#GameObjRaw-use)(comp: Comp): void
Add a component.
``` js
const obj = add([
sprite("bean"),
]);
// Add opacity
obj.use(opacity(0.5));
```
`since`v2000.0
# [unuse](#GameObjRaw-unuse)(comp: string): void
Remove a component with its id (the component name)
`param`comp- The component id to remove. It means the name, if sprite, then it's \"sprite\".
``` js
// Remove sprite component
obj.unuse("sprite");
```
`since`v2000.0
# [has](#GameObjRaw-has)(compId: string \| string\[\], op?: and \| or): boolean
Check if game object has a certain component.
`param`compId- The component id(s) to check.
`param`op- The operator to use when searching for multiple components. Default is \"and\".
``` js
// Check if game object has sprite component
if(obj.has("sprite")) {
debug.log("has sprite component");
}
// Check if game object has tags
obj.has(["tag1", "tag2"]); // AND, it has both tags
obj.has(["tag1", "tag2"], "or"); // OR, it has either tag1 or tag2
```
`returns`true if has the component(s), false otherwise.
`since`v3001.0.5
`experimental`This feature is in experimental phase, it will be fully released in v3001.1.0
# [c](#GameObjRaw-c)(id: string): Comp \| null
Get state for a specific comp.
`param`id- The component id.
`since`v2000.0
# [tag](#GameObjRaw-tag)(tag: Tag \| Tag\[\]): void
Add a tag(s) to the game obj.
`param`tag- The tag(s) to add.
``` js
// add enemy tag
obj.tag("enemy");
// add multiple tags
obj.tag(["enemy", "boss"]);
```
`since`v3001.0.5
`experimental`This feature is in experimental phase, it will be fully released in v3001.1.0
# [untag](#GameObjRaw-untag)(tag: Tag \| Tag\[\]): void
Remove a tag(s) from the game obj.
`param`tag- The tag(s) to remove.
``` js
// remove enemy tag
obj.untag("enemy");
// remove multiple tags
obj.untag(["enemy", "boss"]);
```
`since`v3001.0.5
`experimental`This feature is in experimental phase, it will be fully released in v3001.1.0
# [is](#GameObjRaw-is)(tag: Tag \| Tag\[\], op?: and \| or): boolean
If there's certain tag(s) on the game obj.
`param`tag- The tag(s) for checking.
`param`op- The operator to use when searching for multiple tags. Default is \"and\".
`since`v3001.0.5
`experimental`This feature is in experimental phase, it will be fully released in v3001.1.0
# [on](#GameObjRaw-on)(event: GameObjEventNames \| string & , action: (args: any)=\>void): KEventController
Register an event.
`param`event- The event name.
`param`action- The action to run when event is triggered.
`returns`The event controller.
`since`v2000.0
# [trigger](#GameObjRaw-trigger)(event: string, args: any): void
Trigger an event.
`param`event- The event name.
`parm`args - The arguments to pass to the event action.
`since`v2000.0
# [clearEvents](#GameObjRaw-clearEvents)(): void
Clear all events.
# [onAdd](#GameObjRaw-onAdd)(action: ()=\>void): KEventController
Register an event that runs when the game obj is added to the scene.
`returns`The event controller.
`since`v2000.0
# [onUpdate](#GameObjRaw-onUpdate)(action: ()=\>void): KEventController
Register an event that runs every frame as long as the game obj exists.
`returns`The event controller.
`since`v2000.1
# [onFixedUpdate](#GameObjRaw-onFixedUpdate)(action: ()=\>void): KEventController
Register an event that runs every frame as long as the game obj exists.
`returns`The event controller.
`since`v2000.1
# [onDraw](#GameObjRaw-onDraw)(action: ()=\>void): KEventController
Register an event that runs every frame as long as the game obj exists (this is the same as \`onUpdate()\`, but all draw events are run after all update events).
`returns`The event controller.
`since`v2000.1
# [onDestroy](#GameObjRaw-onDestroy)(action: ()=\>void): KEventController
Register an event that runs when the game obj is destroyed.
`returns`The event controller.
`since`v2000.1
# [onUse](#GameObjRaw-onUse)(action: (id: string)=\>void): KEventController
Register an event that runs when a component is used.
`returns`The event controller.
`since`v4000.0
# [onUnuse](#GameObjRaw-onUnuse)(action: (id: string)=\>void): KEventController
Register an event that runs when a component is unused.
`returns`The event controller.
`since`v4000.0
# [onTag](#GameObjRaw-onTag)(action: (tag: string)=\>void): KEventController
Register an event that runs when a tag is added.
`returns`The event controller.
`since`v4000.0
# [onUntag](#GameObjRaw-onUntag)(action: (tag: string)=\>void): KEventController
Register an event that runs when a tag is removed.
`returns`The event controller.
`since`v4000.0
# [onKeyDown](#GameObjRaw-onKeyDown): KAPLAYCtx\[onKeyDown\]
# [onKeyPress](#GameObjRaw-onKeyPress): KAPLAYCtx\[onKeyPress\]
# [onKeyPressRepeat](#GameObjRaw-onKeyPressRepeat): KAPLAYCtx\[onKeyPressRepeat\]
# [onKeyRelease](#GameObjRaw-onKeyRelease): KAPLAYCtx\[onKeyRelease\]
# [onCharInput](#GameObjRaw-onCharInput): KAPLAYCtx\[onCharInput\]
# [onMouseDown](#GameObjRaw-onMouseDown): KAPLAYCtx\[onMouseDown\]
# [onMousePress](#GameObjRaw-onMousePress): KAPLAYCtx\[onMousePress\]
# [onMouseRelease](#GameObjRaw-onMouseRelease): KAPLAYCtx\[onMouseRelease\]
# [onMouseMove](#GameObjRaw-onMouseMove): KAPLAYCtx\[onMouseMove\]
# [onTouchStart](#GameObjRaw-onTouchStart): KAPLAYCtx\[onTouchStart\]
# [onTouchMove](#GameObjRaw-onTouchMove): KAPLAYCtx\[onTouchMove\]
# [onTouchEnd](#GameObjRaw-onTouchEnd): KAPLAYCtx\[onTouchEnd\]
# [onScroll](#GameObjRaw-onScroll): KAPLAYCtx\[onScroll\]
# [onGamepadButtonDown](#GameObjRaw-onGamepadButtonDown): KAPLAYCtx\[onGamepadButtonDown\]
# [onGamepadButtonPress](#GameObjRaw-onGamepadButtonPress): KAPLAYCtx\[onGamepadButtonPress\]
# [onGamepadButtonRelease](#GameObjRaw-onGamepadButtonRelease): KAPLAYCtx\[onGamepadButtonRelease\]
# [onGamepadStick](#GameObjRaw-onGamepadStick): KAPLAYCtx\[onGamepadStick\]
# [onButtonDown](#GameObjRaw-onButtonDown): KAPLAYCtx\[onButtonDown\]
# [onButtonPress](#GameObjRaw-onButtonPress): KAPLAYCtx\[onButtonPress\]
# [onButtonRelease](#GameObjRaw-onButtonRelease): KAPLAYCtx\[onButtonRelease\]
# [\_parent](#GameObjRaw-_parent): GameObj
`readonly`
# [\_compsIds](#GameObjRaw-_compsIds): Set\<string\>
# [\_compStates](#GameObjRaw-_compStates): Map\<string, Comp\>
# [\_anonymousCompStates](#GameObjRaw-_anonymousCompStates): Comp\[\]
# [\_cleanups](#GameObjRaw-_cleanups): Record\<string, ()=\>any\[\]\>
# [\_events](#GameObjRaw-_events): KEventHandler\<any\>
# [\_fixedUpdateEvents](#GameObjRaw-_fixedUpdateEvents): KEvent\<\[\]\>
# [\_updateEvents](#GameObjRaw-_updateEvents): KEvent\<\[\]\>
# [\_drawEvents](#GameObjRaw-_drawEvents): KEvent\<\[\]\>
# [\_inputEvents](#GameObjRaw-_inputEvents): KEventController\[\]
# [\_onCurCompCleanup](#GameObjRaw-_onCurCompCleanup): Function \| null
# [\_tags](#GameObjRaw-_tags): Set\<Tag\>
# [add](#add)\<T\>(comps?: \[RestType\]): GameObj\<T\[number\]\>
Assemble a game object from a list of components, and add it to the game,
`param`comps- List of components to add to the game object.
``` js
const player = add([
// List of components, each offers a set of functionalities
sprite("mark"),
pos(100, 200),
area(),
body(),
health(8),
// Plain strings are tags, a quicker way to let us define behaviors for a group
"player",
"friendly",
// Components are just plain objects, you can pass an object literal as a component.
{
dir: LEFT,
dead: false,
speed: 240,
},
]);
// .jump is provided by body()
player.jump();
// .moveTo is provided by pos()
player.moveTo(300, 200);
// .onUpdate() is on every game object, it registers an event that runs every frame
player.onUpdate(() => {
// .move() is provided by pos()
player.move(player.dir.scale(player.speed));
});
// .onCollide is provided by area()
player.onCollide("tree", () => {
destroy(player);
});
```
`returns`The added game object that contains all properties and methods each component offers.
# [readd](#readd)(obj: GameObj): GameObj
Remove and re-add the game obj, without triggering add / destroy events.
`param`obj- The game object to re-add.
``` js
// Common way to use this is to have one sprite overlap another sprite, and use readd() to have the bottom sprite on top of the other.
// Create two sprites.
const greenBean = add([
sprite("bean"),
pos(200,140),
color(255, 255, 255),
area(),
]);
// This bean will overlap the green bean.
const purpleBean = add([
sprite("bean"),
pos(230,140),
color(255, 0, 255),
area(),
]);
// Example 1: simply call readd() on the target you want on top.
readd(greenBean);
// Example 2: using onClick() or other functions with readd().
// If you comment out the first example, and use this readd() with a function like onClick(), you
can keep switching which sprite is above the other ( click on edge of face ).
purpleBean.onClick(() => {
readd(greenBean);
});
greenBean.onClick(() => {
readd(purpleBean);
});
```
`returns`The re-added game object.
`since`v3001.0
# [get](#get)\<T\>(tag: Tag \| Tag\[\], opts?: GetOpt): GameObj\[\]
Get a list of all game objs with certain tag.
`param`tag- The tag to search for. Use \"\*\" to get all objects.
`param`opts- Additional options.
``` js
// get a list of all game objs with tag "bomb"
const allBombs = get("bomb");
// To get all objects use "*"
const allObjs = get("*");
// Recursively get all children and descendents
const allObjs = get("*", { recursive: true });
// Get a live query which updates in real-time
const allObjs = get("*", { liveUpdate: true });
```
`returns`A list of game objects that have the tag.
`since`v2000.0
# [query](#query)(opt: QueryOpt): GameObj\[\]
Get a list of game objects in an advanced way.
`param`opt- The query options.
``` js
const bean = k.add(["friend", "bean"]);
const bean2 = k.add(["friend", "bean"]);
const bag = k.add(["friend", "bag"]);
// get bean
query({
include: "bean",
}) // will return [bean, bean2];
// get all friends excluding bean
query({
include: "friend",
exclude: "bean",
}); // will return [bag]
// get all visible friends
query({
include: "friend",
visible: true,
});
// get all friends less than 150 pixels from bean
bean.query({
include: "friend",
distance: 150,
});
```
# [destroy](#destroy)(obj: GameObj): void
Remove the game obj.
`param`obj- The game object to remove.
``` js
// every time bean collides with anything with tag "fruit", remove it
bean.onCollide("fruit", (fruit) => {
destroy(fruit);
});
```
# [destroyAll](#destroyAll)(tag: Tag): void
Remove all game objs with certain tag.
`param`tag- The tag to search for.
``` js
// destroy all objects with tag "bomb" when you click one
onClick("bomb", () => {
destroyAll("bomb");
});
```
# [KeepFlags](#KeepFlags):
# [Pos](#KeepFlags-Pos):
# [Angle](#KeepFlags-Angle):
# [Scale](#KeepFlags-Scale):
# [All](#KeepFlags-All):
# [GameObj](#GameObj)\<T\>: GameObjRaw & MergeComps
The basic unit of object in KAPLAY. The player, a butterfly, a tree, or even a piece of text.
# [GameObjID](#GameObjID): number
# [pos](#pos)(x: number, y: number): PosComp
Set the position of a Game Object.
`param`x- The x position to set.
`param`y- The y position to set.
``` js
// This game object will draw a "bean" sprite at (100, 200)
add([
pos(100, 200),
sprite("bean"),
]);
```
`returns`The position comp.
`since`v2000.0
# [pos](#pos)(xy: number): PosComp
# [pos](#pos)(p: Vec2): PosComp
# [pos](#pos)(): PosComp
# [scale](#scale)(x: number, y: number): ScaleComp
Set the scale of a Game Object.
`param`x- The x scale to set.
`param`y- The y scale to set.
``` js
// scale uniformly with one value
add([
sprite("bean"),
scale(3),
]);
// scale with x & y values. In this case, scales more horizontally.
add([
sprite("bean"),
scale(3, 1),
]);
// scale with vec2(x,y).
bean.scale = vec2(2,4);
```
`returns`The scale comp.
`since`v2000.0
# [scale](#scale)(xy: number): ScaleComp
# [scale](#scale)(s: Vec2): ScaleComp
# [scale](#scale)(): ScaleComp
# [rotate](#rotate)(a?: number): RotateComp
Rotates a Game Object (in degrees).
`param`a- The angle to rotate by. Defaults to 0.
``` js
let bean = add([
sprite("bean"),
rotate(),
])
// bean will be upside down!
bean.angle = 180
```
`returns`The rotate comp.
`since`v2000.0
# [color](#color)(r: number, g: number, b: number): ColorComp
Sets the color of a Game Object (rgb 0-255).
`param`r- The red value to set.
`param`g- The green value to set.
`param`b- The blue value to set.
``` js
// blue frog
add([
sprite("bean"),
color(0, 0, 255),
]);
```
`returns`The color comp.
`since`v2000.0
# [color](#color)(c: Color): ColorComp
# [color](#color)(rgb: \[number, number, number\]): ColorComp
# [color](#color)(c: CSSColor & string \| ): ColorComp
# [color](#color)(): ColorComp
# [blend](#blend)(blend: BlendMode): BlendComp
Sets the blend mode of a Game Object.
``` js
// light
add([
sprite("light"),
blend(BlendMode.Add),
]);
```
`returns`The blend comp.
`since`v4000.0
# [opacity](#opacity)(o?: number): OpacityComp
Sets the opacity of a Game Object (0.0 - 1.0).
`param`o- The opacity value to set.
``` js
const bean = add([
sprite("bean"),
opacity(0.5) // Make bean 50% transparent
])
// Make bean invisible
bean.opacity = 0
// Make bean fully visible
bean.opacity = 1
```
`returns`The opacity comp.
`since`v2000.0
# [sprite](#sprite)(spr: string \| SpriteData \| Asset, opt?: SpriteCompOpt): SpriteComp
Attach and render a sprite to a Game Object.
`param`spr- The sprite to render.
`param`opt- Options for the sprite component. See
``` js
// minimal setup
add([
sprite("bean"),
])
// with options
const bean = add([
sprite("bean", {
// start with animation "idle"
anim: "idle",
}),
])
// play / stop an anim
bean.play("jump")
bean.stop()
// manually setting a frame
bean.frame = 3
```
`returns`The sprite comp.
`since`v2000.0
# [text](#text)(txt?: string, opt?: TextCompOpt): TextComp
Attach and render a text to a Game Object.
`param`txt- The text to display.
`param`opt- Options for the text component. See
``` js
// a simple score counter
const score = add([
text("Score: 0"),
pos(24, 24),
{ value: 0 },
])
player.onCollide("coin", () => {
score.value += 1
score.text = "Score:" + score.value
})
// with options
add([
pos(24, 24),
text("ohhi", {
size: 48, // 48 pixels tall
width: 320, // it'll wrap to next line when width exceeds this value
font: "sans-serif", // specify any font you loaded or browser built-in
}),
])
```
`returns`The text comp.
`since`v2000.0
# [polygon](#polygon)(pts: Vec2\[\], opt?: PolygonCompOpt): PolygonComp
Attach and render a polygon to a Game Object.
`param`pts- The points to render the polygon.
`param`opt- Options for the polygon component. See
``` js
// Make a square the hard way
add([
pos(80, 120),
polygon([vec2(0,0), vec2(50,0), vec2(50,50), vec2(0,50)]),
outline(4),
area(),
])
```
`returns`The polygon comp.
`since`v3001.0
# [rect](#rect)(w: number, h: number, opt?: RectCompOpt): RectComp
Attach and render a rectangle to a Game Object.
`param`w- The width of the rectangle.
`param`h- The height of the rectangle.
`param`opt- Options for the rectangle component. See
``` js
const obstacle = add([
pos(80, 120),
rect(20, 40),
outline(4),
area(),
])
```
`returns`The rectangle component.
# [circle](#circle)(radius: number, opt?: CircleCompOpt): CircleComp
Attach and render a circle to a Game Object.
`param`radius- The radius of the circle.
`param`opt- Options for the circle component. See
``` js
add([
pos(80, 120),
circle(16),
])
```
`returns`The circle comp.
`since`v2000.0
# [ellipse](#ellipse)(radiusX: number, radiusY: number): EllipseComp
Attach and render an ellipse to a Game Object.
`param`radiusX- The radius of the ellipse on the x-axis.
`param`radiusY- The radius of the ellipse on the y-axis.
``` js
add([
pos(80, 120),
ellipse(16, 8),
])
```
`returns`The ellipse comp.
`since`v2000.0
# [uvquad](#uvquad)(w: number, h: number): UVQuadComp
Attach and render a UV quad to a Game Object.
`param`w- The width of the quad.
`param`h- The height of the quad.
``` js
add([
uvquad(width(), height()),
shader("spiral"),
])
```
`returns`The UV quad comp.
`since`v2000.0
# [video](#video)(url: string, opt?: VideoCompOpt): VideoComp
Draws a video.
`param`urlThe video to play. Needs to be on the same webserver due to CORS.
`param`optThe video component options
`returns`The video comp.
`since`v4000.0
# [picture](#picture)(picture: Picture): PictureComp
Draws a picture.
`param`pictureThe picture to draw.
`returns`The picture comp.
`since`v4000.0
# [area](#area)(opt?: AreaCompOpt): AreaComp
Attach a collider area from shape and enables collision detection in a Game Object.
`param`opt- Options for the area component. See
``` js
// Automatically generate area information from the shape of render
const player = add([
sprite("bean"),
area(),
])
// Die if player collides with another game obj with tag "tree"
player.onCollide("tree", () => {
destroy(player)
go("lose")
})
// Check for collision manually every frame instead of registering an event
player.onUpdate(() => {
if (player.isColliding(bomb)) {
score += 1
}
})
```
`returns`The area comp.
`since`v2000.0
# [anchor](#anchor)(o: Anchor \| Vec2): AnchorComp
Anchor point for render (default \"topleft\").
`param`o- The anchor point to set.
``` js
// set anchor to "center" so it'll rotate from center
add([
rect(40, 10),
rotate(45),
anchor("center"),
])
```
`returns`The anchor comp.
`since`v2000.0
# [z](#z)(z: number): ZComp
Determines the draw order for objects on the same layer. Object will be drawn on top if z value is bigger.
`param`z- The z value to set.
``` js
const bean = add([
sprite("bean"),
pos(100, 100),
z(10), // Bean has a z value of 10
])
// Mark has a z value of 20, so he will always be drawn on top of bean
const mark = add([
sprite("mark"),
pos(100, 100),
z(20),
])
bean.z = 30 // Bean now has a higher z value, so it will be drawn on top of mark
```
`returns`The z comp.
`since`v2000.0
# [outline](#outline)(width?: number, color?: Color, opacity?: number, join?: LineJoin, miterLimit?: number, cap?: LineCap): OutlineComp
Give an object an outline. Doesn't support sprite or text components.
`param`width- The width of the outline.
`param`color- The color of the outline.
`param`opacity- The opacity of the outline.
`param`join- -The line join style.
`param`miterLimit- The miter limit ratio.
`param`cap-The line cap style.
``` js
// Add an outline to a rectangle
add([
rect(40, 40),
outline(4),
]);
```
`returns`The outline comp.
`since`v2000.0
# [particles](#particles)(popt: ParticlesOpt, eopt: EmitterOpt): ParticlesComp
Attach a particle emitter to a Game Object.
`param`popt- The options for the particles.
`param`eopt- The options for the emitter.
``` js
// beansplosion
// create the emitter
const emitter = add([
pos(center()),
particles({
max: 100,
speed: [75, 100],
lifeTime: [0.75,1.0],
angle: [0, 360],
opacities: [1.0, 0.0],
texture: getSprite("bean").tex, // texture of a sprite
quads: getSprite("bean").frames, // frames of a sprite
}, {
direction: 0,
spread: 360,
}),
])
onUpdate(() => {
emitter.emit(1)
})
```
`returns`The particles comp.
`since`v3001.0
# [body](#body)(opt?: BodyCompOpt): BodyComp
Physical body that responds to gravity. Requires \"area\" and \"pos\" comp. This also makes the object \"solid\".
`param`opt- Options for the body component. See
``` js
// bean jumpy
const bean = add([
sprite("bean"),
// body() requires "pos" and "area" component
pos(),
area(),
body(),
])
// when bean is grounded, press space to jump
// check out #BodyComp for more methods
onKeyPress("space", () => {
if (bean.isGrounded()) {
bean.jump()
}
})
// run something when bean falls and hits a ground
bean.onGround(() => {
debug.log("oh no!")
})
```
`returns`The body comp.
`since`v2000.0
# [surfaceEffector](#surfaceEffector)(opt: SurfaceEffectorCompOpt): SurfaceEffectorComp
Applies a force on a colliding object in order to make it move along the collision tangent vector. Good for conveyor belts.
`param`opt- Options for the surface effector component. See
``` js
loadSprite("belt", "/sprites/jumpy.png")
// conveyor belt
add([
pos(center()),
sprite("belt"),
rotate(90),
area(),
body({ isStatic: true }),
surfaceEffector({
speed: 50,
})
])
```
`returns`The surface effector comp.
`since`v3001.0
# [areaEffector](#areaEffector)(opt: AreaEffectorCompOpt): AreaEffectorComp
Applies a force on a colliding object. Good to apply anti-gravity, wind or water flow.
`param`opt- Options for the area effector component. See
`returns`The area effector comp.
`since`v3001.0
# [pointEffector](#pointEffector)(opt: PointEffectorCompOpt): PointEffectorComp
Applies a force on a colliding object directed towards this object's origin. Good to apply magnetic attraction or repulsion.
`param`opt- Options for the point effector component. See
`returns`The point effector comp.
`since`v3001.0
# [platformEffector](#platformEffector)(opt?: PlatformEffectorCompOpt): PlatformEffectorComp
The platform effector makes it easier to implement one way platforms or walls. This effector is typically used with a static body, and it will only be solid depending on the direction the object is traveling from.
`param`opt- Options for the platform effector component. See
`returns`The platform effector comp.
`since`v3001.0
# [buoyancyEffector](#buoyancyEffector)(opt: BuoyancyEffectorCompOpt): BuoyancyEffectorComp
Applies an upwards force (force against gravity) to colliding objects depending on the fluid density and submerged area. Good to apply constant thrust.
`param`opt- Options for the buoyancy effector component. See
`returns`The buoyancy effector comp.
`since`v3001.0
# [constantForce](#constantForce)(opt: ConstantForceCompOpt): ConstantForceComp
Applies a constant force to the object. Good to apply constant thrust.
`param`opt- Options for the constant force component. See
`returns`The constant force comp.
`since`v3001.0
# [doubleJump](#doubleJump)(numJumps?: number): DoubleJumpComp
Enables double jump.
`param`numJumps- The number of jumps allowed. Defaults to 1.
`requires`
`returns`The double jump comp.
`since`v3000.0
# [move](#move)(dir: number \| Vec2, speed: number): EmptyComp
Move towards a direction infinitely, and destroys when it leaves game view.
`param`dir- The direction to move towards.
`param`speed- The speed to move at.
`requires`
``` js
// enemy throwing feces at player
const projectile = add([
sprite("feces"),
pos(enemy.pos),
area(),
move(player.pos.angle(enemy.pos), 1200),
offscreen({ destroy: true }),
])
```
`returns`The move comp.
`since`v2000.0
# [offscreen](#offscreen)(opt?: OffScreenCompOpt): OffScreenComp
Control the behavior of object when it goes out of view.
`param`opt- Options for the offscreen component. See
``` js
add([
pos(player.pos),
sprite("bullet"),
offscreen({ destroy: true }),
"projectile",
]);
```
`returns`The offscreen comp.
`since`v2000.2
# [follow](#follow)(obj: GameObj \| null, offset?: Vec2): FollowComp
Follow another game obj's position.
`param`obj- The game obj to follow.
`param`offset- The offset to follow at.
``` js
const bean = add(...)
add([
sprite("bag"),
pos(),
follow(bean) // Follow bean's position
]);
// Using offset
const target = add(...)
const mark = add([
sprite("mark"),
pos(),
follow(target, vec2(32, 32)) // Follow target's position with an offset
])
mark.follow.offset = vec2(64, 64) // Change the offset
```
`returns`The follow comp.
`since`v2000.0
# [shader](#shader)(id: string, uniform?: Uniform \| ()=\>Uniform): ShaderComp
Custom shader to manipulate sprite.
`param`id- The shader id.
`param`uniform- The uniform to pass to the shader.
`returns`The shader comp.
`since`v2000.0
# [textInput](#textInput)(hasFocus?: boolean, maxInputLength?: number): TextInputComp
Get input from the user and store it in the nodes text property, displaying it with the text component and allowing other functions to access it.
`param`hasFocus- Whether the text input should have focus.
`param`maxInputLength- The maximum length of the input.
``` js
const obj = add([
text(""),
textInput(),
])
obj.hasFocus = false
debug.log(obj.text) // oh no i cant see my new text since it was disabled
```
`returns`The text input comp.
`since`v3001.0
# [timer](#timer)(maxLoopsPerFrame?: number): TimerComp
Enable timer related functions like wait(), loop(), tween() on the game object.
`param`maxLoopsPerFrame- The maximum number of loops per frame.
``` js
const obj = add([
timer(),
])
obj.wait(2, () => { ... })
obj.loop(0.5, () => { ... })
obj.tween(obj.pos, mousePos(), 0.5, (p) => obj.pos = p, easings.easeOutElastic)
```
`returns`The timer comp.
`since`v2000.0
# [fixed](#fixed)(): FixedComp
Make a game obj unaffected by camera or parent object transforms, and render at last. Useful for UI elements.
``` js
// this will be be fixed on top left and not affected by camera
const score = add([
text(0),
pos(12, 12),
fixed(),
])
```
`returns`The fixed comp.
`since`v2000.0
# [stay](#stay)(scenesToStay?: string\[\]): StayComp
Don't get destroyed on scene switch. Only works in objects attached to root.
`param`scenesToStay- The scenes to stay in. By default it stays in all scenes.
``` js
player.onCollide("bomb", () => {
// spawn an explosion and switch scene, but don't destroy the explosion game obj on scene switch
add([
sprite("explosion", { anim: "burst", }),
stay(),
lifespan(1),
])
go("lose", score)
})
```
`returns`The stay comp.
`since`v2000.0
# [health](#health)(hp: number, maxHP?: number): HealthComp
Handles health related logic and events.
`param`hp- The initial health points.
`param`maxHP- The maximum health points.
``` js
const player = add([
health(3),
])
player.onCollide("bad", (bad) => {
player.hurt(1)
bad.hurt(1)
})
player.onCollide("apple", () => {
player.heal(1)
})
player.on("hurt", () => {
play("ouch")
})
// triggers when hp reaches 0
player.on("death", () => {
destroy(player)
go("lose")
})
```
`returns`The health comp.
`since`v2000.0
# [lifespan](#lifespan)(time: number, options?: LifespanCompOpt): EmptyComp
Destroy the game obj after certain amount of time
`param`time- The time to live.
`param`options- Options for the lifespan component. See
``` js
// spawn an explosion, destroy after 1.5 seconds (time + fade)
add([
sprite("explosion", { anim: "burst", }),
lifespan(1, {
fade: 0.5 // it start fading 0.5 second after time
}),
]);
```
`returns`The lifespan comp.
`since`v2000.0
# [named](#named)(name: string): NamedComp
Names an game obj.
`param`name- The name to set.
`returns`The named comp.
`since`v3001.0
# [state](#state)(initialState: string, stateList?: string\[\]): StateComp
Finite state machine.
`param`initialState- The initial state.
`param`stateList- The list of states.
``` js
const enemy = add([
pos(80, 100),
sprite("robot"),
state("idle", ["idle", "attack", "move"]),
])
// this callback will run once when enters "attack" state
enemy.onStateEnter("attack", () => {
// enter "idle" state when the attack animation ends
enemy.play("attackAnim", {
// any additional arguments will be passed into the onStateEnter() callback
onEnd: () => enemy.enterState("idle", rand(1, 3)),
})
checkHit(enemy, player)
})
// this will run once when enters "idle" state
enemy.onStateEnter("idle", (time) => {
enemy.play("idleAnim")
wait(time, () => enemy.enterState("move"))
})
// this will run every frame when current state is "move"
enemy.onStateUpdate("move", () => {
enemy.follow(player)
if (enemy.pos.dist(player.pos) < 16) {
enemy.enterState("attack")
}
})
```
`returns`The state comp.
`since`v2000.1
# [state](#state)(initialState: string, stateList: string\[\], transitions: Record): StateComp
state() with pre-defined transitions.
`param`initialState- The initial state.
`param`stateList- The list of states.
`param`transitions- The transitions between states.
``` js
const enemy = add([
pos(80, 100),
sprite("robot"),
state("idle", ["idle", "attack", "move"], {
"idle": "attack",
"attack": "move",
"move": [ "idle", "attack" ],
}),
])
// this callback will only run once when enter "attack" state from "idle"
enemy.onStateTransition("idle", "attack", () => {
checkHit(enemy, player)
})
```
`returns`The state comp.
`since`v2000.2
# [fadeIn](#fadeIn)(time: number): Comp
`deprecated`since v3001.0
`requires`
`returns`An empty comp.
`since`v3000.0
# [mask](#mask)(maskType?: Mask): MaskComp
Mask all children object render.
`param`maskType- The type of mask to use.
`returns`The mask comp.
`since`v3001.0
# [drawon](#drawon)(canvas: FrameBuffer \| Picture, opt?: DrawonOpt): DrawonComp
Specifies the FrameBuffer the object should be drawn on.
`param`canvas- The FrameBuffer to draw on.
``` js
// Draw on another canvas
let canvas = makeCanvas(width(), height());
let beanOnCanvas = add([
sprite("bean"),
drawon(canvas.fb),
]);
```
`returns`The drawon comp.
`since`v3000.0
# [tile](#tile)(opt?: TileCompOpt): TileComp
A tile on a tile map.
`param`opt- Options for the tile component. See
`returns`The tile comp.
`since`v3000.0
# [agent](#agent)(opt?: AgentCompOpt): AgentComp
An agent which can finds it way on a tilemap.
`param`opt- Options for the agent component. See
`returns`The agent comp.
`since`v3000.0
# [animate](#animate)(opt?: AnimateCompOpt): AnimateComp
A component to animate properties.
`param`opt- Options for the animate component. See
``` js
let movingBean = add([
sprite("bean"),
pos(50, 150),
anchor("center"),
animate(),
]);
// Moving right to left using ping-pong
movingBean.animate("pos", [vec2(50, 150), vec2(150, 150)], {
duration: 2,
direction: "ping-pong",
});
```
`returns`The animate comp.
`since`v3001.0
# [fakeMouse](#fakeMouse)(opt?: FakeMouseOpt): FakeMouseComp
A fake mouse that follows the mouse position and triggers events. \[Guide about fake mouse\](https://v4000.kaplayjs.com/guides/fake_mouse/)
`param`opt- Options for the fake mouse comp. See
`returns`The fake mouse comp.
`since`v3001.0
# [serializeAnimation](#serializeAnimation)(obj: GameObj, name: string): Animation
Serializes the animation to plain objects
`param`obj- The game obj to serialize.
`returns`The serialized animation.
`since`v3001.0
# [sentry](#sentry)(candidates: SentryCandidates, opt?: SentryCompOpt): SentryComp
A sentry which reacts to objects coming into view.
`returns`The sentry comp.
`since`v3001.0
# [patrol](#patrol)(opts: PatrolCompOpt): PatrolComp
A patrol which can follow waypoints to a goal.
`param`opts- Options for the patrol component. See
``` js
const bean = add([
sprite("bean"),
pos(40, 30),
patrol({
waypoints: [
vec2(100, 100),
vec2(120, 170),
vec2(50, 50),
vec2(300, 100),
],
}),
]);
bean.onPatrolFinished(gb => {
// Note that the position doesn't exactly match the last waypoint,
// this is an approximation.
debug.log(`Bean reached the end of the patrol at ${gb.pos.x}, ${gb.pos.y}`);
});
```
`returns`The patrol comp.
`since`v3001.0
# [pathfinder](#pathfinder)(opts: PathfinderCompOpt): PathfinderComp
A navigator pathfinder which can calculate waypoints to a goal.
`since`v3001.0
# [level](#level)(map: string\[\], opt?: LevelOpt): LevelComp
Construct a level based on symbols.
`param`map- The map data.
`param`opt- The level options.
`param`unknown- The parent object of the level. Defaults to root.
``` js
const myLevel = add([
level([
" $",
" $",
" $$ = $",
" % ==== = $",
" = ",
" ^^ = > = &",
"===========================",
], {
// define the size of tile block
tileWidth: 32,
tileHeight: 32,
// define what each symbol means, by a function returning a component list (what will be passed to add())
tiles: {
"=": () => [
sprite("floor"),
area(),
body({ isStatic: true }),
],
"$": () => [
sprite("coin"),
area(),
pos(0, -9),
],
"^": () => [
sprite("spike"),
area(),
"danger",
],
}
})
])
```
`returns`A game obj with the level.
`since`v4000.0
# [Comp](#Comp):
# [id](#Comp-id)?: Tag
Component ID (if left out won't be treated as a comp).
# [require](#Comp-require)?: Tag\[\]
What other comps this comp depends on.
# [add](#Comp-add)?(): void
Event that runs when host game obj is added to scene.
# [fixedUpdate](#Comp-fixedUpdate)?(): void
Event that runs at a fixed frame rate.
# [update](#Comp-update)?(): void
Event that runs every frame.
# [draw](#Comp-draw)?(): void
Event that runs every frame after update.
# [destroy](#Comp-destroy)?(): void
Event that runs when obj is removed from scene.
# [inspect](#Comp-inspect)?(): string \| null
Debug info for inspect mode.
# [drawInspect](#Comp-drawInspect)?(): void
Draw debug info in inspect mode
`since`v3000.0
# [TimerComp](#TimerComp):
The timer`timer()` component.
# [maxLoopsPerFrame](#TimerComp-maxLoopsPerFrame): number
The maximum number of loops per frame allowed, to keep loops with sub-frame intervals from freezing the game.
# [wait](#TimerComp-wait)(time: number, action?: ()=\>void): TimerController
Run the callback after n seconds.
# [loop](#TimerComp-loop)(time: number, action: ()=\>void, maxLoops?: number, waitFirst?: boolean): TimerController
Run the callback every n seconds. If waitFirst is false (the default), the function will be called once on the very next frame, and then loop like normal.
`since`v3000.0
# [tween](#TimerComp-tween)\<V\>(from: V, to: V, duration: number, setValue: (value: V)=\>void, easeFunc?: (t: number)=\>number): TweenController
Tweeeeen! Note that this doesn't specifically mean tweening on this object's property, this just registers the timer on this object, so the tween will cancel with the object gets destroyed, or paused when obj.paused is true.
`since`v3000.0
# [BlendComp](#BlendComp):
The blend`blend()` component.
# [blend](#BlendComp-blend): BlendMode
# [CircleComp](#CircleComp):
The circle`circle()` component.
# [draw](#CircleComp-draw): Comp\[draw\]
# [radius](#CircleComp-radius): number
Radius of circle.
# [renderArea](#CircleComp-renderArea)(): Circle
Render area of the circle.
`since`v3000.0
# [CircleCompOpt](#CircleCompOpt):
Options for the circle\`circle()\`\` component.
# [fill](#CircleCompOpt-fill)?: boolean
If fill the circle (useful if you only want to render outline with outline`outline()` component).
# [ColorComp](#ColorComp):
The color`color()` component.
# [color](#ColorComp-color): Color
# [EllipseComp](#EllipseComp):
The ellipse`ellipse()` component.
# [draw](#EllipseComp-draw): Comp\[draw\]
# [radiusX](#EllipseComp-radiusX): number
Semi-major axis of ellipse.
# [radiusY](#EllipseComp-radiusY): number
Semi-minor axis of ellipse.
# [renderArea](#EllipseComp-renderArea)(): Ellipse
Render area of the ellipse.
# [EllipseCompOpt](#EllipseCompOpt):
Options for the ellipse\`ellipse()\`\` component.
# [fill](#EllipseCompOpt-fill)?: boolean
If fill is false, the ellipse is not filled (useful if you only want to render outline with outline`outline()` component).
# [MaskComp](#MaskComp):
The mask`mask()` component.
# [mask](#MaskComp-mask): Mask
# [OpacityComp](#OpacityComp):
The opacity`opacity()` component.
# [opacity](#OpacityComp-opacity): number
Opacity of the current object.
# [fadeIn](#OpacityComp-fadeIn)(time?: number, easeFunc?: EaseFunc): TweenController
Fade in at the start.
# [fadeOut](#OpacityComp-fadeOut)(time?: number, easeFunc?: EaseFunc): TweenController
Fade out at the start.
# [OutlineComp](#OutlineComp):
The outline`outline()` component.
# [outline](#OutlineComp-outline): Outline
[ParticlesOpt](#ParticlesOpt):
# [max](#undefined-max): number
Maximum number of simultaneously rendered particles.
# [lifeTime](#undefined-lifeTime)?: \[number, number\]
Minimum and maximum lifetime of a particle in seconds.
# [speed](#undefined-speed)?: \[number, number\]
Minimum and maximum speed of a particle in pixels per second.
# [acceleration](#undefined-acceleration)?: \[Vec2, Vec2\]
Minimum and maximum acceleration of a particle in pixels per second\^2.
# [damping](#undefined-damping)?: \[number, number\]
Minimum and maximum damping of a particle.
# [angle](#undefined-angle)?: \[number, number\]
Minimum and maximum start angle of a particle.
# [angularVelocity](#undefined-angularVelocity)?: \[number, number\]
Minimum and maximum angular velocity of a particle.
# [scales](#undefined-scales)?: number\[\]
Scale from start to end for a particle.
# [colors](#undefined-colors)?: Color\[\]
Colors from start to end for a particle.
# [opacities](#undefined-opacities)?: number\[\]
Opacity from start to end for a particle.
# [quads](#undefined-quads)?: Quad\[\]
Quads from start to end for a particle.
# [texture](#undefined-texture): Texture
Texture used for the particle.
Options for the particles`particles()`'s component
# [ParticlesComp](#ParticlesComp):
The particles`particles()` component.
[emitter](#ParticlesComp-emitter):
# [position](#undefined-position): Vec2
Relative position of the emitter
# [direction](#undefined-direction): number
Relative direction of the emitter
# [emit](#ParticlesComp-emit)(n: number): void
Emit a number of particles
# [onEnd](#ParticlesComp-onEnd)(cb: ()=\>void): void
Called when the emitter expires
# [PolygonComp](#PolygonComp):
The polygon`polygon()` component.
`since`v3001.0
# [draw](#PolygonComp-draw): Comp\[draw\]
# [pts](#PolygonComp-pts): Vec2\[\]
Points in the polygon.
# [radius](#PolygonComp-radius)?: number \| number\[\]
The radius of each corner.
# [colors](#PolygonComp-colors)?: Color\[\]
The color of each vertex.
# [uv](#PolygonComp-uv)?: Vec2\[\]
The uv of each vertex.
`since`v3001.0
# [tex](#PolygonComp-tex)?: Texture
The texture used when uv coordinates are present.
`since`v3001.0
# [renderArea](#PolygonComp-renderArea)(): Polygon
# [PolygonCompOpt](#PolygonCompOpt): Omit\<DrawPolygonOpt, pts\>
Options for the polygon`polygon()` component.
# [RectComp](#RectComp):
The rect`rect()` component.
# [draw](#RectComp-draw): Comp\[draw\]
# [width](#RectComp-width): number
Width of rectangle.
# [height](#RectComp-height): number
Height of rectangle.
# [radius](#RectComp-radius)?: number \| \[number, number, number, number\]
The radius of each corner.
# [renderArea](#RectComp-renderArea)(): Rect
`since`v3000.0
# [RectCompOpt](#RectCompOpt):
Options for the rect`rect()` component.
# [radius](#RectCompOpt-radius)?: number \| \[number, number, number, number\]
Radius of the rectangle corners.
# [fill](#RectCompOpt-fill)?: boolean
If fill the rectangle (useful if you only want to render outline with outline() component).
# [ShaderComp](#ShaderComp):
The shader`shader()` component.
# [uniform](#ShaderComp-uniform)?: Uniform
Uniform values to pass to the shader.
# [shader](#ShaderComp-shader): string
The shader ID.
# [SpriteComp](#SpriteComp):
The sprite`sprite()` component.
# [draw](#SpriteComp-draw): Comp\[draw\]
# [sprite](#SpriteComp-sprite): string
Name of the sprite.
# [width](#SpriteComp-width): number
Width for sprite.
# [height](#SpriteComp-height): number
Height for sprite.
# [frame](#SpriteComp-frame): number
Current frame in the entire spritesheet.
# [animFrame](#SpriteComp-animFrame): number
Current frame in relative to the animation that is currently playing.
# [quad](#SpriteComp-quad): Quad
The rectangular area of the texture to render.
# [play](#SpriteComp-play)(anim: string, options?: SpriteAnimPlayOpt): void
Play a piece of anim.
# [stop](#SpriteComp-stop)(): void
Stop current anim.
# [numFrames](#SpriteComp-numFrames)(): number
Get total number of frames.
# [getCurAnim](#SpriteComp-getCurAnim)(): SpriteCurAnim \| null
Get the current animation data.
`since`v3001.0
# [curAnim](#SpriteComp-curAnim)(): string \| undefined
Get current anim name.
`deprecated`Use \`getCurAnim().name\` instead.
# [hasAnim](#SpriteComp-hasAnim)(name: string): boolean
Check if object's sprite has an animation.
# [getAnim](#SpriteComp-getAnim)(name: string): SpriteAnim \| null
Get an animation.
# [animSpeed](#SpriteComp-animSpeed): number
Speed multiplier for all animations (for the actual fps for an anim use .play(\"anim\", { speed: 10 })).
# [flipX](#SpriteComp-flipX): boolean
Flip texture horizontally.
# [flipY](#SpriteComp-flipY): boolean
Flip texture vertically.
# [onAnimStart](#SpriteComp-onAnimStart)(action: (anim: string)=\>void): KEventController
Register an event that runs when an animation is played.
# [onAnimEnd](#SpriteComp-onAnimEnd)(action: (anim: string)=\>void): KEventController
Register an event that runs when an animation is ended.
# [renderArea](#SpriteComp-renderArea)(): Rect
`since`v3000.0
# [SpriteCompOpt](#SpriteCompOpt):
Options for the sprite`sprite()` component.
# [frame](#SpriteCompOpt-frame)?: number
If the sprite is loaded with multiple frames, or sliced, use the frame option to specify which frame to draw.
# [tiled](#SpriteCompOpt-tiled)?: boolean
If provided width and height, don't stretch but instead render tiled.
# [width](#SpriteCompOpt-width)?: number
Stretch sprite to a certain width.
# [height](#SpriteCompOpt-height)?: number
Stretch sprite to a certain height.
# [anim](#SpriteCompOpt-anim)?: string
Play an animation on start.
# [animSpeed](#SpriteCompOpt-animSpeed)?: number
Speed multiplier for all animations (for the actual fps for an anim use .play(\"anim\", { speed: 10 })).
# [flipX](#SpriteCompOpt-flipX)?: boolean
Flip texture horizontally.
# [flipY](#SpriteCompOpt-flipY)?: boolean
Flip texture vertically.
# [quad](#SpriteCompOpt-quad)?: Quad
The rectangular sub-area of the texture to render, default to full texture \`quad(0, 0, 1, 1)\`.
# [fill](#SpriteCompOpt-fill)?: boolean
If fill the sprite (useful if you only want to render outline with outline() component).
# [TextComp](#TextComp):
The text`text()` component.
# [draw](#TextComp-draw): Comp\[draw\]
# [text](#TextComp-text): string
The text to render.
# [textSize](#TextComp-textSize): number
The text size.
# [font](#TextComp-font): string \| BitmapFontData
The font to use.
# [width](#TextComp-width): number
Width of text.
# [height](#TextComp-height): number
Height of text.
# [align](#TextComp-align): TextAlign
Text alignment (\"left\", \"center\" or \"right\", default \"left\").
`since`v3000.0
# [lineSpacing](#TextComp-lineSpacing): number
The gap between each line.
`since`v2000.2
# [letterSpacing](#TextComp-letterSpacing): number
The gap between each character.
`since`v2000.2
# [textTransform](#TextComp-textTransform): CharTransform \| CharTransformFunc
Transform the pos, scale, rotation or color for each character based on the index or char.
`since`v2000.1
# [textStyles](#TextComp-textStyles): Record\<string, CharTransform \| CharTransformFunc\>
Stylesheet for styled chunks, in the syntax of \"this is a \[style\]text\[/style\] word\".
`since`v2000.2
# [renderArea](#TextComp-renderArea)(): Rect
`since`v3000.0
# [formattedText](#TextComp-formattedText)(): FormattedText
The text data object after formatting, that contains the renering info as well as the parse data of the formatting tags.
# [TextCompOpt](#TextCompOpt):
Options for the text`text()` component.
# [size](#TextCompOpt-size)?: number
Height of text.
# [font](#TextCompOpt-font)?: string \| BitmapFontData
The font to use.
# [width](#TextCompOpt-width)?: number
Wrap text to a certain width.
# [align](#TextCompOpt-align)?: TextAlign
Text alignment (\"left\", \"center\" or \"right\", default \"left\").
`since`v3000.0
# [lineSpacing](#TextCompOpt-lineSpacing)?: number
The gap between each line.
`since`v2000.2
# [letterSpacing](#TextCompOpt-letterSpacing)?: number
The gap between each character.
`since`v2000.2
# [transform](#TextCompOpt-transform)?: CharTransform \| CharTransformFunc
Transform the pos, scale, rotation or color for each character based on the index or char.
`since`v2000.1
# [styles](#TextCompOpt-styles)?: Record\<string, CharTransform \| CharTransformFunc\>
Stylesheet for styled chunks, in the syntax of \"this is a \[style\]text\[/style\] word\".
`since`v2000.2
# [indentAll](#TextCompOpt-indentAll)?: boolean
If true, any (whitespace) indent on the first line of the paragraph will be copied to all of the lines for those parts that text-wrap.
# [UVQuadComp](#UVQuadComp):
The uvquad`uvquad()` component.
# [draw](#UVQuadComp-draw): Comp\[draw\]
# [width](#UVQuadComp-width): number
Width of rect.
# [height](#UVQuadComp-height): number
Height of height.
# [renderArea](#UVQuadComp-renderArea)(): Rect
`since`v3000.0
# [AgentComp](#AgentComp):
The agent`agent()` component.
# [agentSpeed](#AgentComp-agentSpeed): number
# [allowDiagonals](#AgentComp-allowDiagonals): boolean
# [getDistanceToTarget](#AgentComp-getDistanceToTarget)(): number
# [getNextLocation](#AgentComp-getNextLocation)(): Vec2 \| null
# [getPath](#AgentComp-getPath)(): Vec2\[\] \| null
# [getTarget](#AgentComp-getTarget)(): Vec2 \| null
# [isNavigationFinished](#AgentComp-isNavigationFinished)(): boolean
# [isTargetReachable](#AgentComp-isTargetReachable)(): boolean
# [isTargetReached](#AgentComp-isTargetReached)(): boolean
# [setTarget](#AgentComp-setTarget)(target: Vec2): void
# [onNavigationStarted](#AgentComp-onNavigationStarted)(cb: ()=\>void): KEventController
# [onNavigationNext](#AgentComp-onNavigationNext)(cb: ()=\>void): KEventController
# [onNavigationEnded](#AgentComp-onNavigationEnded)(cb: ()=\>void): KEventController
# [onTargetReached](#AgentComp-onTargetReached)(cb: ()=\>void): KEventController
[AgentCompOpt](#AgentCompOpt):
# [speed](#undefined-speed)?: number
# [allowDiagonals](#undefined-allowDiagonals)?: boolean
Options for the agent`agent()` component.
# [LevelComp](#LevelComp):
The level`level()` component.
# [tileWidth](#LevelComp-tileWidth)(): number
# [tileHeight](#LevelComp-tileHeight)(): number
# [numRows](#LevelComp-numRows)(): number
# [numColumns](#LevelComp-numColumns)(): number
# [spawn](#LevelComp-spawn)(sym: string, p: Vec2): GameObj \| null
Spawn a tile from a symbol defined previously.
# [spawn](#LevelComp-spawn)(sym: string, x: number, y: number): GameObj \| null
# [spawn](#LevelComp-spawn)\<T\>(obj: CompList, p: Vec2): GameObj \| null
Spawn a tile from a component list.
`returns`The spawned game object, or null if the obj hasn't components.
# [spawn](#LevelComp-spawn)\<T\>(sym: CompList, x: number, y: number): GameObj \| null
# [levelWidth](#LevelComp-levelWidth)(): number
Total width of level in pixels.
# [levelHeight](#LevelComp-levelHeight)(): number
Total height of level in pixels.
# [getAt](#LevelComp-getAt)(tilePos: Vec2): GameObj\[\]
Get all game objects that's currently inside a given tile.
# [raycast](#LevelComp-raycast)(origin: Vec2, direction: Vec2): RaycastResult
Raycast all game objects on the given path.
# [tile2Pos](#LevelComp-tile2Pos)(tilePos: Vec2): Vec2
Convert tile position to pixel position.
# [tile2Pos](#LevelComp-tile2Pos)(x: number, y: number): Vec2
# [pos2Tile](#LevelComp-pos2Tile)(pos: Vec2): Vec2
Convert pixel position to tile position.
# [pos2Tile](#LevelComp-pos2Tile)(x: number, y: number): Vec2
# [getTilePath](#LevelComp-getTilePath)(from: Vec2, to: Vec2, opts?: PathFindOpt): Vec2\[\] \| null
Find the path to navigate from one tile to another tile.
`returns`A list of traverse points in tile positions.
# [getPath](#LevelComp-getPath)(from: Vec2, to: Vec2, opts?: PathFindOpt): Vec2\[\] \| null
Find the path to navigate from one tile to another tile.
`returns`A list of traverse points in pixel positions.
# [getSpatialMap](#LevelComp-getSpatialMap)(): GameObj\[\]\[\]
# [removeFromSpatialMap](#LevelComp-removeFromSpatialMap)(obj: GameObj): void
# [insertIntoSpatialMap](#LevelComp-insertIntoSpatialMap)(obj: GameObj): void
# [onSpatialMapChanged](#LevelComp-onSpatialMapChanged)(cb: ()=\>void): KEventController
# [onNavigationMapInvalid](#LevelComp-onNavigationMapInvalid)(cb: ()=\>void): KEventController
# [invalidateNavigationMap](#LevelComp-invalidateNavigationMap)(): void
# [onNavigationMapChanged](#LevelComp-onNavigationMapChanged)(cb: ()=\>void): KEventController
[PathFindOpt](#PathFindOpt):
# [allowDiagonals](#undefined-allowDiagonals)?: boolean
# [FixedComp](#FixedComp):
The fixed`fixed()` component.
# [fixed](#FixedComp-fixed): boolean
If the obj is unaffected by camera
# [PosComp](#PosComp):
The pos`pos()` component.
# [pos](#PosComp-pos): Vec2
Object's current world position.
# [move](#PosComp-move)(xVel: number, yVel: number): void
Move how many pixels per second. If object is 'solid', it won't move into other 'solid' objects.
# [move](#PosComp-move)(vel: Vec2): void
# [moveBy](#PosComp-moveBy)(dx: number, dy: number): void
Move how many pixels, without multiplying dt, but still checking for 'solid'.
# [moveBy](#PosComp-moveBy)(d: Vec2): void
# [moveTo](#PosComp-moveTo)(dest: Vec2, speed?: number): void
Move to a spot with a speed (pixels per second), teleports if speed is not given.
# [moveTo](#PosComp-moveTo)(x: number, y: number, speed?: number): void
# [screenPos](#PosComp-screenPos)(newPos?: Vec2): Vec2 \| null
Get / Set the position of the object on the screen.
`since`v2000.0
# [worldPos](#PosComp-worldPos)(newPos?: Vec2): Vec2 \| null
Get / Set the position of the object relative to the root.
`since`v2000.0
# [toScreen](#PosComp-toScreen)(this: GameObj, p: Vec2): Vec2
Transform a local point (relative to this) to a screen point (relative to the camera)
# [toWorld](#PosComp-toWorld)(this: GameObj, p: Vec2): Vec2
Transform a local point (relative to this) to a world point (relative to the root)
`since`v3001.0
# [fromScreen](#PosComp-fromScreen)(this: GameObj, p: Vec2): Vec2
Transform a screen point (relative to the camera) to a local point (relative to this)
`since`v3001.0
# [fromWorld](#PosComp-fromWorld)(this: GameObj, p: Vec2): Vec2
Transform a world point (relative to the root) to a local point (relative to this)
`since`v3001.0
# [toOther](#PosComp-toOther)(this: GameObj, other: GameObj, p: Vec2): Vec2
Transform a point relative to this to a point relative to other
`since`v3001.0
# [fromOther](#PosComp-fromOther)(this: GameObj, other: GameObj, p: Vec2): Vec2
Transform a point relative to other to a point relative to this
`since`v3001.0
# [SentryComp](#SentryComp):
The sentry`sentry()` component.
# [direction](#SentryComp-direction)?: Vec2
The direction the sentry is pointing to.
# [directionAngle](#SentryComp-directionAngle)?: number
The direction of the sentry as an angle in degrees.
# [fieldOfView](#SentryComp-fieldOfView)?: number
The field of view of the sentry in degrees.
# [spotted](#SentryComp-spotted): GameObj\[\]
The objects spotted most recently.
# [onObjectsSpotted](#SentryComp-onObjectsSpotted)(cb: (objects: GameObj\[\])=\>void): KEventController
Attaches an event handler which is called when objects of interest are spotted.
`param`cbThe event handler called when objects are spotted.
# [isWithinFieldOfView](#SentryComp-isWithinFieldOfView)(obj: GameObj, direction?: Vec2, fieldOfView?: number): boolean
Returns true if the object is within the field of view.
`param`objThe object to test.
`param`directionThe direction to look at.
`param`fieldOfViewThe field of view in degrees.
# [hasLineOfSight](#SentryComp-hasLineOfSight)(obj: GameObj): boolean
Returns true if there is a line of sight to the object.
`param`objThe object to test.
# [SentryCompOpt](#SentryCompOpt):
Options for the sentry`sentry()` component.
# [direction](#SentryCompOpt-direction)?: Vec2 \| number
The direction the sentry is pointing to. If undefined, direction has no influence.
# [fieldOfView](#SentryCompOpt-fieldOfView)?: number
The field of view of the sentry in degrees. If undefined, defaults to human fov of 200 degrees.
# [lineOfSight](#SentryCompOpt-lineOfSight)?: boolean
If true, line of sight matters. This means that objects which are blocked from view by areas are invisible.
# [raycastExclude](#SentryCompOpt-raycastExclude)?: string\[\]
When using line of sight, the objects which are transparent for the ray. Include at least a tag identifying the sentry.
# [checkFrequency](#SentryCompOpt-checkFrequency)?: number
The frequency of checking, defaults to every second.
# [TileComp](#TileComp):
The tile`tile()` component.
# [tilePos](#TileComp-tilePos): Vec2
The tile position inside the level.
# [isObstacle](#TileComp-isObstacle): boolean
If the tile is an obstacle in pathfinding.
# [cost](#TileComp-cost): number
How much a tile is cost to traverse in pathfinding (default 0).
# [edges](#TileComp-edges): Edge\[\]
If the tile has hard edges that cannot pass in pathfinding.
# [tilePosOffset](#TileComp-tilePosOffset): Vec2
Position offset when setting \`tilePos\`.
# [edgeMask](#TileComp-edgeMask): EdgeMask
# [getLevel](#TileComp-getLevel)(): GameObj\<LevelComp\>
# [tileMove](#TileComp-tileMove)(dir: Vec2): void
# [moveLeft](#TileComp-moveLeft)(): void
# [moveRight](#TileComp-moveRight)(): void
# [moveUp](#TileComp-moveUp)(): void
# [moveDown](#TileComp-moveDown)(): void
[TileCompOpt](#TileCompOpt):
# [isObstacle](#undefined-isObstacle)?: boolean
If the tile is an obstacle in pathfinding.
# [cost](#undefined-cost)?: number
How much a tile is cost to traverse in pathfinding (default 0).
# [edges](#undefined-edges)?: Edge\[\]
If the tile has hard edges that cannot pass in pathfinding.
# [offset](#undefined-offset)?: Vec2
Position offset when setting \`tilePos\`.
Options for the tile`tile()` component.
# [HealthComp](#HealthComp):
The health`health()` component.
# [hurt](#HealthComp-hurt)(n?: number): void
Decrease HP by n (defaults to 1).
# [heal](#HealthComp-heal)(n?: number): void
Increase HP by n (defaults to 1).
# [hp](#HealthComp-hp)(): number
Current health points.
# [setHP](#HealthComp-setHP)(hp: number): void
Set current health points.
# [maxHP](#HealthComp-maxHP)(): number \| null
Max amount of HP.
# [setMaxHP](#HealthComp-setMaxHP)(hp: number): void
Set max amount of HP.
# [onHurt](#HealthComp-onHurt)(action: (amount?: number)=\>void): KEventController
Register an event that runs when hurt() is called upon the object.
`since`v2000.1
# [onHeal](#HealthComp-onHeal)(action: (amount?: number)=\>void): KEventController
Register an event that runs when heal() is called upon the object.
`since`v2000.1
# [onDeath](#HealthComp-onDeath)(action: ()=\>void): KEventController
Register an event that runs when object's HP is equal or below 0.
`since`v2000.1
# [LifespanCompOpt](#LifespanCompOpt):
The lifespan`lifespan()` component.
# [fade](#LifespanCompOpt-fade)?: number
Fade out duration (default 0 which is no fade out).
# [NamedComp](#NamedComp):
The named`named()` component.
# [StateComp](#StateComp):
The state`state()` component.
# [state](#StateComp-state): string
Current state.
# [enterState](#StateComp-enterState)(state: string, args: any): void
Enter a state, trigger onStateEnd for previous state and onStateEnter for the new State state.
# [onStateTransition](#StateComp-onStateTransition)(from: string, to: string, action: ()=\>void): KEventController
Register event that runs once when a specific state transition happens. Accepts arguments passed from \`enterState(name, \...args)\`.
`since`v2000.2
# [onStateEnter](#StateComp-onStateEnter)(state: string, action: (args: any)=\>void): KEventController
Register event that runs once when enters a specific state. Accepts arguments passed from \`enterState(name, \...args)\`.
# [onStateEnd](#StateComp-onStateEnd)(state: string, action: ()=\>void): KEventController
Register an event that runs once when leaves a specific state.
# [onStateUpdate](#StateComp-onStateUpdate)(state: string, action: ()=\>void): KEventController
Register an event that runs every frame when in a specific state.
# [onStateDraw](#StateComp-onStateDraw)(state: string, action: ()=\>void): KEventController
Register an event that runs every frame when in a specific state.
# [StayComp](#StayComp):
The stay`stay()` component.
# [stay](#StayComp-stay): boolean
If the obj should not be destroyed on scene switch.
# [scenesToStay](#StayComp-scenesToStay)?: string\[\]
Array of scenes that the obj will stay on.
# [TextInputComp](#TextInputComp):
The textInput`textInput()` component.
# [hasFocus](#TextInputComp-hasFocus): boolean
Enable the text input array to be modified by user input. Setting this to true is the same as calling focus(), and will clear focus on all other active textInput objects.
# [typedText](#TextInputComp-typedText): string
The \"real\" text that the user typed, without any escaping.
# [focus](#TextInputComp-focus)(): void
Focuses this text input so that it will receive input, and removes focus from all other text inputs.
# [onFocus](#TextInputComp-onFocus)(cb: ()=\>void): KEventController
Event that runs when the text input gains focus.
# [onBlur](#TextInputComp-onBlur)(cb: ()=\>void): KEventController
Event that runs when the text input loses focus.
# [onInput](#TextInputComp-onInput)(cb: ()=\>void): KEventController
Event that runs when the user types any character in the text input and causes its value to change. This runs \*after\* the display text is updated with the escaped version of the typed text, so in the event handler you can override the displayed text with another version (like if you want to add syntax highlighting or something). See also .
# [onChange](#TextInputComp-onChange)(cb: ()=\>void): KEventController
Runs immediately after onBlur if the value has changed while the text input has been focused.
# [AreaComp](#AreaComp):
The area`area()` component.
[area](#AreaComp-area):
# [shape](#undefined-shape): Shape \| null
If we use a custom shape over render shape.
# [scale](#undefined-scale): Vec2
Area scale.
# [offset](#undefined-offset): Vec2
Area offset.
# [cursor](#undefined-cursor): Cursor \| null
Cursor on hover.
Collider area info.
# [collisionIgnore](#AreaComp-collisionIgnore): Tag\[\]
If this object should ignore collisions against certain other objects.
`since`v3000.0
# [restitution](#AreaComp-restitution)?: number
Restitution (\"bounciness\") of the object.
# [friction](#AreaComp-friction)?: number
Friction of the object.
# [isClicked](#AreaComp-isClicked)(): boolean
If was just clicked on last frame.
# [isHovering](#AreaComp-isHovering)(): boolean
If is being hovered on.
# [checkCollision](#AreaComp-checkCollision)(other: GameObj): Collision \| null
Check collision with another game obj.
`since`v3000.0
# [getCollisions](#AreaComp-getCollisions)(): Collision\[\]
Get all collisions currently happening.
`since`v3000.0
# [isColliding](#AreaComp-isColliding)(o: GameObj): boolean
If is currently colliding with another game obj.
# [isOverlapping](#AreaComp-isOverlapping)(o: GameObj): boolean
If is currently overlapping with another game obj (like isColliding, but will return false if the objects are just touching edges).
# [onClick](#AreaComp-onClick)(f: ()=\>void, btn?: MouseButton): KEventController
Register an event runs when clicked.
`since`v2000.1
# [onHover](#AreaComp-onHover)(action: ()=\>void): KEventController
Register an event runs once when hovered.
`since`v3000.0
# [onHoverUpdate](#AreaComp-onHoverUpdate)(action: ()=\>void): KEventController
Register an event runs every frame when hovered.
`since`v3000.0
# [onHoverEnd](#AreaComp-onHoverEnd)(action: ()=\>void): KEventController
Register an event runs once when unhovered.
`since`v3000.0
# [onCollide](#AreaComp-onCollide)(tag: Tag, f: (obj: GameObj, col?: Collision)=\>void): KEventController
Register an event runs once when collide with another game obj with certain tag.
`since`v2001.0
# [onCollide](#AreaComp-onCollide)(f: (obj: GameObj, col?: Collision)=\>void): KEventController
Register an event runs once when collide with another game obj.
`since`v2000.1
# [onCollideUpdate](#AreaComp-onCollideUpdate)(tag: Tag, f: (obj: GameObj, col?: Collision)=\>void): KEventController
Register an event runs every frame when collide with another game obj with certain tag.
`since`v3000.0
# [onCollideUpdate](#AreaComp-onCollideUpdate)(f: (obj: GameObj, col?: Collision)=\>void): KEventController
Register an event runs every frame when collide with another game obj.
`since`v3000.0
# [onCollideEnd](#AreaComp-onCollideEnd)(tag: Tag, f: (obj: GameObj)=\>void): KEventController
Register an event runs once when stopped colliding with another game obj with certain tag.
`since`v3000.0
# [onCollideEnd](#AreaComp-onCollideEnd)(f: (obj: GameObj)=\>void): void
Register an event runs once when stopped colliding with another game obj.
`since`v3000.0
# [hasPoint](#AreaComp-hasPoint)(p: Vec2): boolean
If has a certain point inside collider.
# [resolveCollision](#AreaComp-resolveCollision)(obj: GameObj): void
Push out from another solid game obj if currently overlapping.
# [localArea](#AreaComp-localArea)(): Shape
Get the geometry data for the collider in local coordinate space.
`since`v3000.0
# [worldArea](#AreaComp-worldArea)(): Shape
Get the geometry data for the collider in world coordinate space.
# [screenArea](#AreaComp-screenArea)(): Shape
Get the geometry data for the collider in screen coordinate space.
# [AreaCompOpt](#AreaCompOpt):
Options for the area`area()` component.
# [shape](#AreaCompOpt-shape)?: Shape
The shape of the area (currently only Rect and Polygon is supported).
``` js
add([
sprite("butterfly"),
pos(100, 200),
// a triangle shape!
area({ shape: new Polygon([vec2(0), vec2(100), vec2(-100, 100)]) }),
])
```
# [scale](#AreaCompOpt-scale)?: number \| Vec2
Area scale.
# [offset](#AreaCompOpt-offset)?: Vec2
Area offset.
# [cursor](#AreaCompOpt-cursor)?: Cursor
Cursor on hover.
# [collisionIgnore](#AreaCompOpt-collisionIgnore)?: Tag\[\]
If this object should ignore collisions against certain other objects.
`since`v3000.0
# [restitution](#AreaCompOpt-restitution)?: number
Bounciness factor between 0 and 1.
`since`v4000.0
# [friction](#AreaCompOpt-friction)?: number
Friction factor between 0 and 1.
`since`v4000.0
# [BodyComp](#BodyComp):
The body`body()` component.
# [vel](#BodyComp-vel): Vec2
Object current velocity.
`since`v3001.0
# [damping](#BodyComp-damping): number
How much velocity decays (velocity \*= 1 / (1 + damping \* dt) every frame).
`since`v3001.0
# [isStatic](#BodyComp-isStatic): boolean
If object is static, it won't move, all non static objects won't move past it, and all calls to addForce(), applyImpulse(), or jump() on this body will do absolutely nothing.
# [jumpForce](#BodyComp-jumpForce): number
Initial speed in pixels per second for jump().
# [gravityScale](#BodyComp-gravityScale): number
Gravity multiplier.
# [mass](#BodyComp-mass): number
Mass of the body, decides how much a non-static body should move when resolves with another non-static body. (default 1).
`since`v3000.0
# [stickToPlatform](#BodyComp-stickToPlatform)?: boolean
If object should move with moving platform (default true).
`since`v3000.0
# [curPlatform](#BodyComp-curPlatform)(): GameObj \| null
Current platform landing on.
# [isGrounded](#BodyComp-isGrounded)(): boolean
If currently landing on a platform.
`since`v2000.1
# [isFalling](#BodyComp-isFalling)(): boolean
If currently falling.
`since`v2000.1
# [isJumping](#BodyComp-isJumping)(): boolean
If currently rising.
`since`v3000.0
# [applyImpulse](#BodyComp-applyImpulse)(impulse: Vec2): void
Applies an impulse
`param`impulseThe impulse vector, applied directly
# [addForce](#BodyComp-addForce)(force: Vec2): void
Applies a force
`param`forceThe force vector, applied after scaled by the inverse mass
# [jump](#BodyComp-jump)(force?: number): void
Upward thrust.
# [onPhysicsResolve](#BodyComp-onPhysicsResolve)(action: (col: Collision)=\>void): KEventController
Register an event that runs when a collision is resolved.
`since`v3000.0
# [onBeforePhysicsResolve](#BodyComp-onBeforePhysicsResolve)(action: (col: Collision)=\>void): KEventController
Register an event that runs before a collision would be resolved.
`since`v3000.0
# [onGround](#BodyComp-onGround)(action: ()=\>void): KEventController
Register an event that runs when the object is grounded.
`since`v2000.1
# [onFall](#BodyComp-onFall)(action: ()=\>void): KEventController
Register an event that runs when the object starts falling.
`since`v2000.1
# [onFallOff](#BodyComp-onFallOff)(action: ()=\>void): KEventController
Register an event that runs when the object falls off platform.
`since`v3000.0
# [onHeadbutt](#BodyComp-onHeadbutt)(action: ()=\>void): KEventController
Register an event that runs when the object bumps into something on the head.
`since`v2000.1
# [onLand](#BodyComp-onLand)(action: (obj: GameObj)=\>void): KEventController
Register an event that runs when an object lands on this object.
`since`v3001.0
# [onHeadbutted](#BodyComp-onHeadbutted)(action: (obj: GameObj)=\>void): KEventController
Register an event that runs when the object is bumped by another object head.
# [BodyCompOpt](#BodyCompOpt):
Options for the body`body()` component.
# [damping](#BodyCompOpt-damping)?: number
How much velocity decays (velocity \*= 1 / (1 + damping \* dt) every frame).
`since`v3001.0
# [jumpForce](#BodyCompOpt-jumpForce)?: number
Initial speed in pixels per second for jump().
# [maxVelocity](#BodyCompOpt-maxVelocity)?: number
Maximum velocity when falling.
# [gravityScale](#BodyCompOpt-gravityScale)?: number
Gravity multiplier.
# [isStatic](#BodyCompOpt-isStatic)?: boolean
If object is static, it won't move, all non static objects won't move past it, and all calls to addForce(), applyImpulse(), or jump() on this body will do absolutely nothing.
`since`v3000.0
# [stickToPlatform](#BodyCompOpt-stickToPlatform)?: boolean
If object should move with moving platform (default true).
`since`v3000.0
# [mass](#BodyCompOpt-mass)?: number
Mass of the body, decides how much a non-static body should move when resolves with another non-static body. (default 1).
`since`v3000.0
# [DoubleJumpComp](#DoubleJumpComp):
The doubleJump`doubleJump()` component.
# [numJumps](#DoubleJumpComp-numJumps): number
Number of jumps allowed.
# [doubleJump](#DoubleJumpComp-doubleJump)(force?: number): void
Performs double jump (the initial jump only happens if player is grounded).
# [onDoubleJump](#DoubleJumpComp-onDoubleJump)(action: ()=\>void): KEventController
Register an event that runs when the object performs the second jump when double jumping.
# [AnchorComp](#AnchorComp):
The anchor`anchor()` component.
# [anchor](#AnchorComp-anchor): Anchor \| Vec2
Anchor point for render.
# [FollowComp](#FollowComp):
The follow`follow()` component.
[follow](#FollowComp-follow):
# [obj](#undefined-obj): GameObj
The object to follow.
# [offset](#undefined-offset): Vec2
The offset to follow the object by.
# [LayerComp](#LayerComp):
The layer`layer()` component.
# [layerIndex](#LayerComp-layerIndex)(): number \| null
Get the index of the current layer the object is assigned to.
`returns`The index of the layer the object is assigned to, or \`null\` if the layer does not exist.
# [layer](#LayerComp-layer)(): string \| null
Get the name of the current layer the object is assigned to.
`returns`The name of the layer the object is assigned to.
# [layer](#LayerComp-layer)(name: string):
Set the name of the layer the object should be assigned to.
# [OffScreenComp](#OffScreenComp):
The offscreen`offscreen()` component.
# [offscreenDistance](#OffScreenComp-offscreenDistance): number \| undefined
The minimum distance that the object must be off the screen by to be considered \"offscreen\". If it is undefined, it means that the object will be considered to be offscreen when its bounding rectangle (defined by width and height) is not intersecting with the screen rectangle.
# [isOffScreen](#OffScreenComp-isOffScreen)(): boolean
If object is currently out of view.
# [onExitScreen](#OffScreenComp-onExitScreen)(action: ()=\>void): KEventController
Register an event that runs when object goes out of view.
# [onEnterScreen](#OffScreenComp-onEnterScreen)(action: ()=\>void): KEventController
Register an event that runs when object enters view.
# [OffScreenCompOpt](#OffScreenCompOpt):
Options for offscreen`offscreen()` component.
# [hide](#OffScreenCompOpt-hide)?: boolean
If hide object when out of view.
# [pause](#OffScreenCompOpt-pause)?: boolean
If pause object when out of view.
# [unpause](#OffScreenCompOpt-unpause)?: boolean
If unpause object when back in view.
# [destroy](#OffScreenCompOpt-destroy)?: boolean
If destroy object when out of view.
# [distance](#OffScreenCompOpt-distance)?: number
The distance when out of view is triggered (default 200).
`since`v3000.0
# [RotateComp](#RotateComp):
The rotate`rotate()` component.
# [angle](#RotateComp-angle): number
Angle in degrees.
# [rotateBy](#RotateComp-rotateBy)(angle: number): void
Rotate in degrees.
# [rotateTo](#RotateComp-rotateTo)(s: number): void
Rotate to a degree (like directly assign to .angle)
`since`v3000.0
# [ScaleComp](#ScaleComp):
The scale`scale()` component.
# [scale](#ScaleComp-scale): Vec2
The current scale of the object
`returns`The current scale of the object as a
# [scaleTo](#ScaleComp-scaleTo)(s: number): void
Set the scale of the object to a number
# [scaleTo](#ScaleComp-scaleTo)(s: Vec2): void
Set the scale of the object to a Vec2
# [scaleTo](#ScaleComp-scaleTo)(sx: number, sy: number): void
Set the scale of the object to a number for x and y
# [scaleBy](#ScaleComp-scaleBy)(s: number): void
Scale the object by a number
# [scaleBy](#ScaleComp-scaleBy)(s: Vec2): void
Scale the object by a Vec2
# [scaleBy](#ScaleComp-scaleBy)(sx: number, sy: number): void
Scale the object by a number for x and y
# [ZComp](#ZComp):
The z`z()` component.
# [z](#ZComp-z): number
Defines the z-index of this game obj
# [MergeComps](#MergeComps)\<T\>: MergeObj\<RemoveCompProps\>
A type to merge the components of a game object, omitting the default component properties.
# [CompList](#CompList)\<T\>: T \| Tag\[\]
A component list.
[EmptyComp](#EmptyComp):
# [id](#undefined-id): string
& Comp
A component without own properties.
# [getSceneName](#getSceneName)(): string \| null
Gets the name of the current scene. Returns null if no scene is active.
`since`v3001.0
# [scene](#scene)(name: SceneName, def: SceneDef): void
Define a scene.
`param`name- The scene name.
`param`def- The scene definition.
``` js
// define a scene
scene("game", () => {
// ...
});
// get options
scene("game", (opts) => {
debug.log(opts.level);
});
```
# [go](#go)(name: SceneName, args: any): void
Go to a scene, passing all rest args to scene callback.
`param`name- The scene name.
`param`args- The rest args to pass to the scene callback.
``` js
// go to "game" scene
go("game");
// go with options
go("game", { level: 1 });
```
`since`v2000.0
# [layers](#layers)(layers: string\[\], defaultLayer: string): void
`param`layers- The layer names.
`param`defaultLayer- The default layer name.
`deprecated`Use
``` js
setLayers(["bg", "obj", "ui"], "obj")
// no layer specified, will be added to "obj"
add([
sprite("bean"),
]);
// add to "bg" layer
add([
sprite("bg"),
layer("bg"),
]);
```
`since`v3001.0
# [onGamepadConnect](#onGamepadConnect)(action: (gamepad: KGamepad)=\>void): KEventController
Register an event that runs when a gamepad is connected.
`param`action- The function that runs when quit() is called.
``` js
// watch for a controller connecting
onGamepadConnect((gp) => {
debug.log(`ohhi player ${gp.index + 1}`);
});
```
`returns`The event controller.
`since`v3000.0
# [onGamepadDisconnect](#onGamepadDisconnect)(action: (gamepad: KGamepad)=\>void): KEventController
Register an event that runs when a gamepad is disconnected.
`param`action- The function that runs when quit() is called.
``` js
// watch for a controller disconnecting
onGamepadDisconnect((gp) => {
debug.log(`ohbye player ${gp.index + 1}`);
});
```
`returns`The event controller.
`since`v3000.0
# [onClick](#onClick)(tag: Tag, action: (a: GameObj)=\>void): KEventController
Register an event that runs when game objs with certain tags are clicked (required to have the area() component).
`param`tag- The tag to listen for.
`param`action- The function to run when the event is triggered.
``` js
// click on any "chest" to open
onClick("chest", (chest) => chest.open())
```
`returns`The event controller.
`since`v2000.1
# [onClick](#onClick)(action: ()=\>void): KEventController
Register an event that runs when users clicks.
`param`action- The function to run when the event is triggered.
``` js
// click on anywhere to go to "game" scene
onClick(() => go("game"));
```
`returns`The event controller.
`since`v2000.1
# [onKeyDown](#onKeyDown)(key: Key \| Key\[\], action: (key: Key)=\>void): KEventController
Register an event that runs every frame when a key is held down.
`param`key- The key(s) to listen for.
`param`action- The function to run when the event is triggered.
``` js
// move left by SPEED pixels per frame every frame when left arrow key is being held down
onKeyDown("left", () => {
bean.move(-SPEED, 0)
});
```
`returns`The event controller.
`since`v2000.1
# [onKeyDown](#onKeyDown)(action: (key: Key)=\>void): KEventController
Register an event that runs every frame when any key is held down.
`param`action- The function to run when the event is triggered.
`returns`The event controller.
`since`v2000.1
# [onKeyPress](#onKeyPress)(key: Key \| Key\[\], action: (key: Key)=\>void): KEventController
Register an event that runs when user presses certain keys.
`param`key- The key(s) to listen for.
`param`action- The function to run when the event is triggered.
``` js
// .jump() once when "space" is just being pressed
onKeyPress("space", () => {
bean.jump();
});
onKeyPress(["up", "space"], () => {
bean.jump();
});
```
`returns`The event controller.
`since`v2000.1
# [onKeyPress](#onKeyPress)(action: (key: Key)=\>void): KEventController
Register an event that runs when user presses any key.
`param`action- The function to run when the event is triggered.
``` js
// Call restart() when player presses any key
onKeyPress((key) => {
debug.log(`key pressed ${key}`);
restart();
});
```
`returns`The event controller.
`since`v3001.0
# [onKeyPressRepeat](#onKeyPressRepeat)(k: Key \| Key\[\], action: (k: Key)=\>void): KEventController
Register an event that runs when user presses certain keys (also fires repeatedly when the keys are being held down).
`param`k- The key(s) to listen for.
`param`action- The function to run when the event is triggered.
``` js
// delete last character when "backspace" is being pressed and held
onKeyPressRepeat("backspace", () => {
input.text = input.text.substring(0, input.text.length - 1);
});
```
`returns`The event controller.
`since`v3000.1
# [onKeyPressRepeat](#onKeyPressRepeat)(action: (k: Key)=\>void): KEventController
# [onKeyRelease](#onKeyRelease)(k: Key \| Key\[\], action: (k: Key)=\>void): KEventController
Register an event that runs when user release certain keys.
`param`k= The key(s) to listen for. See
`param`action- The function that runs when a user releases certain keys
``` js
// release `a` or `b` keys
onKeyRelease([`a`, `b`], (k) => {
debug.log(`Released the ${k} key...`);
});
```
`returns`The event controller.
`since`v2000.1
# [onKeyRelease](#onKeyRelease)(action: (k: Key)=\>void): KEventController
Register an event that runs when user releases a key.
`param`action- The function that runs when a user releases a
``` js
// release a key
onKeyRelease((k) => {
debug.log(`Released the ${k} key...`);
});
```
`returns`The event controller.
`since`v2000.1
# [onCharInput](#onCharInput)(action: (ch: string)=\>void): KEventController
Register an event that runs when user inputs text.
`param`action- The function to run when the event is triggered.
``` js
// type into input
onCharInput((ch) => {
input.text += ch
})
```
`returns`The event controller.
`since`v2000.1
# [onMouseDown](#onMouseDown)(btn: MouseButton \| MouseButton\[\], action: (m: MouseButton)=\>void): KEventController
Register an event that runs every frame when certain mouse buttons are being held down.
`param`btn- The mouse button(s) to listen for. See
`param`action- The function that is run when certain mouse buttons are being held down.
``` js
// count time with left mouse button down
let mouseTime = 0;
onMouseDown("left", () => {
mouseTime += dt();
debug.log(`Time with mouse down: ${mouseTime});
});
```
`returns`The event controller.
`since`v3001.0
# [onMouseDown](#onMouseDown)(action: (m: MouseButton)=\>void): KEventController
Register an event that runs every frame when any mouse button is being held down.
`param`action- The function that is run when any mouse button is being held down.
``` js
// count time with any mouse button down
let mouseTime = 0;
onMouseDown((m) => {
mouseTime += dt();
});
```
`returns`The event controller.
`since`v3001.0
# [onMousePress](#onMousePress)(action: (m: MouseButton)=\>void): KEventController
Register an event that runs when user clicks mouse.
`param`action- The function that is run when user clicks a mouse button.
``` js
// gives cookies on left press, remove on right press
let cookies = 0;
onMousePress(["left", "right"], (m) => {
if (m == "left") {
cookies++;
} else {
cookies--;
}
});
```
`returns`The event controller.
`since`v3001.0
# [onMousePress](#onMousePress)(btn: MouseButton \| MouseButton\[\], action: (m: MouseButton)=\>void): KEventController
Register an event that runs when user clicks mouse.
`param`btn- The mouse button(s) to listen for. See
`param`action- The function that is run what the user clicks cetain mouse buttons.
``` js
// gives cookies on any mouse press
let cookies = 0;
onMousePress((m) => {
cookies++;
debug.log(`Cookies: ${cookies}`);
});
```
`returns`The event controller.
`since`v3001.0
# [onMouseRelease](#onMouseRelease)(action: (m: MouseButton)=\>void): KEventController
Register an event that runs when user releases mouse.
`param`action- The function that is run what the user clicks a provided mouse button.
``` js
// spawn bean where right mouse is released
onMouseRelease("right", (m) => {
debug.log(`${m} released, spawning bean...`);
add([
pos(mousePos()),
sprite("bean"),
anchor("center"),
]);
});
```
`returns`The event controller.
`since`v3001.0
# [onMouseRelease](#onMouseRelease)(btn: MouseButton \| MouseButton\[\], action: (m: MouseButton)=\>void): KEventController
Register an event that runs when user releases mouse.
`param`btn- The button(s) to listen for. See
`param`action- The function that is run what the user clicks a provided mouse button.
``` js
// spawn bean where right mouse is released
onMouseRelease((m) => {
if (m == "right") {
debug.log(`${m} released, spawning bean...`);
add([
pos(mousePos()),
sprite("bean"),
anchor("center"),
]);
});
});
```
`returns`The event controller.
`since`v3001.0
# [onMouseMove](#onMouseMove)(action: (pos: Vec2, delta: Vec2)=\>void): KEventController
Register an event that runs whenever user moves the mouse.
`param`action- The function that is run what the user moves the mouse.
``` js
// runs when the mouse has moved
onMouseMove((p, d) => {
bean.pos = p; // set bean position to mouse position
});
```
`returns`The event controller.
`since`v2000.1
# [onTouchStart](#onTouchStart)(action: (pos: Vec2, t: Touch)=\>void): KEventController
Register an event that runs when a touch starts.
`param`action- The function to run when the event is triggered.
`returns`The event controller.
`since`v2000.1
# [onTouchMove](#onTouchMove)(action: (pos: Vec2, t: Touch)=\>void): KEventController
Register an event that runs whenever touch moves.
`param`action- The function to run when the event is triggered.
`returns`The event controller.
`since`v2000.1
# [onTouchEnd](#onTouchEnd)(action: (pos: Vec2, t: Touch)=\>void): KEventController
Register an event that runs when a touch ends.
`param`action- The function to run when the event is triggered.
`returns`The event controller.
`since`v2000.1
# [onScroll](#onScroll)(action: (delta: Vec2)=\>void): KEventController
Register an event that runs when mouse wheel scrolled.
`param`action- The function to run when the event is triggered.
``` js
// Zoom camera on scroll
onScroll((delta) => {
const zoom = delta.y / 500;
camScale(camScale().add(zoom));
});
```
`returns`The event controller.
`since`v3000.0
# [onGamepadButtonDown](#onGamepadButtonDown)(btn: KGamepadButton \| KGamepadButton\[\], action: (btn: KGamepadButton, gamepad: KGamepad)=\>void): KEventController
Register an event that runs every frame when certain gamepad buttons are held down.
`param`btn- The button(s) to listen for. See
`param`action- The function that is run while certain gamepad buttons are held down.
``` js
// when button is being held down
onGamepadButtonDown("rtrigger", (gp) => {
car.addForce(Vec2.fromAngle(car.angle).scale(10));
});
```
`returns`The event controller.
`since`v3001.0
# [onGamepadButtonDown](#onGamepadButtonDown)(action: (btn: KGamepadButton, gamepad: KGamepad)=\>void): KEventController
Register an event that runs every frame when any gamepad buttons are held down.
`param`action- The function that is run while any gamepad buttons are held down.
``` js
// when button is being held down
onGamepadButtonDown((btn, gp) => {
if (btn == "rtrigger") {
car.addForce(Vec2.fromAngle(car.angle).scale(10));
} else if (btn == "ltrigger") {
car.addForce(Vec2.fromAngle(car.angle).scale(-5));
}
});
```
`returns`The event controller.
`since`v3001.0
# [onGamepadButtonPress](#onGamepadButtonPress)(btn: KGamepadButton \| KGamepadButton\[\], action: (btn: KGamepadButton, gamepad: KGamepad)=\>void): KEventController
Register an event that runs when user presses certain gamepad button.
`param`btn- The button(s) to listen for. See
`param`action- The function that is run when certain gamepad buttons are pressed.
``` js
// when user presses button
onGamepadButtonPress("south", (btn, gp) => {
player.jump(200);
});
```
`returns`The event controller.
`since`v3001.0
# [onGamepadButtonPress](#onGamepadButtonPress)(action: (btn: KGamepadButton, gamepad: KGamepad)=\>void): KEventController
Register an event that runs when user presses any gamepad button.
`param`action- The function that is run when any gamepad buttons is pressed.
``` js
// when user presses button
onGamepadButtonPress((btn, gp) => {
if (btn == "south") {
player.jump(200); // jump
}
});
```
`returns`The event controller.
`since`v3001.0
# [onGamepadButtonRelease](#onGamepadButtonRelease)(btn: KGamepadButton \| KGamepadButton\[\], action: (btn: KGamepadButton, gamepad: KGamepad)=\>void): KEventController
Register an event that runs when user releases certain gamepad button
`param`btn- The button(s) to listen for. See
`param`action- The function that is run when certain gamepad buttons are released.
``` js
// charged attack
let chargeTime = 0
onGamepadButtonPress("west", (btn, gp) => {
chargeTime = time();
});
// when a gamepad button is released, this is run
onGamepadButtonRelease("west", (btn, gp) => {
let chargedt = time() - chargeTime;
debug.log(`Used ${chargedt * 1000} power!`);
});
```
`returns`The event controller.
`since`v3001.0
# [onGamepadButtonRelease](#onGamepadButtonRelease)(action: (btn: KGamepadButton, gamepad: KGamepad)=\>void): KEventController
Register an event that runs when user releases any gamepad button.
`param`action- The function that is run when any gamepad buttons are released.
``` js
// when a gamepad button is released, this is run
onGamepadButtonRelease((btn, gp) => {
if (btn == "north") {
player.jump(500);
}
});
```
`returns`The event controller.
`since`v3000.0
# [onGamepadStick](#onGamepadStick)(stick: GamepadStick, action: (value: Vec2, gameepad: KGamepad)=\>void): KEventController
Register an event that runs when the gamepad axis exists.
`param`stick- The stick to listen for. See
`param`action- The function that is run when a specific gamepad stick is moved.
``` js
// player move
let player = add([
pos(center()),
sprite(`bean`),
]);
// when left stick is moved
onGamepadStick("left", (stickVector, gp) => {
player.move(stickVector.x, 0);
});
```
`returns`The event controller.
`since`v3000.0
# [onButtonPress](#onButtonPress)(btn: TButton \| TButton\[\], action: (btn: TButton)=\>void): KEventController
Register an event that runs when user press a defined button (like \"jump\") on any input (keyboard, gamepad).
`param`btn- The button(s) to listen for.
`param`action- The function to run when the event is triggered.
`returns`The event controller.
`since`v3001.0
# [onButtonRelease](#onButtonRelease)(btn: TButton \| TButton\[\], action: (btn: TButton)=\>void): KEventController
Register an event that runs when user release a defined button (like \"jump\") on any input (keyboard, gamepad).
`param`btn- The button(s) to listen for.
`param`action- The function to run when the event is triggered.
`returns`The event controller.
`since`v3001.0
# [onButtonRelease](#onButtonRelease)(action: (btn: TButton)=\>void): KEventController
# [onButtonDown](#onButtonDown)(btn: TButton \| TButton\[\], action: (btn: TButton)=\>void): KEventController
Register an event that runs when user press a defined button (like \"jump\") on any input (keyboard, gamepad).
`param`btn- The button(s) to listen for.
`param`action- The function to run when the event is triggered.
`returns`The event controller.
`since`v3001.0
# [onButtonDown](#onButtonDown)(action: (btn: TButton)=\>void): KEventController
# [isTouchscreen](#isTouchscreen)(): boolean
Is currently on a touch screen device.
`returns`true if on a touch screen device.
`since`v3000.0
# [mousePos](#mousePos)(): Vec2
Get current mouse position (without camera transform).
`returns`The current mouse position.
`since`v2000.0
# [mouseDeltaPos](#mouseDeltaPos)(): Vec2
How much mouse moved last frame.
`returns`The delta mouse position.
`since`v2000.0
# [isKeyDown](#isKeyDown)(k?: Key \| Key\[\]): boolean
If any or certain key(s) are currently down.
`param`k- The key(s) to check.
``` js
// Any key down
let lastKeyTime = time()
let triedToWakeUp = false
onUpdate(() => {
if (isKeyDown()) {
lastKeyTime = time()
triedToWakeUp = false
return
}
if (triedToWakeUp || time() - lastKeyTime < 5) return
debug.log("Wake up!")
triedToWakeUp = true
})
// Certain key down
// equivalent to the calling bean.move() in an onKeyDown("left")
onUpdate(() => {
if (isKeyDown("left")) {
bean.move(-SPEED, 0)
}
})
// Certain keys down
let isMoving = false
onUpdate(() => {
isMoving = isKeyDown(["left", "right"])
})
```
`since`v2000.0
# [isKeyPressed](#isKeyPressed)(k?: Key \| Key\[\]): boolean
If any or certain key(s) are just pressed last frame.
`param`k- The key(s) to check.
``` js
onUpdate(() => {
if (!isKeyPressed()) return // early return as no key was pressed
if (isKeyPressed("space")) debug.log("Pressed the jump key")
if (isKeyPressed(["left", "right"])) debug.log("Pressed any of the move keys")
})
```
`since`v2000.0
# [isKeyPressedRepeat](#isKeyPressedRepeat)(k?: Key \| Key\[\]): boolean
If any or certain key(s) are just pressed last frame (also fires repeatedly when the keys are being held down).
`param`k- The key(s) to check.
``` js
let heldKeys = new Set()
onUpdate(() => {
if (isKeyPressedRepeat("space")) {
pressedOrHeld(["space"], 'the jump key')
} else if (isKeyPressedRepeat(["left", "right"])) {
pressedOrHeld(["left", "right"], 'any of the move keys')
} else if (isKeyPressedRepeat()) {
pressedOrHeld(["any"], 'any key')
}
})
onKeyRelease((key) => wait(0.1, () => {
heldKeys.delete(key)
heldKeys.delete("any")
}))
// log message if pressed only or held as well
function pressedOrHeld(keys, string) {
debug.log(`Pressed${keys.some(key => heldKeys.has(key)) ? ' and held' : ''} ${string}`)
keys.forEach((key) => {
if (key == "any" || isKeyDown(key)) heldKeys.add(key)
})
}
```
`since`v2000.0
# [isKeyReleased](#isKeyReleased)(k?: Key \| Key\[\]): boolean
If any or certain key(s) are just released last frame.
`param`k- The key(s) to check.
``` js
onUpdate(() => {
if (!isKeyReleased()) return // early return as no key was released
if (isKeyReleased("space")) debug.log("Released the jump key")
if (isKeyReleased(["left", "right"])) debug.log("Released any of the move keys")
})
```
`since`v2000.0
# [isMouseDown](#isMouseDown)(btn?: MouseButton \| MouseButton\[\]): boolean
If mouse buttons are currently down.
`param`btn- The button(s) to check.
`since`v2000.0
# [isMousePressed](#isMousePressed)(btn?: MouseButton \| MouseButton\[\]): boolean
If mouse buttons are just clicked last frame
`param`btn- The button(s) to check.
`since`v2000.0
# [isMouseReleased](#isMouseReleased)(btn?: MouseButton \| MouseButton\[\]): boolean
If mouse buttons are just released last frame.
`param`btn- The button(s) to check.
`since`v2000.0
# [isMouseMoved](#isMouseMoved)(): boolean
If mouse moved last frame.
`since`v2000.1
# [isGamepadButtonPressed](#isGamepadButtonPressed)(btn?: KGamepadButton \| KGamepadButton\[\]): boolean
If certain gamepad buttons are just pressed last frame
`param`btn- The button(s) to check.
`since`v3000.0
# [isGamepadButtonDown](#isGamepadButtonDown)(btn?: KGamepadButton \| KGamepadButton): boolean
If certain gamepad buttons are currently held down.
`param`btn- The button(s) to check.
`since`v3000.0
# [isGamepadButtonReleased](#isGamepadButtonReleased)(btn?: KGamepadButton \| KGamepadButton\[\]): boolean
If certain gamepad buttons are just released last frame.
`param`btn- The button(s) to check.
`since`v3000.0
# [isButtonPressed](#isButtonPressed)(btn?: TButton \| TButton\[\]): boolean
If any or certain bound button(s) are just pressed last frame on any input (keyboard, gamepad).
`param`btn- The button(s) to check.
``` js
onUpdate(() => {
if (!isButtonPressed()) return // early return as no button was pressed
if (isButtonPressed("jump")) debug.log("Player jumped")
if (isButtonPressed(["left", "right"])) debug.log("Player moved")
})
```
`since`v3001.0
# [isButtonDown](#isButtonDown)(btn?: TButton \| TButton\[\]): boolean
If any or certain bound button(s) are currently held down on any input (keyboard, gamepad).
`param`btn- The button(s) to check.
``` js
onUpdate(() => {
if (!isButtonDown()) return // early return as no button is held down
if (isButtonDown("jump")) debug.log("Player is jumping")
if (isButtonDown(["left", "right"])) debug.log("Player is moving")
})
```
`since`v3001.0
# [isButtonReleased](#isButtonReleased)(btn?: TButton \| TButton\[\]): boolean
If any or certain bound button(s) are just released last frame on any input (keyboard, gamepad).
`param`btn- The button(s) to check.
``` js
onUpdate(() => {
if (!isButtonReleased()) return // early return as no button was released
if (isButtonReleased("jump")) debug.log("Player stopped jumping")
if (isButtonReleased(["left", "right"])) debug.log("Player stopped moving")
})
```
`since`v3001.0
# [getButton](#getButton)(btn: TypeOperator): ButtonBinding
Get a input binding from a button name.
`param`btn- The button to get binding for.
`since`v3001.0
# [setButton](#setButton)(btn: string, def: ButtonBinding): void
Set a input binding for a button name.
`param`btn- The button to set binding for.
`since`v3001.0
# [pressButton](#pressButton)(btn: TButton): void
Press a button virtually.
`param`btn- The button to press.
``` js
// press "jump" button
pressButton("jump"); // triggers onButtonPress, starts onButtonDown
releaseButton("jump"); // triggers onButtonRelease, stops onButtonDown
```
`since`v3001.0
# [releaseButton](#releaseButton)(btn: TButton): void
Release a button virtually.
`param`btn- The button to release.
``` js
// press "jump" button
pressButton("jump"); // triggers onButtonPress, starts onButtonDown
releaseButton("jump"); // triggers onButtonRelease, stops onButtonDown
```
`since`v3001.0
# [getGamepadStick](#getGamepadStick)(stick: GamepadStick): Vec2
Get stick axis values from a gamepad.
`param`stick- The stick to get values from.
`returns`The stick axis Vec2.
`since`v3001.0
# [getLastInputDeviceType](#getLastInputDeviceType)(): ButtonBindingDevice \| null
Get the latest input device type that triggered the input event.
`returns`The last input device type, or null if no input event has been triggered.
`since`v3001.0
# [charInputted](#charInputted)(): string\[\]
List of characters inputted since last frame.
`returnns`An array of characters inputted.
`since`v3000.0
# [Key](#Key): f1 \| f2 \| f3 \| f4 \| f5 \| f6 \| f7 \| f8 \| f9 \| f10 \| f11 \| f12 \| \` \| 1 \| 2 \| 3 \| 4 \| 5 \| 6 \| 7 \| 8 \| 9 \| 0 \| - \| + \| = \| q \| w \| e \| r \| t \| y \| u \| i \| o \| p \| \[ \| \] \| \\ \| a \| s \| d \| f \| g \| h \| j \| k \| l \| ; \| ' \| z \| x \| c \| v \| b \| n \| m \| , \| . \| / \| escape \| backspace \| enter \| tab \| control \| alt \| meta \| space \| \| left \| right \| up \| down \| shift \| string &
A key.
# [MouseButton](#MouseButton): left \| right \| middle \| back \| forward
A mouse button.
# [KGamepadButton](#KGamepadButton): north \| east \| south \| west \| ltrigger \| rtrigger \| lshoulder \| rshoulder \| select \| start \| lstick \| rstick \| dpad-up \| dpad-right \| dpad-down \| dpad-left \| home \| capture
A gamepad button.
# [GamepadStick](#GamepadStick): left \| right
A gamepad stick.
# [KEventController](#KEventController):
A controller for all events in KAPLAY.
``` js
// Create a new event
const logHi = onUpdate(() => {
debug.log("hi");
});
// Pause the event
logHi.paused = true;
// Cancel the event
logHi.cancel();
```
# [paused](#KEventController-paused): boolean
If the event is paused
# [cancel](#KEventController-cancel)(): void
Cancel the event
# [join](#KEventController-join)(events: KEventController\[\]): KEventController
# [replace](#KEventController-replace)(oldEv: KEventController, newEv: KEventController): KEventController
[GameObjEventMap](#GameObjEventMap):
# [update](#undefined-update): \[GameObj\]
Triggered every frame
# [fixedUpdate](#undefined-fixedUpdate): \[GameObj\]
Triggered every frame at a fixed 50fps rate
# [draw](#undefined-draw): \[GameObj\]
Triggered every frame before update
# [add](#undefined-add): \[GameObj\]
Triggered when object is added
# [destroy](#undefined-destroy): \[GameObj\]
Triggered when object is destroyed
# [use](#undefined-use): \[GameObj, string\]
Triggered when component is used
# [unuse](#undefined-unuse): \[GameObj, string\]
Triggered when component is unused
# [tag](#undefined-tag): \[GameObj, string\]
Triggered when tag is added
# [untag](#undefined-untag): \[GameObj, string\]
Triggered when tag is removed
# [collide](#undefined-collide): \[GameObj, GameObj, Collision\]
Triggered when object collides with another object From area`area()` component
# [collideUpdate](#undefined-collideUpdate): \[GameObj, GameObj, Collision\]
Triggered every frame when object collides with another object From area`area()` component
# [collideEnd](#undefined-collideEnd): \[GameObj, GameObj, Collision\]
Triggered when object stops colliding with another object From area`area()` component
# [hurt](#undefined-hurt): \[GameObj, NamedTupleMember\]
Triggered when object is hurted From health`health()` component
# [heal](#undefined-heal): \[GameObj, NamedTupleMember\]
Triggered when object is healed From health`health()` component
# [death](#undefined-death): \[GameObj\]
Triggered when object dies From health`health()` component
# [beforePhysicsResolve](#undefined-beforePhysicsResolve): \[GameObj, NamedTupleMember\]
Triggered before physics resolves From body`body()` component
# [physicsResolve](#undefined-physicsResolve): \[GameObj, NamedTupleMember\]
Triggered after physics resolves From body`body()` component
# [ground](#undefined-ground): \[GameObj\]
Triggered when object is on the ground From body`body()` component
# [fall](#undefined-fall): \[GameObj\]
Triggered when object is falling From body`body()` component
# [fallOff](#undefined-fallOff): \[GameObj\]
Triggered when object stops falling From body`body()` component
# [headbutt](#undefined-headbutt): \[GameObj\]
Triggered when object head butt something (like Mario with brick) From body`body()` component
# [land](#undefined-land): \[GameObj\]
Triggered when an object lands on this object From body`body()` component
# [headbutted](#undefined-headbutted): \[GameObj\]
Triggered when object is headbutted by another object From body`body()` component
# [doubleJump](#undefined-doubleJump): \[GameObj\]
Triggered when object double jumps From doubleJump`doubleJump()` component
# [exitView](#undefined-exitView): \[GameObj\]
Triggered when object goes out of view From offscreen`offscreen()` component
# [enterView](#undefined-enterView): \[GameObj\]
Triggered when object enters view From offscreen`offscreen()` component
# [animStart](#undefined-animStart): \[GameObj, NamedTupleMember\]
Triggered when a sprite animation starts From sprite`sprite()` component
# [animEnd](#undefined-animEnd): \[GameObj, NamedTupleMember\]
Triggered when a sprite animation ends From sprite`sprite()` component
# [navigationNext](#undefined-navigationNext): \[GameObj, GameObj, Vec2\]
From agent`agent()` component
# [navigationEnded](#undefined-navigationEnded): \[GameObj, GameObj\]
From agent`agent()` component
# [navigationStarted](#undefined-navigationStarted): \[GameObj, GameObj\]
From agent`agent()` component
# [targetReached](#undefined-targetReached): \[GameObj, GameObj\]
From agent`agent()` component
# [patrolFinished](#undefined-patrolFinished): \[GameObj\]
From patrol`patrol()` component
# [objectSpotted](#undefined-objectSpotted): \[GameObj, GameObj\[\]\]
From sentry`sentry()` component
# [animateChannelFinished](#undefined-animateChannelFinished): \[GameObj, NamedTupleMember\]
From animate`animate()` component
# [animateFinished](#undefined-animateFinished): \[GameObj\]
From animate`animate()` component
# [spatialMapChanged](#undefined-spatialMapChanged): \[GameObj\]
From level of addLevel`addLevel()` function
# [navigationMapInvalid](#undefined-navigationMapInvalid): \[GameObj\]
From level of addLevel`addLevel()` function
# [navigationMapChanged](#undefined-navigationMapChanged): \[GameObj\]
From level of addLevel`addLevel()` function
Game Object events with their arguments. If looking for use it with \`obj.on()\`, ignore first parameter (Game Obj)
# [trigger](#trigger)(event: string, tag: string, args: any): void
Trigger an event on all game objs with certain tag.
`param`event- The tag to trigger to.
`param`tag- Arguments to pass to the \`on()\` functions
``` js
trigger("shoot", "target", 140);
on("shoot", "target", (obj, score) => {
obj.destroy();
debug.log(140); // every bomb was 140 score points!
});
```
`since`v3001.0.6
`experimental`This feature is in experimental phase, it will be fully released in v3001.1.0
# [on](#on)\<Ev\>(event: Ev, tag: Tag, action: (obj: GameObj, args: TupleWithoutFirst)=\>void): KEventController
Register an event on all game objs with certain tag.
`param`event- The tag to listen for.
`param`tag- The function to run when the event is triggered.
``` js
// a custom event defined by body() comp
// every time an obj with tag "bomb" hits the floor, destroy it and addKaboom()
on("ground", "bomb", (bomb) => {
destroy(bomb)
addKaboom(bomb.pos)
})
// a custom event can be defined manually
// by passing an event name, a tag, and a callback function
// if you want any tag, use a tag of "*"
on("talk", "npc", (npc, message) => {
npc.add([
text(message),
pos(0, -50),
lifespan(2),
opacity(),
])
});
onKeyPress("space", () => {
// the trigger method on game objs can be used to trigger a custom event
npc.trigger("talk", "Hello, KAPLAY!");
});
```
`returns`The event controller.
`since`v2000.0
# [onFixedUpdate](#onFixedUpdate)(action: ()=\>void): KEventController
Register an event that runs at a fixed framerate.
`param`action- The function to run when the event is triggered.
`returns`The event controller.
`since`v3001.0
# [onFixedUpdate](#onFixedUpdate)(tag: Tag, action: (obj: GameObj)=\>void): KEventController
# [onUpdate](#onUpdate)(tag: Tag, action: (obj: GameObj)=\>void): KEventController
Register an event that runs every frame (\~60 times per second) for all game objs with certain tag.
`param`tag- The tag to listen for.
`param`action- The function to run when the event is triggered.
``` js
// move every "tree" 120 pixels per second to the left, destroy it when it leaves screen
// there'll be nothing to run if there's no "tree" obj in the scene
onUpdate("tree", (tree) => {
tree.move(-120, 0)
if (tree.pos.x < 0) {
destroy(tree)
}
})
```
`returns`The event controller.
`since`v2000.1
# [onUpdate](#onUpdate)(action: ()=\>void): KEventController
Register an event that runs every frame (\~60 times per second).
`param`action- The function to run when the event is triggered.
``` js
// This will run every frame
onUpdate(() => {
debug.log("ohhi")
})
```
`returns`The event controller.
`since`v2000.1
# [onDraw](#onDraw)(tag: Tag, action: (obj: GameObj)=\>void): KEventController
Register an event that runs every frame (\~60 times per second) for all game objs with certain tag (this is the same as onUpdate but all draw events are run after update events, drawXXX() functions only work in this phase).
`param`tag- The tag to listen for.
`param`action- The function to run when the event is triggered.
`returns`The event controller.
`since`v2000.1
# [onDraw](#onDraw)(action: ()=\>void): KEventController
Register an event that runs every frame (\~60 times per second) (this is the same as onUpdate but all draw events are run after update events, drawXXX() functions only work in this phase).
``` js
onDraw(() => {
drawLine({
p1: vec2(0),
p2: mousePos(),
color: rgb(0, 0, 255),
})
})
```
`returns`The event controller.
`since`v2000.1
# [onAdd](#onAdd)(tag: Tag, action: (obj: GameObj)=\>void): KEventController
Register an event that runs when an object with the provided tag is added.
`param`tag- The tag to listen for.
`param`action- The function that runs when an object is added.
``` js
// This will run when the object is added.
onAdd("player", () => {
debug.log("ohhi");
});
add([
pos(),
"player"
]);
```
`returns`The event controller.
`since`v2000.0
# [onAdd](#onAdd)(action: (obj: GameObj)=\>void): KEventController
Register an event that runs when an object is added
`param`action- The tag to match, only called for objects with a matching tag.
`param`unknown- The function that runs when an object is added.
``` js
// This will run when the object is added.
onAdd(() => {
debug.log("ohhi");
});
add([
pos(),
]);
```
`returns`The event controller.
`since`v2000.0
# [onDestroy](#onDestroy)(tag: Tag, action: (obj: GameObj)=\>void): KEventController
Register an event that runs when an object with the provided tag is destroyed.
`param`tag- The function that runs when an object is destroyed.
``` js
// This will run when the tagged object is destroyed.
onDestroy("bean", () => {
debug.log("ohbye");
});
let player = add([
pos(),
"bean"
])
// Destroy the tagged object
destroy(player);
```
`returns`The event controller.
`since`v2000.0
# [onDestroy](#onDestroy)(action: (obj: GameObj)=\>void): KEventController
Register an event that runs when an object is destroyed.
`param`action- The tag to match, only called for objects with a matching tag.
`param`unknown- The function that runs when an object is destroyed.
``` js
// This will run when the object is destroyed.
onDestroy(() => {
debug.log("ohbye");
});
let ghosty = add([
pos(),
]);
// Destroy the object
destroy(ghosty);
```
`returns`The event controller.
# [onUse](#onUse)(action: (obj: GameObj, id: string)=\>void): KEventController
Register an event that runs when an object starts using a component.
`param`action- The function that runs when an object starts using component.
`param`unknown- The id of the component that was added.
`returns`The event controller.
`since`v3001.1
# [onUnuse](#onUnuse)(action: (obj: GameObj, id: string)=\>void): KEventController
Register an event that runs when an object stops using a component.
`param`action- The function that runs when an object stops using a component.
`param`unknown- The id of the component that was removed.d
`returns`The event controller.
`since`v3001.1
# [onTag](#onTag)(action: (obj: GameObj, tag: string)=\>void): KEventController
Register an event that runs when an object gains a tag.
`param`action- The function that runs when an object gains a tag.
`param`unknown- The tag which was added.
`returns`The event controller.
`since`v3001.1
# [onUntag](#onUntag)(action: (obj: GameObj, tag: string)=\>void): KEventController
Register an event that runs when an object loses a tag.
`param`action- The function that runs when an object loses a tag.
`param`unknown- The tag which was removed.
`returns`The event controller.
`since`v3001.1
# [onLoad](#onLoad)(action: ()=\>void): KEventController \| undefined
Register an event that runs when all assets finished loading.
`param`action- The function to run when the event is triggered.
``` js
const bean = add([
sprite("bean"),
]);
// certain assets related data are only available when the game finishes loading
onLoad(() => {
debug.log(bean.width)
});
```
`returns`The event controller.
`since`v2000.1
# [onLoadError](#onLoadError)(action: (name: string, failedAsset: Asset)=\>void): KEventController \| undefined
Register an event that runs once for each asset that failed to load, after all others have completed.
`param`actionThe function to run when the event is triggered.
``` js
// this will not load
loadSprite("bobo", "notavalidURL");
// process the error
// you decide whether to ignore it, or throw an error and halt the game
onLoadError((name, asset) => {
debug.error(`${name} failed to load: ${asset.error}`);
});
```
`returns`The event controller.
`since`v3001.0
# [onLoading](#onLoading)(action: (progress: number)=\>void): KEventController
Register an event that runs every frame when assets are initially loading. Can be used to draw a custom loading screen.
`param`action- The function that runs when assets are loading.
```` js
```
// progress bar
onLoading((progress) => {
// Background of the bar
drawRect({
width: 240,
height: 40,
pos: center().add(-120,0),
color: BLACK,
anchor: `left,
});
// Progress of the bar
drawRect({
width: map(progress, 0, 1, 0, 220),
height: 32,
pos: center().add(-116, 0),
color: BLUE,
anchor: `left
});
});
````
`returns`The event controller.
`since`v3000.0
# [onError](#onError)(action: (err: Error)=\>void): KEventController
Register a custom error handler. Can be used to draw a custom error screen.
`param`action- The function that runs when the program errors.
``` js
// Create custom error handler
onError((err) => {
drawRect({
width: width(),
height: height(),
pos: center(),
color: RED,
anchor: `center,
});
drawText({
text: err.message,
size: 48,
width: width()/2,
anchor: `center`,
align: `center`,
pos: center(),
color: BLACK
});
});
// cause common error
let pos = add([
pos()
]);
```
`returns`The event controller.
`since`v3000.0
# [onResize](#onResize)(action: ()=\>void): KEventController
Register an event that runs when the canvas resizes.
`param`action- The function that runs when the canvas resizes.
``` js
// create a rectangle with screen size
let rectangle = add([
rect(width(), height()),
color(GREEN),
]);
// resize the rectangle to screen size
onResize(() => {
debug.log(`Old Size: ${rectangle.width}x${rectangle.height}`);
rectangle.width = width();
rectangle.height = height();
debug.log(`New Size: ${rectangle.width}x${rectangle.height}`);
});
```
`returns`The event controller.
`since`v3000.0
# [onCleanup](#onCleanup)(action: ()=\>void): void
Cleanup function to run when quit() is called.
`param`action- The function that runs when quit() is called.
``` js
// useful externally from KAPLAY
onCleanup(() => {
console.log(`ohbye :(`);
});
quit();
```
`returns`The event controller.
`since`v3000.0
# [onCollide](#onCollide)(t1: Tag, t2: Tag, action: (a: GameObj, b: GameObj, col?: Collision)=\>void): KEventController
Register an event that runs once when 2 game objs with certain tags collides (required to have area() component).
`param`t1- The tag of the first game obj.
`param`t2- The tag of the second game obj.
`param`action- The function to run when the event is triggered.
``` js
onCollide("sun", "earth", () => {
addExplosion()
})
```
`returns`The event controller.
`since`v2000.1
# [onCollideUpdate](#onCollideUpdate)(t1: Tag, t2: Tag, action: (a: GameObj, b: GameObj, col?: Collision)=\>void): KEventController
Register an event that runs every frame when 2 game objs with certain tags collides (required to have area() component).
`param`t1- The tag of the first game obj.
`param`t2- The tag of the second game obj.
`param`action- The function to run when the event is triggered.
``` js
onCollideUpdate("sun", "earth", () => {
debug.log("okay this is so hot");
})l
```
`returns`The event controller.
`since`v3000.0
# [onHover](#onHover)(tag: Tag, action: (a: GameObj)=\>void): KEventController
Register an event that runs once when game objs with certain tags are hovered (required to have area() component).
`param`tag- The tag to listen for.
`param`action- The function to run when the event is triggered.
`returns`The event controller.
`since`v3000.0
# [onHoverUpdate](#onHoverUpdate)(tag: Tag, action: (a: GameObj)=\>void): KEventController
Register an event that runs every frame when game objs with certain tags are hovered (required to have area() component).
`param`tag- The tag to listen for.
`param`action- The function to run when the event is triggered.
``` js
// Rotate bean 90 degrees per second when hovered
onHoverUpdate("bean", (bean) => {
bean.angle += dt() * 90
});
```
`returns`The event controller.
`since`v3000.0
# [onHoverEnd](#onHoverEnd)(tag: Tag, action: (a: GameObj)=\>void): KEventController
Register an event that runs once when game objs with certain tags are unhovered (required to have area() component).
`param`tag- The tag to listen for.
`param`action- The function to run when the event is triggered.
`returns`The event controller.
`since`v3000.0
# [onHide](#onHide)(action: ()=\>void): KEventController
Register an event that runs when tab is hidden.
`param`action- The function that is run what the tab is hidden.
``` js
// spooky ghost
let ghosty = add([
pos(center()),
sprite("ghosty"),
anchor("center"),
]);
// when switching tabs, this runs
onHide(() => {
destroy(ghosty);
add([
text("There was never aa ghosttttt"),
pos(center()),
anchor("center")
]);
});
```
`returns`The event controller.
`since`v3001.0
# [onShow](#onShow)(action: ()=\>void): KEventController
Register an event that runs when tab is shown.
`param`action- The function that is run when the tab is shown.
``` js
// user has returned to this tab
onShow(() => {
burp();
});
```
`returns`The event controller.
`since`v3001.0
# [onSceneLeave](#onSceneLeave)(action: (newScene?: string)=\>void): KEventController
Register an event that runs when current scene ends.
`param`action- The function to run when the event is triggered.
`returns`The event controller.
`since`v3000.0
# [KEvent](#KEvent)\<Args\>:
# [cancellers](#KEvent-cancellers):
# [handlers](#KEvent-handlers):
# [add](#KEvent-add)(action: (args: Args)=\>unknown): KEventController
# [addOnce](#KEvent-addOnce)(action: (args: Args \| PromiseLike\[\])=\>void): KEventController
# [next](#KEvent-next)(): Promise\<Args\>
# [trigger](#KEvent-trigger)(args: Args): void
# [numListeners](#KEvent-numListeners)(): number
# [clear](#KEvent-clear)(): void
# [KEventHandler](#KEventHandler)\<EventMap\>:
# [handlers](#KEventHandler-handlers):
# [registers](#KEventHandler-registers): Partial\<MappedType\>
# [on](#KEventHandler-on)\<Name\>(name: Name, action: (args: EventMap\[Name\])=\>void): KEventController
# [onOnce](#KEventHandler-onOnce)\<Name\>(name: Name, action: (args: EventMap\[Name\])=\>void): KEventController
# [next](#KEventHandler-next)\<Name\>(name: Name): Promise\<unknown\>
# [trigger](#KEventHandler-trigger)\<Name\>(name: Name, args: EventMap\[Name\]): void
# [remove](#KEventHandler-remove)\<Name\>(name: Name): void
# [clear](#KEventHandler-clear)(): void
# [numListeners](#KEventHandler-numListeners)\<Name\>(name: Name): number
# [KEventController](#KEventController):
A controller for all events in KAPLAY.
``` js
// Create a new event
const logHi = onUpdate(() => {
debug.log("hi");
});
// Pause the event
logHi.paused = true;
// Cancel the event
logHi.cancel();
```
# [paused](#KEventController-paused): boolean
If the event is paused
# [cancel](#KEventController-cancel)(): void
Cancel the event
# [join](#KEventController-join)(events: KEventController\[\]): KEventController
# [replace](#KEventController-replace)(oldEv: KEventController, newEv: KEventController): KEventController
# [cancel](#cancel)(): Symbol
Cancels the event by returning the cancel symbol.
``` js
onKeyPress((key) => {
if (key === "q") return cancel();
});
```
`returns`The cancel event symbol.
`since`v3001.0.5
`experimental`This feature is in experimental phase, it will be fully released in v3001.1.0
# [width](#width)(): number
Get the width of game.
`returns`The width of the game.
`since`v2000.0
# [getTreeRoot](#getTreeRoot)(): GameObj
Get the root of all objects.
`returns`The root object.
`since`v2000.0
# [height](#height)(): number
Get the height of game.
`returns`The height of the game.
`since`v2000.0
# [center](#center)(): Vec2
Get the center point of view.
``` js
// add bean to the center of the screen
add([
sprite("bean"),
pos(center()),
// ...
])
```
`returns`The center point of the view.
`since`v2000.0
# [dt](#dt)(): number
Get the delta time since last frame.
``` js
// rotate bean 100 deg per second
bean.onUpdate(() => {
bean.angle += 100 * dt()
})
```
`since`v2000.0
# [fixedDt](#fixedDt)(): number
Get the fixed delta time since last frame.
`since`v3000.0
# [restDt](#restDt)(): number
Get the rest delta time since last frame.
`since`v3000.0
# [time](#time)(): number
Get the total time since beginning.
`since`v3001
# [isFocused](#isFocused)(): boolean
If the game canvas is currently focused.
`returns`true if focused.
`since`v2000.1
# [setBackground](#setBackground)(color: Color): void
Set background color.
`since`v3000.0
# [setBackground](#setBackground)(color: Color, alpha: number): void
# [setBackground](#setBackground)(r: number, g: number, b: number): void
# [setBackground](#setBackground)(r: number, g: number, b: number, alpha: number): void
# [getBackground](#getBackground)(): Color \| null
Get background color.
`returns`The background color.
`since`v3000.0
# [getGamepads](#getGamepads)(): KGamepad\[\]
Get connected gamepads.
`returns`An array of connected gamepads.
`since`v3000.0
# [setCursor](#setCursor)(style: Cursor): void
Set cursor style.
`param`style- The cursor style.
``` js
// Change between cursor styles
// Reset cursor to default at start of every frame
onUpdate(() => setCursor("default"));
button.onHover((c) => {
// change cursor to pointer when hovering over button
setCursor("pointer")
})
// Hide the only cursor at start (useful for fakeMouse)
setCursor("none");
```
`since`v2000.0
# [getCursor](#getCursor)(): Cursor
Get current cursor style.
`returns`The current cursor style.
`since`v2000.0
# [setCursorLocked](#setCursorLocked)(locked: boolean): void
Lock / unlock cursor. Note that you cannot lock cursor within 1 second after user unlocking the cursor with the default unlock gesture (typically the esc key) due to browser policy.
`since`v2000.0
# [isCursorLocked](#isCursorLocked)(): boolean
Get if cursor is currently locked.
`returns`true if locked, false otherwise.
`since`v2000.0
# [setFullscreen](#setFullscreen)(f?: boolean): void
Enter / exit fullscreen mode. (note: mouse position is not working in fullscreen mode at the moment)
``` js
// toggle fullscreen mode on "f"
onKeyPress("f", (c) => {
setFullscreen(!isFullscreen());
});
```
`since`v2000.0
# [isFullscreen](#isFullscreen)(): boolean
If currently in fullscreen mode.
`returns`true if fullscreen, false otherwise.
`since`v2000.0
# [canvas](#canvas): HTMLCanvasElement
The canvas DOM KAPLAY is currently using.
`since`v2000.0
# [VERSION](#VERSION): string
Current KAPLAY library version.
`since`v3000.0
# [wait](#wait)(n: number, action?: ()=\>void): TimerController
Run the function after n seconds.
`param`n- The time to wait in seconds.
`param`action- The function to run.
``` js
// 3 seconds until explosion! Runnn!
wait(3, () => {
explode()
})
// wait() returns a PromiseLike that can be used with await
await wait(1)
```
`returns`A timer controller.
`since`v2000.0
# [loop](#loop)(t: number, action: ()=\>void, maxLoops?: number, waitFirst?: boolean): TimerController
Run the function every n seconds.
`param`t- The time to wait in seconds.
`param`action- The function to run.
`param`maxLoops- The maximum number of loops to run. If not provided, it will run forever.
`param`waitFirst- Whether to wait for the first loop to start.
``` js
// spawn a butterfly at random position every 1 second
loop(1, () => {
add([
sprite("butterfly"),
pos(rand(vec2(width(), height()))),
area(),
"friend",
])
})
```
`returns`A timer controller.
`since`v2000.0
[TimerController](#TimerController):
# [paused](#undefined-paused): boolean
If the event handler is paused.
# [cancel](#undefined-cancel)(): void
Cancel the event handler.
# [onEnd](#undefined-onEnd)(action: ()=\>void): void
Register an event when finished.
# [then](#undefined-then)(action: ()=\>void): TimerController
[TweenController](#TweenController): TimerController &
# [finish](#undefined-finish)(): void
Finish the tween now and cancel.
Event controller for tween.
# [Color](#Color):
0-255 RGBA color.
# [r](#Color-r): number
Red (0-255.
# [g](#Color-g): number
Green (0-255).
# [b](#Color-b): number
Blue (0-255).
# [fromArray](#Color-fromArray)(arr: \[number, number, number\]): Color
# [fromHex](#Color-fromHex)(hex: string \| number): Color
Create color from hex string or literal.
``` js
Color.fromHex(0xfcef8d)
Color.fromHex("#5ba675")
Color.fromHex("d46eb3")
```
`since`v3000.0
# [fromHSL](#Color-fromHSL)(h: number, s: number, l: number): Color
# [fromCSS](#Color-fromCSS)(cssColor: CSSColor): Color
Create a color from a CSS color name
`param`cssColor- The color name.
``` js
loadHappy();
add([
rect(512, 512, {
radius: [0, 96, 96, 96]
}),
color("#663399"),
pos(40, 40),
]);
add([
text("css", { size: 192, font: "happy" }),
pos(90, 310)
]);
```
`static`
`returns`The color.
`experimental`This feature is in experimental phase, it will be fully released in v3001.1.0
# [RED](#Color-RED): Color
# [GREEN](#Color-GREEN): Color
# [BLUE](#Color-BLUE): Color
# [YELLOW](#Color-YELLOW): Color
# [MAGENTA](#Color-MAGENTA): Color
# [CYAN](#Color-CYAN): Color
# [WHITE](#Color-WHITE): Color
# [BLACK](#Color-BLACK): Color
# [clone](#Color-clone)(): Color
# [lighten](#Color-lighten)(a: number): Color
Lighten the color (adds RGB by n).
# [darken](#Color-darken)(a: number): Color
Darkens the color (subtracts RGB by n).
# [invert](#Color-invert)(): Color
# [mult](#Color-mult)(other: Color): Color
# [lerp](#Color-lerp)(dest: Color, t: number): Color
Linear interpolate to a destination color.
`since`v3000.0
# [toHSL](#Color-toHSL)(): \[number, number, number\]
Convert color into HSL format.
`since`v3001.0
# [eq](#Color-eq)(other: Color): boolean
# [toHex](#Color-toHex)(): string
Return the hex string of color.
`since`v3000.0
# [toArray](#Color-toArray)(): Array\<number\>
Return the color converted to an array.
`since`v3001.0
# [Vec2Args](#Vec2Args): \[number, number\] \| \[number\] \| \[Vec2\] \| \[number \| Vec2\] \| \[\]
Possible arguments for a Vec2.
# [Vec2](#Vec2):
A 2D vector.
# [x](#Vec2-x): number
The x coordinate
# [y](#Vec2-y): number
The y coordinate
# [set](#Vec2-set)(x: number, y: number): Vec2
Set the X and Y of this vector
# [fromAngle](#Vec2-fromAngle)(deg: number): Vec2
Create a new Vec2 from an angle in degrees
# [fromArray](#Vec2-fromArray)(arr: Array): Vec2
Create a new Vec2 from an array
# [ZERO](#Vec2-ZERO): Vec2
An empty vector. (0, 0)
# [ONE](#Vec2-ONE): Vec2
A vector with both components of 1. (1, 1)
# [LEFT](#Vec2-LEFT): Vec2
A vector signaling to the left. (-1, 0)
# [RIGHT](#Vec2-RIGHT): Vec2
A vector signaling to the right. (1, 0)
# [UP](#Vec2-UP): Vec2
A vector signaling up. (0, -1)
# [DOWN](#Vec2-DOWN): Vec2
A vector signaling down. (0, 1)
# [toAxis](#Vec2-toAxis)(): Vec2
Closest orthogonal direction: LEFT, RIGHT, UP, or DOWN
# [clone](#Vec2-clone)(): Vec2
Clone the vector
# [copy](#Vec2-copy)(v: Vec2, out: Vec2): Vec2
# [add](#Vec2-add)(args: Vec2Args): Vec2
Returns the sum with another vector.
# [add](#Vec2-add)(v: Vec2, other: Vec2, out: Vec2): Vec2
Calculates the sum of the vectors
`param`vThe first term
`param`otherThe second term
`param`outThe vector sum
`returns`The sum of the vectors
# [addScaled](#Vec2-addScaled)(v: Vec2, other: Vec2, s: number, out: Vec2): Vec2
# [addc](#Vec2-addc)(v: Vec2, x: number, y: number, out: Vec2): Vec2
Calculates the sum of the vectors
`param`vThe first term
`param`xThe x of the second term
`param`yThe y of the second term
`param`outThe vector sum
`returns`The sum of the vectors
# [sub](#Vec2-sub)(args: Vec2Args): Vec2
Returns the difference with another vector.
# [sub](#Vec2-sub)(v: Vec2, other: Vec2, out: Vec2): Vec2
Calculates the difference of the vectors
`param`vThe first term
`param`otherThe second term
`param`outThe vector difference
`returns`The difference of the vectors
# [subc](#Vec2-subc)(v: Vec2, x: number, y: number, out: Vec2): Vec2
Calculates the difference of the vectors
`param`vThe first term
`param`xThe x of the second term
`param`yThe y of the second term
`param`outThe vector difference
`returns`The difference of the vectors
# [scale](#Vec2-scale)(args: Vec2Args): Vec2
Scale by another vector. or a single number
# [scale](#Vec2-scale)(v: Vec2, s: number, out: Vec2): Vec2
Calculates the scale of the vector
`param`vThe vector
`param`sThe x scale
`param`outThe y scale
`param`unknownThe scaled vector
`returns`The scale of the vector
# [scalec](#Vec2-scalec)(v: Vec2, x: number, y: number, out: Vec2): Vec2
Calculates the scale of the vector
`param`vThe vector
`param`xThe x scale
`param`yThe y scale
`param`outThe scaled vector
`returns`The scale of the vector
# [scalev](#Vec2-scalev)(v: Vec2, other: Vec2, out: Vec2): Vec2
Calculates the scale of the vector
`param`vThe vector
`param`otherThe scale
`param`outThe scaled vector
`returns`The scale of the vector
# [invScale](#Vec2-invScale)(args: Vec2Args): Vec2
Scale by the inverse of another vector. or a single number
# [dist](#Vec2-dist)(args: Vec2Args): number
Get distance between another vector
# [dist](#Vec2-dist)(v: Vec2, other: Vec2): number
Calculates the distance between the vectors
`param`vThe vector
`param`otherThe other vector
`returns`The between the vectors
# [sdist](#Vec2-sdist)(args: Vec2Args): number
Get squared distance between another vector
# [sdist](#Vec2-sdist)(v: Vec2, other: Vec2): number
Calculates the squared distance between the vectors
`param`vThe vector
`param`otherThe other vector
`returns`The distance between the vectors
# [len](#Vec2-len)(): number
Get length of the vector
`since`v3000.0
# [len](#Vec2-len)(v: Vec2): number
Calculates the length of the vector
`param`vThe vector
`returns`The length of the vector
# [slen](#Vec2-slen)(): number
Get squared length of the vector
`since`v3000.0
# [slen](#Vec2-slen)(v: Vec2): number
Calculates the squared length of the vector
`param`vThe vector
`returns`The squared length of the vector
# [unit](#Vec2-unit)(): Vec2
Get the unit vector (length of 1).
# [unit](#Vec2-unit)(v: Vec2, out: Vec2): Vec2
# [normal](#Vec2-normal)(): Vec2
Get the perpendicular vector.
# [normal](#Vec2-normal)(v: Vec2, out: Vec2): Vec2
# [reflect](#Vec2-reflect)(normal: Vec2): Vec2
Get the reflection of a vector with a normal.
`since`v3000.0
# [project](#Vec2-project)(on: Vec2): Vec2
Get the projection of a vector onto another vector.
`since`v3000.0
# [reject](#Vec2-reject)(on: Vec2): Vec2
Get the rejection of a vector onto another vector.
`since`v3000.0
# [rotate](#Vec2-rotate)(vecOrAngle: Vec2 \| number): Vec2
# [rotate](#Vec2-rotate)(v: Vec2, dir: Vec2, out: Vec2): Vec2
Calculates the rotated vector
`param`vThe vector
`param`dirThe rotation vector
`param`outThe rotated vector
`returns`The rotated vector
# [rotateByAngle](#Vec2-rotateByAngle)(v: Vec2, angle: number, out: Vec2): Vec2
Calculates the rotated vector
`param`vThe vector
`param`angleThe angle in radians
`param`outThe rotated vector
`returns`The rotated vector
# [invRotate](#Vec2-invRotate)(vecOrAngle: Vec2 \| number): Vec2
# [inverseRotate](#Vec2-inverseRotate)(v: Vec2, dir: Vec2, out: Vec2): Vec2
Calculates the inverse rotated vector
`param`vThe vector
`param`dirThe rotation vector
`param`outThe rotated vector
`returns`The rotated vector
# [dot](#Vec2-dot)(p2: Vec2): number
Get the dot product with another vector.
# [dot](#Vec2-dot)(v: Vec2, other: Vec2): number
Get the dot product between 2 vectors.
`since`v3000.0
# [cross](#Vec2-cross)(p2: Vec2): number
Get the cross product with another vector.
`since`v3000.0
# [cross](#Vec2-cross)(v: Vec2, other: Vec2): number
Get the cross product between 2 vectors.
`since`v3000.0
# [angle](#Vec2-angle)(args: Vec2Args): number
Get the angle of the vector in degrees.
# [toAngle](#Vec2-toAngle)(v: Vec2): number
Calculates the angle represented by the vector in radians
`param`vThe vector
`returns`Angle represented by the vector in radians
# [angleBetween](#Vec2-angleBetween)(args: Vec2Args): number
Get the angle between this vector and another vector.
`since`v3000.0
# [angleBetween](#Vec2-angleBetween)(v: Vec2, other: Vec2): number
Calculates the angle between the vectors in radians
`param`vFirst vector
`param`otherSecond vector
`returns`Angle between the vectors in radians
# [lerp](#Vec2-lerp)(dest: Vec2, t: number): Vec2
Linear interpolate to a destination vector (for positions).
# [lerp](#Vec2-lerp)(src: Vec2, dst: Vec2, t: number, out: Vec2): Vec2
Linear interpolate src and dst by t
`param`srcFirst vector
`param`dstSecond vector
`param`tPercentage
`param`outThe linear interpolation between src and dst by t
`returns`The linear interpolation between src and dst by t
# [slerp](#Vec2-slerp)(dest: Vec2, t: number): Vec2
Spherical linear interpolate to a destination vector (for rotations).
`since`v3000.0
# [slerp](#Vec2-slerp)(src: Vec2, dst: Vec2, t: number, out: Vec2): Vec2
Spherical interpolate src and dst by t
`param`srcFirst vector
`param`dstSecond vector
`param`tPercentage
`param`outThe spherical interpolation between src and dst by t
`returns`The spherical interpolation between src and dst by t
# [isZero](#Vec2-isZero)(): boolean
If the vector (x, y) is zero.
`since`v3000.0
# [toFixed](#Vec2-toFixed)(n: number): Vec2
To n precision floating point.
# [transform](#Vec2-transform)(m: Mat4): Vec2
Multiply by a Mat4.
`since`v3000.0
# [eq](#Vec2-eq)(other: Vec2): boolean
See if one vector is equal to another.
`since`v3000.0
# [bbox](#Vec2-bbox)(): Rect
Converts the vector to a Rect`Rect()` with the vector as the origin.
`since`v3000.0.
# [toArray](#Vec2-toArray)(): Array\<number\>
Converts the vector to an array.
`since`v3001.0
# [Quad](#Quad):
# [x](#Quad-x): number
# [y](#Quad-y): number
# [w](#Quad-w): number
# [h](#Quad-h): number
# [scale](#Quad-scale)(other: Quad): Quad
# [pos](#Quad-pos)(): Vec2
# [clone](#Quad-clone)(): Quad
# [eq](#Quad-eq)(other: Quad): boolean
# [Mat4](#Mat4):
# [m](#Mat4-m): number\[\]
# [translate](#Mat4-translate)(p: Vec2): Mat4
# [translate](#Mat4-translate)(p: Vec2): this
# [scale](#Mat4-scale)(s: Vec2): Mat4
# [scale](#Mat4-scale)(p: Vec2): this
# [rotateX](#Mat4-rotateX)(a: number): Mat4
# [rotateY](#Mat4-rotateY)(a: number): Mat4
# [rotateZ](#Mat4-rotateZ)(a: number): Mat4
# [rotate](#Mat4-rotate)(a: number): Mat4
# [mult](#Mat4-mult)(other: Mat4): Mat4
# [multVec2](#Mat4-multVec2)(p: Vec2): Vec2
# [getTranslation](#Mat4-getTranslation)(): Vec2
# [getScale](#Mat4-getScale)(): Vec2
# [getRotation](#Mat4-getRotation)(): number
# [getSkew](#Mat4-getSkew)(): Vec2
# [invert](#Mat4-invert)(): Mat4
# [clone](#Mat4-clone)(): Mat4
# [RNG](#RNG):
A random number generator using the linear congruential generator algorithm.
# [seed](#RNG-seed): number
The current seed value used by the random number generator.
# [gen](#RNG-gen)(): number
Generate a random number between 0 and 1.
``` js
const rng = new RNG(Date.now())
const value = rng.gen() // Returns number between 0-1
```
`returns`A number between 0 and 1.
# [genNumber](#RNG-genNumber)(a: number, b: number): number
Generate a random number between two values.
`param`a- The minimum value.
`param`b- The maximum value.
``` js
const rng = new RNG(Date.now())
const value = rng.genNumber(10, 20) // Returns number between 10-20
```
`returns`A number between a and b.
# [genVec2](#RNG-genVec2)(a: Vec2, b: Vec2): Vec2
Generate a random 2D vector between two vectors.
`param`a- The minimum vector.
`param`b- The maximum vector.
``` js
const rng = new RNG(Date.now())
const vec = rng.genVec2(vec2(0,0), vec2(100,100))
```
`returns`A vector between vectors a and b.
# [genColor](#RNG-genColor)(a: Color, b: Color): Color
Generate a random color between two colors.
`param`a- The first color.
`param`b- The second color.
``` js
const rng = new RNG(Date.now())
const color = rng.genColor(rgb(0,0,0), rgb(255,255,255))
```
`returns`A color between colors a and b.
# [genAny](#RNG-genAny)\<T\>(args: \[\] \| \[T\] \| \[T, T\]): T
Generate a random value of a specific type.
`param`args- No args for \[0-1\], one arg for \[0-arg\], or two args for \[arg1-arg2\].
``` js
const rng = new RNG(Date.now())
const val = rng.genAny(0, 100) // Number between 0-100
const vec = rng.genAny(vec2(0,0), vec2(100,100)) // Vec2
const col = rng.genAny(rgb(0,0,0), rgb(255,255,255)) // Color
```
`returns`A random value.
# [ShapeType](#ShapeType): Point \| Circle \| Line \| Rect \| Polygon \| Ellipse
[RaycastHit](#RaycastHit):
# [fraction](#undefined-fraction): number
# [normal](#undefined-normal): Vec2
# [point](#undefined-point): Vec2
# [gridPos](#undefined-gridPos)?: Vec2
# [object](#undefined-object)?: GameObj
# [RaycastResult](#RaycastResult): RaycastHit \| null
# [Line](#Line):
# [p1](#Line-p1): Vec2
# [p2](#Line-p2): Vec2
# [transform](#Line-transform)(m: Mat23, s?: Shape): Line
# [bbox](#Line-bbox)(): Rect
# [area](#Line-area)(): number
# [clone](#Line-clone)(): Line
# [collides](#Line-collides)(shape: ShapeType \| Vec2): boolean
# [contains](#Line-contains)(point: Vec2): boolean
# [raycast](#Line-raycast)(origin: Vec2, direction: Vec2): RaycastResult
# [random](#Line-random)(): Vec2
# [Rect](#Rect):
# [pos](#Rect-pos): Vec2
# [width](#Rect-width): number
# [height](#Rect-height): number
# [fromPoints](#Rect-fromPoints)(p1: Vec2, p2: Vec2): Rect
# [center](#Rect-center)(): Vec2
# [points](#Rect-points)(): \[Vec2, Vec2, Vec2, Vec2\]
# [transform](#Rect-transform)(m: Mat23, s?: Shape): Polygon
# [bbox](#Rect-bbox)(): Rect
# [area](#Rect-area)(): number
# [clone](#Rect-clone)(): Rect
# [distToPoint](#Rect-distToPoint)(p: Vec2): number
# [sdistToPoint](#Rect-sdistToPoint)(p: Vec2): number
# [collides](#Rect-collides)(shape: ShapeType \| Vec2): boolean
# [contains](#Rect-contains)(point: Vec2): boolean
# [raycast](#Rect-raycast)(origin: Vec2, direction: Vec2): RaycastResult
# [random](#Rect-random)(): Vec2
# [Circle](#Circle):
# [center](#Circle-center): Vec2
# [radius](#Circle-radius): number
# [transform](#Circle-transform)(tr: Mat23, s?: Shape): Ellipse
# [bbox](#Circle-bbox)(): Rect
# [area](#Circle-area)(): number
# [clone](#Circle-clone)(): Circle
# [collides](#Circle-collides)(shape: ShapeType \| Vec2): boolean
# [contains](#Circle-contains)(point: Vec2): boolean
# [raycast](#Circle-raycast)(origin: Vec2, direction: Vec2): RaycastResult
# [random](#Circle-random)(): Vec2
# [Ellipse](#Ellipse):
# [center](#Ellipse-center): Vec2
# [radiusX](#Ellipse-radiusX): number
# [radiusY](#Ellipse-radiusY): number
# [angle](#Ellipse-angle): number
# [fromMat2](#Ellipse-fromMat2)(tr: Mat2): Ellipse
# [toMat2](#Ellipse-toMat2)(): Mat2
# [transform](#Ellipse-transform)(tr: Mat23): Ellipse
# [bbox](#Ellipse-bbox)(): Rect
# [area](#Ellipse-area)(): number
# [clone](#Ellipse-clone)(): Ellipse
# [collides](#Ellipse-collides)(shape: ShapeType): boolean
# [contains](#Ellipse-contains)(point: Vec2): boolean
# [raycast](#Ellipse-raycast)(origin: Vec2, direction: Vec2): RaycastResult
# [random](#Ellipse-random)(): Vec2
# [Polygon](#Polygon):
# [pts](#Polygon-pts): Vec2\[\]
# [transform](#Polygon-transform)(m: Mat23, s?: Shape): Polygon
# [bbox](#Polygon-bbox)(): Rect
# [area](#Polygon-area)(): number
# [clone](#Polygon-clone)(): Polygon
# [collides](#Polygon-collides)(shape: ShapeType \| Vec2): boolean
# [contains](#Polygon-contains)(point: Vec2): boolean
# [raycast](#Polygon-raycast)(origin: Vec2, direction: Vec2): RaycastResult
# [random](#Polygon-random)(): Vec2
# [cut](#Polygon-cut)(a: Vec2, b: Vec2, srcUv?: Vec2\[\], dstUv?: \[Vec2\[\], Vec2\[\]\]): \[Polygon \| null, Polygon \| null\]
# [UniformValue](#UniformValue): number \| Vec2 \| Color \| Mat4 \| Mat23 \| number\[\] \| Vec2\[\] \| Color\[\]
# [UniformKey](#UniformKey): Exclude\<string, u_tex\>
# [Uniform](#Uniform): Record\<UniformKey, UniformValue\>
# [raycast](#raycast)(origin: Vec2, direction: Vec2, exclude?: string\[\]): RaycastResult
Create a raycast.
`since`v3001.0
# [vec2](#vec2)(x: number, y: number): Vec2
Create a 2D vector.
``` js
// { x: 0, y: 0 }
vec2()
// { x: 10, y: 10 }
vec2(10)
// { x: 100, y: 80 }
vec2(100, 80)
// move to 150 degrees direction with by length 10
player.pos = pos.add(Vec2.fromAngle(150).scale(10))
```
`returns`The vector.
`since`v2000.0
# [vec2](#vec2)(p: Vec2): Vec2
# [vec2](#vec2)(xy: number): Vec2
# [vec2](#vec2)(): Vec2
# [rgb](#rgb)(r: number, g: number, b: number): Color
Create a color from RGB values (0 - 255).
`param`r- The red value.
`param`g- The green value.
`param`b- The blue value.
``` js
// update the color of the sky to light blue
sky.color = rgb(0, 128, 255)
```
`returns`The color.
`since`v2000.0
# [rgb](#rgb)(hex: string): Color
Create a color from hex string.
`param`hex- The hex string.
``` js
sky.color = rgb("#ef6360")
```
`returns`The color.
`since`v2000.0
# [rgb](#rgb)(cssColor: CSSColor): Color
Create a color from CSS name.
`param`cssColor- The CSS name.
``` js
sea.color = rgb("slateblue");
```
`returns`The color.
`since`v3001.0.10
`experimental`This feature is in experimental phase, it will be fully released in v3001.1.0
# [rgb](#rgb)(): Color
Same as rgb(255, 255, 255).
# [hsl2rgb](#hsl2rgb)(hue: number, saturation: number, lightness: number): Color
Convert HSL color (all values in 0.0 - 1.0 range) to RGB color.
`param`hue- The hue value.
`param`saturation- The saturation value.
`param`lightness- The lightness value.
``` js
// animate rainbow color
onUpdate("rainbow", (obj) => {
obj.color = hsl2rgb(wave(0, 1, time()), 0.6, 0.6);
});
```
`returns`The color.
`since`v2000.1
# [quad](#quad)(x: number, y: number, w: number, h: number): Quad
Rectangle area (0.0 - 1.0).
`param`x- The x position of the rectangle.
`param`y- The y position of the rectangle.
`param`w- The width of the rectangle.
`param`h- The height of the rectangle.
`returns`A Quad object.
`since`v3001.0
# [chance](#chance)(p: number): boolean
rand(1) \<= p
``` js
// every frame all objs with tag "unlucky" have 50% chance die
onUpdate("unlucky", (o) => {
if (chance(0.5)) {
destroy(o)
}
})
```
# [lerp](#lerp)\<V\>(from: V, to: V, t: number): V
Linear interpolation. Can take a number, vector, or color.
# [tween](#tween)\<V\>(from: V, to: V, duration: number, setValue: (value: V)=\>void, easeFunc?: (t: number)=\>number): TweenController
Tweeeeeeeening!
`since`v3000.0
``` js
// tween bean to mouse position
tween(bean.pos, mousePos(), 1, (p) => bean.pos = p, easings.easeOutBounce)
```
# [easings](#easings): Record\<EaseFuncs, EaseFunc\>
A collection of easing functions for tweening.
`since`v3000.0
# [easingSteps](#easingSteps)(steps: number, position: StepPosition): number
Steps easing. Eases in discontinious steps.
`since`v3001.0
# [easingLinear](#easingLinear)(keys: Vec2\[\]): number
Linear easing with keyframes
`since`v3001.0
# [easingCubicBezier](#easingCubicBezier)(p1: Vec2, p2: Vec2): number
Bezier easing. Both control points need x to be within 0 and 1.
`since`v3001.0
# [map](#map)(v: number, l1: number, h1: number, l2: number, h2: number): number
Map a value from one range to another range. If the value overshoots, the source range, the result values will also do. For clamping check mapc
`param`vThe value the function will depend on.
`param`l1The minimum value of the source range.
`param`h1The minimum result value.
`param`l2The maximum value of the source range.
`param`h2The maximum result value.
``` js
onUpdate(() => {
// Redness will be 0 when the mouse is at the left edge and 255 when the mouse is at the right edge
const redness = map(mousePos().x, 0, width(), 0, 255)
setBackground(rgb(redness, 0, 0))
})
```
`returns`The result value based on the source value.
`since`v2000.0
# [mapc](#mapc)(v: number, l1: number, h1: number, l2: number, h2: number): number
Map a value from one range to another range, and clamp to the dest range.
`param`vThe value the function will depend on.
`param`l1The minimum value of the source range.
`param`h1The minimum result value.
`param`l2The maximum value of the source range.
`param`h2The maximum result value.
``` js
onUpdate(() => {
// This variable will be 0 when the mouse is at the left edge and 255 when the mouse is at the right edge
const redness = mapc(mousePos().x, 0, width(), 0, 255)
setBackground(rgb(redness, 0, 0))
})
```
`returns`The clamped result value based on the source value.
`since`v2000.0
# [wave](#wave)\<V\>(lo: V, hi: V, t: number, func?: (x: number)=\>number): V
Interpolate back and forth between 2 values. (Optionally takes a custom periodic function, which default to a sine wave.).
``` js
// bounce color between 2 values as time goes on
onUpdate("colorful", (c) => {
c.color.r = wave(0, 255, time())
c.color.g = wave(0, 255, time() + 1)
c.color.b = wave(0, 255, time() + 2)
})
```
# [deg2rad](#deg2rad)(deg: number): number
Convert degrees to radians.
# [rad2deg](#rad2deg)(rad: number): number
Convert radians to degrees.
# [clamp](#clamp)(n: number, min: number, max: number): number
Return a value clamped to an inclusive range of min and max.
# [evaluateQuadratic](#evaluateQuadratic)(pt1: Vec2, pt2: Vec2, pt3: Vec2, t: number): Vec2
Evaluate the quadratic Bezier at the given t
# [evaluateQuadraticFirstDerivative](#evaluateQuadraticFirstDerivative)(pt1: Vec2, pt2: Vec2, pt3: Vec2, t: number): Vec2
Evaluate the first derivative of a quadratic bezier at the given t
`since`v3001.0
# [evaluateQuadraticSecondDerivative](#evaluateQuadraticSecondDerivative)(pt1: Vec2, pt2: Vec2, pt3: Vec2, t: number): Vec2
Evaluate the second derivative of a quadratic bezier at the given t
`since`v3001.0
# [evaluateBezier](#evaluateBezier)(pt1: Vec2, pt2: Vec2, pt3: Vec2, pt4: Vec2, t: number): Vec2
Evaluate the cubic Bezier at the given t
`since`v3001.0
# [evaluateBezierFirstDerivative](#evaluateBezierFirstDerivative)(pt1: Vec2, pt2: Vec2, pt3: Vec2, pt4: Vec2, t: number): Vec2
Evaluate the first derivative of a cubic Bezier at the given t
# [evaluateBezierSecondDerivative](#evaluateBezierSecondDerivative)(pt1: Vec2, pt2: Vec2, pt3: Vec2, pt4: Vec2, t: number): Vec2
Evaluate the second derivative of a cubic bezier at the given t
`since`v3001.0
# [evaluateCatmullRom](#evaluateCatmullRom)(pt1: Vec2, pt2: Vec2, pt3: Vec2, pt4: Vec2, t: number): Vec2
Evaluate the Catmull-Rom spline at the given t
`since`v3001.0
# [evaluateCatmullRomFirstDerivative](#evaluateCatmullRomFirstDerivative)(pt1: Vec2, pt2: Vec2, pt3: Vec2, pt4: Vec2, t: number): Vec2
Evaluate the first derivative of a Catmull-Rom spline at the given t
`since`v3001.0
# [curveLengthApproximation](#curveLengthApproximation)(curve: (t: number)=\>Vec2, entries: number, detail: number): number
Returns a function. entries is the amount of entries in the LUT. detail is the sampling granularity of each segment recorded in the LUT. This new function either returns the length for a given t, or t for a given length, depending on the inverse parameter.
`since`v3001.0
# [normalizedCurve](#normalizedCurve)(curve: (t: number)=\>Vec2): Vec2
Returns a new curve which is normalized. This new curve has constant speed curve is any curve in t (non-constant between 0 and 1) returns a curve in s (constant between 0 and 1)
`since`v3001.0
# [testLinePoint](#testLinePoint)(l: Line, pt: Vec2): boolean
Check if a line and a point intersect.
`param`l- The line.
`param`pt- The point.
`returns`true if the line and point intersects.
`since`v2000.0
# [testLineLine](#testLineLine)(l1: Line, l2: Line): Vec2 \| null
Check if 2 lines intersects, if yes returns the intersection point.
`param`l1- The first line.
`param`l2- The second line.
`return`The intersection point, or null if the lines are parallel.
`since`v2000.0
# [testLineCircle](#testLineCircle)(l: Line, c: Circle): boolean
Check if a line and a circle intersect.
`param`l- The line.
`param`c- The circle.
`returns`true if the line and circle intersects.
`since`v2000.0
# [testRectRect](#testRectRect)(r1: Rect, r2: Rect): boolean
Check if 2 rectangle overlaps.
`param`r1- The first rectangle.
`param`r2- The second rectangle.
`returns`true if the rectangles overlap.
`since`v2000.0
# [testRectLine](#testRectLine)(r: Rect, l: Line): boolean
Check if a line and a rectangle overlaps.
`param`r- The line.
`param`l- The rectangle.
`returns`true if the line and rectangle overlaps.
`since`v2000.0
# [testRectPoint](#testRectPoint)(r: Rect, pt: Vec2): boolean
Check if a point is inside a rectangle.
`param`r- The rectangle.
`param`pt- The point.
`returns`true if the point is inside the rectangle.
`since`v2000.0
# [testCirclePolygon](#testCirclePolygon)(c: Circle, p: Polygon): boolean
Check if a circle and polygon intersect linewise.
`param`c- The circle.
`param`p- The polygon.
`returns`true if the circle and polygon intersect linewise.
`since`v2000.0
# [clipLineToRect](#clipLineToRect)(r: Rect, l: Line, result: Line): boolean
`since`v4000.0
# [clipLineToCircle](#clipLineToCircle)(c: Circle, l: Line, result: Line): boolean
`since`v4000.0
# [gjkShapeIntersects](#gjkShapeIntersects)(shapeA: Shape, shapeB: Shape): boolean
`since`v4000.0
# [gjkShapeIntersection](#gjkShapeIntersection)(shapeA: Shape, shapeB: Shape): GjkCollisionResult \| null
`since`v4000.0
# [isConvex](#isConvex)(pts: Vec2\[\]): boolean
`returns`true if the given polygon is convex
`since`v3001.0
# [step](#step)(edge: number, x: number): number
`returns`1 if over the edge, 0 otherwise
`since`v3001.0
# [smoothstep](#smoothstep)(edge0: number, edge1: number, x: number): number
`returns`1 if over edge1, 0 if under edge0, a smooth hermite curve value otherwise
`since`v3001.0
# [triangulate](#triangulate)(pts: Vec2\[\]): Vec2\[\]\[\]
`since`v3001.0
# [NavMesh](#NavMesh):
# [\_polygons](#NavMesh-_polygons):
# [\_pointCache](#NavMesh-_pointCache):
# [\_edgeCache](#NavMesh-_edgeCache):
# [\_addPoint](#NavMesh-_addPoint):
# [\_addEdge](#NavMesh-_addEdge):
# [\_findEdge](#NavMesh-_findEdge):
# [\_findCommonEdge](#NavMesh-_findCommonEdge):
# [addPolygon](#NavMesh-addPolygon)(vertices: Vec2\[\]): NavPolygon
# [addRect](#NavMesh-addRect)(pos: Vec2, size: Vec2): NavPolygon
# [\_getLocation](#NavMesh-_getLocation):
# [getNeighbours](#NavMesh-getNeighbours)(index: number): number\[\]
# [getCost](#NavMesh-getCost)(a: number, b: number): number
# [getHeuristic](#NavMesh-getHeuristic)(indexA: number, indexB: number): number
# [getPath](#NavMesh-getPath)(start: number, goal: number): number\[\]
# [getWaypointPath](#NavMesh-getWaypointPath)(start: Vec2, goal: Vec2, opt: any): Vec2\[\]
# [Point](#Point):
# [pt](#Point-pt): Vec2
# [transform](#Point-transform)(m: Mat23, s?: Shape): Point
# [bbox](#Point-bbox)(): Rect
# [area](#Point-area)(): number
# [clone](#Point-clone)(): Point
# [collides](#Point-collides)(shape: ShapeType): boolean
# [contains](#Point-contains)(point: Vec2): boolean
# [raycast](#Point-raycast)(origin: Vec2, direction: Vec2): RaycastResult
# [random](#Point-random)(): Vec2
# [Line](#Line):
# [p1](#Line-p1): Vec2
# [p2](#Line-p2): Vec2
# [transform](#Line-transform)(m: Mat23, s?: Shape): Line
# [bbox](#Line-bbox)(): Rect
# [area](#Line-area)(): number
# [clone](#Line-clone)(): Line
# [collides](#Line-collides)(shape: ShapeType \| Vec2): boolean
# [contains](#Line-contains)(point: Vec2): boolean
# [raycast](#Line-raycast)(origin: Vec2, direction: Vec2): RaycastResult
# [random](#Line-random)(): Vec2
# [Rect](#Rect):
# [pos](#Rect-pos): Vec2
# [width](#Rect-width): number
# [height](#Rect-height): number
# [fromPoints](#Rect-fromPoints)(p1: Vec2, p2: Vec2): Rect
# [center](#Rect-center)(): Vec2
# [points](#Rect-points)(): \[Vec2, Vec2, Vec2, Vec2\]
# [transform](#Rect-transform)(m: Mat23, s?: Shape): Polygon
# [bbox](#Rect-bbox)(): Rect
# [area](#Rect-area)(): number
# [clone](#Rect-clone)(): Rect
# [distToPoint](#Rect-distToPoint)(p: Vec2): number
# [sdistToPoint](#Rect-sdistToPoint)(p: Vec2): number
# [collides](#Rect-collides)(shape: ShapeType \| Vec2): boolean
# [contains](#Rect-contains)(point: Vec2): boolean
# [raycast](#Rect-raycast)(origin: Vec2, direction: Vec2): RaycastResult
# [random](#Rect-random)(): Vec2
# [Circle](#Circle):
# [center](#Circle-center): Vec2
# [radius](#Circle-radius): number
# [transform](#Circle-transform)(tr: Mat23, s?: Shape): Ellipse
# [bbox](#Circle-bbox)(): Rect
# [area](#Circle-area)(): number
# [clone](#Circle-clone)(): Circle
# [collides](#Circle-collides)(shape: ShapeType \| Vec2): boolean
# [contains](#Circle-contains)(point: Vec2): boolean
# [raycast](#Circle-raycast)(origin: Vec2, direction: Vec2): RaycastResult
# [random](#Circle-random)(): Vec2
# [Ellipse](#Ellipse):
# [center](#Ellipse-center): Vec2
# [radiusX](#Ellipse-radiusX): number
# [radiusY](#Ellipse-radiusY): number
# [angle](#Ellipse-angle): number
# [fromMat2](#Ellipse-fromMat2)(tr: Mat2): Ellipse
# [toMat2](#Ellipse-toMat2)(): Mat2
# [transform](#Ellipse-transform)(tr: Mat23): Ellipse
# [bbox](#Ellipse-bbox)(): Rect
# [area](#Ellipse-area)(): number
# [clone](#Ellipse-clone)(): Ellipse
# [collides](#Ellipse-collides)(shape: ShapeType): boolean
# [contains](#Ellipse-contains)(point: Vec2): boolean
# [raycast](#Ellipse-raycast)(origin: Vec2, direction: Vec2): RaycastResult
# [random](#Ellipse-random)(): Vec2
# [Polygon](#Polygon):
# [pts](#Polygon-pts): Vec2\[\]
# [transform](#Polygon-transform)(m: Mat23, s?: Shape): Polygon
# [bbox](#Polygon-bbox)(): Rect
# [area](#Polygon-area)(): number
# [clone](#Polygon-clone)(): Polygon
# [collides](#Polygon-collides)(shape: ShapeType \| Vec2): boolean
# [contains](#Polygon-contains)(point: Vec2): boolean
# [raycast](#Polygon-raycast)(origin: Vec2, direction: Vec2): RaycastResult
# [random](#Polygon-random)(): Vec2
# [cut](#Polygon-cut)(a: Vec2, b: Vec2, srcUv?: Vec2\[\], dstUv?: \[Vec2\[\], Vec2\[\]\]): \[Polygon \| null, Polygon \| null\]
# [Vec2](#Vec2):
A 2D vector.
# [x](#Vec2-x): number
The x coordinate
# [y](#Vec2-y): number
The y coordinate
# [set](#Vec2-set)(x: number, y: number): Vec2
Set the X and Y of this vector
# [fromAngle](#Vec2-fromAngle)(deg: number): Vec2
Create a new Vec2 from an angle in degrees
# [fromArray](#Vec2-fromArray)(arr: Array): Vec2
Create a new Vec2 from an array
# [ZERO](#Vec2-ZERO): Vec2
An empty vector. (0, 0)
# [ONE](#Vec2-ONE): Vec2
A vector with both components of 1. (1, 1)
# [LEFT](#Vec2-LEFT): Vec2
A vector signaling to the left. (-1, 0)
# [RIGHT](#Vec2-RIGHT): Vec2
A vector signaling to the right. (1, 0)
# [UP](#Vec2-UP): Vec2
A vector signaling up. (0, -1)
# [DOWN](#Vec2-DOWN): Vec2
A vector signaling down. (0, 1)
# [toAxis](#Vec2-toAxis)(): Vec2
Closest orthogonal direction: LEFT, RIGHT, UP, or DOWN
# [clone](#Vec2-clone)(): Vec2
Clone the vector
# [copy](#Vec2-copy)(v: Vec2, out: Vec2): Vec2
# [add](#Vec2-add)(args: Vec2Args): Vec2
Returns the sum with another vector.
# [add](#Vec2-add)(v: Vec2, other: Vec2, out: Vec2): Vec2
Calculates the sum of the vectors
`param`vThe first term
`param`otherThe second term
`param`outThe vector sum
`returns`The sum of the vectors
# [addScaled](#Vec2-addScaled)(v: Vec2, other: Vec2, s: number, out: Vec2): Vec2
# [addc](#Vec2-addc)(v: Vec2, x: number, y: number, out: Vec2): Vec2
Calculates the sum of the vectors
`param`vThe first term
`param`xThe x of the second term
`param`yThe y of the second term
`param`outThe vector sum
`returns`The sum of the vectors
# [sub](#Vec2-sub)(args: Vec2Args): Vec2
Returns the difference with another vector.
# [sub](#Vec2-sub)(v: Vec2, other: Vec2, out: Vec2): Vec2
Calculates the difference of the vectors
`param`vThe first term
`param`otherThe second term
`param`outThe vector difference
`returns`The difference of the vectors
# [subc](#Vec2-subc)(v: Vec2, x: number, y: number, out: Vec2): Vec2
Calculates the difference of the vectors
`param`vThe first term
`param`xThe x of the second term
`param`yThe y of the second term
`param`outThe vector difference
`returns`The difference of the vectors
# [scale](#Vec2-scale)(args: Vec2Args): Vec2
Scale by another vector. or a single number
# [scale](#Vec2-scale)(v: Vec2, s: number, out: Vec2): Vec2
Calculates the scale of the vector
`param`vThe vector
`param`sThe x scale
`param`outThe y scale
`param`unknownThe scaled vector
`returns`The scale of the vector
# [scalec](#Vec2-scalec)(v: Vec2, x: number, y: number, out: Vec2): Vec2
Calculates the scale of the vector
`param`vThe vector
`param`xThe x scale
`param`yThe y scale
`param`outThe scaled vector
`returns`The scale of the vector
# [scalev](#Vec2-scalev)(v: Vec2, other: Vec2, out: Vec2): Vec2
Calculates the scale of the vector
`param`vThe vector
`param`otherThe scale
`param`outThe scaled vector
`returns`The scale of the vector
# [invScale](#Vec2-invScale)(args: Vec2Args): Vec2
Scale by the inverse of another vector. or a single number
# [dist](#Vec2-dist)(args: Vec2Args): number
Get distance between another vector
# [dist](#Vec2-dist)(v: Vec2, other: Vec2): number
Calculates the distance between the vectors
`param`vThe vector
`param`otherThe other vector
`returns`The between the vectors
# [sdist](#Vec2-sdist)(args: Vec2Args): number
Get squared distance between another vector
# [sdist](#Vec2-sdist)(v: Vec2, other: Vec2): number
Calculates the squared distance between the vectors
`param`vThe vector
`param`otherThe other vector
`returns`The distance between the vectors
# [len](#Vec2-len)(): number
Get length of the vector
`since`v3000.0
# [len](#Vec2-len)(v: Vec2): number
Calculates the length of the vector
`param`vThe vector
`returns`The length of the vector
# [slen](#Vec2-slen)(): number
Get squared length of the vector
`since`v3000.0
# [slen](#Vec2-slen)(v: Vec2): number
Calculates the squared length of the vector
`param`vThe vector
`returns`The squared length of the vector
# [unit](#Vec2-unit)(): Vec2
Get the unit vector (length of 1).
# [unit](#Vec2-unit)(v: Vec2, out: Vec2): Vec2
# [normal](#Vec2-normal)(): Vec2
Get the perpendicular vector.
# [normal](#Vec2-normal)(v: Vec2, out: Vec2): Vec2
# [reflect](#Vec2-reflect)(normal: Vec2): Vec2
Get the reflection of a vector with a normal.
`since`v3000.0
# [project](#Vec2-project)(on: Vec2): Vec2
Get the projection of a vector onto another vector.
`since`v3000.0
# [reject](#Vec2-reject)(on: Vec2): Vec2
Get the rejection of a vector onto another vector.
`since`v3000.0
# [rotate](#Vec2-rotate)(vecOrAngle: Vec2 \| number): Vec2
# [rotate](#Vec2-rotate)(v: Vec2, dir: Vec2, out: Vec2): Vec2
Calculates the rotated vector
`param`vThe vector
`param`dirThe rotation vector
`param`outThe rotated vector
`returns`The rotated vector
# [rotateByAngle](#Vec2-rotateByAngle)(v: Vec2, angle: number, out: Vec2): Vec2
Calculates the rotated vector
`param`vThe vector
`param`angleThe angle in radians
`param`outThe rotated vector
`returns`The rotated vector
# [invRotate](#Vec2-invRotate)(vecOrAngle: Vec2 \| number): Vec2
# [inverseRotate](#Vec2-inverseRotate)(v: Vec2, dir: Vec2, out: Vec2): Vec2
Calculates the inverse rotated vector
`param`vThe vector
`param`dirThe rotation vector
`param`outThe rotated vector
`returns`The rotated vector
# [dot](#Vec2-dot)(p2: Vec2): number
Get the dot product with another vector.
# [dot](#Vec2-dot)(v: Vec2, other: Vec2): number
Get the dot product between 2 vectors.
`since`v3000.0
# [cross](#Vec2-cross)(p2: Vec2): number
Get the cross product with another vector.
`since`v3000.0
# [cross](#Vec2-cross)(v: Vec2, other: Vec2): number
Get the cross product between 2 vectors.
`since`v3000.0
# [angle](#Vec2-angle)(args: Vec2Args): number
Get the angle of the vector in degrees.
# [toAngle](#Vec2-toAngle)(v: Vec2): number
Calculates the angle represented by the vector in radians
`param`vThe vector
`returns`Angle represented by the vector in radians
# [angleBetween](#Vec2-angleBetween)(args: Vec2Args): number
Get the angle between this vector and another vector.
`since`v3000.0
# [angleBetween](#Vec2-angleBetween)(v: Vec2, other: Vec2): number
Calculates the angle between the vectors in radians
`param`vFirst vector
`param`otherSecond vector
`returns`Angle between the vectors in radians
# [lerp](#Vec2-lerp)(dest: Vec2, t: number): Vec2
Linear interpolate to a destination vector (for positions).
# [lerp](#Vec2-lerp)(src: Vec2, dst: Vec2, t: number, out: Vec2): Vec2
Linear interpolate src and dst by t
`param`srcFirst vector
`param`dstSecond vector
`param`tPercentage
`param`outThe linear interpolation between src and dst by t
`returns`The linear interpolation between src and dst by t
# [slerp](#Vec2-slerp)(dest: Vec2, t: number): Vec2
Spherical linear interpolate to a destination vector (for rotations).
`since`v3000.0
# [slerp](#Vec2-slerp)(src: Vec2, dst: Vec2, t: number, out: Vec2): Vec2
Spherical interpolate src and dst by t
`param`srcFirst vector
`param`dstSecond vector
`param`tPercentage
`param`outThe spherical interpolation between src and dst by t
`returns`The spherical interpolation between src and dst by t
# [isZero](#Vec2-isZero)(): boolean
If the vector (x, y) is zero.
`since`v3000.0
# [toFixed](#Vec2-toFixed)(n: number): Vec2
To n precision floating point.
# [transform](#Vec2-transform)(m: Mat4): Vec2
Multiply by a Mat4.
`since`v3000.0
# [eq](#Vec2-eq)(other: Vec2): boolean
See if one vector is equal to another.
`since`v3000.0
# [bbox](#Vec2-bbox)(): Rect
Converts the vector to a Rect`Rect()` with the vector as the origin.
`since`v3000.0.
# [toArray](#Vec2-toArray)(): Array\<number\>
Converts the vector to an array.
`since`v3001.0
# [Color](#Color):
0-255 RGBA color.
# [r](#Color-r): number
Red (0-255.
# [g](#Color-g): number
Green (0-255).
# [b](#Color-b): number
Blue (0-255).
# [fromArray](#Color-fromArray)(arr: \[number, number, number\]): Color
# [fromHex](#Color-fromHex)(hex: string \| number): Color
Create color from hex string or literal.
``` js
Color.fromHex(0xfcef8d)
Color.fromHex("#5ba675")
Color.fromHex("d46eb3")
```
`since`v3000.0
# [fromHSL](#Color-fromHSL)(h: number, s: number, l: number): Color
# [fromCSS](#Color-fromCSS)(cssColor: CSSColor): Color
Create a color from a CSS color name
`param`cssColor- The color name.
``` js
loadHappy();
add([
rect(512, 512, {
radius: [0, 96, 96, 96]
}),
color("#663399"),
pos(40, 40),
]);
add([
text("css", { size: 192, font: "happy" }),
pos(90, 310)
]);
```
`static`
`returns`The color.
`experimental`This feature is in experimental phase, it will be fully released in v3001.1.0
# [RED](#Color-RED): Color
# [GREEN](#Color-GREEN): Color
# [BLUE](#Color-BLUE): Color
# [YELLOW](#Color-YELLOW): Color
# [MAGENTA](#Color-MAGENTA): Color
# [CYAN](#Color-CYAN): Color
# [WHITE](#Color-WHITE): Color
# [BLACK](#Color-BLACK): Color
# [clone](#Color-clone)(): Color
# [lighten](#Color-lighten)(a: number): Color
Lighten the color (adds RGB by n).
# [darken](#Color-darken)(a: number): Color
Darkens the color (subtracts RGB by n).
# [invert](#Color-invert)(): Color
# [mult](#Color-mult)(other: Color): Color
# [lerp](#Color-lerp)(dest: Color, t: number): Color
Linear interpolate to a destination color.
`since`v3000.0
# [toHSL](#Color-toHSL)(): \[number, number, number\]
Convert color into HSL format.
`since`v3001.0
# [eq](#Color-eq)(other: Color): boolean
# [toHex](#Color-toHex)(): string
Return the hex string of color.
`since`v3000.0
# [toArray](#Color-toArray)(): Array\<number\>
Return the color converted to an array.
`since`v3001.0
# [Mat4](#Mat4):
# [m](#Mat4-m): number\[\]
# [translate](#Mat4-translate)(p: Vec2): Mat4
# [translate](#Mat4-translate)(p: Vec2): this
# [scale](#Mat4-scale)(s: Vec2): Mat4
# [scale](#Mat4-scale)(p: Vec2): this
# [rotateX](#Mat4-rotateX)(a: number): Mat4
# [rotateY](#Mat4-rotateY)(a: number): Mat4
# [rotateZ](#Mat4-rotateZ)(a: number): Mat4
# [rotate](#Mat4-rotate)(a: number): Mat4
# [mult](#Mat4-mult)(other: Mat4): Mat4
# [multVec2](#Mat4-multVec2)(p: Vec2): Vec2
# [getTranslation](#Mat4-getTranslation)(): Vec2
# [getScale](#Mat4-getScale)(): Vec2
# [getRotation](#Mat4-getRotation)(): number
# [getSkew](#Mat4-getSkew)(): Vec2
# [invert](#Mat4-invert)(): Mat4
# [clone](#Mat4-clone)(): Mat4
# [Mat23](#Mat23):
# [a](#Mat23-a): number
# [b](#Mat23-b): number
# [c](#Mat23-c): number
# [d](#Mat23-d): number
# [e](#Mat23-e): number
# [f](#Mat23-f): number
# [fromMat2](#Mat23-fromMat2)(m: Mat2): Mat23
# [toMat2](#Mat23-toMat2)(): Mat2
# [fromTranslation](#Mat23-fromTranslation)(t: Vec2): Mat23
# [fromRotation](#Mat23-fromRotation)(radians: number): Mat23
# [fromScale](#Mat23-fromScale)(s: Vec2): Mat23
# [clone](#Mat23-clone)(): Mat23
# [setMat23](#Mat23-setMat23)(m: Mat23): this
# [setIdentity](#Mat23-setIdentity)(): this
# [mul](#Mat23-mul)(other: Mat23): Mat23
# [translateSelfV](#Mat23-translateSelfV)(t: Vec2): Mat23
# [translateSelf](#Mat23-translateSelf)(x: number, y: number): Mat23
# [rotateSelf](#Mat23-rotateSelf)(degrees: number): Mat23
# [scaleSelfV](#Mat23-scaleSelfV)(s: Vec2): Mat23
# [scaleSelf](#Mat23-scaleSelf)(x: number, y: number): Mat23
# [mulSelf](#Mat23-mulSelf)(other: Mat23): void
# [transform](#Mat23-transform)(p: Vec2): Vec2
# [transformPointV](#Mat23-transformPointV)(p: Vec2, o: Vec2): Vec2
# [transformVectorV](#Mat23-transformVectorV)(v: Vec2, o: Vec2): Vec2
# [transformPoint](#Mat23-transformPoint)(x: number, y: number, o: Vec2): Vec2
# [transformVector](#Mat23-transformVector)(x: number, y: number, o: Vec2): Vec2
# [det](#Mat23-det)(): number
# [inverse](#Mat23-inverse)(): Mat23
# [getTranslation](#Mat23-getTranslation)(): Vec2
# [getRotation](#Mat23-getRotation)(): number
# [getScale](#Mat23-getScale)(): Vec2
# [Quad](#Quad):
# [x](#Quad-x): number
# [y](#Quad-y): number
# [w](#Quad-w): number
# [h](#Quad-h): number
# [scale](#Quad-scale)(other: Quad): Quad
# [pos](#Quad-pos)(): Vec2
# [clone](#Quad-clone)(): Quad
# [eq](#Quad-eq)(other: Quad): boolean
# [RNG](#RNG):
A random number generator using the linear congruential generator algorithm.
# [seed](#RNG-seed): number
The current seed value used by the random number generator.
# [gen](#RNG-gen)(): number
Generate a random number between 0 and 1.
``` js
const rng = new RNG(Date.now())
const value = rng.gen() // Returns number between 0-1
```
`returns`A number between 0 and 1.
# [genNumber](#RNG-genNumber)(a: number, b: number): number
Generate a random number between two values.
`param`a- The minimum value.
`param`b- The maximum value.
``` js
const rng = new RNG(Date.now())
const value = rng.genNumber(10, 20) // Returns number between 10-20
```
`returns`A number between a and b.
# [genVec2](#RNG-genVec2)(a: Vec2, b: Vec2): Vec2
Generate a random 2D vector between two vectors.
`param`a- The minimum vector.
`param`b- The maximum vector.
``` js
const rng = new RNG(Date.now())
const vec = rng.genVec2(vec2(0,0), vec2(100,100))
```
`returns`A vector between vectors a and b.
# [genColor](#RNG-genColor)(a: Color, b: Color): Color
Generate a random color between two colors.
`param`a- The first color.
`param`b- The second color.
``` js
const rng = new RNG(Date.now())
const color = rng.genColor(rgb(0,0,0), rgb(255,255,255))
```
`returns`A color between colors a and b.
# [genAny](#RNG-genAny)\<T\>(args: \[\] \| \[T\] \| \[T, T\]): T
Generate a random value of a specific type.
`param`args- No args for \[0-1\], one arg for \[0-arg\], or two args for \[arg1-arg2\].
``` js
const rng = new RNG(Date.now())
const val = rng.genAny(0, 100) // Number between 0-100
const vec = rng.genAny(vec2(0,0), vec2(100,100)) // Vec2
const col = rng.genAny(rgb(0,0,0), rgb(255,255,255)) // Color
```
`returns`A random value.
# [LerpValue](#LerpValue): number \| Vec2 \| Color
# [RNGValue](#RNGValue): number \| Vec2 \| Color
# [Collision](#Collision):
Collision resolution data.
# [source](#Collision-source): GameObj
The first game object in the collision.
# [target](#Collision-target): GameObj
The second game object in the collision.
# [normal](#Collision-normal): Vec2
The contact normal.
# [distance](#Collision-distance): Vec2
The length of the displacement.
# [displacement](#Collision-displacement): Vec2
The displacement source game object have to make to avoid the collision.
# [resolved](#Collision-resolved): boolean
If the collision is resolved.
# [preventResolution](#Collision-preventResolution)(): void
Prevent collision resolution if not yet resolved.
`since`v3000.0
# [hasOverlap](#Collision-hasOverlap)(): boolean
If the 2 objects have any overlap, or they're just touching edges.
`since`v3000.0
# [reverse](#Collision-reverse)(): Collision
Get a new collision with reversed source and target relationship.
# [isTop](#Collision-isTop)(): boolean
If the collision happened (roughly) on the top side.
# [isBottom](#Collision-isBottom)(): boolean
If the collision happened (roughly) on the bottom side.
# [isLeft](#Collision-isLeft)(): boolean
If the collision happened (roughly) on the left side.
# [isRight](#Collision-isRight)(): boolean
If the collision happened (roughly) on the right side.
# [Edge](#Edge): left \| right \| top \| bottom
# [EaseFuncs](#EaseFuncs): linear \| easeInSine \| easeOutSine \| easeInOutSine \| easeInQuad \| easeOutQuad \| easeInOutQuad \| easeInCubic \| easeOutCubic \| easeInOutCubic \| easeInQuart \| easeOutQuart \| easeInOutQuart \| easeInQuint \| easeOutQuint \| easeInOutQuint \| easeInExpo \| easeOutExpo \| easeInOutExpo \| easeInCirc \| easeOutCirc \| easeInOutCirc \| easeInBack \| easeOutBack \| easeInOutBack \| easeInElastic \| easeOutElastic \| easeInOutElastic \| easeInBounce \| easeOutBounce \| easeInOutBounce
The list of easing functions available.
# [EaseFunc](#EaseFunc)(t: number): number
A function that takes a time value and returns a new time value.
# [RGBValue](#RGBValue): \[number, number, number\]
# [RGBAValue](#RGBAValue): \[number, number, number, number\]
# [CSSColor](#CSSColor): CSS_COLOR_MAP
# [ColorArgs](#ColorArgs): \[Color\] \| \[Color, number\] \| RGBValue \| RGBAValue \| \[string\] \| \[number\[\]\] \| \[\] \| \[CSSColor & string & \]
# [Mat2](#Mat2):
# [a](#Mat2-a): number
# [b](#Mat2-b): number
# [c](#Mat2-c): number
# [d](#Mat2-d): number
# [mul](#Mat2-mul)(other: Mat2): Mat2
# [transform](#Mat2-transform)(point: Vec2): Vec2
# [inverse](#Mat2-inverse)(): Mat2
# [transpose](#Mat2-transpose)(): Mat2
# [eigenvalues](#Mat2-eigenvalues)(): number\[\]
# [eigenvectors](#Mat2-eigenvectors)(e1: number, e2: number): number\[\]\[\]
# [det](#Mat2-det)(): number
# [trace](#Mat2-trace)(): number
# [rotation](#Mat2-rotation)(radians: number): Mat2
# [scale](#Mat2-scale)(x: number, y: number): Mat2
# [Mat23](#Mat23):
# [a](#Mat23-a): number
# [b](#Mat23-b): number
# [c](#Mat23-c): number
# [d](#Mat23-d): number
# [e](#Mat23-e): number
# [f](#Mat23-f): number
# [fromMat2](#Mat23-fromMat2)(m: Mat2): Mat23
# [toMat2](#Mat23-toMat2)(): Mat2
# [fromTranslation](#Mat23-fromTranslation)(t: Vec2): Mat23
# [fromRotation](#Mat23-fromRotation)(radians: number): Mat23
# [fromScale](#Mat23-fromScale)(s: Vec2): Mat23
# [clone](#Mat23-clone)(): Mat23
# [setMat23](#Mat23-setMat23)(m: Mat23): this
# [setIdentity](#Mat23-setIdentity)(): this
# [mul](#Mat23-mul)(other: Mat23): Mat23
# [translateSelfV](#Mat23-translateSelfV)(t: Vec2): Mat23
# [translateSelf](#Mat23-translateSelf)(x: number, y: number): Mat23
# [rotateSelf](#Mat23-rotateSelf)(degrees: number): Mat23
# [scaleSelfV](#Mat23-scaleSelfV)(s: Vec2): Mat23
# [scaleSelf](#Mat23-scaleSelf)(x: number, y: number): Mat23
# [mulSelf](#Mat23-mulSelf)(other: Mat23): void
# [transform](#Mat23-transform)(p: Vec2): Vec2
# [transformPointV](#Mat23-transformPointV)(p: Vec2, o: Vec2): Vec2
# [transformVectorV](#Mat23-transformVectorV)(v: Vec2, o: Vec2): Vec2
# [transformPoint](#Mat23-transformPoint)(x: number, y: number, o: Vec2): Vec2
# [transformVector](#Mat23-transformVector)(x: number, y: number, o: Vec2): Vec2
# [det](#Mat23-det)(): number
# [inverse](#Mat23-inverse)(): Mat23
# [getTranslation](#Mat23-getTranslation)(): Vec2
# [getRotation](#Mat23-getRotation)(): number
# [getScale](#Mat23-getScale)(): Vec2
# [Point](#Point):
# [pt](#Point-pt): Vec2
# [transform](#Point-transform)(m: Mat23, s?: Shape): Point
# [bbox](#Point-bbox)(): Rect
# [area](#Point-area)(): number
# [clone](#Point-clone)(): Point
# [collides](#Point-collides)(shape: ShapeType): boolean
# [contains](#Point-contains)(point: Vec2): boolean
# [raycast](#Point-raycast)(origin: Vec2, direction: Vec2): RaycastResult
# [random](#Point-random)(): Vec2
# [StepPosition](#StepPosition): jump-start \| jump-end \| jump-none \| jump-both
# [ShaderData](#ShaderData): Shader
[Material](#Material):
# [tex](#undefined-tex)?: Texture
# [shader](#undefined-shader)?: Shader
# [uniform](#undefined-uniform)?: Uniform
# [blend](#undefined-blend)?: BlendMode
[PictureCommand](#PictureCommand):
# [material](#undefined-material): Material
# [index](#undefined-index): number
# [count](#undefined-count): number
# [Picture](#Picture):
A picture holding drawing data
# [vertices](#Picture-vertices): number\[\]
# [indices](#Picture-indices): number\[\]
# [commands](#Picture-commands): PictureCommand\[\]
# [mesh](#Picture-mesh)?: Mesh
# [archive](#Picture-archive)(): string
Serializes this picture to a JSON string
`returns`a string containing JSON picture data
# [free](#Picture-free)(): void
# [DrawPictureOpt](#DrawPictureOpt): RenderProps &
Drawing options for drawPicture
# [GfxCtx](#GfxCtx): ReturnType\<initGfx\>
# [Texture](#Texture):
# [ctx](#Texture-ctx): GfxCtx
# [src](#Texture-src): null \| ImageSource
# [glTex](#Texture-glTex): WebGLTexture
# [width](#Texture-width): number
# [height](#Texture-height): number
# [fromImage](#Texture-fromImage)(ctx: GfxCtx, img: ImageSource, opt?: TextureOpt): Texture
# [update](#Texture-update)(img: ImageSource, x?: number, y?: number): void
# [bind](#Texture-bind)(): void
# [unbind](#Texture-unbind)(): void
# [free](#Texture-free)(): void
Frees up texture memory. Call this once the texture is no longer being used to avoid memory leaks.
[VertexFormat](#VertexFormat):
# [size](#undefined-size): number
\[\]
# [BatchRenderer](#BatchRenderer):
# [ctx](#BatchRenderer-ctx): GfxCtx
# [glVBuf](#BatchRenderer-glVBuf): WebGLBuffer
# [glIBuf](#BatchRenderer-glIBuf): WebGLBuffer
# [vqueue](#BatchRenderer-vqueue): number\[\]
# [iqueue](#BatchRenderer-iqueue): number\[\]
# [stride](#BatchRenderer-stride): number
# [maxVertices](#BatchRenderer-maxVertices): number
# [maxIndices](#BatchRenderer-maxIndices): number
# [vertexFormat](#BatchRenderer-vertexFormat): VertexFormat
# [numDraws](#BatchRenderer-numDraws): number
# [curPrimitive](#BatchRenderer-curPrimitive): GLenum \| null
# [curTex](#BatchRenderer-curTex): Texture \| null
# [curShader](#BatchRenderer-curShader): Shader \| null
# [curUniform](#BatchRenderer-curUniform): Uniform \| null
# [curBlend](#BatchRenderer-curBlend): BlendMode
# [curFixed](#BatchRenderer-curFixed): boolean \| undefined
# [picture](#BatchRenderer-picture): Picture \| null
# [push](#BatchRenderer-push)(primitive: GLenum, vertices: number\[\], indices: number\[\], shader: Shader, tex: Texture \| null \| undefined, uniform: Uniform \| null \| undefined, blend: BlendMode, width: number, height: number, fixed: boolean): void
# [flush](#BatchRenderer-flush)(width: number, height: number): void
# [free](#BatchRenderer-free)(): void
# [setBlend](#BatchRenderer-setBlend)(blend: BlendMode): void
# [Mesh](#Mesh):
# [ctx](#Mesh-ctx): GfxCtx
# [glVBuf](#Mesh-glVBuf): WebGLBuffer
# [glIBuf](#Mesh-glIBuf): WebGLBuffer
# [vertexFormat](#Mesh-vertexFormat): VertexFormat
# [count](#Mesh-count): number
# [draw](#Mesh-draw)(primitive?: GLenum, index?: GLuint, count?: GLuint): void
# [free](#Mesh-free)(): void
[initGfx](#initGfx)(gl: WebGLRenderingContext, opts?: KAPLAYOpt):
# [gl](#undefined-gl): WebGLRenderingContext
# [opts](#undefined-opts): KAPLAYOpt\<any, any\>
# [onDestroy](#undefined-onDestroy)(action: ()=\>unknown): void
# [destroy](#undefined-destroy)(): void
# [pushTexture2D](#undefined-pushTexture2D)(item: WebGLTexture): void
# [popTexture2D](#undefined-popTexture2D)(): void
# [pushArrayBuffer](#undefined-pushArrayBuffer)(item: WebGLBuffer): void
# [popArrayBuffer](#undefined-popArrayBuffer)(): void
# [pushElementArrayBuffer](#undefined-pushElementArrayBuffer)(item: WebGLBuffer): void
# [popElementArrayBuffer](#undefined-popElementArrayBuffer)(): void
# [pushFramebuffer](#undefined-pushFramebuffer)(item: WebGLFramebuffer): void
# [popFramebuffer](#undefined-popFramebuffer)(): void
# [pushRenderbuffer](#undefined-pushRenderbuffer)(item: WebGLRenderbuffer): void
# [popRenderbuffer](#undefined-popRenderbuffer)(): void
[pushViewport](#undefined-pushViewport)(item:
# [x](#undefined-x): number
# [y](#undefined-y): number
# [w](#undefined-w): number
# [h](#undefined-h): number
): void
# [popViewport](#undefined-popViewport)(): void
# [pushProgram](#undefined-pushProgram)(item: WebGLProgram): void
# [popProgram](#undefined-popProgram)(): void
# [setVertexFormat](#undefined-setVertexFormat)(fmt: VertexFormat): void
# [TexPacker](#TexPacker):
# [lastTextureId](#TexPacker-lastTextureId):
# [textures](#TexPacker-textures):
# [bigTextures](#TexPacker-bigTextures):
# [texturesPosition](#TexPacker-texturesPosition):
# [canvas](#TexPacker-canvas):
# [c2d](#TexPacker-c2d):
# [x](#TexPacker-x):
# [y](#TexPacker-y):
# [curHeight](#TexPacker-curHeight):
# [gfx](#TexPacker-gfx):
# [padding](#TexPacker-padding):
# [add_single](#TexPacker-add_single)(img: ImageSource): \[Texture, Quad, number\]
# [add](#TexPacker-add)(img: ImageSource): \[Texture, Quad, number\]
# [free](#TexPacker-free)(): void
# [remove](#TexPacker-remove)(packerId: number): void
# [GfxFont](#GfxFont):
# [tex](#GfxFont-tex): Texture
# [map](#GfxFont-map): Record\<string, Quad\>
# [size](#GfxFont-size): number
# [BitmapFontData](#BitmapFontData): GfxFont
# [LoadBitmapFontOpt](#LoadBitmapFontOpt):
# [chars](#LoadBitmapFontOpt-chars)?: string
# [filter](#LoadBitmapFontOpt-filter)?: TexFilter
# [outline](#LoadBitmapFontOpt-outline)?: number
# [CharTransformFunc](#CharTransformFunc)(idx: number, ch: string): CharTransform
A function that returns a character transform config. Useful if you're generating dynamic styles.
# [FontData](#FontData):
# [fontface](#FontData-fontface): FontFace
# [filter](#FontData-filter): TexFilter
# [outline](#FontData-outline): Outline \| null
# [size](#FontData-size): number
# [SoundData](#SoundData):
# [buf](#SoundData-buf): AudioBuffer
# [fromAudioBuffer](#SoundData-fromAudioBuffer)(buf: AudioBuffer): SoundData
# [fromArrayBuffer](#SoundData-fromArrayBuffer)(buf: ArrayBuffer): Promise\<SoundData\>
# [fromURL](#SoundData-fromURL)(url: string): Promise\<SoundData\>
[DrawSpriteOpt](#DrawSpriteOpt): RenderProps &
# [sprite](#undefined-sprite): string \| SpriteData \| Asset
The sprite name in the asset manager, or the raw sprite data.
# [frame](#undefined-frame)?: number
If the sprite is loaded with multiple frames, or sliced, use the frame option to specify which frame to draw.
# [width](#undefined-width)?: number
Width of sprite. If \`height\` is not specified it'll stretch with aspect ratio. If \`tiled\` is set to true it'll tiled to the specified width horizontally.
# [height](#undefined-height)?: number
Height of sprite. If \`width\` is not specified it'll stretch with aspect ratio. If \`tiled\` is set to true it'll tiled to the specified width vertically.
# [tiled](#undefined-tiled)?: boolean
When set to true, \`width\` and \`height\` will not scale the sprite but instead render multiple tiled copies of them until the specified width and height. Useful for background texture pattern etc.
# [flipX](#undefined-flipX)?: boolean
If flip the texture horizontally.
# [flipY](#undefined-flipY)?: boolean
If flip the texture vertically.
# [quad](#undefined-quad)?: Quad
The sub-area to render from the texture, by default it'll render the whole \`quad(0, 0, 1, 1)\`
# [anchor](#undefined-anchor)?: Anchor \| Vec2
The anchor point, or the pivot point. Default to \"topleft\".
# [pos](#undefined-pos)?: Vec2
The position
How the sprite should look like.
[SpriteAnim](#SpriteAnim): number \|
# [from](#undefined-from)?: number
The starting frame.
# [to](#undefined-to)?: number
The end frame.
# [loop](#undefined-loop)?: boolean
If this anim should be played in loop.
# [pingpong](#undefined-pingpong)?: boolean
When looping should it move back instead of go to start frame again.
# [speed](#undefined-speed)?: number
This anim's speed in frames per second.
# [frames](#undefined-frames)?: number\[\]
List of frames for the animation. If this property exists, \*\*from, to, and pingpong will be ignored\*\*.
Frame-based animation configuration.
# [SpriteAnims](#SpriteAnims): Record\<string, SpriteAnim\>
A dict of name \<-\> animation.
# [LoadSpriteOpt](#LoadSpriteOpt):
Sprite loading configuration.
# [sliceX](#LoadSpriteOpt-sliceX)?: number
If the defined area contains multiple sprites, how many frames are in the area horizontally.
# [sliceY](#LoadSpriteOpt-sliceY)?: number
If the defined area contains multiple sprites, how many frames are in the area vertically.
# [slice9](#LoadSpriteOpt-slice9)?: NineSlice
9 slice sprite for proportional scaling.
`since`v3000.0
# [frames](#LoadSpriteOpt-frames)?: Quad\[\]
Individual frames.
`since`v3000.0
# [anims](#LoadSpriteOpt-anims)?: SpriteAnims
Animation configuration.
# [singular](#LoadSpriteOpt-singular)?: boolean
If the sprite is a single image.
[NineSlice](#NineSlice):
# [left](#undefined-left): number
The width of the 9-slice's left column.
# [right](#undefined-right): number
The width of the 9-slice's right column.
# [top](#undefined-top): number
The height of the 9-slice's top row.
# [bottom](#undefined-bottom): number
The height of the 9-slice's bottom row.
# [LoadSpriteSrc](#LoadSpriteSrc): string \| ImageSource
# [SpriteData](#SpriteData):
# [tex](#SpriteData-tex): Texture
# [frames](#SpriteData-frames): Quad\[\]
# [anims](#SpriteData-anims): SpriteAnims
# [slice9](#SpriteData-slice9): NineSlice \| null
# [packerId](#SpriteData-packerId): number \| null
# [width](#SpriteData-width)(): number
`since`v3001.0
# [height](#SpriteData-height)(): number
# [from](#SpriteData-from)(src: LoadSpriteSrc, opt?: LoadSpriteOpt): Promise\<SpriteData\>
# [fromImage](#SpriteData-fromImage)(data: ImageSource, opt?: LoadSpriteOpt): SpriteData
# [fromURL](#SpriteData-fromURL)(url: string, opt?: LoadSpriteOpt): Promise\<SpriteData\>
# [Asset](#Asset)\<D\>:
An asset is a resource that is loaded asynchronously. It can be a sprite, a sound, a font, a shader, etc.
# [loaded](#Asset-loaded): boolean
# [loaded](#Asset-loaded)\<D\>(data: D): Asset\<D\>
# [data](#Asset-data): D \| null
# [error](#Asset-error): Error \| null
# [onLoadEvents](#Asset-onLoadEvents):
# [onErrorEvents](#Asset-onErrorEvents):
# [onFinishEvents](#Asset-onFinishEvents):
# [onLoad](#Asset-onLoad)(action: (data: D)=\>void): this
# [onError](#Asset-onError)(action: (err: Error)=\>void): this
# [onFinish](#Asset-onFinish)(action: ()=\>void): this
# [then](#Asset-then)(action: (data: D)=\>void): Asset\<D\>
# [catch](#Asset-catch)(action: (err: Error)=\>void): Asset\<D\>
# [finally](#Asset-finally)(action: ()=\>void): Asset\<D\>
# [AssetBucket](#AssetBucket)\<D\>:
# [assets](#AssetBucket-assets): Map\<string, Asset\>
# [lastUID](#AssetBucket-lastUID): number
# [add](#AssetBucket-add)(name: string \| null, loader: Promise): Asset\<D\>
# [addLoaded](#AssetBucket-addLoaded)(name: string \| null, data: D): Asset\<D\>
# [get](#AssetBucket-get)(handle: string): Asset \| undefined
# [progress](#AssetBucket-progress)(): number
# [getFailedAssets](#AssetBucket-getFailedAssets)(): \[string, Asset\]\[\]
# [AssetsCtx](#AssetsCtx): ReturnType\<initAssets\>
[AsepriteData](#AsepriteData):
[frames](#undefined-frames): Array\<
[frame](#undefined-frame):
# [x](#undefined-x): number
# [y](#undefined-y): number
# [w](#undefined-w): number
# [h](#undefined-h): number
\>
[meta](#undefined-meta):
[size](#undefined-size):
# [w](#undefined-w): number
# [h](#undefined-h): number
[frameTags](#undefined-frameTags): Array\<
# [from](#undefined-from): number
# [to](#undefined-to): number
# [direction](#undefined-direction): forward \| reverse \| pingpong
\>
# [SpriteAtlasData](#SpriteAtlasData): Record\<string, SpriteAtlasEntry\>
[SpriteAtlasEntry](#SpriteAtlasEntry): LoadSpriteOpt &
# [x](#undefined-x): number
X position of the top left corner.
# [y](#undefined-y): number
Y position of the top left corner.
# [width](#undefined-width): number
Sprite area width.
# [height](#undefined-height): number
Sprite area height.
A sprite in a sprite atlas.
# [Registry](#Registry)\<T\>:
# [lastID](#Registry-lastID):
# [push](#Registry-push)(v: T): number
# [pushd](#Registry-pushd)(v: T): void
# [KEvent](#KEvent)\<Args\>:
# [cancellers](#KEvent-cancellers):
# [handlers](#KEvent-handlers):
# [add](#KEvent-add)(action: (args: Args)=\>unknown): KEventController
# [addOnce](#KEvent-addOnce)(action: (args: Args \| PromiseLike\[\])=\>void): KEventController
# [next](#KEvent-next)(): Promise\<Args\>
# [trigger](#KEvent-trigger)(args: Args): void
# [numListeners](#KEvent-numListeners)(): number
# [clear](#KEvent-clear)(): void
# [KEventHandler](#KEventHandler)\<EventMap\>:
# [handlers](#KEventHandler-handlers):
# [registers](#KEventHandler-registers): Partial\<MappedType\>
# [on](#KEventHandler-on)\<Name\>(name: Name, action: (args: EventMap\[Name\])=\>void): KEventController
# [onOnce](#KEventHandler-onOnce)\<Name\>(name: Name, action: (args: EventMap\[Name\])=\>void): KEventController
# [next](#KEventHandler-next)\<Name\>(name: Name): Promise\<unknown\>
# [trigger](#KEventHandler-trigger)\<Name\>(name: Name, args: EventMap\[Name\]): void
# [remove](#KEventHandler-remove)\<Name\>(name: Name): void
# [clear](#KEventHandler-clear)(): void
# [numListeners](#KEventHandler-numListeners)\<Name\>(name: Name): number
# [AudioPlayOpt](#AudioPlayOpt):
Audio play configurations.
# [paused](#AudioPlayOpt-paused)?: boolean
If audio should start out paused.
`since`v3000.0
# [loop](#AudioPlayOpt-loop)?: boolean
If audio should be played again from start when its ended.
# [volume](#AudioPlayOpt-volume)?: number
Volume of audio. 1.0 means full volume, 0.5 means half volume.
# [speed](#AudioPlayOpt-speed)?: number
Playback speed. 1.0 means normal playback speed, 2.0 means twice as fast.
# [detune](#AudioPlayOpt-detune)?: number
Detune the sound. Every 100 means a semitone.
``` js
// play a random note in the octave
play("noteC", {
detune: randi(0, 12) * 100,
})
```
# [seek](#AudioPlayOpt-seek)?: number
The start time, in seconds.
# [pan](#AudioPlayOpt-pan)?: number
The stereo pan of the sound. -1.0 means fully from the left channel, 0.0 means centered, 1.0 means fully right. Defaults to 0.0.
# [connectTo](#AudioPlayOpt-connectTo)?: AudioNode
If the audio node should start out connected to another audio node rather than KAPLAY's default volume node. Defaults to undefined, i.e. use KAPLAY's volume node.
# [AudioPlay](#AudioPlay):
# [play](#AudioPlay-play)(time?: number): void
Start playing audio.
`since`v3000.0
# [seek](#AudioPlay-seek)(time: number): void
Seek time.
`since`v3000.0
# [stop](#AudioPlay-stop)(): void
Stop the sound.
`since`v3001.0
# [paused](#AudioPlay-paused): boolean
If the sound is paused.
`since`v2000.1
# [speed](#AudioPlay-speed): number
Playback speed of the sound. 1.0 means normal playback speed, 2.0 means twice as fast.
# [detune](#AudioPlay-detune): number
Detune the sound. Every 100 means a semitone.
``` js
// tune down a semitone
music.detune = -100
// tune up an octave
music.detune = 1200
```
# [volume](#AudioPlay-volume): number
Volume of the sound. 1.0 means full volume, 0.5 means half volume.
# [pan](#AudioPlay-pan)?: number
The stereo pan of the sound. -1.0 means fully from the left channel, 0.0 means centered, 1.0 means fully right. Defaults to 0.0.
# [loop](#AudioPlay-loop): boolean
If the audio should start again when it ends.
# [time](#AudioPlay-time)(): number
The current playing time (not accurate if speed is changed).
# [duration](#AudioPlay-duration)(): number
The total duration.
# [onEnd](#AudioPlay-onEnd)(action: ()=\>void): KEventController
Register an event that runs when audio ends.
`since`v3000.0
# [then](#AudioPlay-then)(action: ()=\>void): KEventController
# [connect](#AudioPlay-connect)(node?: AudioNode): void
Disconnect the audio node from whatever it is currently connected to and connect it to the passed-in audio node, or to Kaplay's default volume node if no node is passed.
[AppGfxCtx](#AppGfxCtx):
# [lastDrawCalls](#undefined-lastDrawCalls): number
How many draw calls we're doing last frame
# [ggl](#undefined-ggl): GfxCtx
# [defShader](#undefined-defShader): Shader
Default shader
# [defTex](#undefined-defTex): Texture
Default texture
# [frameBuffer](#undefined-frameBuffer): FrameBuffer
FrameBuffer
# [postShader](#undefined-postShader): string \| null
Post Shader, used in postEffect()
# [postShaderUniform](#undefined-postShaderUniform): Uniform \| ()=\>Uniform \| null
# [renderer](#undefined-renderer): BatchRenderer
# [pixelDensity](#undefined-pixelDensity): number
# [gscale](#undefined-gscale): number
This is the scale factor that scales pixel \"kaplay({ scale })\"
# [transform](#undefined-transform): Mat23
# [transformStack](#undefined-transformStack): Mat23\[\]
# [transformStackIndex](#undefined-transformStackIndex): number
# [bgTex](#undefined-bgTex): Texture
The background texture
# [bgColor](#undefined-bgColor): Color \| null
# [bgAlpha](#undefined-bgAlpha): number
# [width](#undefined-width): number
The
# [height](#undefined-height): number
# [viewport](#undefined-viewport): Viewport
Where the game is rendered.
# [fixed](#undefined-fixed): boolean
# [gl](#undefined-gl): WebGLRenderingContext
[Viewport](#Viewport):
# [x](#undefined-x): number
# [y](#undefined-y): number
# [width](#undefined-width): number
# [height](#undefined-height): number
# [scale](#undefined-scale): number
# [GameObjEvents](#GameObjEvents): GameObjEventMap &
# [GameObjEventNames](#GameObjEventNames): GameObjEventMap
[AppEventMap](#AppEventMap):
# [mouseMove](#undefined-mouseMove): \[\]
# [mouseDown](#undefined-mouseDown): \[MouseButton\]
# [mousePress](#undefined-mousePress): \[MouseButton\]
# [mouseRelease](#undefined-mouseRelease): \[MouseButton\]
# [charInput](#undefined-charInput): \[string\]
# [keyPress](#undefined-keyPress): \[Key\]
# [keyDown](#undefined-keyDown): \[Key\]
# [keyPressRepeat](#undefined-keyPressRepeat): \[Key\]
# [keyRelease](#undefined-keyRelease): \[Key\]
# [touchStart](#undefined-touchStart): \[Vec2, Touch\]
# [touchMove](#undefined-touchMove): \[Vec2, Touch\]
# [touchEnd](#undefined-touchEnd): \[Vec2, Touch\]
# [gamepadButtonDown](#undefined-gamepadButtonDown): \[KGamepadButton, KGamepad\]
# [gamepadButtonPress](#undefined-gamepadButtonPress): \[KGamepadButton, KGamepad\]
# [gamepadButtonRelease](#undefined-gamepadButtonRelease): \[KGamepadButton, KGamepad\]
# [gamepadStick](#undefined-gamepadStick): \[string, Vec2, KGamepad\]
# [gamepadConnect](#undefined-gamepadConnect): \[KGamepad\]
# [gamepadDisconnect](#undefined-gamepadDisconnect): \[KGamepad\]
# [buttonDown](#undefined-buttonDown): \[string\]
# [buttonPress](#undefined-buttonPress): \[string\]
# [buttonRelease](#undefined-buttonRelease): \[string\]
# [scroll](#undefined-scroll): \[Vec2\]
# [hide](#undefined-hide): \[\]
# [show](#undefined-show): \[\]
# [resize](#undefined-resize): \[\]
# [input](#undefined-input): \[\]
App events with their arguments
[GameEventMap](#GameEventMap):
# [load](#undefined-load): \[\]
# [loadError](#undefined-loadError): \[string, Asset\]
# [loading](#undefined-loading): \[number\]
# [error](#undefined-error): \[Error\]
# [input](#undefined-input): \[\]
# [frameEnd](#undefined-frameEnd): \[\]
# [resize](#undefined-resize): \[\]
# [sceneLeave](#undefined-sceneLeave): \[string\]
# [sceneEnter](#undefined-sceneEnter): \[string\]
All Game State events with their arguments
# [SceneName](#SceneName): string
The name of a scene.
# [SceneDef](#SceneDef)(args: any): void
[System](#System):
# [run](#undefined-run)(): void
# [when](#undefined-when): LCEvents\[\]
# [LCEvents](#LCEvents):
[Game](#Game):
# [events](#undefined-events): KEventHandler\<GameEventMap & GameObjEventMap\>
Where game object global events are stored.
# [root](#undefined-root): GameObj\<TimerComp\>
The root game object, parent of all game objects.
# [gravity](#undefined-gravity): Vec2 \| null
# [scenes](#undefined-scenes): Record\<SceneName, SceneDef\>
# [currentScene](#undefined-currentScene): string \| null
# [layers](#undefined-layers): string\[\] \| null
# [defaultLayerIndex](#undefined-defaultLayerIndex): number
# [systems](#undefined-systems): System\[\]
# [systemsByEvent](#undefined-systemsByEvent): \[System\[\], System\[\], System\[\], System\[\], System\[\], System\[\]\]
# [kaSprite](#undefined-kaSprite): Asset \| null
# [boomSprite](#undefined-boomSprite): Asset \| null
# [logs](#undefined-logs): Log\[\]
# [cam](#undefined-cam): CamData
The \"Game\" it's all the state related to the game running
[Log](#Log):
# [msg](#undefined-msg): string \|
# [time](#undefined-time): number
[CamData](#CamData):
# [pos](#undefined-pos): Vec2 \| null
# [scale](#undefined-scale): Vec2
# [angle](#undefined-angle): number
# [shake](#undefined-shake): number
# [transform](#undefined-transform): Mat23
# [Engine](#Engine): ReturnType\<createEngine\>
[DrawonOpt](#DrawonOpt):
# [childrenOnly](#undefined-childrenOnly)?: boolean
# [refreshOnly](#undefined-refreshOnly)?: boolean
# [DrawonComp](#DrawonComp):
# [refresh](#DrawonComp-refresh)(): void
[DrawLineOpt](#DrawLineOpt): Omit &
# [p1](#undefined-p1): Vec2
Starting point of the line.
# [p2](#undefined-p2): Vec2
Ending point of the line.
# [width](#undefined-width)?: number
The width, or thickness of the line,
How the line should look like.
# [LineJoin](#LineJoin): none \| round \| bevel \| miter
# [LineCap](#LineCap): butt \| round \| square
[DrawLinesOpt](#DrawLinesOpt): Omit &
# [pts](#undefined-pts): Vec2\[\]
The points that should be connected with a line.
# [width](#undefined-width)?: number
The width, or thickness of the lines,
# [radius](#undefined-radius)?: number \| number\[\]
The radius of each corner.
# [join](#undefined-join)?: LineJoin
Line join style (default \"none\").
# [cap](#undefined-cap)?: LineCap
Line cap style (default \"none\").
# [miterLimit](#undefined-miterLimit)?: number
Maximum miter length, anything longer becomes bevel.
How the lines should look like.
[EmitterOpt](#EmitterOpt):
# [shape](#undefined-shape)?: ShapeType
Shape of the emitter. If given, particles spawn within this shape.
# [lifetime](#undefined-lifetime)?: number
Lifetime of the emitter.
# [rate](#undefined-rate)?: number
Rate of emission in particles per second if the emitter should emit out of itself.
# [position](#undefined-position): Vec2
Position (relative) of emission.
# [direction](#undefined-direction): number
Direction of emission.
# [spread](#undefined-spread): number
Spread (cone) of emission around the direction.
Options for the particles`particles()`'s component
# [PictureComp](#PictureComp):
# [picture](#PictureComp-picture): Picture
[PictureCompOpt](#PictureCompOpt):
# [picture](#undefined-picture): Picture
[FormattedText](#FormattedText):
# [width](#undefined-width): number
# [height](#undefined-height): number
# [chars](#undefined-chars): FormattedChar\[\]
# [opt](#undefined-opt): DrawTextOpt
# [renderedText](#undefined-renderedText): string
Formatted text with info on how and where to render each character.
# [FormattedChar](#FormattedChar):
One formated character.
# [ch](#FormattedChar-ch): string
# [tex](#FormattedChar-tex): Texture
# [width](#FormattedChar-width): number
# [height](#FormattedChar-height): number
# [quad](#FormattedChar-quad): Quad
# [pos](#FormattedChar-pos): Vec2
# [scale](#FormattedChar-scale): Vec2
# [angle](#FormattedChar-angle): number
# [color](#FormattedChar-color): Color
# [opacity](#FormattedChar-opacity): number
# [font](#FormattedChar-font)?: string \| FontData
# [stretchInPlace](#FormattedChar-stretchInPlace): boolean
# [shader](#FormattedChar-shader)?: string
# [uniform](#FormattedChar-uniform)?: Uniform
# [VideoComp](#VideoComp):
# [width](#VideoComp-width): number
# [height](#VideoComp-height): number
# [currentTime](#VideoComp-currentTime): number
# [duration](#VideoComp-duration): number
# [play](#VideoComp-play)(): void
# [pause](#VideoComp-pause)(): void
# [mute](#VideoComp-mute): boolean
# [renderArea](#VideoComp-renderArea)(): Rect
[VideoCompOpt](#VideoCompOpt):
# [width](#undefined-width): number
# [height](#undefined-height): number
# [Graph](#Graph):
# [getNeighbours](#Graph-getNeighbours)(node: number): number\[\]
# [getCost](#Graph-getCost)(node: number, neighbor: number): number
# [getHeuristic](#Graph-getHeuristic)(node: number, goal: number): number
# [getPath](#Graph-getPath)(from: number, to: number): number\[\]
# [getWaypointPath](#Graph-getWaypointPath)(from: Vec2, to: Vec2, opt: any): Vec2\[\]
# [PathfinderMapComp](#PathfinderMapComp):
# [navigate](#PathfinderMapComp-navigate)(origin: Vec2, target: Vec2, navigationOpt: any): Vec2\[\] \| undefined
Get navigation waypoints to reach the given target from the given origin.
# [graph](#PathfinderMapComp-graph): Graph \| undefined
The graph to use for navigation.
# [PathfinderMapCompOpt](#PathfinderMapCompOpt):
# [graph](#PathfinderMapCompOpt-graph)?: Graph
The graph to use for navigation. If null, the ancestors are queried for a pathfinderMap component.
# [PathfinderComp](#PathfinderComp):
# [navigateTo](#PathfinderComp-navigateTo)(target: Vec2): Vec2\[\] \| undefined
Get navigation waypoints to reach the given target from the current position.
# [graph](#PathfinderComp-graph): Graph \| undefined
Get the graph used for navigastion if any.
# [PathfinderCompOpt](#PathfinderCompOpt):
# [graph](#PathfinderCompOpt-graph)?: Graph
The graph to use for navigation. If null, the ancestors are queried for a pathfinderMap component.
# [navigationOpt](#PathfinderCompOpt-navigationOpt)?: any
The navigation options depending on the kind of graph used.
# [PatrolComp](#PatrolComp):
# [waypoints](#PatrolComp-waypoints): Vec2\[\] \| undefined
Path to follow. If null, doesn't move.
# [patrolSpeed](#PatrolComp-patrolSpeed): number
Speed of the movement during patrol.
# [nextLocation](#PatrolComp-nextLocation): Vec2 \| undefined
Current subgoal, if any.
# [onPatrolFinished](#PatrolComp-onPatrolFinished)(cb: (objects: GameObj\[\])=\>void): KEventController
Attaches an event handler which is called when using \"stop\" and the end of the path is reached.
`param`cbThe event handler called when the patrol finishes.
# [PatrolEndBehavior](#PatrolEndBehavior): loop \| ping-pong \| stop
# [PatrolCompOpt](#PatrolCompOpt):
# [waypoints](#PatrolCompOpt-waypoints)?: Vec2\[\]
Path to follow. If null, starts suspended.
# [speed](#PatrolCompOpt-speed)?: number
Speed of the movement during patrol.
# [endBehavior](#PatrolCompOpt-endBehavior)?: PatrolEndBehavior
What to do after the last waypoint has been reached.
# [SentryCandidatesCb](#SentryCandidatesCb)(): GameObj\[\]
# [SentryCandidates](#SentryCandidates): SentryCandidatesCb \| QueryOpt
# [TimeDirection](#TimeDirection): forward \| reverse \| ping-pong
# [Interpolation](#Interpolation): none \| linear \| slerp \| spline
# [AnimateOpt](#AnimateOpt):
# [duration](#AnimateOpt-duration): number
Duration of the animation in seconds
# [loops](#AnimateOpt-loops)?: number
Loops, Default is undefined aka infinite
# [direction](#AnimateOpt-direction)?: TimeDirection
Behavior when reaching the end of the animation. Default is forward.
# [easing](#AnimateOpt-easing)?: EaseFunc
Easing function. Default is linear time.
# [interpolation](#AnimateOpt-interpolation)?: Interpolation
Interpolation function. Default is linear interpolation.
# [timing](#AnimateOpt-timing)?: number\[\]
Timestamps in percent for the given keys, if omitted, keys are equally spaced.
# [easings](#AnimateOpt-easings)?: EaseFunc\[\]
Easings for the given keys, if omitted, easing is used.
# [AnimateCompOpt](#AnimateCompOpt):
# [followMotion](#AnimateCompOpt-followMotion)?: boolean
Changes the angle so it follows the motion, requires the rotate component
# [relative](#AnimateCompOpt-relative)?: boolean
The animation is added to the base values of pos, angle, scale and opacity instead of replacing them
# [BaseValues](#BaseValues):
# [pos](#BaseValues-pos): Vec2
# [angle](#BaseValues-angle): number
# [scale](#BaseValues-scale): Vec2
# [opacity](#BaseValues-opacity): number
# [AnimateComp](#AnimateComp):
# [animate](#AnimateComp-animate)\<T\>(name: string, keys: T\[\], opts: AnimateOpt): void
Animates a property on this object.
`param`nameName of the property to animate.
`param`keysKeys determining the value at a certain point in time.
`param`optsOptions.
# [unanimate](#AnimateComp-unanimate)(name: string): void
Removes the animation from the given property.
`param`nameName of the property to remove the animation from.
# [unanimateAll](#AnimateComp-unanimateAll)(): void
Removes the animations from all properties
# [onAnimateFinished](#AnimateComp-onAnimateFinished)(cb: ()=\>void): KEventController
Attaches an event handler which is called when all the animation channels have finished.
`param`cbThe event handler called when the animation finishes.
# [onAnimateChannelFinished](#AnimateComp-onAnimateChannelFinished)(cb: (name: string)=\>void): KEventController
Attaches an event handler which is called when an animation channels has finished.
`param`cbThe event handler called when an animation channel finishes.
# [base](#AnimateComp-base): BaseValues
Base values for relative animation
[animation](#AnimateComp-animation):
# [paused](#undefined-paused): boolean
Pauses playing
# [seek](#undefined-seek)(time: number): void
Move the animation to a specific point in time
# [duration](#undefined-duration): number
Returns the duration of the animation
# [serializeAnimationChannels](#AnimateComp-serializeAnimationChannels)(): Record\<string, AnimationChannel\>
[serializeAnimationOptions](#AnimateComp-serializeAnimationOptions)():
# [followMotion](#undefined-followMotion)?: boolean
# [relative](#undefined-relative)?: boolean
Serializes the options of this object to plain Javascript types
# [AnimationChannelKeys](#AnimationChannelKeys): number\[\] \| number\[\]\[\]
[AnimationOptions](#AnimationOptions):
# [duration](#undefined-duration): number
# [loops](#undefined-loops)?: number
# [direction](#undefined-direction)?: TimeDirection
# [easing](#undefined-easing)?: string
# [interpolation](#undefined-interpolation)?: Interpolation
# [timing](#undefined-timing)?: number\[\]
# [easings](#undefined-easings)?: string\[\]
[AnimationChannel](#AnimationChannel):
# [keys](#undefined-keys): AnimationChannelKeys
& AnimationOptions
# [FakeMouseComp](#FakeMouseComp):
The fakeMouse`fakeMouse()` component.
# [isPressed](#FakeMouseComp-isPressed)(): boolean
Whether the fake mouse is pressed.
# [press](#FakeMouseComp-press)(): void
Trigger press (onClick).
# [release](#FakeMouseComp-release)(): void
Trigger release.
# [onPress](#FakeMouseComp-onPress)(action: ()=\>void): void
Register an event that runs when the fake mouse performs a click.
# [onRelease](#FakeMouseComp-onRelease)(action: ()=\>void): void
Register an event that runs when the fake mouse releases.
[FakeMouseOpt](#FakeMouseOpt):
# [followMouse](#undefined-followMouse)?: boolean
Whether the fake mouse should follow the real mouse. Defaults to \`true\`.
Options for the fakeMouse`fakeMouse()` component.
[SurfaceEffectorCompOpt](#SurfaceEffectorCompOpt):
# [speed](#undefined-speed): number
# [speedVariation](#undefined-speedVariation)?: number
# [forceScale](#undefined-forceScale)?: number
# [SurfaceEffectorComp](#SurfaceEffectorComp):
# [speed](#SurfaceEffectorComp-speed): number
# [speedVariation](#SurfaceEffectorComp-speedVariation): number
# [forceScale](#SurfaceEffectorComp-forceScale): number
[AreaEffectorCompOpt](#AreaEffectorCompOpt):
# [useGlobalAngle](#undefined-useGlobalAngle)?: boolean
# [force](#undefined-force): Vec2
# [linearDrag](#undefined-linearDrag)?: number
# [AreaEffectorComp](#AreaEffectorComp):
# [useGlobalAngle](#AreaEffectorComp-useGlobalAngle): boolean
# [force](#AreaEffectorComp-force): Vec2
# [linearDrag](#AreaEffectorComp-linearDrag): number
# [ForceMode](#ForceMode): constant \| inverseLinear \| inverseSquared
[PointEffectorCompOpt](#PointEffectorCompOpt):
# [forceMagnitude](#undefined-forceMagnitude): number
# [distanceScale](#undefined-distanceScale)?: number
# [forceMode](#undefined-forceMode)?: ForceMode
# [linearDrag](#undefined-linearDrag)?: number
# [PointEffectorComp](#PointEffectorComp):
# [forceMagnitude](#PointEffectorComp-forceMagnitude): number
# [distanceScale](#PointEffectorComp-distanceScale): number
# [forceMode](#PointEffectorComp-forceMode): ForceMode
# [linearDrag](#PointEffectorComp-linearDrag): number
[ConstantForceCompOpt](#ConstantForceCompOpt):
# [force](#undefined-force)?: Vec2
# [useGlobalAngle](#undefined-useGlobalAngle)?: boolean
# [ConstantForceComp](#ConstantForceComp):
# [force](#ConstantForceComp-force): Vec2 \| undefined
# [useGlobalAngle](#ConstantForceComp-useGlobalAngle): boolean
[PlatformEffectorCompOpt](#PlatformEffectorCompOpt):
# [ignoreSides](#undefined-ignoreSides)?: Vec2\[\]
If the object is about to collide and the collision normal direction is in here (i.e. the object is moving roughly in this direction), the object won't collide. Should be a list of unit vectors \`LEFT\`, \`RIGHT\`, \`UP\`, or \`DOWN\`. Defaults to \`\[UP\]\`, i.e. the object will only be able to pass through when it is jumping upwards, but will collide when it is moving downwards or sideways.
# [shouldCollide](#undefined-shouldCollide)?(this: GameObj, obj: GameObj, normal: Vec2): boolean
A function that determines whether the object should collide. If present, it overrides the \`ignoreSides\`; if absent, it is automatically created from \`ignoreSides\`.
# [PlatformEffectorComp](#PlatformEffectorComp):
# [platformIgnore](#PlatformEffectorComp-platformIgnore): Set\<GameObj\>
A set of the objects that should not collide with this, because \`shouldCollide\` returned true. Objects in here are automatically removed when they stop colliding, so the casual user shouldn't need to touch this much. However, if an object is added to this set before the object collides with the platform effector, it won't collide even if \`shouldCollide\` returns true.
[BuoyancyEffectorCompOpt](#BuoyancyEffectorCompOpt):
# [surfaceLevel](#undefined-surfaceLevel): number
# [density](#undefined-density)?: number
# [linearDrag](#undefined-linearDrag)?: number
# [angularDrag](#undefined-angularDrag)?: number
# [flowAngle](#undefined-flowAngle)?: number
# [flowMagnitude](#undefined-flowMagnitude)?: number
# [flowVariation](#undefined-flowVariation)?: number
# [BuoyancyEffectorComp](#BuoyancyEffectorComp):
# [surfaceLevel](#BuoyancyEffectorComp-surfaceLevel): number
# [density](#BuoyancyEffectorComp-density): number
# [linearDrag](#BuoyancyEffectorComp-linearDrag): number
# [angularDrag](#BuoyancyEffectorComp-angularDrag): number
# [flowAngle](#BuoyancyEffectorComp-flowAngle): number
# [flowMagnitude](#BuoyancyEffectorComp-flowMagnitude): number
# [flowVariation](#BuoyancyEffectorComp-flowVariation): number
# [applyBuoyancy](#BuoyancyEffectorComp-applyBuoyancy)(body: GameObj, submergedArea: Polygon): void
# [applyDrag](#BuoyancyEffectorComp-applyDrag)(body: GameObj, submergedArea: Polygon): void
# [KeepFlags](#KeepFlags):
# [Pos](#KeepFlags-Pos):
# [Angle](#KeepFlags-Angle):
# [Scale](#KeepFlags-Scale):
# [All](#KeepFlags-All):
[SetParentOpt](#SetParentOpt):
# [keep](#undefined-keep): KeepFlags
# [TupleWithoutFirst](#TupleWithoutFirst)\<T\>: ConditionalType
[DrawCurveOpt](#DrawCurveOpt): RenderProps &
# [segments](#undefined-segments)?: number
The amount of line segments to draw.
# [width](#undefined-width)?: number
The width of the line.
[DrawBezierOpt](#DrawBezierOpt): DrawCurveOpt &
# [pt1](#undefined-pt1): Vec2
The first point.
# [pt2](#undefined-pt2): Vec2
The the first control point.
# [pt3](#undefined-pt3): Vec2
The the second control point.
# [pt4](#undefined-pt4): Vec2
The second point.
[DrawCanvasOpt](#DrawCanvasOpt): DrawUVQuadOpt &
# [canvas](#undefined-canvas): Canvas
[DrawCircleOpt](#DrawCircleOpt): Omit &
# [radius](#undefined-radius): number
Radius of the circle.
# [start](#undefined-start)?: number
Starting angle.
# [fill](#undefined-fill)?: boolean
If fill the shape with color (set this to false if you only want an outline).
# [gradient](#undefined-gradient)?: \[Color, Color\]
Use gradient instead of solid color.
`since`v3000.0
# [resolution](#undefined-resolution)?: number
Multiplier for circle vertices resolution (default 1)
# [anchor](#undefined-anchor)?: Anchor \| Vec2
The anchor point, or the pivot point. Default to \"topleft\".
How the circle should look like.
[DrawRectOpt](#DrawRectOpt): RenderProps &
# [width](#undefined-width): number
Width of the rectangle.
# [height](#undefined-height): number
Height of the rectangle.
# [gradient](#undefined-gradient)?: \[Color, Color\]
Use gradient instead of solid color.
`since`v3000.0
# [horizontal](#undefined-horizontal)?: boolean
If the gradient should be horizontal.
`since`v3000.0
# [fill](#undefined-fill)?: boolean
If fill the shape with color (set this to false if you only want an outline).
# [radius](#undefined-radius)?: number \| number\[\]
The radius of each corner.
# [anchor](#undefined-anchor)?: Anchor \| Vec2
The anchor point, or the pivot point. Default to \"topleft\".
How the rectangle should look like.
[DrawTriangleOpt](#DrawTriangleOpt): RenderProps &
# [p1](#undefined-p1): Vec2
First point of triangle.
# [p2](#undefined-p2): Vec2
Second point of triangle.
# [p3](#undefined-p3): Vec2
Third point of triangle.
# [fill](#undefined-fill)?: boolean
If fill the shape with color (set this to false if you only want an outline).
# [radius](#undefined-radius)?: number
The radius of each corner.
How the triangle should look like.
[StyledTextInfo](#StyledTextInfo):
# [charStyleMap](#undefined-charStyleMap): Record\<number, string\[\]\>
# [text](#undefined-text): string
[GjkCollisionResult](#GjkCollisionResult):
# [normal](#undefined-normal): Vec2
The direction the first shape needs to be moved to resolve the collision
# [distance](#undefined-distance): number
The distance the first shape needs to be moved to resolve the collision
# [NavEdge](#NavEdge):
# [a](#NavEdge-a): Vec2
# [b](#NavEdge-b): Vec2
# [polygon](#NavEdge-polygon): WeakRef\<NavPolygon\>
# [isLeft](#NavEdge-isLeft)(x: number, y: number): number
# [middle](#NavEdge-middle)(): Vec2
# [NavPolygon](#NavPolygon):
# [\_edges](#NavPolygon-_edges):
# [\_centroid](#NavPolygon-_centroid):
# [\_id](#NavPolygon-_id):
# [id](#NavPolygon-id)(): number
# [edges](#NavPolygon-edges)(edges: NavEdge\[\]):
# [edges](#NavPolygon-edges)(): NavEdge\[\]
# [centroid](#NavPolygon-centroid)(): Vec2
# [contains](#NavPolygon-contains)(p: Vec2): boolean
# [NavMesh](#NavMesh):
# [\_polygons](#NavMesh-_polygons):
# [\_pointCache](#NavMesh-_pointCache):
# [\_edgeCache](#NavMesh-_edgeCache):
# [\_addPoint](#NavMesh-_addPoint):
# [\_addEdge](#NavMesh-_addEdge):
# [\_findEdge](#NavMesh-_findEdge):
# [\_findCommonEdge](#NavMesh-_findCommonEdge):
# [addPolygon](#NavMesh-addPolygon)(vertices: Vec2\[\]): NavPolygon
# [addRect](#NavMesh-addRect)(pos: Vec2, size: Vec2): NavPolygon
# [\_getLocation](#NavMesh-_getLocation):
# [getNeighbours](#NavMesh-getNeighbours)(index: number): number\[\]
# [getCost](#NavMesh-getCost)(a: number, b: number): number
# [getHeuristic](#NavMesh-getHeuristic)(indexA: number, indexB: number): number
# [getPath](#NavMesh-getPath)(start: number, goal: number): number\[\]
# [getWaypointPath](#NavMesh-getWaypointPath)(start: Vec2, goal: Vec2, opt: any): Vec2\[\]
[\_k](#_k): Engine &
# [k](#undefined-k): KAPLAYCtx
Internal data that should not be accessed directly.
`readonly`
# [addKaboom](#addKaboom)(pos: Vec2, opt?: BoomOpt): GameObj
Add an explosion effect.
`param`pos- The position of the explosion.
`param`opt- The options for the explosion.
``` js
onMousePress(() => {
addKaboom(mousePos());
});
```
`returns`The explosion object.
`since`v2000.0
# [Tag](#Tag): string
# [UnionToIntersection](#UnionToIntersection)\<U\>: ConditionalType
# [Defined](#Defined)\<T\>: ConditionalType
# [Prettify](#Prettify)\<T\>: ConditionalType
It obligates to TypeScript to Expand the type. Instead of being \`{ id: 1 } \| { name: \"hi\" }\` makes It's \`{ id: 1, name: \"hi\" }\` https://www.totaltypescript.com/concepts/the-prettify-helper Previously Expand\<T\>
# [MergeObj](#MergeObj)\<T\>: Prettify\<UnionToIntersection\>
# [RemoveCompProps](#RemoveCompProps)\<T\>: Defined\<MappedType\>
# [MergePlugins](#MergePlugins)\<T\>: MergeObj\<ReturnType\>
# [PluginList](#PluginList)\<T\>: Array\<T \| KAPLAYPlugin\>
[GamepadDef](#GamepadDef):
# [buttons](#undefined-buttons): Record\<string, KGamepadButton\>
# [sticks](#undefined-sticks): Partial\<Record\>
A gamepad definition.
[KGamepad](#KGamepad):
# [index](#undefined-index): number
The order of the gamepad in the gamepad list.
# [isPressed](#undefined-isPressed)(b: KGamepadButton): boolean
If certain button is pressed.
# [isDown](#undefined-isDown)(b: KGamepadButton): boolean
If certain button is held down.
# [isReleased](#undefined-isReleased)(b: KGamepadButton): boolean
If certain button is released.
# [getStick](#undefined-getStick)(stick: GamepadStick): Vec2
Get the value of a stick.
A KAPLAY gamepad
# [GameObjInspect](#GameObjInspect): Record\<Tag, string \| null\>
Inspect info for a game object.
[RenderTarget](#RenderTarget):
# [destination](#undefined-destination): FrameBuffer \| Picture \| null
# [childrenOnly](#undefined-childrenOnly)?: boolean
# [refreshOnly](#undefined-refreshOnly)?: boolean
# [isFresh](#undefined-isFresh)?: boolean
# [SpriteAnimPlayOpt](#SpriteAnimPlayOpt):
Sprite animation configuration when playing.
# [loop](#SpriteAnimPlayOpt-loop)?: boolean
If this anim should be played in loop.
# [pingpong](#SpriteAnimPlayOpt-pingpong)?: boolean
When looping should it move back instead of go to start frame again.
# [speed](#SpriteAnimPlayOpt-speed)?: number
This anim's speed in frames per second.
# [onEnd](#SpriteAnimPlayOpt-onEnd)?(): void
Runs when this animation ends.
# [MusicData](#MusicData): string
# [LoadFontOpt](#LoadFontOpt):
# [filter](#LoadFontOpt-filter)?: TexFilter
# [outline](#LoadFontOpt-outline)?: number \| Outline
# [size](#LoadFontOpt-size)?: number
The size to load the font in (default 64).
`since`v3001.0
[TextureOpt](#TextureOpt):
# [filter](#undefined-filter)?: TexFilter
# [wrap](#undefined-wrap)?: TexWrap
# [ImageSource](#ImageSource): Exclude\<TexImageSource, VideoFrame\>
[Canvas](#Canvas):
# [width](#undefined-width): number
# [height](#undefined-height): number
# [toImageData](#undefined-toImageData)(): ImageData
# [toDataURL](#undefined-toDataURL)(): string
# [clear](#undefined-clear)(): void
# [draw](#undefined-draw)(action: ()=\>void): void
# [free](#undefined-free)(): void
# [fb](#undefined-fb): FrameBuffer
# [Vertex](#Vertex):
# [pos](#Vertex-pos): Vec2
# [uv](#Vertex-uv): Vec2
# [color](#Vertex-color): Color
# [opacity](#Vertex-opacity): number
# [BlendMode](#BlendMode):
# [Normal](#BlendMode-Normal):
# [Add](#BlendMode-Add):
# [Multiply](#BlendMode-Multiply):
# [Screen](#BlendMode-Screen):
# [Overlay](#BlendMode-Overlay):
# [Attributes](#Attributes):
# [pos](#Attributes-pos): number\[\]
# [uv](#Attributes-uv): number\[\]
# [color](#Attributes-color): number\[\]
# [opacity](#Attributes-opacity): number\[\]
# [TexFilter](#TexFilter): nearest \| linear
Texture scaling filter. \"nearest\" is mainly for sharp pixelated scaling, \"linear\" means linear interpolation.
# [TexWrap](#TexWrap): repeat \| clampToEdge
# [RenderProps](#RenderProps):
Common render properties.
# [pos](#RenderProps-pos)?: Vec2
# [scale](#RenderProps-scale)?: Vec2
# [angle](#RenderProps-angle)?: number
# [color](#RenderProps-color)?: Color
# [opacity](#RenderProps-opacity)?: number
# [fixed](#RenderProps-fixed)?: boolean
# [shader](#RenderProps-shader)?: string \| ShaderData \| Asset \| null
# [uniform](#RenderProps-uniform)?: Uniform \| null
# [blend](#RenderProps-blend)?: BlendMode
# [outline](#RenderProps-outline)?: Outline
[DrawTextureOpt](#DrawTextureOpt): RenderProps &
# [tex](#undefined-tex): Texture
# [width](#undefined-width)?: number
# [height](#undefined-height)?: number
# [tiled](#undefined-tiled)?: boolean
# [flipX](#undefined-flipX)?: boolean
# [flipY](#undefined-flipY)?: boolean
# [quad](#undefined-quad)?: Quad
# [anchor](#undefined-anchor)?: Anchor \| Vec2
[DrawUVQuadOpt](#DrawUVQuadOpt): RenderProps &
# [width](#undefined-width): number
Width of the UV quad.
# [height](#undefined-height): number
Height of the UV quad.
# [flipX](#undefined-flipX)?: boolean
If flip the texture horizontally.
# [flipY](#undefined-flipY)?: boolean
If flip the texture vertically.
# [tex](#undefined-tex)?: Texture
The texture to sample for this quad.
# [quad](#undefined-quad)?: Quad
The texture sampling area.
# [anchor](#undefined-anchor)?: Anchor \| Vec2
The anchor point, or the pivot point. Default to \"topleft\".
[DrawEllipseOpt](#DrawEllipseOpt): RenderProps &
# [radiusX](#undefined-radiusX): number
The horizontal radius.
# [radiusY](#undefined-radiusY): number
The vertical radius.
# [start](#undefined-start)?: number
Starting angle.
# [fill](#undefined-fill)?: boolean
If fill the shape with color (set this to false if you only want an outline).
# [gradient](#undefined-gradient)?: \[Color, Color\]
Use gradient instead of solid color.
`since`v3000.0
# [resolution](#undefined-resolution)?: number
Multiplier for circle vertices resolution (default 1)
# [anchor](#undefined-anchor)?: Anchor \| Vec2
The anchor point, or the pivot point. Default to \"topleft\".
How the ellipse should look like.
[DrawPolygonOpt](#DrawPolygonOpt): RenderProps &
# [pts](#undefined-pts): Vec2\[\]
The points that make up the polygon
# [fill](#undefined-fill)?: boolean
If fill the shape with color (set this to false if you only want an outline).
# [indices](#undefined-indices)?: number\[\]
Manual triangulation.
# [offset](#undefined-offset)?: Vec2
The center point of transformation in relation to the position.
# [radius](#undefined-radius)?: number \| number\[\]
The radius of each corner.
# [colors](#undefined-colors)?: Color\[\]
The color of each vertex.
`since`v3000.0
# [uv](#undefined-uv)?: Vec2\[\]
The uv of each vertex.
`since`v3001.0
# [tex](#undefined-tex)?: Texture
The texture if uv are supplied.
`since`v3001.0
# [triangulate](#undefined-triangulate)?: boolean
Triangulate concave polygons.
`since`v3001.0
How the polygon should look like.
# [Outline](#Outline):
# [width](#Outline-width)?: number
The width, or thickness of the line.
# [color](#Outline-color)?: Color
The color of the line.
# [opacity](#Outline-opacity)?: number
Opacity (overrides fill opacity).
`since`v3001.0
# [join](#Outline-join)?: LineJoin
Line join.
`since`v3000.0
# [miterLimit](#Outline-miterLimit)?: number
Miter limit. If the length of the miter divided by the line width exceeds this limit, the style is converted to a bevel.
`since`v3001.0
# [cap](#Outline-cap)?: LineCap
Line cap.
`since`v3001.0
# [Mask](#Mask): intersect \| subtract
# [EdgeMask](#EdgeMask):
# [None](#EdgeMask-None):
# [Left](#EdgeMask-Left):
# [Top](#EdgeMask-Top):
# [LeftTop](#EdgeMask-LeftTop):
# [Right](#EdgeMask-Right):
# [Horizontal](#EdgeMask-Horizontal):
# [RightTop](#EdgeMask-RightTop):
# [HorizontalTop](#EdgeMask-HorizontalTop):
# [Bottom](#EdgeMask-Bottom):
# [LeftBottom](#EdgeMask-LeftBottom):
# [Vertical](#EdgeMask-Vertical):
# [LeftVertical](#EdgeMask-LeftVertical):
# [RightBottom](#EdgeMask-RightBottom):
# [HorizontalBottom](#EdgeMask-HorizontalBottom):
# [RightVertical](#EdgeMask-RightVertical):
# [All](#EdgeMask-All):
# [SpriteCurAnim](#SpriteCurAnim):
# [timer](#SpriteCurAnim-timer): number
# [loop](#SpriteCurAnim-loop): boolean
# [speed](#SpriteCurAnim-speed): number
# [frameIndex](#SpriteCurAnim-frameIndex): number
The current index relative to the start of the associated \`frames\` array for this animation. This may be greater than the number of frames in the sprite.
# [pingpong](#SpriteCurAnim-pingpong): boolean
# [onEnd](#SpriteCurAnim-onEnd)(): void
# [ButtonState](#ButtonState)\<T\>:
# [pressed](#ButtonState-pressed): Set\<T\>
# [pressedRepeat](#ButtonState-pressedRepeat): Set\<T\>
# [released](#ButtonState-released): Set\<T\>
# [down](#ButtonState-down): Set\<T\>
# [update](#ButtonState-update)(): void
# [press](#ButtonState-press)(btn: T): void
# [pressRepeat](#ButtonState-pressRepeat)(btn: T): void
# [release](#ButtonState-release)(btn: T): void
# [GamepadState](#GamepadState):
# [buttonState](#GamepadState-buttonState): ButtonState\<KGamepadButton\>
# [stickState](#GamepadState-stickState): Map\<GamepadStick, Vec2\>
# [FPSCounter](#FPSCounter):
# [dts](#FPSCounter-dts): number\[\]
# [timer](#FPSCounter-timer): number
# [fps](#FPSCounter-fps): number
# [tick](#FPSCounter-tick)(dt: number): void
# [App](#App): ReturnType\<initApp\>
# [AppState](#AppState): ReturnType\<initAppState\>
# [AppEvents](#AppEvents): MappedType
The App method names that will have a helper in GameObjRaw
# [PeditFile](#PeditFile):
# [width](#PeditFile-width): number
# [height](#PeditFile-height): number
# [frames](#PeditFile-frames): string\[\]
# [anims](#PeditFile-anims): SpriteAnims
# [AudioCtx](#AudioCtx): ReturnType\<initAudio\>
# [FrameRenderer](#FrameRenderer): ReturnType\<createFrameRenderer\>
# [Grid](#Grid):
A grid is a graph consisting of connected grid cells
# [\_columns](#Grid-_columns):
# [\_rows](#Grid-_rows):
# [\_tileWidth](#Grid-_tileWidth):
# [\_tileHeight](#Grid-_tileHeight):
# [\_data](#Grid-_data):
# [\_diagonals](#Grid-_diagonals):
# [\_connMap](#Grid-_connMap):
# [\_buildConnectivityMap](#Grid-_buildConnectivityMap):
# [\_getTile](#Grid-_getTile):
# [\_getTileX](#Grid-_getTileX):
# [\_getTileY](#Grid-_getTileY):
# [getNeighbours](#Grid-getNeighbours)(tile: number): number\[\]
# [getCost](#Grid-getCost)(a: number, b: number): number
# [getHeuristic](#Grid-getHeuristic)(a: number, b: number): number
# [getPath](#Grid-getPath)(start: number, goal: number): number\[\]
# [getWaypointPath](#Grid-getWaypointPath)(start: Vec2, goal: Vec2): Vec2\[\]
[SatResult](#SatResult):
# [normal](#undefined-normal): Vec2
# [distance](#undefined-distance): number
# [Edge\$1](#Edge$1):
# [obj](#Edge$1-obj): GameObj\<AreaComp\>
# [x](#Edge$1-x): number
# [isLeft](#Edge$1-isLeft): boolean
# [SweepAndPrune](#SweepAndPrune):
One dimensional sweep and prune
# [edges](#SweepAndPrune-edges): Array\<Edge\$1\>
# [objects](#SweepAndPrune-objects): Map\<GameObj, \[Edge\$1, Edge\$1\]\>
# [add](#SweepAndPrune-add)(obj: GameObj): void
Add the object and its edges to the list
`param`objThe object to add
# [remove](#SweepAndPrune-remove)(obj: GameObj): void
Remove the object and its edges from the list
`param`objThe object to remove
# [clear](#SweepAndPrune-clear)(): void
# [update](#SweepAndPrune-update)(): void
Update edges and sort
# [Vec3](#Vec3):
# [x](#Vec3-x): number
# [y](#Vec3-y): number
# [z](#Vec3-z): number
# [dot](#Vec3-dot)(other: Vec3): number
# [cross](#Vec3-cross)(other: Vec3): Vec3
# [BinaryHeap](#BinaryHeap)\<T\>:
# [\_items](#BinaryHeap-_items): T\[\]
# [\_compareFn](#BinaryHeap-_compareFn)(a: T, b: T): boolean
# [insert](#BinaryHeap-insert)(item: T): void
Insert an item into the binary heap
# [remove](#BinaryHeap-remove)(): T \| null
Remove the smallest item from the binary heap in case of a min heap or the greatest item from the binary heap in case of a max heap
# [clear](#BinaryHeap-clear)(): void
Remove all items
# [moveUp](#BinaryHeap-moveUp)(pos: number): void
# [moveDown](#BinaryHeap-moveDown)(pos: number): void
# [swap](#BinaryHeap-swap)(index1: number, index2: number): void
# [length](#BinaryHeap-length)(): number
Returns the amount of items
[CSS_COLOR_MAP](#CSS_COLOR_MAP):
# [black](#undefined-black): string
# [silver](#undefined-silver): string
# [gray](#undefined-gray): string
# [white](#undefined-white): string
# [maroon](#undefined-maroon): string
# [red](#undefined-red): string
# [purple](#undefined-purple): string
# [fuchsia](#undefined-fuchsia): string
# [green](#undefined-green): string
# [lime](#undefined-lime): string
# [olive](#undefined-olive): string
# [yellow](#undefined-yellow): string
# [navy](#undefined-navy): string
# [blue](#undefined-blue): string
# [teal](#undefined-teal): string
# [aqua](#undefined-aqua): string
# [aliceblue](#undefined-aliceblue): string
# [antiquewhite](#undefined-antiquewhite): string
# [aquamarine](#undefined-aquamarine): string
# [azure](#undefined-azure): string
# [beige](#undefined-beige): string
# [bisque](#undefined-bisque): string
# [blanchedalmond](#undefined-blanchedalmond): string
# [blueviolet](#undefined-blueviolet): string
# [brown](#undefined-brown): string
# [burlywood](#undefined-burlywood): string
# [cadetblue](#undefined-cadetblue): string
# [chartreuse](#undefined-chartreuse): string
# [chocolate](#undefined-chocolate): string
# [coral](#undefined-coral): string
# [cornflowerblue](#undefined-cornflowerblue): string
# [cornsilk](#undefined-cornsilk): string
# [crimson](#undefined-crimson): string
# [cyan](#undefined-cyan): string
# [darkblue](#undefined-darkblue): string
# [darkcyan](#undefined-darkcyan): string
# [darkgoldenrod](#undefined-darkgoldenrod): string
# [darkgray](#undefined-darkgray): string
# [darkgreen](#undefined-darkgreen): string
# [darkkhaki](#undefined-darkkhaki): string
# [darkmagenta](#undefined-darkmagenta): string
# [darkolivegreen](#undefined-darkolivegreen): string
# [darkorange](#undefined-darkorange): string
# [darkorchid](#undefined-darkorchid): string
# [darkred](#undefined-darkred): string
# [darksalmon](#undefined-darksalmon): string
# [darkseagreen](#undefined-darkseagreen): string
# [darkslateblue](#undefined-darkslateblue): string
# [darkslategray](#undefined-darkslategray): string
# [darkturquoise](#undefined-darkturquoise): string
# [darkviolet](#undefined-darkviolet): string
# [deeppink](#undefined-deeppink): string
# [deepskyblue](#undefined-deepskyblue): string
# [dimgray](#undefined-dimgray): string
# [dodgerblue](#undefined-dodgerblue): string
# [firebrick](#undefined-firebrick): string
# [floralwhite](#undefined-floralwhite): string
# [forestgreen](#undefined-forestgreen): string
# [gainsboro](#undefined-gainsboro): string
# [ghostwhite](#undefined-ghostwhite): string
# [gold](#undefined-gold): string
# [goldenrod](#undefined-goldenrod): string
# [greenyellow](#undefined-greenyellow): string
# [honeydew](#undefined-honeydew): string
# [hotpink](#undefined-hotpink): string
# [indianred](#undefined-indianred): string
# [indigo](#undefined-indigo): string
# [ivory](#undefined-ivory): string
# [khaki](#undefined-khaki): string
# [lavender](#undefined-lavender): string
# [lavenderblush](#undefined-lavenderblush): string
# [lawngreen](#undefined-lawngreen): string
# [lemonchiffon](#undefined-lemonchiffon): string
# [lightblue](#undefined-lightblue): string
# [lightcoral](#undefined-lightcoral): string
# [lightcyan](#undefined-lightcyan): string
# [lightgoldenrodyellow](#undefined-lightgoldenrodyellow): string
# [lightgray](#undefined-lightgray): string
# [lightgreen](#undefined-lightgreen): string
# [lightpink](#undefined-lightpink): string
# [lightsalmon](#undefined-lightsalmon): string
# [lightseagreen](#undefined-lightseagreen): string
# [lightskyblue](#undefined-lightskyblue): string
# [lightslategray](#undefined-lightslategray): string
# [lightsteelblue](#undefined-lightsteelblue): string
# [lightyellow](#undefined-lightyellow): string
# [limegreen](#undefined-limegreen): string
# [linen](#undefined-linen): string
# [mediumaquamarine](#undefined-mediumaquamarine): string
# [mediumblue](#undefined-mediumblue): string
# [mediumorchid](#undefined-mediumorchid): string
# [mediumpurple](#undefined-mediumpurple): string
# [mediumseagreen](#undefined-mediumseagreen): string
# [mediumslateblue](#undefined-mediumslateblue): string
# [mediumspringgreen](#undefined-mediumspringgreen): string
# [mediumturquoise](#undefined-mediumturquoise): string
# [mediumvioletred](#undefined-mediumvioletred): string
# [midnightblue](#undefined-midnightblue): string
# [mintcream](#undefined-mintcream): string
# [mistyrose](#undefined-mistyrose): string
# [moccasin](#undefined-moccasin): string
# [navajowhite](#undefined-navajowhite): string
# [oldlace](#undefined-oldlace): string
# [olivedrab](#undefined-olivedrab): string
# [orange](#undefined-orange): string
# [orangered](#undefined-orangered): string
# [orchid](#undefined-orchid): string
# [palegoldenrod](#undefined-palegoldenrod): string
# [palegreen](#undefined-palegreen): string
# [paleturquoise](#undefined-paleturquoise): string
# [palevioletred](#undefined-palevioletred): string
# [papayawhip](#undefined-papayawhip): string
# [peachpuff](#undefined-peachpuff): string
# [peru](#undefined-peru): string
# [pink](#undefined-pink): string
# [plum](#undefined-plum): string
# [powderblue](#undefined-powderblue): string
# [rebeccapurple](#undefined-rebeccapurple): string
# [rosybrown](#undefined-rosybrown): string
# [royalblue](#undefined-royalblue): string
# [saddlebrown](#undefined-saddlebrown): string
# [salmon](#undefined-salmon): string
# [sandybrown](#undefined-sandybrown): string
# [seagreen](#undefined-seagreen): string
# [seashell](#undefined-seashell): string
# [sienna](#undefined-sienna): string
# [skyblue](#undefined-skyblue): string
# [slateblue](#undefined-slateblue): string
# [slategray](#undefined-slategray): string
# [snow](#undefined-snow): string
# [springgreen](#undefined-springgreen): string
# [steelblue](#undefined-steelblue): string
# [tan](#undefined-tan): string
# [thistle](#undefined-thistle): string
# [tomato](#undefined-tomato): string
# [turquoise](#undefined-turquoise): string
# [violet](#undefined-violet): string
# [wheat](#undefined-wheat): string
# [whitesmoke](#undefined-whitesmoke): string
# [yellowgreen](#undefined-yellowgreen): string
[initAssets](#initAssets)(ggl: GfxCtx, spriteAtlasPadding: number):
# [urlPrefix](#undefined-urlPrefix): string
# [sprites](#undefined-sprites): AssetBucket\<SpriteData\>
# [fonts](#undefined-fonts): AssetBucket\<FontData\>
# [bitmapFonts](#undefined-bitmapFonts): AssetBucket\<GfxFont\>
# [sounds](#undefined-sounds): AssetBucket\<SoundData\>
# [shaders](#undefined-shaders): AssetBucket\<Shader\>
# [custom](#undefined-custom): AssetBucket\<any\>
# [music](#undefined-music): Record\<string, string\>
# [packer](#undefined-packer): TexPacker
# [loaded](#undefined-loaded): boolean
[createEngine](#createEngine)(gopt: KAPLAYOpt):
# [globalOpt](#undefined-globalOpt): KAPLAYOpt\<any, any\>
# [canvas](#undefined-canvas): HTMLCanvasElement
[app](#undefined-app):
[state](#undefined-state):
# [canvas](#undefined-canvas): HTMLCanvasElement
# [buttons](#undefined-buttons): ButtonsDef
# [buttonsByKey](#undefined-buttonsByKey): Map\<Key, string\[\]\>
# [buttonsByMouse](#undefined-buttonsByMouse): Map\<MouseButton, string\[\]\>
# [buttonsByGamepad](#undefined-buttonsByGamepad): Map\<KGamepadButton, string\[\]\>
# [buttonsByKeyCode](#undefined-buttonsByKeyCode): Map\<string, string\[\]\>
# [loopID](#undefined-loopID): null \| number
# [stopped](#undefined-stopped): boolean
# [dt](#undefined-dt): number
# [fixedDt](#undefined-fixedDt): number
# [restDt](#undefined-restDt): number
# [time](#undefined-time): number
# [realTime](#undefined-realTime): number
[fpsCounter](#undefined-fpsCounter):
# [dts](#undefined-dts): number\[\]
# [timer](#undefined-timer): number
# [fps](#undefined-fps): number
# [tick](#undefined-tick)(dt: number): void
# [timeScale](#undefined-timeScale): number
# [skipTime](#undefined-skipTime): boolean
# [isHidden](#undefined-isHidden): boolean
# [numFrames](#undefined-numFrames): number
# [capsOn](#undefined-capsOn): boolean
# [mousePos](#undefined-mousePos): Vec2
# [mouseDeltaPos](#undefined-mouseDeltaPos): Vec2
# [keyState](#undefined-keyState): ButtonState\<Key\>
# [mouseState](#undefined-mouseState): ButtonState\<MouseButton\>
[mergedGamepadState](#undefined-mergedGamepadState):
# [buttonState](#undefined-buttonState): ButtonState\<KGamepadButton\>
# [stickState](#undefined-stickState): Map\<GamepadStick, Vec2\>
[gamepadStates](#undefined-gamepadStates): Map\<number,
# [buttonState](#undefined-buttonState): ButtonState\<KGamepadButton\>
# [stickState](#undefined-stickState): Map\<GamepadStick, Vec2\>
\>
# [lastInputDevice](#undefined-lastInputDevice): mouse \| keyboard \| gamepad \| null
# [buttonState](#undefined-buttonState): ButtonState\<string\>
# [gamepads](#undefined-gamepads): KGamepad\[\]
# [charInputted](#undefined-charInputted): string\[\]
# [isMouseMoved](#undefined-isMouseMoved): boolean
# [lastWidth](#undefined-lastWidth): number
# [lastHeight](#undefined-lastHeight): number
# [events](#undefined-events): KEventHandler\<AppEventMap\>
# [dt](#undefined-dt)(): number
# [fixedDt](#undefined-fixedDt)(): number
# [restDt](#undefined-restDt)(): number
# [time](#undefined-time)(): number
# [run](#undefined-run)(fixedUpdate: ()=\>void, update: (processInput: ()=\>void, resetInput: ()=\>void)=\>void): void
# [canvas](#undefined-canvas): HTMLCanvasElement
# [fps](#undefined-fps)(): number
# [numFrames](#undefined-numFrames)(): number
# [quit](#undefined-quit)(): void
# [isHidden](#undefined-isHidden)(): boolean
# [setFullscreen](#undefined-setFullscreen)(f?: boolean): void
# [isFullscreen](#undefined-isFullscreen)(): boolean
# [setCursor](#undefined-setCursor)(c: Cursor): void
# [screenshot](#undefined-screenshot)(): string
# [getGamepads](#undefined-getGamepads)(): KGamepad\[\]
# [getCursor](#undefined-getCursor)(): Cursor
# [setCursorLocked](#undefined-setCursorLocked)(b: boolean): void
# [isCursorLocked](#undefined-isCursorLocked)(): boolean
# [isTouchscreen](#undefined-isTouchscreen)(): boolean
# [mousePos](#undefined-mousePos)(): Vec2
# [mouseDeltaPos](#undefined-mouseDeltaPos)(): Vec2
# [isKeyDown](#undefined-isKeyDown)(k?: Key \| Key\[\]): boolean
# [isKeyPressed](#undefined-isKeyPressed)(k?: Key \| Key\[\]): boolean
# [isKeyPressedRepeat](#undefined-isKeyPressedRepeat)(k?: Key \| Key\[\]): boolean
# [isKeyReleased](#undefined-isKeyReleased)(k?: Key \| Key\[\]): boolean
# [isMouseDown](#undefined-isMouseDown)(m?: MouseButton): boolean
# [isMousePressed](#undefined-isMousePressed)(m?: MouseButton): boolean
# [isMouseReleased](#undefined-isMouseReleased)(m?: MouseButton): boolean
# [isMouseMoved](#undefined-isMouseMoved)(): boolean
# [isGamepadButtonPressed](#undefined-isGamepadButtonPressed)(btn?: KGamepadButton \| KGamepadButton\[\]): boolean
# [isGamepadButtonDown](#undefined-isGamepadButtonDown)(btn?: KGamepadButton \| KGamepadButton\[\]): boolean
# [isGamepadButtonReleased](#undefined-isGamepadButtonReleased)(btn?: KGamepadButton \| KGamepadButton\[\]): boolean
# [getGamepadStick](#undefined-getGamepadStick)(stick: GamepadStick): Vec2
# [isButtonPressed](#undefined-isButtonPressed)(btn?: string \| string\[\]): boolean
# [isButtonDown](#undefined-isButtonDown)(btn?: string \| string\[\]): boolean
# [isButtonReleased](#undefined-isButtonReleased)(btn?: string \| string\[\]): boolean
# [setButton](#undefined-setButton)(btn: string, binding: ButtonBinding): void
# [getButton](#undefined-getButton)(btn: string): ButtonBinding
# [pressButton](#undefined-pressButton)(btn: string): void
# [releaseButton](#undefined-releaseButton)(btn: string): void
# [charInputted](#undefined-charInputted)(): string\[\]
# [onResize](#undefined-onResize)(action: ()=\>void): KEventController
# [onKeyDown](#undefined-onKeyDown): (action: (key: Key)=\>void)=\>KEventController & (key: Key \| Key\[\], action: (key: Key)=\>void)=\>KEventController
# [onKeyPress](#undefined-onKeyPress): (action: (key: Key)=\>void)=\>KEventController & (key: Key \| Key\[\], action: (key: Key)=\>void)=\>KEventController
# [onKeyPressRepeat](#undefined-onKeyPressRepeat): (action: (key: Key)=\>void)=\>KEventController & (key: Key \| Key\[\], action: (key: Key)=\>void)=\>KEventController
# [onKeyRelease](#undefined-onKeyRelease): (action: (key: Key)=\>void)=\>KEventController & (key: Key \| Key\[\], action: (key: Key)=\>void)=\>KEventController
# [onMouseDown](#undefined-onMouseDown): (action: (m: MouseButton)=\>void)=\>KEventController & (mouse: MouseButton \| MouseButton\[\], action: (m: MouseButton)=\>void)=\>KEventController
# [onMousePress](#undefined-onMousePress): (action: (m: MouseButton)=\>void)=\>KEventController & (mouse: MouseButton \| MouseButton\[\], action: (m: MouseButton)=\>void)=\>KEventController
# [onMouseRelease](#undefined-onMouseRelease): (action: (m: MouseButton)=\>void)=\>KEventController & (mouse: MouseButton \| MouseButton\[\], action: (m: MouseButton)=\>void)=\>KEventController
# [onMouseMove](#undefined-onMouseMove)(f: (pos: Vec2, dpos: Vec2)=\>void): KEventController
# [onCharInput](#undefined-onCharInput)(action: (ch: string)=\>void): KEventController
# [onTouchStart](#undefined-onTouchStart)(f: (pos: Vec2, t: Touch)=\>void): KEventController
# [onTouchMove](#undefined-onTouchMove)(f: (pos: Vec2, t: Touch)=\>void): KEventController
# [onTouchEnd](#undefined-onTouchEnd)(f: (pos: Vec2, t: Touch)=\>void): KEventController
# [onScroll](#undefined-onScroll)(action: (delta: Vec2)=\>void): KEventController
# [onHide](#undefined-onHide)(action: ()=\>void): KEventController
# [onShow](#undefined-onShow)(action: ()=\>void): KEventController
# [onGamepadButtonDown](#undefined-onGamepadButtonDown): (action: (btn: KGamepadButton, gamepad: KGamepad)=\>void)=\>KEventController & (btn: KGamepadButton, action: (btn: KGamepadButton, gamepad: KGamepad)=\>void)=\>KEventController
# [onGamepadButtonPress](#undefined-onGamepadButtonPress): (action: (btn: KGamepadButton, gamepad: KGamepad)=\>void)=\>KEventController & (btn: KGamepadButton \| KGamepadButton\[\], action: (btn: KGamepadButton, gamepad: KGamepad)=\>void)=\>KEventController
# [onGamepadButtonRelease](#undefined-onGamepadButtonRelease): (action: (btn: KGamepadButton, gamepad: KGamepad)=\>void)=\>KEventController & (btn: KGamepadButton \| KGamepadButton\[\], action: (btn: KGamepadButton, gamepad: KGamepad)=\>void)=\>KEventController
# [onGamepadStick](#undefined-onGamepadStick)(stick: GamepadStick, action: (value: Vec2, gp: KGamepad)=\>void): KEventController
# [onGamepadConnect](#undefined-onGamepadConnect)(action: (gamepad: KGamepad)=\>void): KEventController
# [onGamepadDisconnect](#undefined-onGamepadDisconnect)(action: (gamepad: KGamepad)=\>void): KEventController
# [onButtonPress](#undefined-onButtonPress): (action: (btn: string)=\>void)=\>KEventController & (btn: string \| string, action: (btn: string)=\>void)=\>KEventController
# [onButtonDown](#undefined-onButtonDown): (action: (btn: string)=\>void)=\>KEventController & (btn: string \| string, action: (btn: string)=\>void)=\>KEventController
# [onButtonRelease](#undefined-onButtonRelease): (action: (btn: string)=\>void)=\>KEventController & (btn: string \| string, action: (btn: string)=\>void)=\>KEventController
# [getLastInputDeviceType](#undefined-getLastInputDeviceType)(): ButtonBindingDevice \| null
# [events](#undefined-events): KEventHandler\<AppEventMap\>
[ggl](#undefined-ggl):
# [gl](#undefined-gl): WebGLRenderingContext
# [opts](#undefined-opts): KAPLAYOpt\<any, any\>
# [onDestroy](#undefined-onDestroy)(action: ()=\>unknown): void
# [destroy](#undefined-destroy)(): void
# [pushTexture2D](#undefined-pushTexture2D)(item: WebGLTexture): void
# [popTexture2D](#undefined-popTexture2D)(): void
# [pushArrayBuffer](#undefined-pushArrayBuffer)(item: WebGLBuffer): void
# [popArrayBuffer](#undefined-popArrayBuffer)(): void
# [pushElementArrayBuffer](#undefined-pushElementArrayBuffer)(item: WebGLBuffer): void
# [popElementArrayBuffer](#undefined-popElementArrayBuffer)(): void
# [pushFramebuffer](#undefined-pushFramebuffer)(item: WebGLFramebuffer): void
# [popFramebuffer](#undefined-popFramebuffer)(): void
# [pushRenderbuffer](#undefined-pushRenderbuffer)(item: WebGLRenderbuffer): void
# [popRenderbuffer](#undefined-popRenderbuffer)(): void
[pushViewport](#undefined-pushViewport)(item:
# [x](#undefined-x): number
# [y](#undefined-y): number
# [w](#undefined-w): number
# [h](#undefined-h): number
): void
# [popViewport](#undefined-popViewport)(): void
# [pushProgram](#undefined-pushProgram)(item: WebGLProgram): void
# [popProgram](#undefined-popProgram)(): void
# [setVertexFormat](#undefined-setVertexFormat)(fmt: VertexFormat): void
# [gfx](#undefined-gfx): AppGfxCtx
[audio](#undefined-audio):
# [ctx](#undefined-ctx): AudioContext
# [masterNode](#undefined-masterNode): GainNode
# [burpSnd](#undefined-burpSnd): SoundData
[assets](#undefined-assets):
# [urlPrefix](#undefined-urlPrefix): string
# [sprites](#undefined-sprites): AssetBucket\<SpriteData\>
# [fonts](#undefined-fonts): AssetBucket\<FontData\>
# [bitmapFonts](#undefined-bitmapFonts): AssetBucket\<GfxFont\>
# [sounds](#undefined-sounds): AssetBucket\<SoundData\>
# [shaders](#undefined-shaders): AssetBucket\<Shader\>
# [custom](#undefined-custom): AssetBucket\<any\>
# [music](#undefined-music): Record\<string, string\>
# [packer](#undefined-packer): TexPacker
# [loaded](#undefined-loaded): boolean
[frameRenderer](#undefined-frameRenderer):
# [frameStart](#undefined-frameStart)(): void
# [frameEnd](#undefined-frameEnd)(): void
# [fixedUpdateFrame](#undefined-fixedUpdateFrame)(): void
# [updateFrame](#undefined-updateFrame)(): void
# [fontCacheC2d](#undefined-fontCacheC2d): CanvasRenderingContext2D \| null
# [fontCacheCanvas](#undefined-fontCacheCanvas): HTMLCanvasElement
# [game](#undefined-game): Game
# [debug](#undefined-debug): Debug
# [k](#undefined-k): KAPLAYCtx
[initAppState](#initAppState)(opt:
# [canvas](#undefined-canvas): HTMLCanvasElement
# [touchToMouse](#undefined-touchToMouse)?: boolean
# [gamepads](#undefined-gamepads)?: Record\<string, GamepadDef\>
# [pixelDensity](#undefined-pixelDensity)?: number
# [maxFPS](#undefined-maxFPS)?: number
# [buttons](#undefined-buttons)?: ButtonsDef
):
# [canvas](#undefined-canvas): HTMLCanvasElement
# [buttons](#undefined-buttons): ButtonsDef
# [buttonsByKey](#undefined-buttonsByKey): Map\<Key, string\[\]\>
# [buttonsByMouse](#undefined-buttonsByMouse): Map\<MouseButton, string\[\]\>
# [buttonsByGamepad](#undefined-buttonsByGamepad): Map\<KGamepadButton, string\[\]\>
# [buttonsByKeyCode](#undefined-buttonsByKeyCode): Map\<string, string\[\]\>
# [loopID](#undefined-loopID): null \| number
# [stopped](#undefined-stopped): boolean
# [dt](#undefined-dt): number
# [fixedDt](#undefined-fixedDt): number
# [restDt](#undefined-restDt): number
# [time](#undefined-time): number
# [realTime](#undefined-realTime): number
# [fpsCounter](#undefined-fpsCounter): FPSCounter
# [timeScale](#undefined-timeScale): number
# [skipTime](#undefined-skipTime): boolean
# [isHidden](#undefined-isHidden): boolean
# [numFrames](#undefined-numFrames): number
# [capsOn](#undefined-capsOn): boolean
# [mousePos](#undefined-mousePos): Vec2
# [mouseDeltaPos](#undefined-mouseDeltaPos): Vec2
# [keyState](#undefined-keyState): ButtonState\<Key\>
# [mouseState](#undefined-mouseState): ButtonState\<MouseButton\>
# [mergedGamepadState](#undefined-mergedGamepadState): GamepadState
# [gamepadStates](#undefined-gamepadStates): Map\<number, GamepadState\>
# [lastInputDevice](#undefined-lastInputDevice): mouse \| keyboard \| gamepad \| null
# [buttonState](#undefined-buttonState): ButtonState\<string\>
# [gamepads](#undefined-gamepads): KGamepad\[\]
# [charInputted](#undefined-charInputted): string\[\]
# [isMouseMoved](#undefined-isMouseMoved): boolean
# [lastWidth](#undefined-lastWidth): number
# [lastHeight](#undefined-lastHeight): number
# [events](#undefined-events): KEventHandler\<AppEventMap\>
[initApp](#initApp)(opt:
# [canvas](#undefined-canvas): HTMLCanvasElement
& KAPLAYOpt):
[state](#undefined-state):
# [canvas](#undefined-canvas): HTMLCanvasElement
# [buttons](#undefined-buttons): ButtonsDef
# [buttonsByKey](#undefined-buttonsByKey): Map\<Key, string\[\]\>
# [buttonsByMouse](#undefined-buttonsByMouse): Map\<MouseButton, string\[\]\>
# [buttonsByGamepad](#undefined-buttonsByGamepad): Map\<KGamepadButton, string\[\]\>
# [buttonsByKeyCode](#undefined-buttonsByKeyCode): Map\<string, string\[\]\>
# [loopID](#undefined-loopID): null \| number
# [stopped](#undefined-stopped): boolean
# [dt](#undefined-dt): number
# [fixedDt](#undefined-fixedDt): number
# [restDt](#undefined-restDt): number
# [time](#undefined-time): number
# [realTime](#undefined-realTime): number
# [fpsCounter](#undefined-fpsCounter): FPSCounter
# [timeScale](#undefined-timeScale): number
# [skipTime](#undefined-skipTime): boolean
# [isHidden](#undefined-isHidden): boolean
# [numFrames](#undefined-numFrames): number
# [capsOn](#undefined-capsOn): boolean
# [mousePos](#undefined-mousePos): Vec2
# [mouseDeltaPos](#undefined-mouseDeltaPos): Vec2
# [keyState](#undefined-keyState): ButtonState\<Key\>
# [mouseState](#undefined-mouseState): ButtonState\<MouseButton\>
# [mergedGamepadState](#undefined-mergedGamepadState): GamepadState
# [gamepadStates](#undefined-gamepadStates): Map\<number, GamepadState\>
# [lastInputDevice](#undefined-lastInputDevice): mouse \| keyboard \| gamepad \| null
# [buttonState](#undefined-buttonState): ButtonState\<string\>
# [gamepads](#undefined-gamepads): KGamepad\[\]
# [charInputted](#undefined-charInputted): string\[\]
# [isMouseMoved](#undefined-isMouseMoved): boolean
# [lastWidth](#undefined-lastWidth): number
# [lastHeight](#undefined-lastHeight): number
# [events](#undefined-events): KEventHandler\<AppEventMap\>
# [dt](#undefined-dt)(): number
# [fixedDt](#undefined-fixedDt)(): number
# [restDt](#undefined-restDt)(): number
# [time](#undefined-time)(): number
# [run](#undefined-run)(fixedUpdate: ()=\>void, update: (processInput: ()=\>void, resetInput: ()=\>void)=\>void): void
# [canvas](#undefined-canvas): HTMLCanvasElement
# [fps](#undefined-fps)(): number
# [numFrames](#undefined-numFrames)(): number
# [quit](#undefined-quit)(): void
# [isHidden](#undefined-isHidden)(): boolean
# [setFullscreen](#undefined-setFullscreen)(f?: boolean): void
# [isFullscreen](#undefined-isFullscreen)(): boolean
# [setCursor](#undefined-setCursor)(c: Cursor): void
# [screenshot](#undefined-screenshot)(): string
# [getGamepads](#undefined-getGamepads)(): KGamepad\[\]
# [getCursor](#undefined-getCursor)(): Cursor
# [setCursorLocked](#undefined-setCursorLocked)(b: boolean): void
# [isCursorLocked](#undefined-isCursorLocked)(): boolean
# [isTouchscreen](#undefined-isTouchscreen)(): boolean
# [mousePos](#undefined-mousePos)(): Vec2
# [mouseDeltaPos](#undefined-mouseDeltaPos)(): Vec2
# [isKeyDown](#undefined-isKeyDown)(k?: Key \| Key\[\]): boolean
# [isKeyPressed](#undefined-isKeyPressed)(k?: Key \| Key\[\]): boolean
# [isKeyPressedRepeat](#undefined-isKeyPressedRepeat)(k?: Key \| Key\[\]): boolean
# [isKeyReleased](#undefined-isKeyReleased)(k?: Key \| Key\[\]): boolean
# [isMouseDown](#undefined-isMouseDown)(m?: MouseButton): boolean
# [isMousePressed](#undefined-isMousePressed)(m?: MouseButton): boolean
# [isMouseReleased](#undefined-isMouseReleased)(m?: MouseButton): boolean
# [isMouseMoved](#undefined-isMouseMoved)(): boolean
# [isGamepadButtonPressed](#undefined-isGamepadButtonPressed)(btn?: KGamepadButton \| KGamepadButton\[\]): boolean
# [isGamepadButtonDown](#undefined-isGamepadButtonDown)(btn?: KGamepadButton \| KGamepadButton\[\]): boolean
# [isGamepadButtonReleased](#undefined-isGamepadButtonReleased)(btn?: KGamepadButton \| KGamepadButton\[\]): boolean
# [getGamepadStick](#undefined-getGamepadStick)(stick: GamepadStick): Vec2
# [isButtonPressed](#undefined-isButtonPressed)(btn?: string \| string\[\]): boolean
# [isButtonDown](#undefined-isButtonDown)(btn?: string \| string\[\]): boolean
# [isButtonReleased](#undefined-isButtonReleased)(btn?: string \| string\[\]): boolean
# [setButton](#undefined-setButton)(btn: string, binding: ButtonBinding): void
# [getButton](#undefined-getButton)(btn: string): ButtonBinding
# [pressButton](#undefined-pressButton)(btn: string): void
# [releaseButton](#undefined-releaseButton)(btn: string): void
# [charInputted](#undefined-charInputted)(): string\[\]
# [onResize](#undefined-onResize)(action: ()=\>void): KEventController
# [onKeyDown](#undefined-onKeyDown): (action: (key: Key)=\>void)=\>KEventController & (key: Key \| Key\[\], action: (key: Key)=\>void)=\>KEventController
# [onKeyPress](#undefined-onKeyPress): (action: (key: Key)=\>void)=\>KEventController & (key: Key \| Key\[\], action: (key: Key)=\>void)=\>KEventController
# [onKeyPressRepeat](#undefined-onKeyPressRepeat): (action: (key: Key)=\>void)=\>KEventController & (key: Key \| Key\[\], action: (key: Key)=\>void)=\>KEventController
# [onKeyRelease](#undefined-onKeyRelease): (action: (key: Key)=\>void)=\>KEventController & (key: Key \| Key\[\], action: (key: Key)=\>void)=\>KEventController
# [onMouseDown](#undefined-onMouseDown): (action: (m: MouseButton)=\>void)=\>KEventController & (mouse: MouseButton \| MouseButton\[\], action: (m: MouseButton)=\>void)=\>KEventController
# [onMousePress](#undefined-onMousePress): (action: (m: MouseButton)=\>void)=\>KEventController & (mouse: MouseButton \| MouseButton\[\], action: (m: MouseButton)=\>void)=\>KEventController
# [onMouseRelease](#undefined-onMouseRelease): (action: (m: MouseButton)=\>void)=\>KEventController & (mouse: MouseButton \| MouseButton\[\], action: (m: MouseButton)=\>void)=\>KEventController
# [onMouseMove](#undefined-onMouseMove)(f: (pos: Vec2, dpos: Vec2)=\>void): KEventController
# [onCharInput](#undefined-onCharInput)(action: (ch: string)=\>void): KEventController
# [onTouchStart](#undefined-onTouchStart)(f: (pos: Vec2, t: Touch)=\>void): KEventController
# [onTouchMove](#undefined-onTouchMove)(f: (pos: Vec2, t: Touch)=\>void): KEventController
# [onTouchEnd](#undefined-onTouchEnd)(f: (pos: Vec2, t: Touch)=\>void): KEventController
# [onScroll](#undefined-onScroll)(action: (delta: Vec2)=\>void): KEventController
# [onHide](#undefined-onHide)(action: ()=\>void): KEventController
# [onShow](#undefined-onShow)(action: ()=\>void): KEventController
# [onGamepadButtonDown](#undefined-onGamepadButtonDown): (action: (btn: KGamepadButton, gamepad: KGamepad)=\>void)=\>KEventController & (btn: KGamepadButton, action: (btn: KGamepadButton, gamepad: KGamepad)=\>void)=\>KEventController
# [onGamepadButtonPress](#undefined-onGamepadButtonPress): (action: (btn: KGamepadButton, gamepad: KGamepad)=\>void)=\>KEventController & (btn: KGamepadButton \| KGamepadButton\[\], action: (btn: KGamepadButton, gamepad: KGamepad)=\>void)=\>KEventController
# [onGamepadButtonRelease](#undefined-onGamepadButtonRelease): (action: (btn: KGamepadButton, gamepad: KGamepad)=\>void)=\>KEventController & (btn: KGamepadButton \| KGamepadButton\[\], action: (btn: KGamepadButton, gamepad: KGamepad)=\>void)=\>KEventController
# [onGamepadStick](#undefined-onGamepadStick)(stick: GamepadStick, action: (value: Vec2, gp: KGamepad)=\>void): KEventController
# [onGamepadConnect](#undefined-onGamepadConnect)(action: (gamepad: KGamepad)=\>void): KEventController
# [onGamepadDisconnect](#undefined-onGamepadDisconnect)(action: (gamepad: KGamepad)=\>void): KEventController
# [onButtonPress](#undefined-onButtonPress): (action: (btn: string)=\>void)=\>KEventController & (btn: string \| string, action: (btn: string)=\>void)=\>KEventController
# [onButtonDown](#undefined-onButtonDown): (action: (btn: string)=\>void)=\>KEventController & (btn: string \| string, action: (btn: string)=\>void)=\>KEventController
# [onButtonRelease](#undefined-onButtonRelease): (action: (btn: string)=\>void)=\>KEventController & (btn: string \| string, action: (btn: string)=\>void)=\>KEventController
# [getLastInputDeviceType](#undefined-getLastInputDeviceType)(): ButtonBindingDevice \| null
# [events](#undefined-events): KEventHandler\<AppEventMap\>
[initAudio](#initAudio)():
# [ctx](#undefined-ctx): AudioContext
# [masterNode](#undefined-masterNode): GainNode
# [burpSnd](#undefined-burpSnd): SoundData
[createFrameRenderer](#createFrameRenderer)(gfx: AppGfxCtx, game: Game, pixelDensity: number):
# [frameStart](#undefined-frameStart)(): void
# [frameEnd](#undefined-frameEnd)(): void
# [fixedUpdateFrame](#undefined-fixedUpdateFrame)(): void
# [updateFrame](#undefined-updateFrame)(): void
[ButtonBinding](#ButtonBinding):
# [keyboard](#undefined-keyboard)?: Key \| Key\[\]
# [keyboardCode](#undefined-keyboardCode)?: string \| string\[\]
# [gamepad](#undefined-gamepad)?: KGamepadButton \| KGamepadButton\[\]
# [mouse](#undefined-mouse)?: MouseButton \| MouseButton\[\]
A button binding.
# [ButtonsDef](#ButtonsDef): Record\<string, ButtonBinding\>
A buttons definition for an action (jump, walk-left, run).
# [ButtonBindingDevice](#ButtonBindingDevice): keyboard \| gamepad \| mouse
A button binding device
# [Shader](#Shader):
# [ctx](#Shader-ctx): GfxCtx
# [glProgram](#Shader-glProgram): WebGLProgram
# [bind](#Shader-bind)(): void
# [unbind](#Shader-unbind)(): void
# [send](#Shader-send)(uniform: Uniform): void
# [free](#Shader-free)(): void
# [FrameBuffer](#FrameBuffer):
# [ctx](#FrameBuffer-ctx): GfxCtx
# [tex](#FrameBuffer-tex): Texture
# [glFramebuffer](#FrameBuffer-glFramebuffer): WebGLFramebuffer
# [glRenderbuffer](#FrameBuffer-glRenderbuffer): WebGLRenderbuffer
# [width](#FrameBuffer-width)(): number
# [height](#FrameBuffer-height)(): number
# [toImageData](#FrameBuffer-toImageData)(): ImageData
# [toDataURL](#FrameBuffer-toDataURL)(): string
# [clear](#FrameBuffer-clear)(): void
# [draw](#FrameBuffer-draw)(action: ()=\>void): void
# [bind](#FrameBuffer-bind)(): void
# [unbind](#FrameBuffer-unbind)(): void
# [free](#FrameBuffer-free)(): void
[DrawTextOpt](#DrawTextOpt): RenderProps &
# [text](#undefined-text): string
The text to render.
# [font](#undefined-font)?: string \| FontData \| Asset \| BitmapFontData \| Asset
The name of font to use.
# [size](#undefined-size)?: number
The size of text (the height of each character).
# [align](#undefined-align)?: TextAlign
Text alignment (default \"left\")
`since`v3000.0
# [width](#undefined-width)?: number
The maximum width. Will wrap word around if exceed.
# [lineSpacing](#undefined-lineSpacing)?: number
The gap between each line (only available for bitmap fonts).
`since`v2000.2
# [letterSpacing](#undefined-letterSpacing)?: number
The gap between each character (only available for bitmap fonts).
`since`v2000.2
# [anchor](#undefined-anchor)?: Anchor \| Vec2
The anchor point, or the pivot point. Default to \"topleft\".
# [transform](#undefined-transform)?: CharTransform \| CharTransformFunc
Transform the pos, scale, rotation or color for each character based on the index or char (only available for bitmap fonts).
`since`v2000.1
# [styles](#undefined-styles)?: Record\<string, CharTransform \| CharTransformFunc\>
Stylesheet for styled chunks, in the syntax of \"this is a \[stylename\]styled\[/stylename\] word\" (only available for bitmap fonts).
`since`v2000.2
# [indentAll](#undefined-indentAll)?: boolean
If true, any (whitespace) indent on the first line of the paragraph will be copied to all of the lines for those parts that text-wrap.
How the text should look like.
# [TextAlign](#TextAlign): center \| left \| right
How the text should be aligned.
# [drawSprite](#drawSprite)(opt: DrawSpriteOpt): void
Draw a sprite.
`param`opt- The draw sprite options.
``` js
drawSprite({
sprite: "bean",
pos: vec2(100, 200),
frame: 3,
});
```
`since`v2000.0
# [drawText](#drawText)(opt: DrawTextOpt): void
Draw a piece of text.
`param`opt- The draw text options.
``` js
drawText({
text: "oh hi",
size: 48,
font: "sans-serif",
width: 120,
pos: vec2(100, 200),
color: rgb(0, 0, 255),
});
```
`since`v2000.0
# [drawRect](#drawRect)(opt: DrawRectOpt): void
Draw a rectangle.
`param`opt- The draw rect options.
``` js
drawRect({
width: 120,
height: 240,
pos: vec2(20, 20),
color: YELLOW,
outline: { color: BLACK, width: 4 },
});
```
`since`v2000.0
# [drawLine](#drawLine)(opt: DrawLineOpt): void
Draw a line.
`param`opt- The draw line options.
``` js
drawLine({
p1: vec2(0),
p2: mousePos(),
width: 4,
color: rgb(0, 0, 255),
});
```
`since`v3000.0
# [drawLines](#drawLines)(opt: DrawLinesOpt): void
Draw lines.
`param`opt- The draw lines options.
``` js
drawLines({
pts: [ vec2(0), vec2(0, height()), mousePos() ],
width: 4,
pos: vec2(100, 200),
color: rgb(0, 0, 255),
});
```
`since`v3000.0
# [drawCurve](#drawCurve)(curve: (t: number)=\>Vec2, opt: DrawCurveOpt): void
Draw a curve.
``` js
drawCurve(t => evaluateBezier(a, b, c, d, t)
{
width: 2,
color: rgb(0, 0, 255),
});
```
`since`v3001.0
# [drawBezier](#drawBezier)(opt: DrawBezierOpt): void
Draw a cubic Bezier curve.
`param`opt- The draw cubic bezier options.
``` js
drawBezier({
pt1: vec2(100, 100),
pt2: vec2(200, 100),
pt3: vec2(200, 200),
pt4: vec2(100, 200),
width: 2,
color: GREEN
});
```
`since`v3001.0
# [drawTriangle](#drawTriangle)(opt: DrawTriangleOpt): void
Draw a triangle.
`param`opt- The draw triangle options.
``` js
drawTriangle({
p1: vec2(0),
p2: vec2(0, height()),
p3: mousePos(),
pos: vec2(100, 200),
color: rgb(0, 0, 255),
});
```
`since`v3001.0
# [drawCircle](#drawCircle)(opt: DrawCircleOpt): void
Draw a circle.
`param`opt- The draw circle options.
``` js
drawCircle({
pos: vec2(100, 200),
radius: 120,
color: rgb(255, 255, 0),
});
```
`since`v2000.0
# [drawEllipse](#drawEllipse)(opt: DrawEllipseOpt): void
Draw an ellipse.
`param`opt- The draw ellipse options.
``` js
drawEllipse({
pos: vec2(100, 200),
radiusX: 120,
radiusY: 120,
color: rgb(255, 255, 0),
});
```
`since`v3000.0
# [drawPolygon](#drawPolygon)(opt: DrawPolygonOpt): void
Draw a convex polygon from a list of vertices.
`param`opt- The draw polygon options.
``` js
drawPolygon({
pts: [
vec2(-12),
vec2(0, 16),
vec2(12, 4),
vec2(0, -2),
vec2(-8),
],
pos: vec2(100, 200),
color: rgb(0, 0, 255),
});
```
`since`v3000.0
# [drawUVQuad](#drawUVQuad)(opt: DrawUVQuadOpt): void
Draw a rectangle with UV data.
`param`opt- The draw rect with UV options.
`since`v2000.0
# [drawFormattedText](#drawFormattedText)(text: FormattedText): void
Draw a piece of formatted text from formatText().
`param`text- The formatted text object.
``` js
// text background
const txt = formatText({
text: "oh hi",
});
drawRect({
width: txt.width,
height: txt.height,
});
drawFormattedText(txt);
```
`since`v2000.2
# [drawMasked](#drawMasked)(content: ()=\>void, mask: ()=\>void): void
Whatever drawn in content will only be drawn if it's also drawn in mask (mask will not be rendered).
`since`v3000.0
# [drawSubtracted](#drawSubtracted)(content: ()=\>void, mask: ()=\>void): void
Subtract whatever drawn in content by whatever drawn in mask (mask will not be rendered).
`since`v3000.0
# [pushTransform](#pushTransform)(): void
Push current transform matrix to the transform stack.
``` js
pushTransform();
// These transforms will affect every render until popTransform()
pushTranslate(120, 200);
pushRotate(time() * 120);
pushScale(6);
drawSprite("bean");
drawCircle(vec2(0), 120);
// Restore the transformation stack to when last pushed
popTransform();
```
`since`v2000.0
# [popTransform](#popTransform)(): void
Pop the topmost transform matrix from the transform stack.
`since`v2000.0
# [pushTranslate](#pushTranslate)(t?: Vec2): void
Translate all subsequent draws.
``` js
pushTranslate(100, 100)
// this will be drawn at (120, 120)
drawText({
text: "oh hi",
pos: vec2(20, 20),
})
```
`since`v2000.0
# [pushScale](#pushScale)(s?: Vec2): void
Scale all subsequent draws.
`since`v2000.0
# [pushRotate](#pushRotate)(angle?: number): void
Rotate all subsequent draws.
`since`v2000.0
# [pushMatrix](#pushMatrix)(mat?: Mat23): void
Apply a transform matrix, ignore all prior transforms.
`since`v3000.0
# [usePostEffect](#usePostEffect)(name: string, uniform?: Uniform \| ()=\>Uniform): void
Apply a post process effect from a shader name.
``` js
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")
```
`since`v3000.0
# [formatText](#formatText)(options: DrawTextOpt): FormattedText
Format a piece of text without drawing (for getting dimensions, etc).
``` js
// text background
const txt = formatText({
text: "oh hi",
});
drawRect({
width: txt.width,
height: txt.height,
});
drawFormattedText(txt);
```
`returns`The formatted text object.
`since`v2000.2
# [compileStyledText](#compileStyledText)(text: any): StyledTextInfo
Parses the text that has formatting tags, and returns the unstyled text (the actual characters that will be displayed) as well as which styles are active on each character.
`since`v4000
# [makeCanvas](#makeCanvas)(w: number, h: number): Canvas
Create a canvas to draw stuff offscreen.
`returns`The canvas object.
`since`v3001.0
# [drawCanvas](#drawCanvas)(opt: DrawCanvasOpt): void
Draw a canvas.
`param`optThe canvas object.
`since`v4000.0
# [Cursor](#Cursor): string \| auto \| default \| none \| context-menu \| help \| pointer \| progress \| wait \| cell \| crosshair \| text \| vertical-text \| alias \| copy \| move \| no-drop \| not-allowed \| grab \| grabbing \| all-scroll \| col-resize \| row-resize \| n-resize \| e-resize \| s-resize \| w-resize \| ne-resize \| nw-resize \| se-resize \| sw-resize \| ew-resize \| ns-resize \| nesw-resize \| nwse-resize \| zoom-int \| zoom-out
# [Anchor](#Anchor): topleft \| top \| topright \| left \| center \| right \| botleft \| bot \| botright
# [Shape](#Shape): Rect \| Line \| Point \| Circle \| Ellipse \| Polygon
# [CharTransform](#CharTransform):
Describes how to transform each character.
# [pos](#CharTransform-pos)?: Vec2
Offset to apply to the position of the text character. Shifts the character's position by the specified 2D vector.
# [scale](#CharTransform-scale)?: Vec2 \| number
Scale transformation to apply to the text character's current scale. When a number, it is scaled uniformly. Given a 2D vector, it is scaled independently along the X and Y axis.
# [angle](#CharTransform-angle)?: number
Increases the amount of degrees to rotate the text character.
# [color](#CharTransform-color)?: Color
Color transformation applied to the text character. Multiplies the current color with this color.
# [opacity](#CharTransform-opacity)?: number
Opacity multiplication applied to the text character. For example, an opacity of 0.4 with 2 set in the transformation, the resulting opacity will be 0.8 (0.4 × 2).
# [override](#CharTransform-override)?: boolean
If true, the styles applied by this specific entry transform will override, rather than compose with, the default styles given in and by other components' styles.
# [font](#CharTransform-font)?: string \| FontData
If the font for this character should be different from the default font or the one specified in . Because the font can't be composed like the other properties, this will override the font even if is false.
# [stretchInPlace](#CharTransform-stretchInPlace)?: boolean
If true, characters that have a X scale that is not 1 won't have the bounding box stretched to fit the character, and may end up overlapping with adjacent characters.
`default`true
# [shader](#CharTransform-shader)?: string
A name for a shader that will be applied to this character only.
# [uniform](#CharTransform-uniform)?: Uniform
Values to use for the shader's uniform inputs. If there is no shader set (by this character's transform or an entire-text transform), this is not used.
# [LevelOpt](#LevelOpt):
Options for the level`level()` component.
# [tileWidth](#LevelOpt-tileWidth): number
Width of each block.
# [tileHeight](#LevelOpt-tileHeight): number
Height of each block.
# [tiles](#LevelOpt-tiles):
Definition of each tile.
# [wildcardTile](#LevelOpt-wildcardTile)?(sym: string, pos: Vec2): CompList \| null \| undefined
Called when encountered a symbol not defined in \"tiles\".
# [BoomOpt](#BoomOpt):
# [speed](#BoomOpt-speed)?: number
Animation speed.
# [scale](#BoomOpt-scale)?: number
Scale.
# [comps](#BoomOpt-comps)?: CompList\<any\>
Additional components.
`since`v3000.0
[GetOpt](#GetOpt):
# [recursive](#undefined-recursive)?: boolean
Recursively get all children and their descendants.
# [liveUpdate](#undefined-liveUpdate)?: boolean
Live update the returned list every time object is added / removed.
# [only](#undefined-only)?: tags \| comps
Get only by tags or components.
[QueryOpt](#QueryOpt):
# [include](#undefined-include)?: string \| string\[\]
All objects which include all or any of these tags, depending on includeOp.
# [includeOp](#undefined-includeOp)?: and \| or
Selects the operator to use. Defaults to and.
# [exclude](#undefined-exclude)?: string \| string\[\]
All objects which do not have all or any of these tags, depending on excludeOp.
# [excludeOp](#undefined-excludeOp)?: and \| or
Selects the operator to use. Defaults to and.
# [distance](#undefined-distance)?: number
All objects which are near or far to the position of this, depending on distanceOp.
# [distanceOp](#undefined-distanceOp)?: near \| far
Selects the operator to use. Defaults to near.
# [visible](#undefined-visible)?: boolean
All objects visible from this standpoint.
# [hierarchy](#undefined-hierarchy)?: children \| siblings \| ancestors \| descendants
All objects in the given group. Defaults to children.
# [AddLevelOpt](#AddLevelOpt):
Options for the addLevel`addLevel()`.
# [pos](#AddLevelOpt-pos)?: Vec2
Position of the first block.
# [layer](#layer)(name: string): LayerComp
Determines the layer for objects. Object will be drawn on top if the layer index is higher.
`param`name- The layer name to set.
``` js
// Define layers
layers(["background", "game", "foreground"], "game")
const bean = add([
sprite("bean"),
pos(100, 100),
layer("background"),
])
// Mark is in a higher layer, so he will be drawn on top of bean
const mark = add([
sprite("mark"),
pos(100, 100),
layer("game"),
])
bean.layer("foreground") // Bean is now in the foreground layer and will be drawn on top of mark
```
`returns`The layer comp.
`since`v3001.0
# [onCollideEnd](#onCollideEnd)(t1: Tag, t2: Tag, action: (a: GameObj, b: GameObj, col?: Collision)=\>void): KEventController
Register an event that runs once frame when 2 game objs with certain tags stops colliding (required to have area() component).
`param`t1- The tag of the first game obj.
`param`t2- The tag of the second game obj.
`param`action- The function to run when the event is triggered.
``` js
onCollideEnd("bean", "earth", () => {
debug.log("destroying world in 3... 2... 1...")
});
```
`returns`The event controller.
`since`v3000.0
# [setGravity](#setGravity)(g: number): void
Set gravity.
`param`g- The gravity to set.
`since`v2000.0
# [getGravity](#getGravity)(): number
Get gravity.
`since`v3001.0
# [setGravityDirection](#setGravityDirection)(d: Vec2): void
Set gravity direction.
`since`v3001.0
# [getGravityDirection](#getGravityDirection)(): Vec2
Get gravity direction.
`returns`The gravity direction.
`since`v3001.0
# [setCamPos](#setCamPos)(pos: Vec2): void
Set camera position.
`param`pos- The position to set the camera to.
``` js
// move camera to (100, 100)
setCamPos(100, 100);
setCamPos(vec2(100, 100));
setCamPos(100); // x and y are the same
```
`since`v3001.1
# [setCamPos](#setCamPos)(x: number, y: number): void
# [setCamPos](#setCamPos)(xy: number): void
# [getCamPos](#getCamPos)(): Vec2
Get camera position.
`returns`The current camera position.
`since`v3001.1
# [setCamScale](#setCamScale)(scale: Vec2): void
Set camera scale.
`param`scale- The scale to set the camera to.
``` js
// set camera scale to (2, 2)
setCamScale(2, 2);
setCamScale(vec2(2, 2));
setCamScale(2); // x and y are the same
```
`since`v3001.1
# [setCamScale](#setCamScale)(x: number, y: number): void
# [setCamScale](#setCamScale)(xy: number): void
# [getCamScale](#getCamScale)(): Vec2
Get camera scale.
`returns`The current camera scale.
`since`v3001.1
# [setCamRot](#setCamRot)(angle: number): void
Set camera rotation.
`param`angle- The angle to rotate the camera.
``` js
// rotate camera 90 degrees
setCamRot(90);
```
`since`v3001.1
# [getCamRot](#getCamRot)(): number
Get camera rotation.
`returns`The current camera rotation.
`since`v3001.1
# [getCamTransform](#getCamTransform)(): Mat23
Get camera transform.
`returns`The current camera transform.
`since`v3001.1
# [shake](#shake)(intensity?: number): void
Camera shake.
`param`intensity- The intensity of the shake. Default to 12.
``` js
// shake intensively when bean collides with a "bomb"
bean.onCollide("bomb", () => {
shake(120)
})
```
`since`v3000.0
# [flash](#flash)(flashColor: Color, fadeOutTime: number): TimerController
Camera flash.
`param`flashColor- The color of the flash.
`param`fadeOutTime- The time it takes for the flash to fade out.
``` js
onClick(() => {
// flashed
flash(WHITE, 0.5);
});
```
`returns`A timer controller.
`since`v3001.0
# [camPos](#camPos)(pos: Vec2): Vec2
`param`pos- The position to set the camera to.
`deprecated`Use
``` js
// camera follows player
player.onUpdate(() => {
camPos(player.pos)
})
```
`returns`The current camera position.
`since`v2000.0
# [camPos](#camPos)(x: number, y: number): Vec2
`deprecated`
# [camPos](#camPos)(xy: number): Vec2
`deprecated`
# [camPos](#camPos)(): Vec2
`deprecated`
# [camScale](#camScale)(scale: Vec2): Vec2
`param`scale- The scale to set the camera to.
`deprecated`Use
`returns`The current camera scale.
`since`v2000.0
# [camScale](#camScale)(x: number, y: number): Vec2
`deprecated`
# [camScale](#camScale)(xy: number): Vec2
`deprecated`
# [camScale](#camScale)(): Vec2
`deprecated`
# [camRot](#camRot)(angle?: number): number
`param`angle- The angle to rotate the camera.
`deprecated`Use
`returns`The current camera rotation.
`since`v2000.0
# [camFlash](#camFlash)(flashColor: Color, fadeOutTime: number): TimerController
`param`flashColor- The color of the flash.
`param`fadeOutTime- The time it takes for the flash to fade out.
`deprecated`use
``` js
onClick(() => {
// flashed
camFlash(WHITE, 0.5)
})
```
`returns`A timer controller.
`since`v3001.0
# [camTransform](#camTransform)(): Mat23
`deprecated`use
# [toScreen](#toScreen)(p: Vec2): Vec2
Transform a point from world position (relative to the root) to screen position (relative to the screen).
`param`p- The point to transform.
`since`v3001.0
# [toWorld](#toWorld)(p: Vec2): Vec2
Transform a point from screen position (relative to the screen) to world position (relative to the root).
`param`p- The point to transform.
`since`v3001.0
# [play](#play)(src: string \| SoundData \| Asset \| MusicData \| Asset, options?: AudioPlayOpt): AudioPlay
Play a piece of audio.
``` js
// play a one off sound
play("wooosh")
// play a looping soundtrack (check out AudioPlayOpt for more options)
const music = play("OverworldlyFoe", {
volume: 0.8,
loop: true
})
// using the handle to control (check out AudioPlay for more controls / info)
music.paused = true
music.speed = 1.2
```
`returns`A control handle.
`since`v2000.0
# [burp](#burp)(options?: AudioPlayOpt): AudioPlay
Yep. Plays a burp sound.
`returns`A control handle.
`since`v2000.0
# [setVolume](#setVolume)(v: number): void
Set the global volume.
`param`v- The volume to set.
``` js
setVolume(0.5)
```
`since`v3001.1
# [getVolume](#getVolume)(): number
Get the global volume.
`returns`The current volume.
`since`v3001.1
# [volume](#volume)(v?: number): number
`deprecated`Use
``` js
// makes everything quieter
volume(0.5)
```
`returns`The new volume or the current volume.
`since`v2000.0
# [audioCtx](#audioCtx): AudioContext
Get the underlying browser AudioContext.
`since`v2000.0
# [rand](#rand)\<T\>(a?: T, b?: T): T
Get a random value between the given bound.
`param`a- The lower bound. If not upper bound, this is the upper bound and the lower bound is 0.
`param`b- The upper bound.
``` js
// a random number between 0 - 8
rand(8)
// a random point on screen
rand(vec2(width(), height()))
// a random color
rand(rgb(255, 255, 255))
// a random number between 50 - 100
rand(50, 100);
// a random point on screen with x between 20 - 100 and y between 20 - 100
rand(vec2(20), vec2(100));
// spawn something on the right side of the screen but with random y value within screen height
add([
pos(width(), rand(0, height())),
]);
```
`since`v2000.0
# [randi](#randi)(a?: number, b?: number): number
rand() but floored to integer. If not arguments, returns 0 or 1.
`param`a- The lower bound. If not upper bound, this is the upper bound.
`param`b- The upper bound.
``` js
randi(); // returns either 0 or 1
randi(10); // returns a random integer between 0 and 9
randi(10, 20); // returns a random integer between 10 and 19
```
`returns`A random integer between 0 and 1.
`since`v2000.0
# [randSeed](#randSeed)(seed?: number): number
Get / set the random number generator seed.
`param`seed- The seed to set.
``` js
randSeed(Date.now())
```
`returns`The new seed.
`since`v2000.0
# [choose](#choose)\<T\>(lst: T\[\]): T
Choose a random item from a list.
`param`lst- The list to choose from.
``` js
// decide the best fruit randomly
const bestFruit = choose(["apple", "banana", "pear", "watermelon"]);
```
`returns`A random item from the list.
`since`v3001.0
# [chooseMultiple](#chooseMultiple)\<T\>(lst: T\[\], count: number): T\[\]
Choose multiple random items from a list.
`param`lst- The list to choose from.
`param`count- The number of items to choose.
`returns`An array of random items from the list.
`since`v3001.0
# [shuffle](#shuffle)\<T\>(lst: T\[\]): T\[\]
Shuffle an array.
`param`lst- The list to shuffle.
`returns`A shuffled array.
`since`v3001.0
# [setLayers](#setLayers)(layers: string\[\], defaultLayer: string): void
Define the layer names. Should be called before any objects are made.
`param`layers- The layer names.
`param`defaultLayer- The default layer name.
``` js
layers(["bg", "obj", "ui"], "obj")
// no layer specified, will be added to "obj"
add([
sprite("bean"),
]);
// add to "bg" layer
add([
sprite("bg"),
layer("bg"),
]);
```
`since`v3001.1
# [getLayers](#getLayers)(): string\[\] \| null
Get the layer names.
`returns`The layer names or null if not set.
`since`v3001.1
`experimental`This feature is in experimental phase, it will be fully released in v3001.1
# [getDefaultLayer](#getDefaultLayer)(): string \| null
Get the default layer name.
`returns`The default layer name or null if not set.
`since`v3001.0.5
`experimental`This feature is in experimental phase, it will be fully released in v3001.1
# [addLevel](#addLevel)(map: string\[\], opt: AddLevelOpt, parent?: GameObj): GameObj\<PosComp \| LevelComp\>
Construct a level based on symbols.
`param`map- The map data.
`param`opt- The level options.
`param`parent- The parent object of the level. Defaults to root.
``` js
addLevel([
" $",
" $",
" $$ = $",
" % ==== = $",
" = ",
" ^^ = > = &",
"===========================",
], {
// define the size of tile block
tileWidth: 32,
tileHeight: 32,
// define what each symbol means, by a function returning a component list (what will be passed to add())
tiles: {
"=": () => [
sprite("floor"),
area(),
body({ isStatic: true }),
],
"$": () => [
sprite("coin"),
area(),
pos(0, -9),
],
"^": () => [
sprite("spike"),
area(),
"danger",
],
}
})
```
`returns`A game obj with the level.
`since`v2000.0
# [getData](#getData)\<T\>(key: string, def?: T): T \| null
Get data from local storage, if not present can set to a default value.
`param`key- The key to get data from.
`param`def- The default value to set if not found.
`returns`The data or null if not found.
`since`v2000.0
# [setData](#setData)(key: string, data: any): void
Set data from local storage.
`param`key- The key to set data to.
`param`data- The data to set.
`since`v2000.0
# [screenshot](#screenshot)(): string
Take a screenshot and get the data url of the image.
`returns`The dataURL of the image.
`since`v2000.0
# [download](#download)(filename: string, dataurl: string): void
Trigger a file download from a url.
`since`v3000.0
# [downloadText](#downloadText)(filename: string, text: string): void
Trigger a text file download.
`since`v3000.0
# [downloadJSON](#downloadJSON)(filename: string, data: any): void
Trigger a json download from a .
`since`v3000.0
# [downloadBlob](#downloadBlob)(filename: string, blob: Blob): void
Trigger a file download from a blob.
`since`v3000.0
# [record](#record)(frameRate?: number): Recording
Start recording the canvas into a video. If framerate is not specified, a new frame will be captured each time the canvas changes.
`returns`A control handle.
`since`v2000.1
# [Recording](#Recording):
Screen recording control handle.
# [pause](#Recording-pause)(): void
Pause the recording.
# [resume](#Recording-resume)(): void
Resume the recording.
# [stop](#Recording-stop)(): Promise\<Blob\>
Stop the recording and get the video data as mp4 Blob.
`since`v3000.0
# [download](#Recording-download)(filename?: string): void
Stop the recording and downloads the file as mp4. Trying to resume later will lead to error.
# [debug](#debug): Debug
The Debug interface for debugging stuff.
``` js
// pause the whole game
debug.paused = true
// enter inspect mode
debug.inspect = true
```
`returns`The debug interface.
`since`v2000.0
# [Debug](#Debug):
# [paused](#Debug-paused): boolean
Pause the whole game.
# [inspect](#Debug-inspect): boolean
Draw bounding boxes of all objects with \`area()\` component, hover to inspect their states.
# [timeScale](#Debug-timeScale): number
Global time scale.
# [showLog](#Debug-showLog): boolean
Show the debug log or not.
# [fps](#Debug-fps)(): number
Current frames per second.
# [numFrames](#Debug-numFrames)(): number
Total number of frames elapsed.
`since`v3000.0
# [drawCalls](#Debug-drawCalls)(): number
Number of draw calls made last frame.
# [stepFrame](#Debug-stepFrame)(): void
Step to the next frame. Useful with pausing.
# [clearLog](#Debug-clearLog)(): void
Clear the debug log.
# [log](#Debug-log)(msg: any): void
Log some text to on screen debug log.
# [error](#Debug-error)(msg: any): void
Log an error message to on screen debug log.
# [curRecording](#Debug-curRecording): Recording \| null
The recording handle if currently in recording mode.
`since`v2000.1
# [numObjects](#Debug-numObjects)(): number
Get total number of objects.
`since`v3001.0
# [plug](#plug)\<T\>(plugin: KAPLAYPlugin): KAPLAYCtx & T
Import a plugin.
`param`plugin- The plugin to import.
`returns`The updated context with the plugin.
`since`v2000.0
# [system](#system)(name: string, cb: ()=\>void, when: LCEvents\[\]): void
Runs a system at the specified events in the pipeline
`param`nameThe name of the system. Overwrites an existing system if the name has been used before.
`param`cbThe function to run.
`param`whenWhen to run the function.
`since`v4000.0
# [KAPLAYPlugin](#KAPLAYPlugin)\<T\>(k: KAPLAYCtx): T \| (args: any)=\>(k: KAPLAYCtx)=\>T
A plugin for KAPLAY.
``` js
// a plugin that adds a new function to KAPLAY
const myPlugin = (k) => ({
myFunc: () => {
k.debug.log("hello from my plugin")
}
})
// use the plugin
kaplay({
plugins: [ myPlugin ]
})
// now you can use the new function
myFunc()
```
# [ASCII_CHARS](#ASCII_CHARS): string
All chars in ASCII.
`since`v2000.0
# [LEFT](#LEFT): Vec2
Left directional vector vec2(-1, 0).
`since`v2000.0
# [RIGHT](#RIGHT): Vec2
Right directional vector vec2(1, 0).
`since`v2000.0
# [UP](#UP): Vec2
Up directional vector vec2(0, -1).
`since`v2000.0
# [DOWN](#DOWN): Vec2
Down directional vector vec2(0, 1).
`since`v2000.0
# [RED](#RED): Color
Red color.
`since`v2000.0
# [GREEN](#GREEN): Color
Green color.
`since`v2000.0
# [BLUE](#BLUE): Color
Blue color.
`since`v2000.0
# [YELLOW](#YELLOW): Color
Yellow color.
`since`v2000.0
# [MAGENTA](#MAGENTA): Color
Cyan color.
`since`v2000.0
# [CYAN](#CYAN): Color
Cyan color.
`since`v2000.0
# [WHITE](#WHITE): Color
White color.
`since`v2000.0
# [BLACK](#BLACK): Color
Black color.
`since`v2000.0
# [BlendMode](#BlendMode):
# [Normal](#BlendMode-Normal):
# [Add](#BlendMode-Add):
# [Multiply](#BlendMode-Multiply):
# [Screen](#BlendMode-Screen):
# [Overlay](#BlendMode-Overlay):
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment