API Documentation

Документация по API

Complete reference for the PLUTO-8 Lua API.

Полный справочник по Lua API для PLUTO-8.

PLUTO-8 uses a sandboxed Lua 5.1 environment. Your cartridge code runs server-side; draw commands are sent to clients each frame. Optional parameters are shown as param?. Color values are integers 0–255.

PLUTO-8 использует изолированную среду Lua 5.1. Код картриджа выполняется на сервере; команды рисования отправляются клиентам каждый кадр. Необязательные параметры обозначаются как param?. Значения цвета — целые числа от 0 до 255.

Specifications

Спецификации

DisplayЭкран256×256 px
PaletteПалитра256 colorsцветов
Frame rateЧастота кадров30 FPS
RAM128 KB
ROM (cartridgeкартридж)512 KB
VRAM64 KB (256×256 × 1 byteбайт)
SpritesСпрайты256 × 8×8 px
TilemapТайлмап128×128 tilesтайлов
LanguageЯзыкLua 5.1 (sandbox)

Cartridge Format

Формат картриджа

A cartridge is a plain Lua source file. PLUTO-8 looks for three optional lifecycle functions:

Картридж — это обычный файл исходного кода на Lua. PLUTO-8 ищет три необязательные функции жизненного цикла:

lua
--[[__PLUTO8__
SPRITES:<hex data>
MAP:<hex data>
]]

function _init()
  -- called once when the cartridge loads
end

function _update(dt)
  -- called 30 times per second; dt = real delta time (~0.033s)
end

function _draw()
  -- called after _update; issue draw commands here
end

Sprite and map data are stored as hex strings in the header comment and are loaded automatically at boot time.

Данные спрайтов и карты хранятся в виде шестнадцатеричных строк в заголовочном комментарии и загружаются автоматически при запуске.

Memory Map

Карта памяти

PLUTO-8 provides 128 KB of addressable RAM:

PLUTO-8 предоставляет 128 КБ адресуемой оперативной памяти:

Address Size ContentsСодержимое
0x00000–0x03FFF16 KBSprite sheet (256 sprites × 8×8 pixels, 1 byte per pixel)Лист спрайтов (256 спрайтов × 8×8 пикселей, 1 байт на пиксель)
0x04000–0x07FFF16 KBTilemap (128×128 tiles, 1 byte per tile)Тайлмап (128×128 тайлов, 1 байт на тайл)
0x08000–0x08FFF4 KBSprite flags (256 × 1 byte, 8 flags per sprite)Флаги спрайтов (256 × 1 байт, 8 флагов на спрайт)
0x09000–0x09FFF4 KBReserved (SFX / music)Зарезервировано (SFX / музыка)
0x0A000–0x1EFFF84 KBGeneral-purpose RAM (user data)Пользовательская RAM (данные игры)
0x1F000–0x1FFFF4 KBSystem registers (palette, camera, etc.)Системные регистры (палитра, камера и т.д.)

ROM (512 KB) — cartridge code, stored separately from RAM.

ROM (512 КБ) — код картриджа, хранится отдельно от RAM.

VRAM (64 KB) — video buffer (256×256 × 1 byte), separate from main RAM.

VRAM (64 КБ) — видеобуфер (256×256 × 1 байт), отдельно от основной RAM.

Graphics — cls

Графика — cls

cls(color?)

Clear the screen to color (default 0 = black). Also resets cursor to (0,0).

Очистить экран цветом color (по умолчанию 0 = чёрный). Также сбрасывает курсор в (0,0).

cls()         -- clear to black
cls(1)        -- clear to dark blue

Graphics — pset / pget

Графика — pset / pget

pset(x, y, color)

Set pixel at screen position (x, y) to color.

Установить пиксель на экране в позиции (x, y) цветом color.

pget(x, y) → color

Return the color index of the pixel at (x, y). Returns 0 if out of bounds.

Возвращает индекс цвета пикселя в позиции (x, y). Возвращает 0, если координаты за пределами экрана.

pset(10, 20, 8)
local c = pget(10, 20)  -- c == 8

Graphics — color

Графика — color

color(c)

Set the default draw color used when the optional c? argument is omitted from other drawing functions.

Устанавливает цвет рисования по умолчанию, который используется когда необязательный аргумент c? не передан другим функциям рисования.

Graphics — line

Графика — line

line(x0, y0, x1, y1, c?)

Draw a line from (x0,y0) to (x1,y1) using Bresenham's algorithm.

Нарисовать линию от (x0,y0) до (x1,y1) алгоритмом Брезенхема.

line(0, 0, 255, 255, 7)   -- white diagonal

Graphics — rect / rectfill

Графика — rect / rectfill

rect(x, y, w, h, c?)

Draw a rectangle outline. (x,y) is the top-left corner; w and h are width and height in pixels.

Нарисовать контур прямоугольника. (x,y) — верхний левый угол; w и h — ширина и высота в пикселях.

rectfill(x, y, w, h, c?)

Draw a filled rectangle.

Нарисовать закрашенный прямоугольник.

rectfill(10, 10, 50, 30, 8)  -- filled red box
rect(10, 10, 50, 30, 7)      -- white outline

Graphics — circ / circfill

Графика — circ / circfill

circ(cx, cy, r, c?)

Draw a circle outline with center (cx,cy) and radius r.

Нарисовать контур окружности с центром (cx,cy) и радиусом r.

circfill(cx, cy, r, c?)

Draw a filled circle.

Нарисовать закрашенный круг.

circfill(128, 128, 40, 10)  -- filled yellow circle

Graphics — oval / ovalfill

Графика — oval / ovalfill

oval(x0, y0, x1, y1, c?)

Draw an ellipse outline inscribed in the bounding box (x0,y0)–(x1,y1).

Нарисовать контур эллипса, вписанного в ограничивающий прямоугольник (x0,y0)–(x1,y1).

ovalfill(x0, y0, x1, y1, c?)

Draw a filled ellipse.

Нарисовать закрашенный эллипс.

Graphics — print / cursor

Графика — print / cursor

print(text, x?, y?, c?)

Draw text at (x, y) in color c. Uses the built-in 4×6 bitmap font. If x/y are omitted, uses the current cursor position. Advances cursor after printing.

Нарисовать текст в позиции (x, y) цветом c. Использует встроенный растровый шрифт 4×6. Если x/y не указаны, используется текущая позиция курсора. После вывода курсор смещается.

print("SCORE: "..score, 2, 2, 7)
cursor(x, y, c?)

Set the text cursor position (used by print when coordinates are omitted). Optionally sets default color.

Установить позицию текстового курсора (используется функцией print когда координаты не указаны). Необязательно задаёт цвет по умолчанию.

Graphics — camera

Графика — camera

camera(x, y)

Set the camera offset. All subsequent draw calls are offset by (-x, -y). Call camera(0,0) to reset.

Установить смещение камеры. Все последующие вызовы рисования смещаются на (-x, -y). Вызовите camera(0,0) для сброса.

camera(cam_x, cam_y)
map(0, 0, 0, 0, 16, 16)
camera(0, 0)   -- draw HUD at fixed position
print("HP: "..hp, 2, 2, 8)

Graphics — clip

Графика — clip

clip(x, y, w, h)

Set the clipping region. Only pixels within this rectangle are drawn.

Установить область отсечения. Рисуются только пиксели внутри этого прямоугольника.

clip()

Reset clipping to full screen.

Сбросить отсечение на весь экран.

Graphics — pal / palt

Графика — pal / palt

pal(c0, c1, p?)

Remap color c0 to c1. p=0 (default) affects the draw palette; p=1 affects the display palette (applied at blit time).

Перемаппировать цвет c0 на c1. p=0 (по умолчанию) изменяет палитру рисования; p=1 изменяет палитру отображения (применяется при блите).

pal()

Reset all palette mappings to identity.

Сбросить все маппинги палитры к исходным.

palt(c, t)

Set transparency for color c. If t is true, pixels of color c are not drawn (transparent). Only color 0 is transparent by default.

Установить прозрачность для цвета c. Если t равно true, пиксели цвета c не рисуются (прозрачны). По умолчанию прозрачен только цвет 0.

palt()

Reset transparency table to defaults (color 0 transparent, all others opaque).

Сбросить таблицу прозрачности к значениям по умолчанию (цвет 0 прозрачный, остальные непрозрачные).

palt(0, false)  -- make black opaque
palt(3, true)   -- make dark green transparent

Sprites — spr

Спрайты — spr

Note: Sprite 255 is reserved as the game icon. Set it via the SET ICON button in the Sprite Editor. It is displayed in the game catalog (32–36 px in-console, 64×64 px on the website). Do not use sprite 255 for in-game graphics.
Примечание: Спрайт 255 зарезервирован как иконка игры. Установите его через кнопку SET ICON в редакторе спрайтов. Он отображается в каталоге игр (32–36 px в приставке, 64×64 px на сайте). Не используйте спрайт 255 для игровой графики.
spr(n, x, y, w?, h?, flipX?, flipY?)

Draw sprite number n at screen position (x, y). w and h are the number of sprites wide/tall to draw (default 1×1). flipX/flipY mirror the sprite.

Нарисовать спрайт номер n на экране в позиции (x, y). w и h — количество спрайтов по ширине/высоте (по умолчанию 1×1). flipX/flipY зеркалят спрайт.

spr(1, x, y)               -- sprite 1, 8x8
spr(2, x, y, 2, 2)         -- 16x16 from sprites 2,3,18,19
spr(1, x, y, 1, 1, true)   -- flipped horizontally

Sprites — sget / sset

Спрайты — sget / sset

sget(x, y) → color

Get the color of pixel (x,y) in the sprite sheet. Coordinates are in sprite-sheet pixel space (0–127 × 0–127).

Получить цвет пикселя (x,y) в листе спрайтов. Координаты в пространстве листа спрайтов (0–127 × 0–127).

sset(x, y, c?)

Set pixel (x,y) in the sprite sheet to color c (or default color).

Установить пиксель (x,y) в листе спрайтов цветом c (или цветом по умолчанию).

Map — map

Карта — map

map(tileX, tileY, sx, sy, tileW, tileH, layers?)

Draw a section of the tilemap. (tileX, tileY) is the top-left tile in map space; (sx, sy) is the screen destination; (tileW, tileH) is the number of tiles to draw. layers is a bitmask filtering sprite flags (e.g. 0x1 draws only tiles with flag 0 set).

Нарисовать секцию тайлмапа. (tileX, tileY) — верхний левый тайл в пространстве карты; (sx, sy) — позиция на экране; (tileW, tileH) — количество тайлов для рисования. layers — битовая маска для фильтрации по флагам спрайтов (например, 0x1 рисует только тайлы с установленным флагом 0).

map(0, 0, 0, 0, 32, 32)   -- draw 32x32 tiles at screen origin

Map — mget / mset

Карта — mget / mset

mget(x, y) → n

Return the sprite number stored at tilemap cell (x, y).

Возвращает номер спрайта в ячейке тайлмапа (x, y).

mset(x, y, val)

Set tilemap cell (x, y) to sprite number val.

Установить ячейку тайлмапа (x, y) в номер спрайта val.

Input — btn / btnp

Управление — btn / btnp

btn(id) → boolean

Returns true while button id is held down. Button IDs:

Возвращает true, пока кнопка id зажата. Идентификаторы кнопок:

IDButtonКнопкаKeyboardКлавиша
0LeftВлево← / A
1RightВправо→ / D
2UpВверх↑ / W
3DownВниз↓ / S
4A / OZ
5B / XX
6StartEnter
btnp(id) → boolean

Returns true only on the first frame a button is pressed (not held). Useful for menus and single-press actions.

Возвращает true только в первый кадр нажатия кнопки (не при удержании). Удобно для меню и действий по одному нажатию.

if btnp(4) then
  fire_bullet()
end

Input — Mouse / Touch

Управление — Мышь / Касание

mx() → number

Returns the mouse cursor X position in screen coordinates (0–255). Returns -1 if the cursor is outside the console screen.

On mobile, returns the X position of the active touch on the game screen.

Возвращает X-позицию курсора мыши в экранных координатах (0–255). Возвращает -1, если курсор за пределами экрана консоли.

На мобильных устройствах возвращает X-позицию активного касания на экране игры.

my() → number

Returns the mouse cursor Y position in screen coordinates (0–255). Returns -1 if outside the screen.

Возвращает Y-позицию курсора мыши в экранных координатах (0–255). Возвращает -1, если курсор за пределами экрана.

mbtn(b) → boolean

Returns true while mouse button b is held. b=0 is the left button or primary touch. Other values always return false (reserved for future use).

Возвращает true, пока кнопка мыши b зажата. b=0 — левая кнопка или основное касание. Другие значения всегда возвращают false (зарезервировано для будущего использования).

if mbtn(0) then
  circfill(mx(), my(), 4, 7)
end
mbtnp(b) → boolean

Returns true only on the first frame the mouse button is pressed (edge trigger, like btnp). Useful for click actions.

Возвращает true только в первый кадр нажатия кнопки мыши (фронт сигнала, как btnp). Удобно для обработки кликов.

if mbtnp(0) then
  spawn_particle(mx(), my())
end

Note: Coordinates are in screen space (0–255), independent of the camera offset. Guard against off-screen with if mx() >= 0 then.

Примечание: Координаты в экранном пространстве (0–255), независимо от смещения камеры. Защититесь от выхода за экран: if mx() >= 0 then.

Sound — sfx

Звук — sfx

sfx(n, vol?)

Play sound effect number n (0–7). vol controls volume from 0.0 to 1.0 (default 1.0). Sound effects are defined in the cartridge SFX editor.

Воспроизвести звуковой эффект номер n (0–7). vol управляет громкостью от 0.0 до 1.0 (по умолчанию 1.0). Звуковые эффекты задаются в редакторе SFX картриджа.

sfx(0)          -- play sfx 0 at full volume
sfx(2, 0.5)     -- play sfx 2 at half volume

Built-in SFX Presets

Встроенные пресеты SFX

SlotСлотCharacterХарактерUsageПрименение
0Low hitНизкий ударDeath, damage, loseСмерть, урон, проигрыш
1Soft bumpМягкий бампPick up item, touchПодбор предмета, касание
2Medium stepСредний шагInteraction, footstepВзаимодействие, шаг
3Neutral beepНейтральный бипMenu navigation, selectНавигация, выбор
4Rising toneПодъёмCoin, score pointМонета, очко
5High pitchВысокийJump, launch, startПрыжок, запуск
6ExplosionВзрывDestruction, crashРазрушение, столкновение
7VictoryПобедаBonus, level completeБонус, финал уровня

Delta Time — dt

Дельта-время — dt

dtnumber (global variable)

Real time between frames in seconds. At stable 30 FPS, dt ≈ 0.033. Available as a global variable and as an argument to _update(dt). Use it for frame-rate independent movement and timers.

Реальное время между кадрами в секундах. При стабильных 30 FPS: dt ≈ 0.033. Доступна как глобальная переменная и как аргумент _update(dt). Используйте для движения и таймеров, независимых от частоты кадров.

function _update(dt)
  x += speed * dt       -- pixels per second
  timer -= dt            -- countdown in seconds
end

Math — t / time

Математика — t / time

t() / time() → number

Return elapsed time in seconds since the cartridge started.

Возвращает время в секундах, прошедшее с момента запуска картриджа.

circfill(128 + cos(t()) * 50, 128, 4, 10)

Math — arithmetic functions

Математика — арифметические функции

flr(x)

Floor (round down to nearest integer).

Нижнее округление (до ближайшего целого вниз).

ceil(x)

Ceiling (round up).

Верхнее округление (вверх).

sqrt(x)

Square root.

Квадратный корень.

abs(x)

Absolute value.

Абсолютное значение.

min(a, b) / max(a, b)

Return the smaller/larger of two values.

Возвращает меньшее/большее из двух значений.

mid(a, b, c)

Return the median (middle value) of three numbers. Useful for clamping: mid(0, x, 255).

Возвращает медиану (среднее значение) из трёх чисел. Удобно для ограничения диапазона: mid(0, x, 255).

sgn(x)

Return 1 if x ≥ 0, -1 if x < 0.

Возвращает 1, если x ≥ 0, и -1, если x < 0.

Math — trigonometry

Математика — тригонометрия

sin(x) / cos(x)

Sine/cosine. Input is in turns (0–1 = full circle), not radians. sin(0.25) = 1, cos(0) = 1. Note: sin is negated compared to standard math (y increases downward).

Синус/косинус. Аргумент задаётся в оборотах (0–1 = полный круг), не в радианах. sin(0.25) = 1, cos(0) = 1. Примечание: sin инвертирован относительно стандартной математики (y увеличивается вниз).

local px = 128 + cos(t() * 0.5) * 40
local py = 128 + sin(t() * 0.5) * 40
atan2(dx, dy) → turns

Return angle in turns (0–1) from the origin to (dx, dy). Useful for aiming.

Возвращает угол в оборотах (0–1) от начала координат до (dx, dy). Удобно для прицеливания.

Math — rnd / srand

Математика — rnd / srand

rnd(x) → number

Return a random number in [0, x). If x is a table, return a random element.

Возвращает случайное число в диапазоне [0, x). Если x — таблица, возвращает случайный элемент.

local n = flr(rnd(256))   -- random 0-255
local item = rnd(loot_table)
srand(seed)

Seed the random number generator for reproducible sequences.

Устанавливает зерно генератора случайных чисел для воспроизводимых последовательностей.

Memory — peek / poke

Память — peek / poke

peek(addr) → byte

Read one byte from memory address addr.

Прочитать один байт из адреса памяти addr.

poke(addr, val)

Write one byte to memory address addr.

Записать один байт по адресу памяти addr.

peek2/poke2 — 16-bit  |  peek4/poke4 — 32-bit

Multi-byte read/write variants. Values are little-endian.

Многобайтовые варианты чтения/записи. Значения в формате little-endian.

Memory — memcpy / memset

Память — memcpy / memset

memcpy(dst, src, len)

Copy len bytes from address src to address dst.

Копировать len байт из адреса src по адресу dst.

memset(dst, val, len)

Fill len bytes starting at dst with byte value val.

Заполнить len байт начиная с dst байтовым значением val.

memset(0x4000, 0, 0x4000)  -- zero all user RAM

String functions

Строковые функции

split(str, sep) → table

Split a string by separator sep and return a table of substrings.

Разбить строку по разделителю sep и вернуть таблицу подстрок.

sub(str, i, j) → string

Return a substring from index i to j (1-based, inclusive).

Возвращает подстроку от индекса i до j (нумерация с 1, включительно).

chr(n) → string

Return the single-character string for character code n.

Возвращает строку из одного символа с кодом n.

ord(str, i?) → number

Return the character code at position i (default 1) in str.

Возвращает код символа в позиции i (по умолчанию 1) в строке str.

tostr(x) / tonum(str)

Convert a number to string or string to number.

Преобразовать число в строку или строку в число.

print(tostr(score), 2, 2, 7)
local n = tonum("42")  -- n == 42

Table functions

Функции таблиц

add(t, v)

Append value v to table t (equivalent to table.insert).

Добавить значение v в конец таблицы t (аналог table.insert).

del(t, v)

Remove the first occurrence of value v from table t.

Удалить первое вхождение значения v из таблицы t.

deli(t, i)

Remove element at index i from table t.

Удалить элемент с индексом i из таблицы t.

count(t) → number

Return the number of elements in table t (same as #t for sequences).

Возвращает количество элементов в таблице t (аналог #t для последовательностей).

all(t) → iterator

Return an iterator for use in for … in all(t) loops.

Возвращает итератор для использования в циклах for … in all(t).

foreach(t, fn)

Call fn(v) for each element v in table t.

Вызвать fn(v) для каждого элемента v в таблице t.

foreach(bullets, update_bullet)
for b in all(bullets) do
  circfill(b.x, b.y, 2, 7)
end

DataStore — Save & Load

Сохранение данных

save_score(score)

Save a numeric score for the current game. Only saves if score is higher than the previous best.

Сохранить числовой результат для текущей игры. Сохраняется только если score больше предыдущего лучшего.

save_score(150)  -- saves 150 as best score
save_score(100)  -- ignored (100 < 150)
load_score() → number

Load the current player's best score for this game. Returns 0 if no data exists.

Загрузить лучший результат текущего игрока в этой игре. Возвращает 0, если данных нет.

best = load_score()
print("BEST: "..best, 10, 10, 7)
get_leaderboard(n) → table

Return top-N players (max 10) for the current game. Each entry: {name="...", score=N}. Results are cached for 30 seconds.

Возвращает топ-N игроков (макс. 10) для текущей игры. Каждый элемент: {name="...", score=N}. Результат кешируется на 30 секунд.

top = get_leaderboard(5)
for i, e in pairs(top) do
  print(i..". "..e.name.." "..e.score, 10, 10+i*8, 7)
end
load_game_score(game_name) → number

Load the current player's best score in a different game (by name).

Загрузить лучший результат текущего игрока в другой игре (по имени).

snake_best = load_game_score("Snake")

Modules & Libraries

Модули и библиотеки

PLUTO-8 uses a single require() function to load both cartridge modules and platform libraries.

Loading Priority

require("name") searches in this order:

  1. Cartridge modules — files inside your project
  2. Platform libraries — built-in PLUTO-8 libraries

Cartridge Modules

The code editor supports up to 256 modules per cartridge.

  • Main — the entry point module. Always present, cannot be deleted.
  • Additional modules — helper code loaded via require("name").
  • Switch between modules using the dropdown at the top of the editor.
  • Modules can be renamed and deleted (except Main).
  • Each module must return a value (typically a table).

Platform Libraries

LibraryDescription
collisionAABB, circle-circle, point-in-rect, circle-rect checks
tweenEasing functions (linear, ease in/out, cubic, bounce) and lerp
particlesSimple particle system (emit, update, draw)
timerTimer system: delayed and repeating actions
geom2D geometry: distance, angle, normalize, rotate, lerp
sceneScene/state manager with transitions
gameobjectEntity management with tagging
spriteAnimated sprites with rotation and bounding box

Example

PLUTO-8 использует единую функцию require() для подключения модулей картриджа и платформенных библиотек.

Приоритет загрузки

require("name") ищет в следующем порядке:

  1. Модули картриджа — файлы внутри вашего проекта
  2. Платформенные библиотеки — встроенные библиотеки PLUTO-8

Модули картриджа

Редактор кода поддерживает до 256 модулей в одном картридже.

  • Main — главный модуль, точка входа. Всегда присутствует, удалить нельзя.
  • Дополнительные модули — вспомогательный код, подключаемый через require("name").
  • Переключение между модулями через dropdown в верхней части редактора.
  • Модули можно переименовывать и удалять (кроме Main).
  • Каждый модуль должен возвращать значение через return (обычно таблицу).

Платформенные библиотеки

БиблиотекаОписание
collisionAABB, circle-circle, point-in-rect, circle-rect коллизии
tweenEasing-функции (linear, ease in/out, cubic, bounce) и lerp
particlesПростая система частиц (emit, update, draw)
timerТаймеры: отложенные и повторяющиеся действия
geom2D-геометрия: расстояние, угол, нормализация, поворот, lerp
sceneМенеджер сцен с переходами
gameobjectСистема сущностей с тегами
spriteАнимированные спрайты с rotation и bounding box

Пример

-- Module "utils":
local utils = {}
function utils.lerp(a, b, t) return a + (b - a) * t end
function utils.clamp(v, lo, hi) return max(lo, min(hi, v)) end
return utils

-- Module "Main":
local utils = require("utils")        -- cartridge module
local col = require("collision")      -- platform library

function _init()
  x = 128
end

function _update()
  x = utils.lerp(x, mx(), 0.2)
end

function _draw()
  cls(0)
  circfill(utils.clamp(x, 10, 246), 128, 10, 10)
end

Library — timer

Библиотека — timer

Timer system for delayed and repeating actions. Call timer.update() every frame in _update().

Система таймеров для отложенных и повторяющихся действий. Вызывайте timer.update() каждый кадр в _update().

timer.after(sec, fn) → handle

Call fn once after sec seconds. Returns a handle that can be passed to timer.cancel().

Вызвать fn один раз через sec секунд. Возвращает handle для отмены через timer.cancel().

timer.every(sec, fn) → handle

Call fn repeatedly every sec seconds.

Вызывать fn каждые sec секунд.

timer.cancel(handle)

Cancel a scheduled timer by its handle.

Отменить запланированный таймер по его handle.

timer.update()

Advance all timers. Must be called in _update() every frame.

Обновить все таймеры. Должна вызываться в _update() каждый кадр.

timer.clear()

Remove all active timers.

Удалить все активные таймеры.

local tmr = require("timer")

function _init()
  tmr.after(2, function() sfx(7) end)
  tmr.every(0.5, function() spawn_enemy() end)
end

function _update()
  tmr.update()
end

Library — geom

Библиотека — geom

2D geometry helpers: distance, angle, normalization, rotation, interpolation and point-in-rect test.

Вспомогательные функции 2D-геометрии: расстояние, угол, нормализация, поворот, интерполяция и проверка точки в прямоугольнике.

geom.dist(x1, y1, x2, y2) → number

Euclidean distance between two points.

Евклидово расстояние между двумя точками.

geom.angle(x1, y1, x2, y2) → radians

Angle in radians from point (x1,y1) to (x2,y2).

Угол в радианах от точки (x1,y1) до (x2,y2).

geom.norm(x, y) → nx, ny

Normalize a 2D vector to unit length. Returns (0,0) if the input is zero.

Нормализовать 2D-вектор до единичной длины. Возвращает (0,0) если вход нулевой.

geom.dot(x1, y1, x2, y2) → number

Dot product of two 2D vectors.

Скалярное произведение двух 2D-векторов.

geom.rot(x, y, a) → rx, ry

Rotate vector (x,y) by a radians around the origin.

Повернуть вектор (x,y) на a радиан вокруг начала координат.

geom.lerp2(x1, y1, x2, y2, t) → ix, iy

Linearly interpolate between two 2D points. t=0 returns (x1,y1), t=1 returns (x2,y2).

Линейная интерполяция между двумя 2D-точками. t=0 возвращает (x1,y1), t=1 возвращает (x2,y2).

geom.in_rect(px, py, rx, ry, rw, rh) → boolean

Returns true if point (px,py) is inside the rectangle (rx, ry, rw, rh).

Возвращает true, если точка (px,py) находится внутри прямоугольника (rx, ry, rw, rh).

local g = require("geom")

local d = g.dist(x1, y1, x2, y2)
local nx, ny = g.norm(dx, dy)
if g.in_rect(mx(), my(), 10, 10, 50, 20) then
  print("HOVER", 10, 10, 7)
end

Library — scene

Библиотека — scene

Scene/state manager. Register named scenes with lifecycle callbacks, then switch between them with scene.go().

Менеджер сцен/состояний. Регистрируйте именованные сцены с колбэками жизненного цикла, затем переключайтесь между ними через scene.go().

scene.reg(name, {enter, update, draw, leave})

Register a scene with the given name. The table may contain enter, update, draw, and leave functions (all optional).

Зарегистрировать сцену с указанным именем. Таблица может содержать функции enter, update, draw и leave (все необязательные).

scene.go(name, ...)

Switch to the named scene. Calls leave() on the current scene and enter(...) on the new one. Extra arguments are passed to enter.

Переключиться на указанную сцену. Вызывает leave() текущей сцены и enter(...) новой. Дополнительные аргументы передаются в enter.

scene.update() / scene.draw()

Delegate to the current scene's update/draw callback. Call these from your global _update() and _draw().

Делегирует вызов в update/draw текущей сцены. Вызывайте из глобальных _update() и _draw().

scene.cur() → string

Return the name of the currently active scene.

Возвращает имя текущей активной сцены.

local sc = require("scene")

sc.reg("menu", {
  draw = function()
    cls(0)
    print("PRESS START", 90, 128, 7)
  end,
  update = function()
    if btnp(6) then sc.go("game") end
  end
})

sc.reg("game", {
  enter = function() score = 0 end,
  update = function() score = score + 1 end,
  draw = function()
    cls(1)
    print("SCORE: "..score, 2, 2, 7)
  end
})

function _init() sc.go("menu") end
function _update() sc.update() end
function _draw() sc.draw() end

Library — gameobject

Библиотека — gameobject

Lightweight entity management with optional tagging. Create objects, update/draw them in bulk, and query by tag.

Легковесная система сущностей с опциональными тегами. Создавайте объекты, обновляйте/рисуйте их массово и запрашивайте по тегу.

gameobject.new({x, y, tag, update, draw}) → obj

Create and register a new game object. Fields x, y, tag, update, draw are all optional. The object is automatically tracked. Set obj.alive = false to destroy it on the next update cycle.

Создать и зарегистрировать новый игровой объект. Поля x, y, tag, update, draw необязательны. Объект автоматически отслеживается. Установите obj.alive = false для удаления в следующем цикле обновления.

gameobject.update() / gameobject.draw()

Call update(self) / draw(self) on every alive object, then remove dead ones.

Вызвать update(self) / draw(self) для всех живых объектов, затем удалить мёртвые.

gameobject.all(tag?) → table

Return a table of all alive objects, optionally filtered by tag.

Вернуть таблицу всех живых объектов, опционально отфильтрованных по tag.

gameobject.count(tag?) → number

Return the count of alive objects, optionally filtered by tag.

Вернуть количество живых объектов, опционально по тегу.

gameobject.clear(tag?)

Destroy all objects, or only those matching tag.

Уничтожить все объекты или только с указанным tag.

local go = require("gameobject")

function _init()
  go.new({
    x = 128, y = 128, tag = "player",
    update = function(self)
      if btn(0) then self.x = self.x - 2 end
      if btn(1) then self.x = self.x + 2 end
    end,
    draw = function(self)
      circfill(self.x, self.y, 4, 8)
    end
  })
end

function _update() go.update() end
function _draw() cls(0) go.draw() end

Library — sprite

Библиотека — sprite

Animated sprite system with rotation, flipping and bounding box support. Also extends the collision library with sprite-aware checks.

Система анимированных спрайтов с вращением, отражением и bounding box. Также расширяет библиотеку collision функциями для спрайтов.

sprite.anim(name, {frames}, fps)

Define a named animation. frames is a table of sprite indices; fps is playback speed.

Определить именованную анимацию. frames — таблица индексов спрайтов; fps — скорость воспроизведения.

sprite.new(n, x, y) → s

Create a sprite instance at (x,y) showing sprite n. Fields: s.x, s.y, s.flipX, s.flipY, s.rot (0–1, in turns), s.w, s.h (size in sprites, default 1).

Создать экземпляр спрайта в (x,y) с номером спрайта n. Поля: s.x, s.y, s.flipX, s.flipY, s.rot (0–1, в оборотах), s.w, s.h (размер в спрайтах, по умолчанию 1).

sprite.play(s, name)

Start playing the named animation on sprite s. If already playing the same animation, does nothing.

Запустить именованную анимацию на спрайте s. Если та же анимация уже проигрывается — ничего не делает.

sprite.update(s) / sprite.draw(s)

Advance sprite animation and draw it at its current position.

Обновить анимацию спрайта и нарисовать его в текущей позиции.

sprite.bbox(s) → x, y, w, h

Return the axis-aligned bounding box of the sprite (in pixels).

Возвращает ограничивающий прямоугольник спрайта (в пикселях).

local sp = require("sprite")

sp.anim("walk", {1, 2, 3, 4}, 8)
sp.anim("idle", {1}, 1)

local hero
function _init()
  hero = sp.new(1, 128, 128)
  sp.play(hero, "idle")
end

function _update()
  if btn(1) then
    hero.x = hero.x + 2
    hero.flipX = false
    sp.play(hero, "walk")
  elseif btn(0) then
    hero.x = hero.x - 2
    hero.flipX = true
    sp.play(hero, "walk")
  else
    sp.play(hero, "idle")
  end
  sp.update(hero)
end

function _draw()
  cls(0)
  sp.draw(hero)
end

Touch / Mouse Input

Тач / мышь

sprite.tapped(s) → boolean

True if the sprite was tapped/clicked this frame (mbtnp(0) and cursor inside bounding box).

True если спрайт нажат/кликнут в этом кадре (mbtnp(0) и курсор внутри bounding box).

sprite.held(s) → boolean

True if touch/mouse button is held down on the sprite (mbtn(0) and cursor inside bounding box).

True если касание/кнопка мыши удерживается на спрайте (mbtn(0) и курсор внутри bounding box).

sprite.hover(s) → boolean

True if cursor is over the sprite (no button press required).

True если курсор находится над спрайтом (нажатие не требуется).

local sp = require("sprite")
local btn1 = sp.new(10, 100, 100)

function _update()
  if sp.tapped(btn1) then sfx(0) end
  if sp.hover(btn1) then btn1.n = 11
  else btn1.n = 10 end
end

Collision + Sprite Extensions

Collision + расширения для спрайтов

When both collision and sprite are loaded, the following additional functions become available:

Когда загружены и collision, и sprite, становятся доступны дополнительные функции:

collision.sprites(s1, s2) → boolean

AABB collision test between two sprite objects (uses their bounding boxes).

AABB-проверка коллизии между двумя спрайт-объектами (по их bounding box).

collision.sprite_point(s, px, py) → boolean

Check if point (px,py) is inside the sprite's bounding box.

Проверить, находится ли точка (px,py) внутри bounding box спрайта.

collision.sprite_tag(s, objs) → boolean

Check sprite s against a list of objects (from gameobject.all(tag)). Returns true if any object's bounding box overlaps.

Проверить спрайт s против списка объектов (из gameobject.all(tag)). Возвращает true, если bounding box любого объекта пересекается.

local col = require("collision")
local sp = require("sprite")
local go = require("gameobject")

if col.sprites(hero, enemy) then
  sfx(0)
end

if col.sprite_point(hero, mx(), my()) then
  print("CLICKED", 2, 2, 7)
end

if col.sprite_tag(hero, go.all("coin")) then
  score = score + 1
end

Library — physics

Библиотека — physics

2D physics engine with gravity, dynamic/static/sensor bodies (rectangles and circles), impulse-based collision response, explosions and spatial queries.

2D-физический движок с гравитацией, динамическими/статическими/сенсорными телами (прямоугольники и круги), импульсным откликом на столкновения, взрывами и пространственными запросами.

World

Мир

physics.world(gx, gy) → world

Create a physics world with gravity vector (gx, gy). Default (0, 0).

Создать физический мир с вектором гравитации (gx, gy). По умолчанию (0, 0).

physics.step(w)

Advance physics simulation by one frame. Call in _update(). Automatically uses sub-stepping (up to 8 steps) at high velocities to prevent tunneling through thin walls.

Продвинуть физическую симуляцию на один кадр. Вызывать в _update(). Автоматически разбивает шаг на подшаги (до 8) при высоких скоростях для предотвращения туннелирования через тонкие стены.

physics.gravity(w, gx, gy)

Change the world's gravity vector.

Изменить вектор гравитации мира.

Bodies

Тела

physics.body(w, kind, x, y, w, h) → body

Create a rectangular body. kind: "dynamic", "static", or "sensor".

Создать прямоугольное тело. kind: "dynamic", "static" или "sensor".

physics.circle(w, kind, x, y, r) → body

Create a circular body with radius r.

Создать круглое тело с радиусом r.

physics.remove(w, b)

Remove a body from the world.

Удалить тело из мира.

Body properties: b.x, b.y — position; b.vx, b.vy — velocity; b.bounce — restitution (0–1, default 0.2); b.friction — friction (0–1, default 0.1); b.mass — mass (default 1); b.tag — string tag.

Свойства тела: b.x, b.y — позиция; b.vx, b.vy — скорость; b.bounce — упругость (0–1, по умолчанию 0.2); b.friction — трение (0–1, по умолчанию 0.1); b.mass — масса (по умолчанию 1); b.tag — строковый тег.

Forces

Силы

physics.push(b, fx, fy)

Apply force (acceleration = F/mass).

Приложить силу (ускорение = F/масса).

physics.impulse(b, ix, iy)

Instantly change velocity.

Мгновенно изменить скорость.

physics.blast(w, x, y, r, force)

Radial explosion: push all dynamic bodies within radius r away from (x, y).

Радиальный взрыв: оттолкнуть все динамические тела в радиусе r от точки (x, y).

Queries

Запросы

physics.at(w, px, py) → table

Return all bodies that contain point (px, py).

Вернуть все тела, содержащие точку (px, py).

physics.overlaps(w, rx, ry, rw, rh) → table

Return all bodies that overlap a rectangle.

Вернуть все тела, пересекающие прямоугольник.

Collision Callback

Коллбэк столкновений

w.on_collide = function(a, b)

Called when two bodies collide. Return false to ignore the collision.

Вызывается при столкновении двух тел. Верните false, чтобы игнорировать столкновение.

local phys = require("physics")
local w = phys.world(0, 0.3)

-- ground
phys.body(w, "static", 0, 240, 256, 16)

-- bouncing balls
for i = 1, 10 do
  local b = phys.circle(w, "dynamic", 64 + rnd(128), rnd(100), 4 + rnd(4))
  b.bounce = 0.6
end

function _update()
  phys.step(w)
  if mbtnp(0) then phys.blast(w, mx(), my(), 40, 5) end
end

function _draw()
  cls(0)
  for _,b in ipairs(w.bodies) do
    if b.shape=="c" then circfill(b.x, b.y, b.r, 10)
    else rectfill(b.x, b.y, b.w, b.h, 5) end
  end
  print("TAP TO EXPLODE", 60, 2, 7)
end