1. Create and assign a script
Each project has a folder scripts. You can create, edit, rename and delete scripts from the Scripts tab in the bottom panel. Each object can have a script assigned from the Inspector. The same script can be assigned to several objects.
Use Refresh, on the right side of the Scripts tab, after creating, deleting or renaming a file directly in VS Code or File Explorer. When you use Rename inside the editor, GameCrom renames the file and automatically updates its assignments in objects, saved scenes and prefabs.
- Select an object in the scene or in the hierarchy.
- In the Inspector look for the component Script or open the tab Scripts.
- Click Create to create a new one or choose an existing one.in File.
- Click Edit to open it in Visual Studio Code.
- Press Play to run the script.
Scripts only run in Play. When you exit Play, the scene returns to the editing state.
Prefabs
A prefab is a reusable template of an object. It is used to save a scene object with its properties and its children, and then create new copies when you need them.
- Select the object you want to convert into a prefab.
- Open the tab Prefabs in the lower panel.
- Click Create From Selection.
- Write the name of the prefab andcommit.
- Use Instantiate to create a copy of the prefab in the scene.
- Use Delete to delete the prefab file from the project.
The prefab list displays a thumbnail of the root object. If the object has texture, the image is seen;if not, a shape is displayed with its color.
In the top bar of the editor, Snap preserves step scrolling. The check Snap to Grid snaps the top left corner of the object directly onto the grid.
Prefabs are saved inside the project's prefabs folder. When instantiating one, the engine creates new objects with new IDs so as not to modify the original prefab or step on objects in the scene.
| It is saved | Detail |
|---|---|
| Root object | Name, tag, position, scale, rotation, color, texture, collision, visibility and Static. |
| Children | The complete hierarchy hanging from the selected object. |
| Script | The reference to the script assigned to the object. |
| Animation | The assigned animation and its playback options. |
| Particles | The systemof particles assigned and its options. |
| Components | Components added to the object, such as Audio Source, Parallax or Character Controller. |
At the moment the prefab works as a reusable template. If you edit the instantiated object in the scene, those changes belong to that copy. They are not automatically applied to the saved prefab.
2D Lights
You can create an object Light from Add GameObject. In Play it is not drawn as a normal sprite: it illuminates the scene with a radial light on the canvas. Light objects do not display Sprite Renderer nor Collider 2D because they are not physical objects or game sprites. Light only affects the layers below it in the drawing order;Objects placed above are drawn later and are not illuminated by that light.
| Property | Use |
|---|---|
Enabled | Activates or deactivates the light. |
Light Color | Color of the light. |
Radius | Range of light in world pixels. |
Intensity | Light strength, from 0 a 1. |
Opacity | Global transparency of light, from 0 a 1. |
Softness | Edge smoothing, from 0 a 1. |
Effect | Light animation: None, Torch, Candle, Alarm, Fluorescent or Pulse. |
Effect Speed | Speed of theeffect. 0 leaves the light practically fixed. |
Effect Amount | Amount of intensity variation of the effect. |
Radius Amount | Amount of radius variation during the effect. |
Effect Color | Secondary color used by effects such as Alarm and Pulse. |
The effects are animated duringPlay. Torch and Candle simulate organic flicker, Alarm alternates towards a secondary color, Fluorescent creates small cuts of intensity and Pulse breathes gently. The Play button on the component allows you to preview the effect in the editor without launching the game.
Crop sprites
The trimmer is used to separate a large texture that contains many mixed sprites, such as a sprite sheet. Slices are saved as new PNG textures within the project.
- Open the tab Slice Sprite from the bottom panel.
- Choose the source texture.
- Set Cell W and Cell H with the size of each sprite.
- Adjusts Offset X/Y if the sheet has an outside margin.
- Adjusts Spacing X/Y if there is separation between sprites.
- Use Columns and Rows to limit the area, or leave
0to calculate it automatically. - Click Save Slices to save each slice as a new texture.
The original texture is not modified. If Empty is disabled, fully transparent clippings are skipped.
2. Execution cycle
A script can export loop functions. They all receive the object assigned to the script. If you do not declare a function, it is simply not called.
| Function | When called | Parameters |
|---|---|---|
start(object) | Once when entering Play. | object: object that owns the script. |
fixedUpdate(object, fixedDeltaTime) | At a fixed pace, 60 times per second if performance allows. | Movementstable, physics and pushes. |
update(object, deltaTime) | Every frame during Play. | Input, normal logic, visual movement and UI. |
lateUpdate(object, deltaTime) | At the end of the frame, after update and collisions. | Camera, UI dependent on final positions and final settings. |
export function start(object) {
debug("Empieza: " + object.name);
}
export function fixedUpdate(object, fixedDeltaTime) {
// Fixed step: ideal for physics.
}
export function update(object, deltaTime) {
object.x += 100 * deltaTime;
}
export function lateUpdate(object, deltaTime) {
// Runs after every update in the frame has finished.
}
3. The object received
The parameter object is the actual scene object during Play. You can read its data and change properties such as position, rotation, scale, color, opacity or active state.
export function start(object) {
debug({
id: object.id,
name: object.name,
tag: object.tag,
x: object.x,
y: object.y
});
}
If you want to see everything that an object has, you can send it completely to the console:
export function start(object) {
debug(object);
}
4. Variable handling
In scripts you can create normal JavaScript variables. Depending on where you save them, they last only within a function, they belong to an object, the current scene or the entire project game.
Common types
| Type | Example | Use |
|---|---|---|
| number | let vida = 100; | Numbers, speed, time,punctuation. |
| string | let estado = "idle"; | Text, names, states. |
| boolean | let vivo = true; | True/false values. |
| object | let datos = { vida: 100 }; | Group data. |
| array | let inventario = []; | Lists of values. |
Local variables
They live only within the function where they are created. They are lost when that call ends.
export function update(object, deltaTime) {
const speed = 120;
object.translate(speed * deltaTime, 0);
}
Script variables
If you create them outside of start and update, they are preserved while that script is loaded in Play. If the same script is assigned to multiple objects, that variable is shared between them.
let totalUpdates = 0;
export function update(object, deltaTime) {
totalUpdates += 1;
debug(totalUpdates);
}
Local variables of an object
To save data for a specific object, create your own properties within object. Each object will have its own values.
export function start(object) {
object.vida = 100;
object.velocidad = 180;
}
export function update(object, deltaTime) {
object.translate(object.velocidad * deltaTime, 0);
}
Global scene variables
Use Scene.vars for data shared by all scripts in the current scene. It resets when you enter Play and also when you load another scene with Scene.load.
export function start(object) {
Scene.vars.enemigos = Scene.vars.enemigos || 0;
Scene.vars.enemigos += 1;
}
Global project variables
Use Project.vars for data that must survive changing scenes during the same game, such as score, lives or progress.
export function start(object) {
Project.vars.score = Project.vars.score || 0;
}
export function update(object, deltaTime) {
Project.vars.score += 1;
debug("Score: " + Project.vars.score);
}
Data saved with PlayerPrefs
Use PlayerPrefs for saving data that must continue to exist even if you close the game, such as record, options, volume, coins or the last levelunlocked. The data is saved separately by project.
Project.vars it is deleted when you exit Play. PlayerPrefs it stays saved in the browser/Tauri until you delete the key or call PlayerPrefs.deleteAll().
| Function | Use | Example |
|---|---|---|
PlayerPrefs.setString(key, value) | Save text. | PlayerPrefs.setString("playerName", "Alex") |
PlayerPrefs.getString(key, defaultValue) | Read text. | PlayerPrefs.getString("playerName", "Player") |
PlayerPrefs.setNumber(key, value) | Save a number. | PlayerPrefs.setNumber("volume", 0.8) |
PlayerPrefs.getNumber(key, defaultValue) | Read a number. | PlayerPrefs.getNumber("volume", 1) |
PlayerPrefs.setInt(key, value) | Save an integer. | PlayerPrefs.setInt("coins", 25) |
PlayerPrefs.getInt(key, defaultValue) | Read an integer. | PlayerPrefs.getInt("coins", 0) |
PlayerPrefs.setBool(key, value) | Save true/false. | PlayerPrefs.setBool("music", true) |
PlayerPrefs.getBool(key, defaultValue) | Readtrue/false. | PlayerPrefs.getBool("music", true) |
PlayerPrefs.setJSON(key, value) | Saves objects or arrays. | PlayerPrefs.setJSON("inventory", ["key"]) |
PlayerPrefs.getJSON(key, defaultValue) | Reads objects or arrays. | PlayerPrefs.getJSON("inventory", []) |
PlayerPrefs.hasKey(key) | Checks if a key exists. | PlayerPrefs.hasKey("record") |
PlayerPrefs.deleteKey(key) | Deletes a key. | PlayerPrefs.deleteKey("record") |
PlayerPrefs.deleteAll() | Deletes all saved data from the current project. | PlayerPrefs.deleteAll() |
PlayerPrefs.keys() | Returns saved keys from the current project. | PlayerPrefs.keys() |
PlayerPrefs.save() | Exists forcompatibility. In this engine the saving is immediate. | PlayerPrefs.save() |
Example: save record
export function start(object) {
Project.vars.score = 0;
Project.vars.record = PlayerPrefs.getInt("record", 0);
}
export function update(object, deltaTime) {
Project.vars.score += Math.round(10 * deltaTime);
if (Project.vars.score > Project.vars.record) {
Project.vars.record = Project.vars.score;
PlayerPrefs.setInt("record", Project.vars.record);
}
debug({
score: Project.vars.score,
record: Project.vars.record
});
}
Example: save options
export function start(object) {
const volume = PlayerPrefs.getNumber("volume", 1);
const fullscreen = PlayerPrefs.getBool("fullscreen", false);
debug({ volume, fullscreen });
}
export function update(object) {
if (Input.getKeyDown("M")) {
PlayerPrefs.setNumber("volume", 0);
}
if (Input.getKeyDown("F")) {
const current = PlayerPrefs.getBool("fullscreen", false);
PlayerPrefs.setBool("fullscreen", !current);
}
}
Available Mathematics
Scripts can directly use the standard Math JavaScript object. The engine also includes the APIs Random, Mathf and Vector2.
| Current operation | Example |
|---|---|
| Minimum, maximum and absolute value | Math.min(a, b), Math.max(a, b), Math.abs(x) |
| Rounding | Math.floor(x), Math.ceil(x), Math.round(x) |
| Powers and root | Math.pow(x, 2), Math.sqrt(x) |
| 2D distance | Math.hypot(dx, dy) |
| Angles andtrigonometry | Math.atan2(y, x), Math.sin(x), Math.cos(x) |
| Sign | Math.sign(x) |
| Random between 0 and 1 | Math.random() |
const clamp = (value, min, max) => Math.min(Math.max(value, min), max);
const lerp = (a, b, t) => a + (b - a) * t;
const randomRange = (min, max) => min + Math.random() * (max - min);
API Random
| Function | Use | Example |
|---|---|---|
Random.value() | Decimal between 0 included and 1 excluded. | Random.value() |
Random.range(min, max) | Decimal between the two values. | Random.range(10, 20) |
Random.int(min, max) | Integer between min and max, including both. | Random.int(1, 6) |
Random.choose(array) | Random elemento null if the array is empty. | Random.choose(["red", "blue"]) |
Random.chance(probability) | Returns true with a probability between 0 and 1. | Random.chance(0.25) |
Random.sign() | Randomly returns -1 or 1. | Random.sign() |
Random.shuffle(array) | Returns a shuffled copy without modifying the original array. | Random.shuffle(cards) |
export function start(object) {
object.x = Random.range(100, 700);
object.vida = Random.int(2, 5);
object.color = Random.choose(["#ff0000", "#00ff00", "#0088ff"]);
if (Random.chance(0.2)) {
debug("Enemigo especial");
}
}
Mathf works with numbers and angles. Vector2 returns new objects
{ x, y };does not modify the received vectors.
Mathf API
Mathf.clamp(value, min, max) | Limits a value. |
Mathf.clamp01(value) | Limits between 0 and 1. |
Mathf.lerp(a, b, t) | Interpolates using t between 0 and 1. |
Mathf.inverseLerp(a, b, value) | Calculates the ratio of value between a and b. |
Mathf.moveTowards(current, target, step) | Narrows a number withoutexceed it. |
Mathf.repeat(value, length) | Repeats a value within an interval. |
Mathf.pingPong(value, length) | Oscillates between 0 and length. |
Mathf.degToRad(degrees), radToDeg(radians) | Converts angles. |
Mathf.deltaAngle(a, b) | Smallest signed angular difference. |
Mathf.lerpAngle(a, b, t) | Interpolates along the shortest angular path. |
Vector2 API
Vector2.create(x, y) | Creates a vector. |
Vector2.add(a, b), subtract(a, b) | Add or subtract. |
Vector2.multiply(v, scalar), divide(v, scalar) | Scale a vector. |
Vector2.length(v) | Length. |
Vector2.distance(a, b) | Distance betweenpoints. |
Vector2.normalize(v) | Length vector 1. |
Vector2.dot(a, b) | Scalar product. |
Vector2.angle(a, b) | Angle in degrees. |
Vector2.lerp(a, b, t) | Interpolates two vectors. |
Vector2.moveTowards(a, b, distance) | Zooms one point closer to another. |
const direction = Vector2.normalize({
x: enemy.x - object.x,
y: enemy.y - object.y
});
object.translate(direction.x * 120 * deltaTime, direction.y * 120 * deltaTime);
5. Object movement
During Play objects have useful methods to move and orient themselves. These methods return the object itself, so you can chain them if that's comfortable for you.
| Method | Use | Example |
|---|---|---|
object.translate(x, y) | Moves the object in its local coordinates. | player.translate(10, 0) |
object.lookAt(target, eje) | Rotates the object facing another object or point using the indicated axis. | player.lookAt(enemy, "x") |
object.moveTowards(target, speed, deltaTime) | Moves the object toward a target. | player.moveTowards(target, 150, deltaTime) |
export function update(object, deltaTime) {
object.translate(100 * deltaTime, 0);
}
export function update(object, deltaTime) {
const enemy = FindByTag("Enemy");
if (!enemy) return;
object.lookAt(enemy, "x");
object.moveTowards(enemy, 120, deltaTime);
}
lookAt and moveTowards accept an object or point as { x: 100, y: 50 }. In lookAt, the default axis is "x". You can also use "-x",
"y" or "-y". For example, if your sprite is facing up, use
object.lookAt(enemy, "-y").
6. Object Hierarchy
During Play you can check and change parent/child relationships. When changing parents, the engine tries to maintain the visual position of the object in the world.
| Method | Use | Example |
|---|---|---|
object.addChild(child) | Makes another object a child of this object. | player.addChild(gun) |
object.removeChild(child) | Removes a direct child and leaves it without a parent. | player.removeChild(gun) |
object.parent() | Returns the parent of the object or null. | const p = gun.parent() |
object.root() | Returns the root object of the hierarchy. | const root = gun.root() |
object.children() | Returns an array with the direct children. | const hijos = player.children() |
object.destroyAllChildren(tiempo) | Destroys all direct children, immediately or after a while. | player.destroyAllChildren(1) |
export function start(object) {
const gun = FindByName("Gun");
if (!gun) return;
object.addChild(gun);
}
export function update(object, deltaTime) {
for (const child of object.children()) {
debug(child.name);
}
}
export function start(object) {
object.destroyAllChildren(2);
}
addChild does not allow creating hierarchy loops. For example, you cannot make an object a child of one of its own descendants.
7. Object properties
These are the main properties that you can read and modify from a script.
| Property | Type | Use | Example |
|---|---|---|---|
id | string/number | Unique identifier of the object. | debug(object.id) |
name | string | Name visible in the editor. | object.name = "Player" |
tag | string | Label to search for objects by category. | object.tag = "Enemy" |
parentId | string/null | Parent IDin the hierarchy. | debug(object.parentId) |
type | string | Visual type: square or circle. | debug(object.type) |
active | boolean | Turns the object on or off. | object.active = false |
isStatic | boolean | Marks the object as static for future optimizations. | object.isStatic = true |
visibleInPlay | boolean | Controls whether it is visible during Play. | object.visibleInPlay = true |
x, y | number | Local position of the object. | object.x += 10 |
w, h | number | Base size of the object. | object.w = 80 |
rotation | number | Rotation in degrees. | object.rotation += 90 * deltaTime |
scaleX, scaleY | number | Horizontal scale andvertical. | object.scaleX = 2 |
z | number | Visual order layer. | object.z = 5 |
color | string | Color in hexadecimal format. | object.color = "#ff0000" |
opacity | number | Opacity between 0 and 1. | object.opacity = 0.5 |
texture | string | Name of the assigned texture. | object.texture = "player.png" |
textureTilingX, textureTilingY | number | Repetition of the texture. | object.textureTilingX = 2 |
textureOffsetX, textureOffsetY | number | Offset of the texture. | object.textureOffsetX += deltaTime |
textureFlipX, textureFlipY | boolean | Flip thetexture. | object.textureFlipX = true |
pixelPerfect | boolean | Render of texture with a pixel art look. | object.pixelPerfect = true |
animation | string | Assigned animation ID. | debug(object.animation) |
animationPlaying | boolean | Activates or pauses the animation. | object.animationPlaying = true |
animationRunInPlay | boolean | Indicates if the animation starts in Play. | object.animationRunInPlay = true |
particleSystem | string | ID of the assigned particle system. | debug(object.particleSystem) |
particlesPlaying | boolean | Activates or pauses particles. | object.particlesPlaying = true |
particlesRunInPlay | boolean | Indicates if the particles start in Play. | object.particlesRunInPlay = true |
particlesDetached | boolean | Allows the particle trailis separated from the object. | object.particlesDetached = true |
collisionEnabled | boolean | Marks the collider as active. | object.collisionEnabled = true |
isTrigger | boolean | Marks the collider as trigger. | object.isTrigger = true |
collider | object | Collider data: shape, offsetX/Y, width/height and radius. | object.collider.shape = "capsule" |
script | string | Name of the assigned script. | debug(object.script) |
If an object has isStatic = true, it is recommended not to move it, rotate it, scale it or change its hierarchy during Play. This flag is used so that the engine can optimize rendering, collisions, navigation and other systems in the future.
Activation cycle: if active es false, the components, collisions and object script are not executed. It also applies when one of its parents is inactive. If activated after starting the scene, start(object) is then executed only once and before the first update(object, deltaTime). Automatic components, such as Audio Source / Play On Start, start when activated.
8.debug API
Messages appear in the tab Console from the bottom panel of the editor.
| Function | Use | Example |
|---|---|---|
debug(value) | Displays any value. | debug("Hola") |
Debug.log(value) | Normal message. | Debug.log(object.name) |
Debug.warn(value) | Warning message. | Debug.warn("Vida baja") |
Debug.error(value) | Error message. | Debug.error("No hay objetivo") |
Debug.clear() | Clears the console. | Debug.clear() |
export function start(object) {
Debug.log({ nombre: object.name, posicion: { x: object.x, y: object.y } });
}
9. You wait with Wait
Wait allows you to pause an asynchronous function, similar to a coroutine. To use it, the function must be declared with async.
| Function | Use | Example |
|---|---|---|
await Wait.seconds(segundos) | Wait a number of seconds. | await Wait.seconds(0.2) |
await Wait.frames(frames) | Wait a number of frames. | await Wait.frames(1) |
export async function start(object) {
object.color = "#ff0000";
await Wait.seconds(0.2);
object.color = "#ffffff";
}
export async function start(object) {
debug("3");
await Wait.seconds(1);
debug("2");
await Wait.seconds(1);
debug("1");
}
Property animations with Tween
Tween smoothly change numeric properties during Play. It is used to move, rotate, scale or fade objects without programming the interpolation within update. Duration and delays are expressed in seconds.
| Function | Use | Example |
|---|---|---|
Tween.to(target, values, duration, options) | Animates from the current values to those indicated. | Tween.to(object, { x: 400 }, 1) |
Tween.from(target, values, duration, options) | Places the initial values and animates up to those the object had. | Tween.from(object, { opacity: 0 }, 0.5) |
Tween.cancel(target) | Cancels all tweens of an object. | Tween.cancel(object) |
Tween.cancel(target, property) | Cancels only the tweens of a property. | Tween.cancel(object, "x") |
Tween.cancelAll() | Cancels all tweensactive. | Tween.cancelAll() |
Tween.isTweening(target, property) | Checks if there is an active tween. | Tween.isTweening(object, "x") |
Tween.pauseAll() | Pauses all tweens. | Tween.pauseAll() |
Tween.resumeAll() | Resume all tweens. | Tween.resumeAll() |
export function start(object) {
Tween.to(object, {
x: object.x + 240,
rotation: 360,
scaleX: 2,
scaleY: 2
}, 1.5, {
ease: "cubicInOut",
yoyo: true,
repeat: 1
});
}
Available options: ease, delay, repeat,
repeatDelay, yoyo, paused, overwrite,
onStart, onUpdate, onRepeat, onComplete and
onCancel. By default, a new tween cancels previous tweens that modify the same properties of the same object. Use overwrite: false to allow them.
Curves included: linear, easeIn, easeOut,
easeInOut, quadIn, quadOut, quadInOut,
cubicIn, cubicOut, cubicInOut, backIn,
backOut, sineIn, sineOut and sineInOut.
export async function start(object) {
const movement = Tween.to(object, { y: object.y - 100 }, 0.8, {
ease: "backOut"
});
const result = await movement;
debug(result.status); // "completed" or "cancelled"
}
The return value allows pause(), resume(), cancel() and
complete(). You can also wait directly with await. Tweens are automatically canceled when you exit Play, destroy your object or change scenes.
Tween only interpolates numerical properties. If a physical component or a script modifies the same property at the same time, both systems will compete for the value.
10. Find objects
| Function | Returns | Example |
|---|---|---|
FindByName(name) | The first object with that name or null. | FindByName("Player") |
FindByTag(tag) | The first object with that tag or null. | FindByTag("Enemy") |
FindAllByName(name) | Array with all active objects that have that name. | FindAllByName("Coin") |
FindAllByTag(tag) | Array with all active objects that have that tag. | FindAllByTag("Enemy") |
FindAllByComponent(type) | Array of active objects with that component. | FindAllByComponent("PhysicsBody") |
FindAllInArea(x, y, w, h) | Active objects whose limits overlap with the indicated rectangle. | FindAllInArea(0, 0, 800, 600) |
export function start(object) {
const player = FindByName("Player");
if (player) {
debug("Player found at X: " + player.x);
}
}
export function update(object, deltaTime) {
const target = FindByTag("Target");
if (!target) return;
object.x += Math.sign(target.x - object.x) * 80 * deltaTime;
}
Temporary groups
Groups allows you to gather objects during Play without changing their name, tag or hierarchy. Groups are automatically emptied when changing scenes.
Groups.create(name, objects) | Creates a group and adds an optional list. |
Groups.add(name, object) | Adds an object. |
Groups.remove(name, object) | Removes an object. |
Groups.get(name) | Returns valid members. |
Groups.has(name, object) | Checks if it belongs to the group. |
Groups.forEach(name, callback) | Executes a function for eachmember. |
Groups.setActive(name, active) | Activates or disables all its members. |
Groups.clear(name) | Empties the group. |
Groups.delete(name) | Deletes the group. |
Groups.names() | Returns all group names. |
export function start(object) {
const enemies = FindAllByTag("Enemy");
Groups.create("wave", enemies);
}
export function update(object) {
if (Input.getKeyDown("K")) {
Groups.setActive("wave", false);
}
}
11. Destroy objects
| Function | Use | Example |
|---|---|---|
Destroy(object) | Destroys an object instantly. | Destroy(enemy) |
Destroy(object, tiempo) | Destroys an object after a few seconds. | Destroy(object, 2) |
If you destroy an object that has children, its children are also destroyed. Destroy should only be used during Play.
export function start(object) {
Destroy(object, 3);
}
export function update(object, deltaTime) {
const enemy = FindByTag("Enemy");
if (enemy && enemy.x < -500) {
Destroy(enemy);
}
}
Instantiate prefabs from code
Prefab allows you to create copies of prefabs during Play. The prefab must exist in the
Prefabs tab of the project.
| Function | Use | Example |
|---|---|---|
await Prefab.instantiate(nombre) | Creates a copy of the prefab. | await Prefab.instantiate("Enemy") |
await Prefab.instantiate(nombre, opciones) | Creates a copy with position, name or parent. | await Prefab.instantiate("Bullet", { x: 100, y: 40 }) |
await Prefab.create(nombre, opciones) | Alias of instantiate. | await Prefab.create("Coin") |
await Prefab.spawn(nombre, opciones) | Alias of instantiate. | await Prefab.spawn("Explosion") |
If the prefab has a single root object, the function returns that object. If the prefab has multiple root objects, it returns a list. The prefab scripts are loaded and start running in Play.
| Option | Type | Description |
|---|---|---|
x | number | X position of the root object. |
y | number | Y position of the root object. |
offsetX | number | Displacement X if you do not indicate x e y. |
offsetY | number | Displacement Y if you do not indicate x e y. |
name | string | Base name for the created copy. |
parent | object | Object that will be the parent of the instantiated prefab. |
rotation | number | Initial rotation of the root object. |
scaleX | number | Initial X scale of the root object. |
scaleY | number | Initial Y scale of the root object. |
export async function start(object) {
const enemy = await Prefab.instantiate("Enemy", {
x: object.x + 120,
y: object.y,
name: "EnemySpawned"
});
debug(enemy.name);
}
export async function start(object) {
await Wait.seconds(1);
const bullet = await Prefab.instantiate("Bullet", {
x: object.x + 32,
y: object.y,
parent: object
});
bullet.translate(10, 0);
}
Prefab.instantiate it is only used during Play and requires Tauri to read the prefab saved in the project.
Prefab Pool
Pool preloads inactive copies and reuses them. It is recommended for bullets, enemies, coins and explosions that appear many times.
await Pool.create(name, prefab, size) | Creates the pool and preloads the indicated amount. |
await Pool.spawn(name, { x, y }) | Obtains and activates a copy. If none remain, expands the default pool. |
Pool.release(object) | Deactivates and returns the object to its pool. |
Pool.releaseAll(name) | Returns all active members. |
Pool.get(name) | Returns size, active, and available. |
Pool.has(name) | Checks if it exists. |
Pool.clear(name) | Deregisters the pool. |
export async function start(object) {
await Pool.create("bullets", "Bullet", 32);
}
export async function update(object) {
if (Input.getKeyDown("Space")) {
const bullet = await Pool.spawn("bullets", {
x: object.x + 24,
y: object.y
});
Physics.setVelocity(bullet, 500, 0);
}
}
export function recycleBullet(bullet) {
Pool.release(bullet);
}
Pools are temporary and are cleared when changing pools.scene. Use Pool.release instead of
Destroy to return a scratchable instance.
12. Load scenes
Scene.load loads a project scene by name. During Play it keeps the game running, switches to the new scene and starts the scripts for the objects in that scene.
| Function | Use | Example |
|---|---|---|
await Scene.load(nombre) | Loads a scene by name. | await Scene.load("Level1") |
await Scene.load(nombre, opciones) | Allows a fade transition. | await Scene.load("Boss", { transition: "fade", duration: 0.4 }) |
await Scene.reload() | Reloads the current scene. | await Scene.reload() |
await Scene.preload(nombre) | Reads and prepares a scene to speed up the next load. | await Scene.preload("Boss") |
Scene.current | Scene namecurrent. | debug(Scene.current) |
Scene.getCurrent() | Returns the name of the current scene. | Scene.getCurrent() |
Scene.onLoad(callback) | Registers a function when finishing a load and returns a function to cancel it. | Scene.onLoad(name => debug(name)) |
Scene.onUnload(callback) | Registers a function before leaving the scene. | Scene.onUnload(name => debug(name)) |
export async function start(object) {
await Wait.seconds(2);
await Scene.load("Level1");
}
Fade Transition
You can pass options as a second parameter. With transition: "fade", the screen fades to black, the engine changes the scene when it is already covered and then gradually shows the new scene. Use duration to indicate the seconds of each phase of the fade.
export async function update(object) {
if (object.x > 800) {
await Scene.load("Level2", {
transition: "fade",
duration: 0.4
});
}
}
Use await to wait until the charge and fade have finished. If you omit
duration, 0.3 seconds are used. Without options, the change is immediate:
await Scene.load("Level2").
export async function update(object, deltaTime) {
if (object.x > 800) {
await Scene.load("NextLevel");
}
}
The name must match an existing scene in the project. Do not write the file extension.
Scene.vars, groups and pools are reset when changing scenes.
13. Animations API
Sprite and Property Animations
The editor separates the two systems so that they do not mix. The tab Animations Contains exclusively Sprite clips with textures and FPS. The Timeline tab contains exclusively Property clips organized by tracks and keyframes.
To create a property clip open Timeline and press New Property. Then assign that clip from the field Animation Timeline of the Object Inspector. Timeline automatically uses that object as a Target Object;It is not selected within the editor. The name and ID always indicate which object is being edited. Choose a track and place the cursor on the desired time. Press Add/Update Key to capture the current value of the object. Modify the object, move the time and add another key;the engine will interpolate the values between both.
To assign it to an object use the field Animation Timeline of the Timeline Animator section of the Inspector. The field Animation is reserved exclusively for Sprite animations. When you open the Timeline tab with that object selected, the editor loads its assigned clip and allows you to view it with Play.
| Track | Animated property |
|---|---|
Position X / Y | Local position x e y. |
Rotation | Rotation of the object in degrees. |
Scale X / Y | Scale independent of each axis. |
Opacity | Interpolated opacity of the object. |
Color | Interpolated color between two keys. |
- Duration defines the total duration of the clip in seconds.
- Target Object automatically shows the object that has the clip assigned in its field Animation Timeline.
- Local Position checked applies the offset of the clip from the initial position of each object;unchecked uses the absolute X/Y values of the clip.
- The Timeline panel docks at the bottom of the editor to keep the scene visible while you transform the object.
- The red line is the playhead: it indicates the current instant and advances along the tracks during preview.
- Play plays from the current time, Pause and Stop preserve the position, and Rewind returns to the start.
- The playback controls preserve the zoom and the visible area of the Timeline.
- Activate Follow Playhead so that the horizontal view automatically follows the red line during playback.
- When you move the cursor, the position, scale, rotation, opacity and color of the target object are updated live.
- Closing Timeline, changing tabs or entering Play automatically restores the stateoriginal.
- Loop repeat the clip continuously.
- Pingpong plays back and forth when Loop is active.
- Tap a diamond to select its timing.
- Drag a diamond horizontally with the mouse to change the timing of that keyframe and preview the result.
- Select a diamond and press Duplicate Key to copy it 0.10 seconds later.
- Use Zoom - and Zoom + to compress or horizontally expand the Timeline between 50% and 400%.
- Right click on a diamond to delete that key.
Property clips are assigned and played from the Inspector the samethan Sprite clips. They also work with the same API Animations and are included in the exported game.
Control from scripts
Animations allows you to assign and control animations from a script. You can use the ID or the name of the animation.
| Function | Use | Example |
|---|---|---|
Animations.find(nombreOId) | Search for an animation. | Animations.find("Run") |
Animations.assign(object, nombreOId) | Assign an animation to the object. | Animations.assign(object, "Run") |
Animations.play(object) | Play the assigned animation. | Animations.play(object) |
Animations.play(object, nombreOId) | Assign and play an animation. | Animations.play(object, "Jump") |
Animations.stop(object) | Stop the animation. | Animations.stop(object) |
Animations.enable(object) | Enable it to start automatically onPlay. | Animations.enable(object) |
Animations.disable(object) | Deactivates automatic start and stops it. | Animations.disable(object) |
Animations.activate(object) | Alias of enable. | Animations.activate(object) |
Animations.deactivate(object) | Alias of disable. | Animations.deactivate(object) |
export function start(object) {
Animations.assign(object, "Idle");
Animations.play(object);
}
export async function start(object) {
Animations.play(object, "Hit");
await Wait.seconds(0.5);
Animations.play(object, "Idle");
}
14. Particle API
Particles allows you to assign and control particle systems from a script. You can use the system ID or name.
| Function | Use | Example |
|---|---|---|
Particles.find(nombreOId) | Searches for a particle system. | Particles.find("Explosion") |
Particles.assign(object, nombreOId) | Assigns particles to the object. | Particles.assign(object, "Smoke") |
Particles.play(object) | Plays the assigned particles. | Particles.play(object) |
Particles.play(object, nombreOId) | Assigns and plays particles. | Particles.play(object, "Explosion") |
Particles.stop(object) | Stops the particles. | Particles.stop(object) |
Particles.enable(object) | Activates automatic start in Play. | Particles.enable(object) |
Particles.disable(object) | Disables automatic start andstops. | Particles.disable(object) |
Particles.activate(object) | Alias of enable. | Particles.activate(object) |
Particles.deactivate(object) | Alias of disable. | Particles.deactivate(object) |
export function start(object) {
Particles.assign(object, "Smoke");
Particles.play(object);
}
export async function start(object) {
Particles.play(object, "Explosion");
await Wait.seconds(1);
Destroy(object);
}
15. Complete examples
Move an object
export function update(object, deltaTime) {
object.x += 120 * deltaTime;
}
Rotate constantly
export function update(object, deltaTime) {
object.rotation += 180 * deltaTime;
}
Blink changing opacity
let time = 0;
export function update(object, deltaTime) {
time += deltaTime;
object.opacity = 0.5 + Math.sin(time * 8) * 0.5;
}
Follow the player
export function update(object, deltaTime) {
const player = FindByName("Player");
if (!player) return;
const speed = 90;
object.x += Math.sign(player.x - object.x) * speed * deltaTime;
object.y += Math.sign(player.y - object.y) * speed * deltaTime;
}
Eliminate enemies by tag
export function start(object) {
const enemy = FindByTag("Enemy");
if (enemy) {
Destroy(enemy, 1.5);
}
}
Change scene after a wait
export async function start(object) {
debug("Cargando siguiente nivel...");
await Wait.seconds(1);
await Scene.load("Level2");
}
Follow Camera
The Play camera can automatically follow an object by tag. In the left panel
Scene > Camera, activate Follow Player and choose the tag of the object you want to follow, for example Player.
| Property | Use |
|---|---|
Follow Player | Activate camera tracking during Play. |
Tag | Tag of the object that the camera will follow. The list comes from the scene tags. |
Dead Zone X/Y | Dead zone before moving the camera. It is used so that the character can move a little without dragging the camera. |
Smooth | Tracking response between 0 and 1. 0 does not move the camera, 1 follows immediately. |
Lock X/Y | Locks the tracking on one axis. |
Offset X/Y | Moves the tracking point with respect to the center of the object. |
Bounds | Limits the camera within aworld rectangle with min/max X/Y. |
Effect | Visual filter applied only during Play: None, Scanlines, CRT, Noir, Sepia or Dream. |
FX | Intensity of the effect between 0 and 1. |
Scanline Size | Separation of the lines when you use Scanlines or CRT. |
Vignette | Gently darkens the edges of the camera. |
Noise | Adds light old screen type noise. It is also activated with CRT. |
Backgrounds with component Parallax use this camera when they do not have a manual target. That's why the parallax moves naturally when activating Follow Player.
Camera API
Camera allows you to move the game camera from scripts during Play. If
Follow Player is active, tracking can move it again in the next frame;use { disableFollow: true } when you want to place it manually.
| Function | Use | Example |
|---|---|---|
Camera.moveTo(x, y) | Moves the top left corner of the camera to a position in the world. | Camera.moveTo(400, 120) |
Camera.setPosition(x, y) | Alias of moveTo. | Camera.setPosition(0, 0) |
Camera.centerOn(x, y) | Centers the camera on a point in the world. | Camera.centerOn(player.x, player.y) |
Camera.getPosition() | Returns { x, y } with the current position of the camera. | const pos = Camera.getPosition() |
Camera.getRect(margen) | Returns the visible camera rectangle with optional margin. | const rect = Camera.getRect(32) |
Camera.isObjectOutside(object, margen) | Indicates whether the entire object is out of camera. The optional margin enlarges the rectangle. | Camera.isObjectOutside(enemy, 64) |
object.isOutsideCamera(margen) | Direct method of the object to know if it left the camera. | object.isOutsideCamera(64) |
await Camera.fadeOut(tiempo, color) | Darks the camera until it is covered with the indicated color. The default color is black. | await Camera.fadeOut(1) |
await Camera.fadeIn(tiempo, color) | Remove the fade color and show the scene again. | await Camera.fadeIn(0.8, "#000") |
await Camera.fade(tipo, tiempo, color) | Generic function. tipo can be "in" or "out". | await Camera.fade("out", 1, "black") |
Camera.cutToBlack(color) | Instant color cut, default black. | Camera.cutToBlack() |
Camera.clearFade() | Remove any active fade instantly. | Camera.clearFade() |
export function start(object) {
Camera.moveTo(0, 0, { disableFollow: true });
}
export function update(object) {
const player = FindByTag("Player");
if (player && Input.getKeyDown("C")) {
Camera.centerOn(player.x, player.y, { disableFollow: true });
}
}
Detect camera output
export function update(object) {
object.translate(300 * deltaTime, 0);
if (object.isOutsideCamera(64)) {
Destroy(object);
}
}
Fade for scene change
export async function start(object) {
await Camera.fadeOut(1, "#000000");
await Scene.load("Level2");
await Camera.fadeIn(1, "#000000");
}
16. UI Canvas
The user UI is drawn inside the game canvas. In the editor it is placed inside the camera rectangle and in Play it appears as Screen Space Overlay, above the scene and without moving with the world camera.
From Add GameObject you can create: UI Canvas, UI Panel,
UI Text, UI Image, UI Button, UI Input,
UI Checkbox, UI Select, UI Progress Bar and UI Slider.
| Control | Use |
|---|---|
UI Panel | Background or visual container. UI children are placed relative to the panel in Play. |
UI Text | Text for punctuation, messages, names or labels. |
UI Image | Image from Textures or color block if no image is assigned. Does not use text or font. |
UI Button | Interactive button. It has normal color, color Hover on hover, and color Pressed while pressed. From script you can hear click with UI.onClick. |
UI Input | Editable field during Play. On mobile it automatically opens the system virtual keyboard. |
UI Checkbox | Interactive true/false value. Has color Hover on hover. |
UI Select | HTML select style drop-down list. In Play it opens its options, highlights the option under the pointer, allows you to choose one and fires UI.onChange when changing. If there are too many options, it shows a scroll bar. |
UI Progress Bar | Non-interactive bar for life, energy, charge or experience. Uses Value, Min, Max and color Fill. |
UI Slider | Interactive numerical value control. In Play you can drag and shoot UI.onChange. |
The UI uses Rect Transform: Anchor, Pivot, X/Y offset, size and order Z. To create windows, make a UI Panel and put texts, buttons, inputs, checks, selects, sliders or bars as children in the hierarchy.
Anchor works as a preset: by choosing Center, Top Right,
Bottom, etc.the control is placed in that zone, sets its Pivot and leaves the X/Y offset at zero. Then you can move it with X/Y as a margin from that anchor. In Play, UI children are drawn on top of their parent even if they have a smaller Z. All controls have Opacity. The field Font allows you to choose Arial
or any font imported into Fonts. Controls with text have Align and V Align to align the text left, center, right, top, middle or bottom.
UI Text can activate Multiline to work as a block of text: accept line breaks with \n, Word Wrap, Line Height,
Max Lines and Overflow in mode Clip,
Visible or Ellipsis. UI objects can also carry a Script just like any other object: they receive start(object) and update(object, deltaTime) only during Play. In UI Select, options are edited in the Inspector as a list: you can add, delete, and change each option separately.
Visible Rows controls how many options are seen before scrolling and
Row Height allows you to adjust the height of each row of the dropdown.
UI Panel and UI Button have Corner Radius to round edges.
UI API
| Function | Use | Example |
|---|---|---|
UI.find(name) | Search for a UI object by name. | UI.find("ScoreText") |
UI.show(target) | Show and activate a control. | UI.show("PausePanel") |
UI.hide(target) | Hide a control in Play. | UI.hide("PausePanel") |
UI.setText(target, text) | Change the textvisible. | UI.setText(score, "100") |
UI.getValue(target) | Read input, checkbox, select, slider, progress bar or text. | UI.getValue("VolumeSlider") |
UI.setValue(target, value) | Change the internal value. | UI.setValue("MusicCheck", true) |
UI.setRange(target, min, max, value) | Change range and value of slider or progress bar. | UI.setRange("HealthBar", 0, 100, 75) |
UI.setImage(target, texture) | Change the texture of a UI image. | UI.setImage(icon, "coin.png") |
UI.setButtonColors(target, normal, hover, pressed) | Change the normal, hover and button pressed colors. | UI.setButtonColors("PlayButton", "#1f8fff", "#2fb0ff", "#0d4f9a") |
UI.clear(target) | Clearthe value of an input. | UI.clear("NameInput") |
UI.onClick(target, fn) | Listen for button clicks. | UI.onClick(button, fn) |
UI.onChange(target, fn) | Listen for input, checkbox, select or slider changes. | UI.onChange(slider, fn) |
export function start(object) {
const score = UI.find("ScoreText");
const button = UI.find("StartButton");
UI.setText(score, "Score: 0");
UI.onClick(button, () => {
Scene.load("Level1");
});
}
// UI Text multiline.
export function start(object) {
UI.setText("DialogText", "Linea 1\nLinea 2\nLinea 3");
}
// Script assigned directly to a UI Button.
export function start(object) {
UI.onClick(object, () => {
debug("Boton pulsado");
});
}
// Progress Bar: display the player's health.
let vida = 100;
export function start(object) {
const healthBar = UI.find("HealthBar");
const healthText = UI.find("HealthText");
UI.setRange(healthBar, 0, 100, vida);
UI.setText(healthText, `Vida: ${vida}`);
}
export function update(object, deltaTime) {
const healthBar = UI.find("HealthBar");
const healthText = UI.find("HealthText");
// Example: health decreases gradually.
vida = Math.max(vida - 5 * deltaTime, 0);
UI.setValue(healthBar, vida);
UI.setText(healthText, `Vida: ${Math.round(vida)}`);
}
// Slider: display the value in a UI Text.
export function start(object) {
const slider = UI.find("VolumeSlider");
const valueText = UI.find("VolumeValueText");
UI.setRange(slider, 0, 100, 50);
UI.setText(valueText, "Volumen: 50");
UI.onChange(slider, () => {
const value = Math.round(UI.getValue(slider));
UI.setText(valueText, `Volumen: ${value}`);
});
}
17. Components
Components add extra behavior or data to an object. Select an object, click Add Component in the Inspector and find the component you want to add.
Audio Source
Audio Source play project sounds from an object. Its parameters are: sound, volume, pitch, loop, play on start and enabled.
The project sounds are loaded into memory when opening/refreshing the project. Audio Source does not hot-load sounds during Play;if a sound is not preloaded, an error will be displayed.
| Property | Use |
|---|---|
Sound | Imported sound file in the Sounds tab. |
Volume | Volume between 0 and 1. |
Pitch | Pitch and speed between 0.1 and 4. Less than 1 sounds lower and slower;More than 1 sounds higher and faster. The value 1 preserves the original sound. |
Loop | Repeat the sound automatically. |
Play On Start | Play the sound when entering Play. |
Enabled | Turns the component on or off. |
AudioSource API
| Function | Use | Example |
|---|---|---|
AudioSource.get(object) | Returns the Audio Source component of the object. | AudioSource.get(object) |
await AudioSource.play(object) | Plays the sound.assigned. | await AudioSource.play(object) |
AudioSource.pause(object) | Pauses the current playback. | AudioSource.pause(object) |
AudioSource.stop(object) | Stops and returns to the start. | AudioSource.stop(object) |
AudioSource.isPlaying(object) | Indicates if it is playing. | AudioSource.isPlaying(object) |
AudioSource.setSound(object, sound) | Change the sound. | AudioSource.setSound(object, "jump.wav") |
AudioSource.setVolume(object, volume) | Change the volume. | AudioSource.setVolume(object, 0.5) |
AudioSource.getPitch(object) | Returns the current pitch. | AudioSource.getPitch(object) |
AudioSource.setPitch(object, pitch) | Changes speed and pitch between 0.1 and 4. | AudioSource.setPitch(object, 1.5) |
AudioSource.setLoop(object, loop) | Turns loop on or off. | AudioSource.setLoop(object, true) |
AudioSource.setEnabled(object, enabled) | Turns the component on or off. | AudioSource.setEnabled(object, false) |
export async function start(object) {
AudioSource.setVolume(object, 0.7);
AudioSource.setPitch(object, 1.2);
await AudioSource.play(object);
}
export function update(object) {
if (Input.getKeyDown("Space")) {
AudioSource.play(object);
}
}
Audio Effect
Audio Effect processes the sound of the Audio Source that is on the same object. Multiple Audio Effects can be added: the engine connects them in the same order they appear in the component list.
The object requires an Audio Source. For example, you can chain
Filter → Delay → Reverb. On low-power equipment it is advisable to limit the number of reverbs and delays that play simultaneously.
| Effect | Parameters | Common use |
|---|---|---|
Reverb | Mix, Duration and Decay | Rooms, caves, halls and large spaces. |
Delay / Echo | Mix, Delay Time and Feedback | Echoes and repetitions. High feedback produces more repetitions. |
Filter | Low/High/Band Pass, Frequency, Resonance and Mix | Sound underwater, behind walls, radios or phones. |
Distortion | Amount and Mix | Engines, weapons, impacts and saturated sound. |
Stereo Pan | Pan from -1 to 1 andMix | Places the sound to the left or right. |
Pitch | Pitch from 0.1 to 4 | Change speed and pitch;1 preserves the original sound. |
Audio Effect API
| Function | Use |
|---|---|
AudioEffect.getAll(object) | Returns all effects in chain order. |
AudioEffect.get(object, index) | Returns an effect by its index, starting at 0. |
AudioEffect.setEnabled(object, index, enabled) | Turns an effect on or off. |
AudioEffect.setMix(object, index, mix) | Toggles the dry/process mix between 0 and 1. |
AudioEffect.setReverb(object, index, options) | Configure duration, decay and mix. |
AudioEffect.setDelay(object, index, options) | Configure time, feedback and mix. |
AudioEffect.setFilter(object, index, options) | Configure type, frequency, resonance and mix. |
AudioEffect.setDistortion(object, index, amount, mix) | Configure distortion. |
AudioEffect.setPan(object, index, pan) | Configure pan between -1 and 1. |
AudioEffect.setPitch(object, index, pitch) | Configure pitch between 0.1 and 4. |
Example: delayand reverb
export function start(object) {
// First Audio Effect: Delay.
AudioEffect.setDelay(object, 0, {
time: 0.25,
feedback: 0.35,
mix: 0.25
});
// Second Audio Effect: Reverb.
AudioEffect.setReverb(object, 1, {
duration: 1.8,
decay: 2.2,
mix: 0.4
});
AudioSource.play(object);
}
export function update(object) {
if (Input.getKeyDown("R")) {
AudioEffect.setEnabled(object, 1, false);
}
}
Direct push on objects
To apply force you don't need to add Physics Body manually. You can call these functions directly from the object and the engine will create the physical component automatically if necessary.
| Function | Use | Example |
|---|---|---|
object.addForwardForce(amount, axis) | Pushes the object where it is facing. axis indicates which axis of the sprite is the front. | object.addForwardForce(500, "x") |
object.addForce(x, y) | Applies force in a specific direction. | object.addForce(0, -650) |
object.setGravity(enabled, scale) | Activates/disables gravity. Create Physics Body if missing. | object.setGravity(false) |
object.forward(axis) | Returns the frontal vector of the object. | object.forward("-y") |
Add Physics Body in the editor only when you want to configure mass, drag, bounce, friction, gravity or axis lock visually.
Example: Asteroids type ship
For a shiptype Asteroids, disables gravity and applies thrust in the direction the ship is facing. If you want it to not speed up infinitely, add Physics Body in the editor and go up a little Drag.
export function start(object) {
object.setGravity(false);
}
export function update(object, deltaTime) {
if (Input.getKey("ArrowLeft")) {
object.rotation -= 180 * deltaTime;
}
if (Input.getKey("ArrowRight")) {
object.rotation += 180 * deltaTime;
}
if (Input.getKey("ArrowUp")) {
// Use "x" if the sprite faces right by default.
// Use "-y" if the sprite faces up by default.
object.addForwardForce(520 * deltaTime, "x");
}
}
Bouncy Ball
Bouncy Ball turn an object into a ball type Pong or Arkanoid. No need Physics Body: Uses its own internal velocity and bounces against colliders in the scene.
When adding this component, the engine activates Collision, disables Trigger and marks the object as no Static. Use colliders on walls, paddles, blocks and boundaries so the ball can bounce.
| Property | Use |
|---|---|
Enabled | Turns the component on or off. |
Start On Play | If active, the ball starts moving when entering Play. |
Speed | Speed of the ball in pixels per second. |
Angle | Initial exit direction in degrees. 0 right, 90 down, -90 up and 180 left. |
Constant Speed | Maintains the same speed after each bounce. |
Bouncy Ball API
| Function | Use | Example |
|---|---|---|
BouncyBall.get(object) | Returns the Bouncy Ball component. | BouncyBall.get(ball) |
BouncyBall.setSpeed(object, speed) | Change the speed. | BouncyBall.setSpeed(ball, 420) |
BouncyBall.getSpeed(object) | Returns the current speed. | BouncyBall.getSpeed(ball) |
BouncyBall.launch(object, angle, speed) | Throws the ball with angle and speedoptional. | BouncyBall.launch(ball, -45, 360) |
BouncyBall.stop(object) | Stops the ball. | BouncyBall.stop(ball) |
object.setBouncySpeed(speed) | Direct version from the object. | object.setBouncySpeed(500) |
object.launchBouncy(angle, speed) | Launches the ball from the object itself. | object.launchBouncy(-45, 360) |
Example: Pong ball or Arkanoid
Creates a ball, adds the component Bouncy Ball and activates Start On Play. Then place colliders on the walls, the shovel and the blocks. For Pong it usually works well to go out diagonally. For Arkanoid you can relaunch it from below when you lose a life.
// Ball script
export function start(object) {
// Launch upward and to the right.
object.launchBouncy(-45, 360);
}
export function update(object) {
// Relaunch the ball during testing.
if (Input.getKeyDown("R")) {
object.launchBouncy(-45, 360);
}
// Increase speed gradually.
if (Input.getKeyDown("Space")) {
const speed = BouncyBall.getSpeed(object);
BouncyBall.setSpeed(object, speed + 40);
}
}
Example: Arkanoid Shovel
The shovel only needs to move and have Collision active. The ball will bounce off it because the Bouncy Ball component manages its own direction after the collision.
// Paddle script
export function update(object, deltaTime) {
const speed = 420;
if (Input.getKey("A") || Input.getKey("ArrowLeft")) {
object.translate(-speed * deltaTime, 0);
}
if (Input.getKey("D") || Input.getKey("ArrowRight")) {
object.translate(speed * deltaTime, 0);
}
}
Waypoint Move
Waypoint Move moves an object following a list of world points. It is used for patrols, platforms, flying enemies, cameras, moving decorations or any object that must travel a route during Play.
In the editor, when you select the object, you will see the points WP and the route arrows. The component only moves the object during Play.
| Property | Use |
|---|---|
Speed | Speed in pixels per second. |
Loop | When it reaches the end it starts again. |
Ping Pong | Traverses the route forward and then back. |
Random | Chooses the next waypoint at random, avoiding repeating the current point when there is more than one. |
Move Points With Object | When moving the object in the editor, it moves all itswaypoints for the same distance. It is useful to relocate the object and its complete path at once. It works by dragging the object and changing its X/Y values in the inspector;does not modify movement during Play. |
Rotate To Target | Rotates the object facing the waypoint it is moving to. |
Flip X | Inverts the texture at X when the object moves left and restores it when moving right. |
Flip Y | Inverts the texture at Y when the object moves up and restores it when moving down. |
Pause Min/Max | General random pause between points. |
Waypoint P Min/P Max | Specific random pause for that point. |
Rotation Offset | Set in degrees if the sprite does not face right by default. |
Arrive Distance | Distance at which the object is considered to have already arrived. |
To reposition an entire patrol, activate Move Points With Object before moving the object. Disable it if you want to change the initial position of the object without moving the path.
Waypoint Move API
| Function | Use | Example |
|---|---|---|
WaypointMover.get(object) | Returns the component. | WaypointMover.get(enemy) |
WaypointMover.setSpeed(object, speed) | Change the speed. | WaypointMover.setSpeed(enemy, 180) |
WaypointMover.setLoop(object, loop, pingPong) | Change loop and optionally ping pong. | WaypointMover.setLoop(enemy, true, true) |
WaypointMover.setRandom(object, random) | Activate or disable random mode. | WaypointMover.setRandom(enemy, true) |
WaypointMover.setRotateToWaypoint(object, enabled, offset) | Activate rotation towards the target. | WaypointMover.setRotateToWaypoint(enemy, true, 0) |
WaypointMover.setFlip(object, flipX, flipY) | Activate automatic flip according to direction. | WaypointMover.setFlip(enemy, true, false) |
WaypointMover.setPause(object, min, max) | Change general random pause. | WaypointMover.setPause(enemy, 0.2, 1) |
WaypointMover.setWaypoints(object, points) | Replace the entire path. | WaypointMover.setWaypoints(enemy, points) |
WaypointMover.addWaypoint(object, x, y) | Add a point forcode. | WaypointMover.addWaypoint(enemy, 400, 120) |
WaypointMover.clearWaypoints(object) | Delete the route. | WaypointMover.clearWaypoints(enemy) |
WaypointMover.goTo(object, index) | Force the next waypoint. | WaypointMover.goTo(enemy, 2) |
WaypointMover.pause(object, seconds) | Pause temporarily. | WaypointMover.pause(enemy, 2) |
WaypointMover.resume(object) | Resume movement. | WaypointMover.resume(enemy) |
WaypointMover.reset(object) | Restart the cycle. | WaypointMover.reset(enemy) |
object.setWaypointSpeed(speed) | Direct version from the object. | object.setWaypointSpeed(200) |
object.goToWaypoint(index) | Direct version to change target. | object.goToWaypoint(1) |
Example: patrol with pingpong
export function start(object) {
WaypointMover.setWaypoints(object, [
{ x: 100, y: 200, pauseMin: 0.2, pauseMax: 0.5 },
{ x: 360, y: 200, pauseMin: 0.2, pauseMax: 0.5 },
{ x: 360, y: 320, pauseMin: 0.8, pauseMax: 1.2 }
]);
WaypointMover.setLoop(object, true, true);
WaypointMover.setSpeed(object, 120);
}
Example: enemy choosing random points
export function start(object) {
WaypointMover.setRandom(object, true);
WaypointMover.setPause(object, 0.3, 1.4);
WaypointMover.setRotateToWaypoint(object, true, 0);
}
Example: changing movement during Play
export function update(object) {
if (Input.getKeyDown("1")) {
object.goToWaypoint(0);
}
if (Input.getKeyDown("2")) {
object.goToWaypoint(1);
}
if (Input.getKeyDown("Space")) {
object.pauseWaypointMover(1);
}
if (Input.getKeyDown("R")) {
object.resumeWaypointMover();
object.setWaypointSpeed(220);
}
}
Pathfinding Agent
Pathfinding Agent turns an object into an agent capable of automatically finding and following a path around colliding objects. It is useful for enemies that chase the player, NPC, strategy units or characters that must reach a point without crossing walls.
Add the component from Add Component > Pathfinding Agent. The active colliders form the obstacles;objects marked as triggers do not block the route. Activate
Debug Path to see the route in magenta during Play in the editor.
| Property | Use |
|---|---|
Target Mode | Search for the destination by tag, by name or use fixed coordinates. |
Target Tag / Name | Tag or name of the object that the agent must pursue. |
Destination X/Y | Fixed destination when the selected mode is Position. |
Speed | Movement speed in pixels per second. |
Cell Size | Size of each search cell. A small value gives more accurate routes, but requires more calculation. |
Padding | Additional margin around obstacles to avoid brushing against them. |
Arrive Distance | Distance at which the destination is considered reached. |
Repath Interval | Seconds between recalculations while the target moves. Lowering it improves the reaction and increases CPU work. |
Max Nodes | Limit of cells that a search can explore. |
Diagonal | Allows paths and diagonal movement. |
Rotate To Target | Orients the object in the direction of movement. |
Flip X/Y | Automatically inverts the sprite according to the direction. |
Rotation Offset | Corrects the orientation if the sprite is not facing right.by default. |
Pathfinding Agent API
| Function | Use |
|---|---|
PathfindingAgent.get(object) | Returns the object component. |
PathfindingAgent.setEnabled(object, enabled) | Enables or disables the agent. |
PathfindingAgent.setTarget(object, target) | Makes it chase a specific object. |
PathfindingAgent.setDestination(object, x, y) | Switches to Position mode and searches for those coordinates. |
PathfindingAgent.setSpeed(object, speed) | Change the speed. |
PathfindingAgent.pause(object) | Pauses movement without deleting the destination. |
PathfindingAgent.resume(object) | Resume and recalculate the route. |
PathfindingAgent.stop(object) | Stops the agent and deletes its current route. |
PathfindingAgent.recalculate(object) | Forces a new route calculation. |
PathfindingAgent.hasPath(object) | Indicates if an active route exists. |
PathfindingAgent.hasArrived(object) | Indicates if it has reached the destination. |
Example: chase the player
export function start(object) {
const player = FindByTag("Player");
PathfindingAgent.setTarget(object, player);
PathfindingAgent.setSpeed(object, 100);
}
Example: send an object to a position
export function update(object) {
if (Input.getKeyDown("Space")) {
PathfindingAgent.setDestination(object, 640, 320);
}
if (PathfindingAgent.hasArrived(object)) {
// The object has arrived.
}
}
Waypoint Move follows a drawn routemanually. Pathfinding Agent calculates the path and modifies it to go around obstacles.
Look At Target
Look At Target keeps one object facing another. It is designed for turrets, cannons, spotlights, eyes, enemies and any object that must visually follow a target without changing its position.
| Property | Use |
|---|---|
Target Mode | Locates the target by tag or name. |
Target Tag / Name | Tag or name of the object at which it must look. |
Turn Speed | Maximum rotation speed in degrees per second. With 0 it spins instantly. |
Reaction Delay | Time in seconds between updates of the target address. With 0 it follows the target in each frame. |
Original Direction | Direction in which the drawing points without any rotation: right, down, left, up or custom. |
Original Angle | Custom angle of the sprite's original orientation. Right is 0°, down 90°, left 180° and up -90°. |
Example: If the image canon points up, select Up (-90°). The component will automatically apply the necessary correction for that tip to look at the target.
Look At Target API
| Function | Use |
|---|---|
LookAtTarget.get(object) | Returns the component. |
LookAtTarget.setEnabled(object, enabled) | Activates or deactivates the orientation. |
LookAtTarget.setTarget(object, target) | Directly assigns another object as a target. |
LookAtTarget.setTarget(object, "Enemy", "tag") | Looks for the target by tag. |
LookAtTarget.setTurnSpeed(object, speed) | Change the rotation speed in degrees per second. |
LookAtTarget.setReactionDelay(object, seconds) | Change thereaction delay. |
LookAtTarget.setOriginalAngle(object, angle) | Indicates the original orientation of the sprite. |
LookAtTarget.refresh(object) | Forces an immediate update of the direction. |
Example: turret that follows the player
export function start(object) {
LookAtTarget.setTarget(object, "Player", "tag");
LookAtTarget.setTurnSpeed(object, 120);
LookAtTarget.setReactionDelay(object, 0.1);
// The original cannon image points upward.
LookAtTarget.setOriginalAngle(object, -90);
}
Physics Body
Physics Body adds gravity, speed and simple physical response to an object. Use it for boxes, enemies, projectiles, falling objects or items you want to move with force. For playable platform characters it is still better to use Character Controller.
The component is only updated during Play. When you add it, the object automatically activates
Collision and stops being Static, because it needs to be able to move. Objects with Body Type: Dynamic can be pushed laterally by the player, by another Character Controller or by another Physics Body. The more
Mass the object has, the more it will cost to move it.
| Property | Use |
|---|---|
Body Type | Dynamic receives gravity and collisions. Kinematic moves by speed/script, but does not receive gravity. |
Use Gravity | Activates or disables the gravity of the component. |
Gravity Scale | Multiplies the gravity of the motor. 1 is normal, 0.5 falls slower and 2 falls faster. |
Mass | Mass usedby Physics.addForce and by the pushes. More mass means that the same force or push changes the speed less. |
Velocity X/Y | Current speed in pixels per second. |
Drag | Gradual brake applied to the speed. |
Max Fall Speed | Speed limit when falling. |
Freeze X/Y | Blocks physical movement in one axis. |
Bounce | Bounce when colliding. 0 does not bounce;Larger values return part of the speed. |
Friction | Reduces horizontal speed when touching the ground. |
Physics API
| Function | Use | Example |
|---|---|---|
Physics.get(object) | Returns the Physics Body component. | Physics.get(object) |
Physics.has(object) | Indicates whether the object has a Physics Body. | Physics.has(box) |
Physics.getVelocity(object) | Returns { x, y }. | Physics.getVelocity(object).y |
Physics.setVelocity(object, x, y) | Change the speed directly. | Physics.setVelocity(object, 200, -350) |
Physics.addVelocity(object, x, y) | Adds speed to thecurrent. | Physics.addVelocity(object, 0, -120) |
Physics.addForce(object, x, y) | Applies an instantaneous force taking into account the mass. | Physics.addForce(object, 0, -500) |
Physics.addForwardForce(object, amount, axis) | Applies force towards where the object is facing. axis indicates which axis of the sprite is the front. | Physics.addForwardForce(ship, 420, "x") |
Physics.forward(object, axis) | Returns the frontal direction vector of the object. | Physics.forward(ship, "-y") |
Physics.stop(object) | Sets X/Y velocity to zero. | Physics.stop(object) |
Physics.setGravity(object, enabled, scale) | Activates/disables gravity and optionally changes scale. | Physics.setGravity(object, true, 1.5) |
Physics.setKinematic(object, kinematic) | Switches between kinematicdynamic. | Physics.setKinematic(object, true) |
Physics.setEnabled(object, enabled) | Turns the component on or off. | Physics.setEnabled(object, false) |
Physics.isGrounded(object) | Indicates if it is touching the ground. | Physics.isGrounded(object) |
export function start(object) {
Physics.setVelocity(object, 120, -300);
}
export function update(object) {
if (Input.getKeyDown("Space") && Physics.isGrounded(object)) {
Physics.addForce(object, 0, -650);
}
if (object.isOutsideCamera(100)) {
Destroy(object);
}
}
Parallax
Parallax Move the texture of the object using the Play camera or a target object. For backgrounds, clouds and stage layers, parallax uses the Play camera when there is no target assigned. It will only move if the Play camera has Follow Player active.
In the editor the effect remains static. The Parallax move is only executed during Play. The object maintains its original position and size on the screen;the component offsets the camera and only shifts the texture. The manual target is for special cases where you want the layer to respond to a specific object instead of the camera.
| Property | Use |
|---|---|
Target | Object that controls the displacement of the texture. |
Target | Optional object that controls the parallax. If it is empty, the Play camera is used. |
Speed X/Y | Axis displacement multiplier. 1 is a normal speed;can be negative. |
Smooth X/Y | Axis smoothing. 0 is immediate;High values smooth more. |
Margin X/Y | Dead zone per axis before moving the texture, useful for Mario-type cameras. |
Repeat X/Y | Repeat the texture horizontally or vertically. |
Lock X/Y | Locks the movement of the texture on that axis. |
Enabled | Turns the component on or off. |
Parallax API
| Function | Use | Example |
|---|---|---|
Parallax.get(object) | Returns the active Parallax component. | Parallax.get(bg) |
Parallax.setTarget(object, target) | Change the target object. | Parallax.setTarget(bg, player) |
Parallax.setSpeed(object, x, y) | Change X/Y speed. | Parallax.setSpeed(bg, 1, 0) |
Parallax.setSmooth(object, x, y) | Changes X/Y smoothing. | Parallax.setSmooth(bg, 0.85, 0) |
Parallax.setMargin(object, x, y) | Change X/Y margin in world pixels. | Parallax.setMargin(bg, 120, 0) |
Parallax.setRepeat(object, x, y) | Activates X/Y repetition. | Parallax.setRepeat(bg, true, false) |
Parallax.setLock(object, x, y) | Locks axes. | Parallax.setLock(bg, false, true) |
Parallax.setEnabled(object, enabled) | Activate or deactivate. | Parallax.setEnabled(bg, true) |
export function start(object) {
const player = FindByName("Player");
Parallax.setTarget(object, player);
Parallax.setSpeed(object, 1, 0);
Parallax.setSmooth(object, 0.85, 0);
Parallax.setMargin(object, 120, 0);
Parallax.setRepeat(object, true, false);
Parallax.setLock(object, false, true);
}
Character Controller
Character Controller move a 2D character without having to write all the movement code by hand. It is used for platform games and top-down free movement.
The component only runs during Play. In the editor it does not move the object. A summary card is displayed in the Inspector;Press Edit to open the full settings window in the center of the screen. The window changes depending on the chosen mode and hides the options that are not used in that type of controller.
Common parameters
| Parameter | Type | Explanation |
|---|---|---|
Mode | Selector | Choose the type of controller: Platformer for platforms with gravity or Top Down for free movement in top view. |
Analog Movement | Selector | Progressive preserves stick intensity, so a slight tilt moves more slowly. Fixed converts any tilt beyond the dead zone into full-speed input. |
Gamepad Dead Zone | Number 0-0.95 | Ignores small stick offsets to prevent drift. The default is 0.12; values between 0.10 and 0.20 are usually recommended. |
Enabled | Check | Activates or disables the component without removing it from the object. |
Use Collisions | Check | Uses the engine collision system. In Platformer used for floors, walls, platforms and stairs. In Top Down keeps the controller ready for world contacts. |
Apply Animations | Check | Automatically changes the object's animation when the controller's state changes. |
Flip X Direction | Check | Flips the texture in X when changing the horizontal direction. This is typical for left/right facing characters. |
Flip Y Direction | Check | Flips the Y texture when changing the vertical direction. It is usually only used in top-down games or special cases. |
Horizontal | Check | Allows or blocks movement in the X axis. |
Vertical | Check | Allows or blocks movement in the Y axis. On platforms it is normally left active for jump/gravity;in top-down it controls going up and down. |
Move Speed | Number | Base speed of the character in pixels per second. |
Death State | Check | Allows the use of the death state from script with CharacterController.setDead(object, true). |
Platformer type
Use Platformer for lateral games with gravity: platforms, jumps, floor, ramps, stairs and platformsmobiles. The controller applies horizontal motion, gravity, jump, and ground detection during Play.
| Parameter | Type | Explanation |
|---|---|---|
Run | Check | Activates an optional running speed while holding down the configured key. |
Run Speed | Number | Speed used when running. It must be greater than Move Speed if you want the race to be noticed. |
Run Key | Text | Running key. By default it is usually used Shift. |
Run Button | Selector | Gamepad button held to run. The Xbox default is X. |
Jump | Check | Allows jumping. If disabled, the character does not respond to the jump key. |
Jump Key | Text | Jump key. By default, Space. |
Jump Button | Selector | Gamepad button used to jump. The Xbox default is A. |
Jump Force | Number | Initial force of the jump is usually used. Higher values make the character climb faster and higher. |
Gravity | Number | Force that pushes the character down. Higher values produce faster falls. |
Max Fall | Number | Maximum fall speed. Prevents the character from accelerating indefinitely. |
Double Jump | Check | Allows you to jump again in the air. |
Max Jumps | Number | Total number of jumps allowed before hitting the ground again. For double jump it is usually 2. |
Crouch | Check | Activates crouch state. |
Crouch Key | Text | Crouch key. By default it is usually used S. |
Crouch Button | Selector | Gamepad button held to crouch. The Xbox default is B. |
Crouch Speed | Number 0-1 | Speed multiplier when crouching. 0.5 means moving at half speed. |
Use Ladders | Check | Allows the use of objects with component Ladder. When touching a staircase the character loses gravity and can go up or down with the input. |
Ladder Speed | Number | Speed when moving down a staircase. |
For stairs to work, the staircase object must have the component Ladder. The character can jump from the ladder to get off it.
Top Down Type
Use Top Down for games seen from above or with free movement in X/Y: adventures, shooters, action RPGs or games where the character does not have gravity or jump. The controller normalizes the diagonal so that moving diagonally is not faster.
| Parameter | Type | Explanation |
|---|---|---|
Move Speed | Number | Base speed for moving in any direction. |
Run | Check | Activates optional dash also in top-down. |
Run Speed | Number | Speed used while the dash key is pressed. |
Run Key | Text | Run key. |
Run Button | Selector | Gamepad button used to run. Default: X. |
Crouch | Check | Activates a slow or stealth state if your game allows it.needs. |
Crouch Key | Text | Key to activate the crouch/stealth state. |
Crouch Button | Selector | Gamepad button used for the crouch or stealth state. Default: B. |
Crouch Speed | Number 0-1 | Speed multiplier during the state crouch. |
Horizontal | Check | Allows you to move left/right. |
Vertical | Check | Allows you to move up/down. |
Flip X Direction | Check | Useful for characters that look left/right according to the horizontal direction. |
Flip Y Direction | Check | Useful for sprites that must be inverted when looking up/down. |
Animations and sounds by state
| Mode | Available states | Use |
|---|---|---|
Platformer | Idle, Move, Run, Jump, Fall, Crouch, Death, Ladder Idle, Ladder Walk | Allows you to assign animation and sound to each platform state, includingstaircase. |
Top Down | Idle, Move, Run, Crouch, Death | Only shows states that make sense without jump, gravity, or stairs. |
| Parameter | Explanation |
|---|---|
* Anim | Animation assigned to a state. For example, Run Anim played when running. |
* Sound | Sound played when entering that state. Sounds do not inherit from other states to avoid double triggering. |
Vol | Volume independent of the sound of that state, between 0 and 1. |
Loop | Causes the state sound to repeat until changing state or exiting Play. |
Character Controller sounds use panel sounds Sounds. They are loaded when the project starts and kept in memory;the component only chooses which one to play when changing state. If Mute in Play is active, these sounds are also muted.
CharacterController API
| Function | Use | Example |
|---|---|---|
CharacterController.get(object) | Returns the object component. | CharacterController.get(object) |
CharacterController.isGrounded(object) | Indicates whether the character is touching the ground. | CharacterController.isGrounded(object) |
CharacterController.getVelocity(object) | Returns { x, y } with the internal speed. | CharacterController.getVelocity(object) |
CharacterController.setVelocity(object, x, y) | Change the internal speed. | CharacterController.setVelocity(object, 0, -300) |
CharacterController.setDead(object, dead) | Turns the mute state on or off.death. | CharacterController.setDead(object, true) |
CharacterController.isDead(object) | Check if it is in a state of death. | CharacterController.isDead(object) |
CharacterController.resetJumps(object) | Resets available jumps. | CharacterController.resetJumps(object) |
CharacterController.setEnabled(object, enabled) | Turns the component on or off. | CharacterController.setEnabled(object, false) |
export function update(object) {
if (Input.getKeyDown("K")) {
CharacterController.setDead(object, true);
}
if (CharacterController.isGrounded(object)) {
debug("En suelo");
}
}
18. Input
Input allows you to read keyboard, mouse, gamepad and touch from scripts. The API works on Play. In editor mode it does not control the scene or return keystrokes so as not to interfere with the editor tools.
Out of Play, Input returns neutral values: false on buttons/keys,
0 on axes and positions, and null on getTouch.
Keyboard
| Function | Use | Example |
|---|---|---|
Input.getKey(key) | While a key is onpressed. | Input.getKey("A") |
Input.getKeyDown(key) | Only the frame in which it is pressed. | Input.getKeyDown("Space") |
Input.getKeyUp(key) | Only the frame in which it is released. | Input.getKeyUp("Escape") |
Input.anyKey() | Some key is pressed. | Input.anyKey() |
Input.anyKeyDown() | Some key has just been pressed. | Input.anyKeyDown() |
You can use letters like "A", special keys like "Escape",
"Enter", "Shift", "Control", "Alt",
"Space", arrows like "ArrowLeft" and also codes of
KeyboardEvent.code like "KeyA".
Common keys supported: "A", "B", "Escape",
"Enter", "Shift", "Control", "Alt",
"ArrowLeft", "ArrowRight", "ArrowUp",
"ArrowDown" and "Space".
export function update(object, deltaTime) {
if (Input.getKey("D")) {
object.translate(160 * deltaTime, 0);
}
if (Input.getKeyDown("Space")) {
debug("Salto");
}
}
Mouse
| Property or function | Use |
|---|---|
Input.mouseX, Input.mouseY | Mouse position inscreen/canvas. |
Input.mouseWorldX, Input.mouseWorldY | Mouse position in world coordinates. |
Input.mouseDeltaX, Input.mouseDeltaY | Mouse movement during the frame. |
Input.mouseWheel | Wheel movement during the frame. |
Input.getMouseButton(0) | Left button pressed. |
Input.getMouseButtonDown(0) | Left button pressed this frame. |
Input.getMouseButtonUp(0) | Left button released this frame.frame. |
Input.hideCursor() | Hides the mouse pointer during Play. |
Input.showCursor() | Redisplays the mouse pointer. |
Input.setCursorVisible(false) | Shows or hides the pointer with a boolean. |
Input.isCursorVisible() | Returns whether the pointer isvisible. |
Buttons: 0 left, 1 center, 2 right.
export function update(object, deltaTime) {
if (Input.getMouseButtonDown(0)) {
object.x = Input.mouseWorldX;
object.y = Input.mouseWorldY;
}
}
export function start(object) {
Input.hideCursor();
}
export function update(object, deltaTime) {
if (Input.getKeyDown("Escape")) {
Input.showCursor();
}
}
Gamepad
Input uses the Gamepad API of the browser and normalizes Xbox, PlayStation, Nintendo, USB, Bluetooth and generic controllers. There may be several controls connected.
| Function | Use | Example |
|---|---|---|
Input.gamepadCount | Controls connected. | Input.gamepadCount |
Input.getButton(button) | Button pressed. | Input.getButton("A") |
Input.getButtonDown(button) | Button pressed this frame. | Input.getButtonDown("Cross") |
Input.getButtonUp(button) | Button released this frame. | Input.getButtonUp("Start") |
Input.getAxis(axis, deadZone?) | Axis value between -1 and 1. The optional second parameter sets the dead zone; its default is 0.12. | Input.getAxis("LeftStickX", 0.15) |
await Input.vibrate(ms, fuerte, suave, indice) | Activates the vibration of the control and returns whether it is supported. | await Input.vibrate(250, 1, 0.5, 0) |
Input.stopVibration(indice) | Stops the vibration of the controller. | Input.stopVibration(0) |
Supported buttons: A, B, X, Y,
Cross, Circle, Square, Triangle,
L1, R1, L2, R2, Start,
Select, Back, Options, Share,
LeftStick, RightStick, DPadUp, DPadDown,
DPadLeft and DPadRight.
Supported axes: LeftStickX, LeftStickY, RightStickX,
RightStickY, LeftTrigger and RightTrigger.
If there are several controllers, you can indicate the index as the second parameter:
Input.getButton("A", 0). If you do not indicate an index, the first command that has that button pressed is accepted.
The vibration depends on the command, browser and operating system. Hard and soft intensity use values between 0 and 1. If the device does not have an actuator, the function returns false without stopping the game.
Activate and stop the vibration
export async function update(object) {
if (Input.getButtonDown("A")) {
const supported = await Input.vibrate(
300, // duration in milliseconds
1, // strong motor: 0 to 1
0.4, // weak motor: 0 to 1
0 // gamepad index
);
if (!supported) {
debug("Este mando no soporta vibracion");
}
}
if (Input.getButtonDown("B")) {
Input.stopVibration(0);
}
}
export function onPlayerHit() {
// Short pulse.
Input.vibrate(120, 0.8, 0.3);
}
export function onExplosionStart() {
// Start a long vibration.
Input.vibrate(2000, 1, 1);
}
export function onExplosionEnd() {
// Stop it before the 2000 ms duration ends.
Input.stopVibration();
}
Axes of movement
Horizontal and Vertical combine keyboard and gamepad. Default: A/D, left/right arrows, W/S and up/down arrows.
Vertical movement for Pong
export function update(object, deltaTime) {
const vertical = Input.getAxis("Vertical");
object.translate(0, -vertical * speed * deltaTime);
}
This example controls one axis with W/S, the up/down arrow keys and the left stick.
Stick intensity is preserved, so a slight tilt produces slower movement.
export function update(object, deltaTime) {
const move = Input.getMovementVector();
object.translate(
move.x * 180 * deltaTime,
-move.y * 180 * deltaTime
);
}
Input.getMovementVector() combines Horizontal and Vertical and normalizes the diagonal. This way it doesn't move faster when pressing two directions. In this engine
Vertical returns positive upward;that's why the example uses -move.y.
Keyboard and gamepad use the same API in both Editor Play and Web/Windows builds. After an input-system update, generate a new build because existing builds keep the runtime they were created with.
Touch
| Function | Use |
|---|---|
Input.touchCount | Number of fingers touching the screen. |
Input.getTouch(index) | Returns { id, x, y, worldX, worldY } or null. |
Canvas UI on mobile
Interactive Canvas UI controls work with both mouse and touch: UI Button,
UI Checkbox, UI Select and UI Slider respond to a finger.
Tapping a UI Input opens the mobile virtual keyboard and GameCrom synchronizes its
text with UI.getValue and UI.onChange.
In the Inspector, Input Type can be Text, Number,
Email or Password. This asks the device for the most suitable keyboard.
Password masks characters visually, while its value remains available to scripts as
text. Visual-only elements—panels, text, images and progress bars—render normally on mobile but
do not capture taps.
18.1. Mobile controls
GameCrom includes visual touch controls so Web games can be played on phones and tablets. They are Canvas UI objects, support simultaneous touches and feed the same Input API used by keyboard and gamepad. You do not need separate movement code for mobile.
Creating touch controls
- Create or select a UI Canvas.
- Open Add GameObject > Mobile Controls.
- Add a Touch Joystick, Touch D-Pad or Touch Button.
- Place movement controls at the bottom left and action buttons at the bottom right.
- Configure their axes or action in the Inspector.
- Optionally assign an image from the project Textures to each control.
- Test with the mouse in Play or create a new build to test multitouch on a device.
| Control | Purpose | Common setup |
|---|---|---|
Touch Joystick | Analog movement in any direction, producing values from -1 to 1. | Horizontal and Vertical. |
Touch D-Pad | Digital directional pad producing -1, 0 or 1. | Horizontal and Vertical. |
Touch Button | An action that can be held, newly pressed or newly released. | Jump, Run, Crouch, Attack or Pause. |
Inspector properties
| Property | Purpose |
|---|---|
Horizontal Axis | Horizontal axis fed by a joystick or D-pad. Usually Horizontal. |
Vertical Axis | Vertical axis name. Usually Vertical; positive means up. |
Action | Action sent by a Touch Button. Action names are case-sensitive. |
Image | The Touch Button normal image, complete D-pad image or joystick base image. |
Pressed Image | Image displayed while a Touch Button is held. When set to None, the normal image remains in use. |
Inner Image | Image for the moving inner circle of a Touch Joystick. It is automatically clipped to a circle. |
Inner Opacity | Independent opacity for the joystick inner circle, from 0 to 1. |
Visual Style | D-pad appearance: 4 Arrows, 8 Arrows or Classic Cross. This is visual only; every style keeps identical input behaviour and supports diagonals. |
Joystick Mode | Fixed keeps the joystick at its scene position. Floating in Area hides it until the area is touched and centres it under the finger. |
Activation Area | Area that can start a floating joystick: Left Half, Right Half, Full Screen or Custom Area. |
Always Visible | When enabled, the joystick remains visible at rest and moves to the touched position. When disabled, it stays hidden and only appears while a finger holds its activation area. |
Area Position % | Custom area X/Y position as a percentage of the game screen. |
Area Size % | Custom area width and height percentages. For example, X 0, Y 0, W 50, H 100 covers the left half. |
Dead Zone | Ignores small movements near the joystick centre. 0.12 is a good starting point. |
Sensitivity | Multiplies joystick response before clamping it between -1 and 1. |
Touch devices only | Hides the control on devices without touch support. Disable it while testing with a mouse in Play. |
Background, Border, Opacity | Control appearance. Moderate opacity keeps the game visible beneath it. |
Anchor, position and size | Attach controls to screen corners and adapt them to different displays. |
Reading movement and actions
With Floating in Area, players do not need to hit a small fixed control. The first touch inside the activation area creates the joystick centre at that exact point. Movement is measured from that centre and the joystick disappears when the finger is released. Touch buttons placed over the area have priority, so they continue to work when areas overlap.
When a floating Touch Joystick is selected in the editor, its activation area is displayed with a dashed outline and a subtle blue fill. This guide is editor-only and is never rendered in the game.
export function update(object, deltaTime) {
// Keyboard, gamepad, touch joystick and D-pad share these axes.
const x = Input.getAxis("Horizontal");
const y = Input.getAxis("Vertical");
object.translate(x * 220 * deltaTime, -y * 220 * deltaTime);
if (Input.isActionPressed("Attack")) {
// Continuous attack while held.
}
if (Input.isActionDown("Jump")) {
// Jump once when pressed.
}
if (Input.isActionUp("Pause")) {
// Open or close the pause menu when released.
}
}
| Function | Result |
|---|---|
Input.isActionPressed(name) | true while at least one button using that action is held. |
Input.isActionDown(name) | true only on the first frame of a press. |
Input.isActionUp(name) | true only on the release frame. |
Input.isTouchDevice() | Reports whether the device exposes touch support. |
Character Controller
The Character Controller automatically reads the Horizontal and Vertical axes. It also recognises the touch actions Jump, Run and Crouch. For a basic character, add a joystick and a button whose action is Jump; no extra movement script is required.
Multitouch and builds
Each finger retains its own control, so players can move the joystick and press several buttons simultaneously. This works in Web and Windows builds on devices with touch input. Generate a new build after changing controls or updating the engine because existing builds retain their original runtime.
Visual controls and Input.getTouch(index) solve different needs. Use visual controls for regular movement and actions. Use getTouch when you need finger positions, finger drawing, world selection or custom gestures.
19.2D Collisions
The engine includes 2D collisions based on SAT. To have an object participate in collisions, activate Collision in the Collider 2D block of the Inspector. If you activate Trigger, the object detects contacts but does not push or block other objects.
| Option | What it does |
|---|---|
Collision | Includes the object in the collision system during Play. |
Trigger | Detects contact without physically resolving the collision. |
One Way Platform | Allows you to cross the platform by jumping from below and fall on it from above. |
Shape | Collider shape. Square objects use Box by default;Circle objects use Circle and can also use Capsule. |
Offset | Moves the collider with respect to the center of the object without moving the render. |
Size | Width and height of the collider for Box and Capsule. |
Radius | Radius of the collider when the shape is Circle. |
Static | The object does not move when resolving collisions. It works for floors, walls and platforms. |
Collisions work with rotation, scale and hierarchies. The collider appears blue in the scene when the object is selected and Collision is active. They only update in Play.
Scenery Components
| Component | Use |
|---|---|
Ladder | Turns the object into a stair area. Adding it activates Collision and Trigger. The Character Controller suspends gravity while touching it and can jump from it. |
Moving Platform | Moves the object between its initial position and an X/Y offset. When selecting the object in the editor, a visual reference is drawn with START, END, path arrow and destination silhouette without moving the platform. |
Conveyor Belt | Converts a solid collider into a conveyor belt that moves the characters and physical bodies resting on it to the left or right. |
Texture Scroller | Animates the X/Y offset of the object's texture during Play, with configurable speed and control from scripts. |
Conveyor Belt
Conveyor Belt creates the classic conveyor belt effect. While a compatible object is resting on it, the belt moves it horizontally at the configured speed. It works both in the Play editor and in the exported game.
To use it, select the floor or platform, press
Add Component > Conveyor Belt and adjust its properties. When you add it, the editor automatically turns on Collision and off Trigger on the ribbon.
| Property | Use |
|---|---|
Enabled | Turns ribbon movement on or off. |
Direction | Choose whether the ribbon drags toward Left or Right. |
Speed | Horizontal speed in pixels per second. |
Affect Characters | Drags objects that have a component Character Controller active. |
Affect Physics Bodies | Drags objects that have a component Physics Body active. |
The transported object must be resting on the top of the belt and have
Character Controller or Physics Body, according to the activated filters. The belt does not move decorative objects without one of those components.
Conveyor Belt API
| Function | Use | Example |
|---|---|---|
ConveyorBelt.get(object) | Returns the component. | ConveyorBelt.get(object) |
ConveyorBelt.setEnabled(object, enabled) | Activates or stops the belt. | ConveyorBelt.setEnabled(object, false) |
ConveyorBelt.setSpeed(object, speed) | Change the speed in pixels per second. | ConveyorBelt.setSpeed(object, 160) |
ConveyorBelt.setDirection(object, direction) | Change the direction to "left" or "right". | ConveyorBelt.setDirection(object, "left") |
ConveyorBelt.setAffects(object, characters, physicsBodies) | Choose the types of object it carries. | ConveyorBelt.setAffects(object, true, false) |
TextureScroller
TextureScroller continuously modifies Texture Offset X and
Texture Offset Y during Play. It works for animated tapes, water, lava, clouds, moving backgrounds or any repeating texture. The texture must have proper tiling so that the scroll is visible continuously.
| Property | Use |
|---|---|
Enabled | Turns the offset animation on or off. |
Speed X | Positive horizontal speed of the offset per second. |
Speed Y | Positive vertical speed of the offset per second. |
Scroll Right | Marking shifts the texture to the right;unchecked moves it to the left. |
Scroll Down | Checked moves the texture down;unchecked moves it up. |
Texture Scroller API
| Function | Use | Example |
|---|---|---|
TextureScroller.get(object) | Returns the component. | TextureScroller.get(object) |
TextureScroller.setEnabled(object, enabled) | Activates or stops the scroll. | TextureScroller.setEnabled(object, true) |
TextureScroller.setSpeed(object, x, y) | Change the speed of the two axes. | TextureScroller.setSpeed(object, 0.5, 0) |
TextureScroller.setDirection(object, right, down) | Change the direction of each axis with booleans. | TextureScroller.setDirection(object, true, false) |
TextureScroller.setOffset(object, x, y) | Immediately sets the texture offset. | TextureScroller.setOffset(object, 0, 0) |
TextureScroller.getOffset(object) | Returns { x, y } with the offsetcurrent. | const offset = TextureScroller.getOffset(object) |
export function start(object) {
TextureScroller.setSpeed(object, 0.4, 0);
}
export function update(object) {
if (Input.getKeyDown("Space")) {
const component = TextureScroller.get(object);
TextureScroller.setEnabled(object, !component.enabled);
}
}
Callbacks in scripts
If your object has a script assigned to it, you can export these functions. The engine calls them when the object's collider enters, remains or leaves contact with another.
| Function | When called |
|---|---|
onCollisionEnter(object, collision) | First frame of contact with a normal collider. |
onCollisionStay(object, collision) | Each frame while contact continues. |
onCollisionExit(object, collision) | When contact ends. |
onTriggerEnter(object, collision) | First frame of contact with a trigger. |
onTriggerStay(object, collision) | Each frame while still within thetrigger. |
onTriggerExit(object, collision) | When the trigger exits. |
export function onCollisionEnter(object, collision) {
debug(object.name + " choca con " + collision.other.name);
}
export function onTriggerEnter(object, collision) {
if (collision.other.tag === "Coin") {
Destroy(collision.other);
}
}
Collision data
| Property | Content |
|---|---|
collision.other | The other object of the contact. |
collision.self | The object that receives the callback. |
collision.normal | Separation address from the point of view of self. |
collision.overlap | Overlap depth. |
collision.point | Approximate point of the contact. |
collision.isTrigger | true if the contact includes a trigger. |
Collision API
| Function | Use | Example |
|---|---|---|
Collision.check(a, b) | Checks if two objects are colliding now. | Collision.check(player, enemy) |
Collision.all(object) | Returns the current contacts of an object. | Collision.all(object) |
Collision.contacts() | Returns all contacts in the frame. | Collision.contacts() |
export function update(object, deltaTime) {
const enemy = FindByName("Enemy");
const hit = Collision.check(object, enemy);
if (hit) {
debug("Tocando enemigo");
}
}
Events and Time
Events
Events communicates scripts withoutsearch or directly reference other objects. Events are cleared when changing scenes.
Events.on(name, callback) | Listen to an event and return a function to stop listening to it. |
Events.once(name, callback) | Listen only to the next broadcast. |
Events.emit(name, data) | Send data to all listeners. |
Events.off(name, callback) | Delete a specific callback. |
Events.clear(name) | Clear an event;no name cleans all. |
Events.count(name) | Number of listeners. |
export function start(object) {
Events.on("player-hit", data => {
UI.setText("HealthText", `Vida: ${data.health}`);
});
}
export function hitPlayer(health) {
Events.emit("player-hit", { health });
}
Time
Time.deltaTime | Frame scaling delta. |
Time.unscaledDeltaTime | Actual delta, even with pause or slow motion. |
Time.fixedDeltaTime | Fixed motor step. |
Time.time, Time.unscaledTime | Scaled and real accumulated time. |
Time.frameCount | Frames processed. |
Time.timeScale | Global scale:1 normal, 0.5 slow motion, 0 stopped. |
Time.pause(), resume(), isPaused() | Pause control. |
export function update(object) {
if (Input.getKeyDown("P")) {
if (Time.isPaused()) Time.resume();
else Time.pause();
}
if (Input.getKeyDown("T")) {
Time.timeScale = 0.35;
}
}
Time.pause() only stops scaled time. To stop the complete game in a coordinated way,
use the global Game API described below.
Global game pause
Game.pause() applies a complete, safe pause in both Editor Play and builds. It stops normal scripts, physics, collisions, animations, particles, tweens, pathfinding, camera and audio. Rendering continues and Input remains available for controlling the pause menu.
Game.pause() | Pauses the game. Returns true when the state changes. |
Game.resume() | Resumes without animation or particle jumps. |
Game.togglePause() | Toggles pause and resume. |
Game.isPaused() | Reports whether global pause is active. |
How to pause and resume
export function update(object, deltaTime) {
// update stops running after the game is paused.
if (Input.getKeyDown("Escape") || Input.getButtonDown("Start")) {
Game.pause();
UI.show("PauseMenu");
}
}
export function pausedUpdate(object, unscaledDeltaTime) {
// Runs only during the global pause.
if (Input.getKeyDown("Escape") || Input.getButtonDown("Start")) {
UI.hide("PauseMenu");
Game.resume();
}
}
To resume from a script, use pausedUpdate(object, unscaledDeltaTime), because update, fixedUpdate and lateUpdate remain stopped. Do not place Game.togglePause() only inside update: that callback no longer runs after pausing. unscaledDeltaTime can be used to animate a pause interface manually.
Additional Component APIs
MovingPlatform.get(object) | Gets the component. |
MovingPlatform.setEnabled(object, value) | Activate or deactivate. |
MovingPlatform.setSpeed(object, speed) | Change speed. |
MovingPlatform.setMovement(object, x, y) | Change traversal. |
MovingPlatform.setPingPong(object, value) | Controls round trip. |
MovingPlatform.reset(object) | Resets its state. |
Rotation.get(object) | Gets Rotation. |
Rotation.setEnabled(object, value) | Activate or deactivate. |
Rotation.setSpeed(object, speed) | Change degrees per second. |
Rotation.setPivot(object, x, y) | Change pivot. |
Rotation.reset(object) | Resets the accumulated rotation. |
Ladder.get(object), Ladder.setEnabled(object, value) | Queries or activates a ladder. |
Light.get(object), Light.setEnabled(object, value) | Queries or activates alight. |
Light.setColor(object, color) | Change hexadecimal color. |
Light.setIntensity(object, value) | Intensity between 0 and 1. |
Light.setRadius(object, radius) | Change radius. |
Light.setEffect(object, effect, options) | Effect and options speed, amount and color. |
const platform = FindByName("Lift");
MovingPlatform.setSpeed(platform, 120);
MovingPlatform.setMovement(platform, 0, -300);
const alarm = FindByName("AlarmLight");
Light.setColor(alarm, "#ff2020");
Light.setEffect(alarm, "alarm", { speed: 3, amount: 0.8 });
Save games with Save
Save saves complete objects per slot and project. For small options it is still suitable PlayerPrefs;for games uses Save.
Save.write(slot, data, metadata) | Saves optional data and metadata. |
Save.read(slot, fallback) | Read the data. |
Save.info(slot) | Date and metadata without loading the game. |
Save.exists(slot) | Check the slot. |
Save.delete(slot) | Delete a slot. |
Save.list() | List slots sorted by date. |
Save.clear() | Delete all games in the project. |
Save.write("slot1", {
scene: Scene.current,
score: Project.vars.score,
lives: 3,
player: { x: object.x, y: object.y }
}, {
title: "Main save"
});
const game = Save.read("slot1", null);
if (game) {
Project.vars.score = game.score;
object.x = game.player.x;
object.y = game.player.y;
}
The data must be able to be converted to JSON. Do not save features, HTML elements, Audio or circular references.
TXT and JSON files
GameCrom uses the same Files API for TXT and JSON, but separates files into two areas with different purposes and permissions. Choosing the correct area keeps original project content separate from data generated by each player.
| Area | Purpose | While playing | Examples |
|---|---|---|---|
assets/data/ | Internal content prepared by the developer. | Read-only | Translations, dialogue, configuration, levels and data tables. |
user/ | Local data created or changed at runtime. | Read and write | Profiles, generated content, logs and custom game data. |
Case 1: internal project data — assets/data/
Open the Data tab in the Assets panel. You can import .txt and
.json files, or create one with New TXT and New JSON.
Files are stored in assets/data/; Open in VS Code opens them directly
in Visual Studio Code. Subfolders can be included in the name, for example
dialogues/en.json.
assets/data/ is always read-only while the game is running. Its files belong to the project and are included in builds, but scripts cannot change or delete them. To change this content, return to the project, edit it with VS Code and create a new build.
// Read content prepared by the developer
const translations = await Files.readJSON("assets/data/translations/en.json", {});
const dialogues = await Files.readText("assets/data/dialogues.txt", "");
// This is forbidden because assets/data is read-only:
// await Files.writeJSON("assets/data/config.json", newConfig);
Case 2: writable player files — user/
Use user/ when the game needs to create, read, change or delete TXT and JSON files at runtime. These files are not part of the original project and are independent for each game, browser or installation.
// Create or overwrite a player file
await Files.writeJSON("user/profile.json", {
name: "Player",
level: 3
}, { pretty: true });
// Read it, change it and save it again
const profile = await Files.readJSON("user/profile.json", { level: 1 });
profile.level += 1;
await Files.writeJSON("user/profile.json", profile);
await Files.writeText("user/notes.txt", "Level completed");
const files = await Files.list("user/");
await Files.delete("user/notes.txt");
Where user/ is stored
- Editor Play: in the editor's local storage.
- Build Web: in the browser, associated with the domain running the game. It does not create visible files beside the website.
- Windows Build: in the application's local data, separately for each game. It is not stored beside the EXE or inside
assets/data/.
| Method | Description |
|---|---|
await Files.readText(path, fallback?) | Reads a .txt file. |
await Files.readJSON(path, fallback?) | Reads and parses a .json file. |
await Files.writeText(path, content) | Writes text inside user/. |
await Files.writeJSON(path, value, options?) | Writes JSON. Use { pretty: true } to format it. |
await Files.exists(path) | Checks whether a file exists. |
await Files.list(path) | Lists files in a folder. |
await Files.delete(path) | Deletes a file from user/. |
Handle errors with try/catch and inspect error.code: NOT_FOUND, INVALID_JSON, ACCESS_DENIED or QUOTA_EXCEEDED.
Only .txt and .json files are accepted, up to 5 MB per file. Absolute paths and ../ are blocked. Use PlayerPrefs for simple preferences, Save for slot-based save games and Files for custom auxiliary files.
Local saving
Which system should you use?
| System | Recommended use | Persistence |
|---|---|---|
PlayerPrefs | Volume, language, controls, graphics quality and other preferences. | Local storage, separated by project. |
Save | Save games, levels, inventory, score, campaign and checkpoints. | Local storage, organized into slots and separated by project. |
GameCrom 2D Studio does not use accounts or cloud saving. Data is not synchronized between browsers, computers or devices.
Where data is stored
- Editor Play: in the editor's local storage.
- Build Web: in the local storage of the browser and domain where the game is running.
- Build Windows: in the application's local storage.
On the Web, each browser and domain keeps an independent copy. Clearing site data, using private browsing or running the game from another domain may make a save unavailable. On Windows, deleting the application's local data also deletes its preferences and save games.
Recommended use
// Device preferences
PlayerPrefs.setNumber("volume", 0.8);
PlayerPrefs.setString("language", "en");
// Game progress
Save.write("autosave", {
level: 4,
score: 12500,
player: { x: object.x, y: object.y }
});
const data = Save.read("autosave", null);
Save at checkpoints and after important changes. Do not wait only for the browser tab or application to close, because a forced shutdown may prevent the final write.
Pathfinding
Pathfinding.findPath use A* on a temporal grid. Objects with active collision lock cells;Triggers do not block. Does not require Tilemap.
Pathfinding.findPath(start, end, options) | Returns world points or an empty array. |
Pathfinding.follow(object, path, speed, options) | Makes the object follow the path. |
Pathfinding.stop(object) | Stops tracking. |
Pathfinding.isFollowing(object) | Checks if it follows a path. |
Main options: cellSize, diagonal, padding,
marginCells, maxNodes e ignore. A small cellSize finds more precise routes but costs more CPU.
export function start(object) {
const player = FindByTag("Player");
const path = Pathfinding.findPath(object, player, {
cellSize: 32,
diagonal: true,
padding: 6,
ignore: [object, player]
});
Pathfinding.follow(object, path, 110, {
arriveDistance: 3,
onComplete(enemy) {
debug(enemy.name + " ha llegado");
}
});
}
export function update(object) {
if (Input.getKeyDown("Escape")) {
Pathfinding.stop(object);
}
}
Pixel Canvas
The object Pixel Canvas It is a dynamic and scalable image whose content comes from a script-controlled framebuffer. It is used for emulators, drawing programs, minimaps, screens, procedural effects and games based directly on pixels.
Create Add GameObject > Pixel Canvas and configure its internal resolution. The size and scale of the object control the visible size;its resolution controls how many pixels the framebuffer contains.
PixelCanvas.create(object, width, height, options) | Creates or replaces the surface. |
PixelCanvas.get(object) | Returns the existing surface. |
PixelCanvas.getOrCreate(object) | Gets or creates using the object's configuration. |
surface.getBuffer() | RGBA buffer Uint8ClampedArray;four bytes per pixel. |
surface.getIndexBuffer() | Buffer Uint8Array of indices for palettes of up to 256 colors. |
surface.setPixel(x, y, color) | Draws a pixel. |
surface.clear(color) | Cleans the entire surface. |
surface.fillRect(x, y, w, h, color) | Fills a rectangle. |
surface.drawLine(x0, y0, x1, y1, color) | Draws a line. |
surface.setPalette(colors) | Defines the indexed mode palette. |
surface.present() | Publishes buffer changes torender them. |
let screen;
export function start(object) {
screen = PixelCanvas.create(object, 256, 192, {
indexed: true
});
screen.setPalette([
"#000000", "#0000d7", "#d70000", "#d700d7",
"#00d700", "#00d7d7", "#d7d700", "#d7d7d7"
]);
screen.clear(0).present();
}
export function update(object) {
const pixels = screen.getIndexBuffer();
pixels[40 * screen.width + 80] = 6;
screen.markDirty();
screen.present();
}
For maximum performance directly modify the buffer and call markDirty() before
present(). With Auto Present active, the renderer automatically publishes any surface marked as modified.
Engine, types and API contract
Engine.version | Engine version. |
Engine.apiVersion | Script contract version. |
Engine.isEditor | True in Editor Play and false in compiled. |
Engine.platform | System Communicated Platform. |
export function start(object) {
debug({
engine: Engine.version,
api: Engine.apiVersion,
editor: Engine.isEditor,
platform: Engine.platform
});
}
The file DOCUMENTOS/gamecrom-2d-studio-api.d.ts provides autocompletion and types for new APIs. The test node TESTS/runtimeApiContract.mjs validates math, events, time, Random, Save, Pathfinding and PixelCanvas.
API Application: exit the game
Use Application.quit() to leave the game from any script. The same call works during Play in the editor, in a web version published in GameCrom, and in a Windows executable. Application.exit() is an equivalent alias.
| Environment | Result |
|---|---|
| Editor Play | Stops Play and returns to the scene without closing the editor. |
| Web game in GameCrom | Close the web player and end the game session. |
| Game EXE | Cleanly close the window and the native game process. |
Exit directly
export async function salirDelJuego() {
await Application.quit();
}
You can call this function fromthe logic of a menu button, a Game Over screen or any other script. The promise returns true if the request has been sent and
false if other code has canceled the exit.
Exit on Escape
export function start(object) {
// No setup is required at startup.
}
export async function update(object, deltaTime) {
if (Input.getKeyDown("Escape")) {
await Application.quit("escape-key");
}
}
Save before exit
export async function salirGuardando(object) {
PlayerPrefs.setInt("record", Project.vars.record || 0);
PlayerPrefs.setJSON("configuracion", Project.vars.configuracion || {});
PlayerPrefs.save();
await Application.quit("main-menu");
}
Save first and request exit later. Do not place long trades after
Application.quit(), because the game can close immediately.
Temporarily cancel exit
let hasUnsavedChanges = true;
export async function intentarSalir() {
if (hasUnsavedChanges) {
window.addEventListener("gamecrom:before-quit", event => {
event.preventDefault();
debug("Save the game before quitting");
}, { once: true });
}
const quitting = await Application.quit("main-menu");
debug({ quitting }); // false when cancelled
}
export async function saveAndQuit() {
PlayerPrefs.setInt("nivel", Project.vars.nivel || 1);
hasUnsavedChanges = false;
await Application.quit("saved-game");
}
The cancelable event gamecrom:before-quitis emitted before closing. Its property
event.detail.reason contains the reason sent to quit. The listener must synchronously decide whether to cancel the output using event.preventDefault().
Available Methods
| Method | Use |
|---|---|
await Application.quit(reason?) | Request a clean output and return true or false. |
await Application.exit(reason?) | Alias of Application.quit(). |
20. Compile and export the game
From Project Settings you can locally generate different versions of the game. Before building, the editor saves the current scene and project settings.
The Builds field above the build buttons selects the output folder. The default is
C:\GAMECROM_BUILDS. After a successful build, Open Folder opens the generated
folder directly; the button stays hidden until a valid output path exists.
| Button | Output | Recommended use |
|---|---|---|
| Build Web | <BUILDS_ROOT>/<Project>/web | Minified and protected web version for publishing. |
| Build Windows | <BUILDS_ROOT>/<Project>/windows | Protected portable Windows executable. |
Build Web
The protected version does not leave the folders visible scripts, scenes,
assets, prefabs nor ENGINE. The game is packaged in a few files and is rebuilt in memory upon startup.
The engine is bundled into a single module and minified together with the boot code and project scripts. Game scripts also receive moderate identifier renaming, without aggressive control-flow transforms, junk code or per-frame decoders. The shared physics and collision core receives safe minification and local identifier renaming only; it uses no control-flow obfuscation or extra runtime work, preserving performance and stability. Original editor and project files are never modified; the process works only on copies inside the build output folder.
C:\GAMECROM_BUILDS\PONG\web\
index.html
p.js
s.css
m.json
d.json
r/
e.js
There is no absolute protection on the web: the browser always needs to download the game data. This output makes analysis and copying more difficult, but should not be used to store secrets, private keys, or sensitive logic.
Build Windows
Builds the game as an executable application without an installer, for example PONG.exe.
It is ideal for running the game directly, distributing it in a ZIP file, or publishing it on platforms that accept Windows applications.
The necessary resources are packaged with the application andthey do not appear as separate folders next to the executable.
Which one should I use?
To publish in a browser: Build Web
To distribute a protected executable: Build Windows
For Steam and other stores: consult the corresponding publishing guide.
21. Usage tips
- Use
deltaTimeso that movement does not depend on FPS. - Always check if
FindByNameorFindByTagreturnnull. - Use tags for categories like
Enemy,Player,PickuporTarget. - If a script is assigned to multiple objects, each object will receive its own call to
startandupdate. - Changes made during Play are temporary and are restored when exiting Play.