Last active
April 28, 2025 04:47
-
-
Save canadaduane/c4ae93d0e2e2425c540bcb16a2bb3de1 to your computer and use it in GitHub Desktop.
Kaplay JS Docs - llms.txt
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# 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