Skip to content

Components

A component is one ability you give an entity: draw a picture, make a sound, be touchable, cast light. You build every game object by stacking a few components on an entity — there is nothing else to it.

You add and edit components in the Inspector (select an entity, click Add Component), and read or change the same fields from scripts through an entity handle. Each accessor (e:sprite(), e:collider(), …) returns the component, or nil if the entity doesn’t have it.

Some typical builds, to give you a feel for it:

You want a…Give it
PlayerTransform + Sprite + Collider + Script
CoinTransform + Sprite + Animation + Collider
LevelTransform + TileMap
CameraTransform + Camera + MainCamera
TorchTransform + Sprite + PointLight
Score labelTransform + Text
Background musicAudioSource (with looping and play_on_create)

Every entity automatically starts with a Transform (its position), so in practice you only add the rest.

The foundation: an entity’s position, rotation, and scale in 2D space. Every visible or positioned entity needs a Transform — sprites, text, tilemaps, colliders, and lights are all placed by it.

Fields

  • translationvec3 world position (z orders draw depth).
  • scalevec3 scale.
  • angle — rotation about the Z axis, in radians.
local t = self:transform()
t.translation = t.translation + vec3.new(0, 1, 0) * speed * dt
t.angle = t.angle + dt -- spin

e:world_transform() returns a read-only Transform snapshot with the parent chain applied — useful when an entity is parented and you need its absolute position.

Draws a picture at the entity’s position. With no texture picked it draws a plain white rectangle — useful as a placeholder while you work.

Fields

  • texture — name of an Image asset.
  • colorvec4 tint (multiplied with the texture).
  • sizevec2 on-screen size in world units.
  • regionRect (x, y, w, h) sub-rectangle of the texture, in pixels measured from the image’s top-left corner (for atlases and spritesheets).
  • unlitbool; when true the sprite ignores scene lighting.
  • intensityfloat emissive multiplier (drives bloom for glowing sprites).
  • blend"alpha" or "additive".

Requires a Transform.

local s = self:sprite()
s.color = vec4.new(1, 0, 0, 1)
s.blend = "additive"

Draws text at the entity’s position — scores, labels, dialogue. The text stays crisp at any size.

Fields

  • text — the string to draw.
  • font — name of a Font asset.
  • sizefloat pixel size.
  • colorvec4.

Requires a Transform. Measure laid-out text with e:text_size()width, height.

local label = self:text()
label.text = "Score: " .. score

Plays a SpriteAnimation clip by advancing a Sprite’s region over time — so it drives an existing Sprite.

Fields

  • clip — name of the current Animation asset (read/write via play).
  • playingbool.
  • speedfloat playback multiplier.
  • elapsedfloat playback position in seconds (read/seek).
  • finishedbool, read-only.

Methodsplay(clip) starts a clip from the beginning; stop() pauses.

Requires a Sprite (and therefore a Transform).

local a = self:animation()
if moving then a:play("run") else a:play("idle") end

A grid of tiles drawn from a TileSet, batched into a single draw. Great for level geometry and backgrounds.

Fields

  • tileset — name of a TileSet asset.
  • width, height — grid dimensions, read-only.
  • tile_sizevec2 size of a cell in world units.
  • colorvec4 tint.
  • unlitbool.

Methods

  • get_tile(x, y) — the tile index at a cell, or nil if empty.
  • set_tile(x, y, index) — set a cell (nil/negative clears it).

Requires a Transform and a TileSet asset. Author tilemaps visually in the Tilemap Editor.

local map = self:tilemap()
map:set_tile(3, 2, 7) -- place tile 7 at column 3, row 2

An invisible shape used to ask “are these things touching?” — from scripts, via e:overlaps(other) and the kione.query_* functions. Kione doesn’t push objects apart or simulate physics for you; your script asks and decides what happens (the platformer demo’s player script shows how).

Fields

  • shape"box", "circle", or "pill".
  • layeruint bitmask this collider belongs to.
  • maskuint bitmask of layers it collides with.
  • width, height — box extents (box only).
  • radius — radius (circle and pill).
  • half_height — half of the straight section (pill only).

Accessing a field that doesn’t apply to the current shape raises a script error.

Requires a Transform.

for _, other in ipairs(kione.query_circle(x, y, 32)) do
if other:has_component("Collider") then handle(other) end
end

Defines the view. Tag the active camera entity with MainCamera (in the Inspector) so the renderer uses it.

Fields

  • position, target, upvec3 view vectors; look_at(x, y) points it at a spot.
  • projection"orthographic" (2D default) or "perspective".
  • scale_mode — how the view maps to a window of a different aspect: "stretch", "fit_width", "fit_height", "expand", "letterbox".
  • Orthographic bounds: left, right, top, bottom.
  • Perspective: fov (radians), aspect_ratio.
  • near_clip, far_clip — clip planes (both projections).
local cam = kione.find_main_camera():camera()
cam:look_at(player.x, player.y)
cam.scale_mode = "letterbox"

Scene-wide lighting and post-processing. Usually placed on the camera or a root entity.

Fields

  • ambient_colorvec3 ambient light color.
  • ambient_intensityfloat.
  • clear_colorvec4 background color.
  • bloombool enable bloom.
  • bloom_intensityfloat.
  • bloom_thresholdfloat brightness cutoff for bloom.
local env = self:environment()
env.bloom = true
env.ambient_intensity = 0.8

Three components add light to your scene. Sprites are shaded by the lights around them (unless marked unlit), so a dark scene with a few lights instantly looks moody. All lights sit at their entity’s position.

PointLight — omni-directional.

  • colorvec3, intensityfloat, radiusfloat.

SpotLight — a cone.

  • color, intensity, radius, plus inner_angle and outer_angle (the cone falloff).

SpriteLight — projects a texture as light (e.g. a soft glow or gobo).

  • colorvec3, intensityfloat, texture — name of an Image asset.
local light = self:point_light()
light.color = vec3.new(1.0, 0.8, 0.5)
light.radius = 400

Plays an Audio clip positioned on the entity.

Fieldsclip (asset name), volume, pitch, looping (bool), play_on_create (bool).

play_on_create arms the source: the first frame the engine sees it true, the clip starts — exactly once per component. Set it false in on_create to suppress an autoplay authored in the editor; setting it true later from a script plays the clip once. It never re-triggers, and it doesn’t stop a sound that’s already playing — for on-demand sounds use kione.play_sound.

local a = self:audio_source()
a.volume = 0.5
a.looping = true

Attaches a Script asset to the entity, which is what makes the lifecycle hooks run for it. Add it in the Inspector and pick your .lua script; there are no scriptable fields on the component itself.

Every entity carries a free-form Lua table, reachable with e:data(). It behaves like a custom component you define in script — store whatever state your game needs, and read it from other entities’ scripts too:

-- on the player
function on_create(self)
self:data().health = 100
end
-- from an enemy's script
local player = kione.find("Player")
if player then
player:data().health = player:data().health - 10
end

This is how entities share custom state without any engine change — the table is per-entity, persists for the entity’s lifetime, and is copied when the entity is cloned.