
| Manual | Physics | Operations | Others |
A new created project consists of a meta info asset (“info.json”) and an entry source (“main.lua”). The meta info indicates basic information of the project in JSON. The entry is where the project starts to execute. You can add supported existing file or create new blank assets into a project. All text-based assets use Unix LF (‘\n’) for line ending.
Note that it requires external programs to open file dialogs on Linux for opening, saving, exporting, etc. Make sure that at least one of the following is available: “zenity”, “kdialog”, “matedialog”, “qarma”.
All assets are stored as raw files under a specific directory in this format.
A text-based project archive is a plain text file with the “*.bit” extension, with all assets encoded in printable UTF-8 characters or Base64 string. This format uses Unix LF (‘\n’) for line ending.
A binary-based project archive is just a compressed ZIP package replaced with the “*.bit” extension.
Bitty Engine makes backup once you save an asset or a project, click “Project”, “Browse Data Directory…” to locate it.
There are shortcuts to capture canvas during running.
Bitty project is programmable in the Lua programming language.
Lua is widely used and validated in the software industry, there are a lot of learning materials about the language on the internet. Click to see on the Wikipedia or read the official documentations.
Lua is 1-based for list accessing, Bitty Engine follows the same convention for sequenced structures, like Bytes, File, etc. Otherwise it is 0-based for coordinates and graphical units, like Noiser, Pathfinder, Image, Sprite, Palette, Map, etc.
This document uses a meta method form to describe operators. Eg. foo:__len() denotes #foo, foo:__add(bar) denotes foo + bar, foo:__unm() denotes -foo, etc. Just write the symbol form #, +, -, etc. in your calculation.
Additionally, this is not about the syntax, but for description convenience in this document, optional parameter is described between square brackets [optional]; default value is appended after an equal sign foo = 42; variadic list is described as ....
Lua uses GC to free unused memory automatically, thus you don’t have to do so manually most of the time. However resources loaded by Resources.load(...) are not, consider unloading them properly. See Resources for details.
The ready to use modules, package, coroutine, math, table, string, utf8, debug are reserved from the original language.
The trivial modules, io, os are removed. Bitty Engine offers alternatives.
Bitty Engine offers some handy built-in functions, some are reserved from the original but the behaviour is improved, some are extended.
Functions
print(...): outputs some values to the console window as message, for debugging purposeswarn(...): outputs some values to the console window as warn, for debugging purposeserror(...): outputs some values to the console window as error, and stops execution, for debugging purposes
msgbox(msg): popups a message box with the specific content
msg: the message stringinput(prompt[, default]): popups an input box
prompt: the prompt on the boxdefault: the default contentnil for canceledexit(): exits execution of the current programA conventional entry program of Bitty project is made up of a setup function which is called once program starts, and an update which is called periodically:
function setup()
end
function update(delta)
end
Define another quit function to run code on execution termination:
function quit()
end
Define focusLost, focusGained functions to run code on focus changed:
function focusLost()
end
function focusGained()
end
Define a fileDropped function to run code on file dropped:
function fileDropped(paths) -- For desktop only.
end
Define a rendererReset function to run code on renderer reset:
function rendererReset()
end
Define a call function for callback from JavaScript to Lua (for HTML build only). See Invoking for details.
function call()
end
Generally setup is used to initial game variables, states, update is where gameplay logic and rendering goes, and quit is for persisting necessary data on disk. All these entries above are optional.
Bitty Engine uses a timeout mechanism to avoid unexpected infinite loops, it raises an error when any invoking to the entries takes more than 10 seconds by default. The timeout value can be changed by Debug.setTimeout(…).
This module generates 2D or 3D noise values.
Constructors
Noiser.new(): constructs a noiser objectMethods
noiser:setOption(key, val): sets option value of the specific key
key: the option key to setval: the value to setAvailable options:
| Key | Value | Note |
|---|---|---|
| “frequency” | Real number | Defaults to 0.01 |
| “noise_type” | Can be one in “open_simplex2”, “open_simplex2s”, “cellular”, “perlin”, “value_cubic”, “value” | Defaults to “open_simplex2” |
| “rotation_type_3d” | Can be one in “none”, “improve_xy_planes”, “improve_xz_planes” | Defaults to “none” |
| “fractal_type” | Can be one in “none”, “fbm”, “ridged”, “pingpong”, “domain_warp_progressive”, “domain_warp_independent” | Defaults to “none” |
| “fractal_octaves” | Integer | Defaults to 3 |
| “fractal_lacunarity” | Real number | Defaults to 2.0 |
| “fractal_gain” | Real number | Defaults to 0.5 |
| “fractal_weighted_strength” | Real number | Defaults to 0.0 |
| “fractal_pingpong_strength” | Real number | Defaults to 2.0 |
| “cellular_distance_function” | Can be one in “euclidean”, “euclidean_sq”, “manhattan”, “hybrid” | Defaults to “euclidean_sq” |
| “cellular_return_type” | Can be one in “cell_value”, “distance”, “distance2”, “distance2_add”, “distance2_sub”, “distance2_mul”, “distance2_div” | Defaults to “distance” |
| “cellular_jitter” | Real number | Defaults to 1.0 |
| “domain_warp_type” | Can be one in “open_simplex2”, “open_simplex2_reduced”, “basic_grid” | Defaults to “open_simplex2” |
| “domain_warp_amplitude” | Real number | Defaults to 1.0 |
noiser:seed(seed): seeds the Noiser for all noise types
seed: the seed integernoiser:get(pos): gets the value at the specific position
pos: the position to get, either Vec2 or Vec3noiser:domainWarp(pos): applies domain warping at the specific position
pos: the position to warp, either Vec2 or Vec3This module performs a pathfinding algorithm on 2D grids.
Constructors
Pathfinder.new(w, n, e, s): constructs a pathfinder object with finite borders
w: the west edge, minimum in the x directionn: the north edge, minimum in the y directione: the east edge, maximum in the x directions: the south edge, maximum in the y directionObject Fields
pathfinder.diagonalCost: gets or sets the walking cost of diagonal direction, defaults to 1.414; set to -1 for not walkableMethods
pathfinder:get(pos): gets the walking cost of a prefilled grid at the specific position
pos: the position to getpathfinder:set(pos, cost): sets the walking cost of a grid, initializes a cost matrix with 1 for all grids when first calling to this function
pos: the position to setcost: the cost value to setpathfinder:clear(): clears prefilled matrix and internal cached datapathfinder:solve(beginPos, endPos, eval): resolves for a possible path with the specific evaluator
beginPos: the beginning positionendPos: the ending positioneval: in form of function (pos) return number end, an invokable object which accepts position and returns the walking cost at that pointVec2, could be emptypathfinder:solve(beginPos, endPos): resolves for a possible path with the prefilled cost matrix
beginPos: the beginning positionendPos: the ending positionVec2, could be emptyGrid coordinates can be any integer, with range of values from -32,767 to 32,767. A cost matrix will be prefilled once calling the pathfinder:set(...) function; this data exists until calling pathfinder:clear(). The pathfinder:solve(...) function prefers to use invokable to get grid cost, and falls to use prefilled matrix if no evaluator provided. Call pathfinder:clear() before solving in either way, if any grid data has been changed.
Walking cost is combined with two parts by multiplicative: neighbor cost and map cost. Neighbor cost stands for how much does it cost to walk from the current grid to its neighbor directions as following, in which D defaults to 1.414:
_________________
| | | |
| D | 1 | D |
|_____|_____|_____|
| | | |
| 1 | | 1 |
|_____|_____|_____|
| | | |
| D | 1 | D |
|_____|_____|_____|
Pathfinder retrieves grid cost from either an evaluator or prefilled matrix. All cost states must be immutable during calling the pathfinder:solve(...) function. It’s not walkable if either part of the cost combination results -1; positive cost means walkable, and the pathfinder prefers lower cost grids.
This module provides a random algorithm organized by object, other than the built-in random function in Lua.
Constructors
Random.new(): constructs a randomizer objectMethods
random:seed([seed]): seeds the randomizer
seed: the seed; omit to seed with the current timerandom:next(low, up): generates a random number
low: the low boundup: the up boundrandom:next(n): generates a random number
random:next(1, n) for a positive n; returns an integer with all bits random for a zero nrandom:next(): generates a random number
This module performs a raycasting algorithm on 2D grids.
Constructors
Raycaster.new(): constructs a raycaster objectObject Fields
raycaster.tileSize: gets or sets the tile size as Vec2, defaults to 8x8raycaster.offset: gets or sets the Raycaster offset as Vec2, defaults to 0, 0Methods
raycaster:solve(rayPos, rayDir, eval): resolves for raycasting
rayPos: the ray positionrayDir: the ray directioneval: in form of function (pos) return boolean end, an invokable object which accepts position and returns true for blocked, false for passVec2 or nil, and a secondary value for intersection index as Vec2 or nilThis module performs a smooth walking algorithm on 2D grids.
Constants
Walker.NoneWalker.LeftWalker.RightWalker.UpWalker.DownConstructors
Walker.new(): constructs a walker objectObject Fields
walker.objectSize: gets or sets the object size as Vec2, defaults to 8x8walker.tileSize: gets or sets the tile size as Vec2, defaults to 8x8walker.offset: gets or sets the Walker offset as Vec2, defaults to 0, 0Methods
walker:solve(objPos, expDir, eval, slidable = 5): resolves for a walking step
objPos: the object positionexpDir: the expected directioneval: in form of function (pos) return boolean, enum end, an invokable object which accepts position and returns true for blocked, false for pass; in addition this evaluator can return a secondary value in Walker.None, Walker.Left, Walker.Right, Walker.Up, Walker.Down for one-way walkslidable: non-zero for slidable at edge, with range of values from 0 to 10Vec2, could be zeroThis module offers manipulations of ZIP package.
Constructors
Archive.new(): constructs an archive objectMethods
archive:open(path, access = Stream.Read): opens an Archive file for reading or writing
path: the Archive file pathaccess: can be one in Stream.Read, Stream.Write, Stream.Append, for reading, truncated writing, non-truncated writing respectivelytrue for success, otherwise falsearchive:close(): closes an opened Archive
true for success, otherwise falsearchive:all(): gets all entry names in the Archive
nilarchive:exists(entry): gets whether the specific entry exists in the Archive
entry: the entry name to look fortrue for exists, otherwise falsearchive:make(entry): makes an entry in the Archive
entry: the entry name to maketrue for success, otherwise falsearchive:toBytes(entry, bytes): reads the specific entry and writes to Bytes
entry: the entry name to readbytes: the Bytes to receive, its cursor will be at the endbytes for success, otherwise nilarchive:fromBytes(entry, bytes): writes the specific entry from Bytes
entry: the entry name to writebytes: the Bytes to retrieve from start till end, its cursor won’t be movedtrue for success, otherwise falsearchive:toFile(entry, path): reads the specific entry and writes to file
entry: the entry name to readpath: the file path to receivetrue for success, otherwise falsearchive:fromFile(entry, path): writes the specific entry from file
entry: the entry name to writepath: the file path to retrievetrue for success, otherwise falsearchive:toDirectory(path): reads all the entries and writes to directory
path: the directory path to receivetrue for success, otherwise falsearchive:fromDirectory(path): writes all the entries from directory
path: the directory path to retrievetrue for success, otherwise falseBeing the same as Lua list, a Bytes’ index starts from 1. Implements a Stream protocol as memory buffer.
Constructors
Bytes.new(): constructs a bytes objectOperators
=bytes[index]: reads a byte from the specific index
index: starts from 1bytes[index]=: writes a byte to the specific index
index: starts from 1bytes:__len(): gets the length in bytesMethods
bytes:peek(): peeks the reading/writing cursor
bytes:poke(index): pokes the reading/writig cursor
index: starts from 1true for success, otherwise falsebytes:count(): gets the length in bytes
bytes:empty(): gets whether the Bytes is empty
true for empty, otherwise falsebytes:endOfStream(): gets whether the cursor is at the end
true for end, otherwise falsebytes:readByte(): reads a byte and moves the cursor forward
bytes:readInt16(): reads a 16-bit signed integer and moves the cursor forward
bytes:readUInt16(): reads a 16-bit unsigned integer and moves the cursor forward
bytes:readInt32(): reads a 32-bit signed integer and moves the cursor forward
bytes:readUInt32(): reads a 32-bit unsigned integer and moves the cursor forward
bytes:readInt64(): reads a 64-bit signed integer and moves the cursor forward
bytes:readSingle(): reads a single precision real number and moves the cursor forward
bytes:readDouble(): reads a double precision real number and moves the cursor forward
bytes:readBytes([expSize[, bytes_]]): reads some Bytes and moves the cursor forward
expSize: optional, the expected size in bytes to read; omit to read till endbytes_: optional, Bytes to receive, its content will be cleared; omit to return a new BytesBytes, its cursor will be at the endbytes:readString([expSize]): reads some text and moves the cursor forward
expSize: optional, the expected size in bytes to read; omit to read till endbytes:readLine(): reads a line of text and moves the cursor forward
bytes:writeByte(val): writes a byte and moves the cursor forward
val: the byte to writebytes:writeInt16(val): writes a 16-bit signed integer and moves the cursor forward
val: the 16-bit signed integer to writebytes:writeUInt16(val): writes a 16-bit unsigned integer and moves the cursor forward
val: the 16-bit unsigned integer to writebytes:writeInt32(val): writes a 32-bit signed integer and moves the cursor forward
val: the 32-bit signed integer to writebytes:writeUInt32(val): writes a 32-bit unsigned integer and moves the cursor forward
val: the 32-bit unsigned integer to writebytes:writeInt64(val): writes a 64-bit signed integer and moves the cursor forward
val: the 64-bit signed integer to writebytes:writeSingle(val): writes a single precision real number and moves the cursor forward
val: the single precision real number to writebytes:writeDouble(val): writes a double precision real number and moves the cursor forward
val: the double precision real number to writebytes:writeBytes(bytes_[, expSize]): writes some Bytes and moves the cursor forward
bytes_: the Bytes to write from start till end, its cursor won’t be movedexpSize: optional, the expected size in bytes to write; omit to write till bytes_’s endbytes:writeString(val): writes some text and moves the cursor forward
val: the string to writebytes:writeLine(val): writes a line of text and moves the cursor forward
val: the line to writebytes:get(index): gets a byte at the specific index, doesn’t moves the cursor
index: the index to get, starts from 1bytes:set(index, val): sets a byte to the specific index, doesn’t moves the cursor
index: the index to set, starts from 1val: the byte to setbytes:resize(expSize): resizes the Bytes
expSize: the expected new sizebytes:clear(): clears all content and resets the cursorConstructors
Color.new(r, g, b, a = 255): constructs a color object
r: the red component, with range of values from 0 to 255g: the green component, with range of values from 0 to 255b: the blue component, with range of values from 0 to 255a: the alpha component, with range of values from 0 to 255Color.new(): constructs a color object in whiteOperators
color:__add(color_): adds with another Color componentwiselycolor:__sub(color_): subtracts by another Color componentwiselycolor:__mul(num): multiplies with another number
num: real numbercolor:__mul(color_): multiplies with another Color componentwisely
color_: with range of values from 0 to 255 for each componentcolor:__mul(vec4): multiplies with another Vec4 componentwisely
vec4: real number for each componentcolor:__unm(): takes the opposite Color componentwiselycolor:__eq(color_): compares with another Color for equalityObject Fields
color.r: gets or sets the red componentcolor.g: gets or sets the green componentcolor.b: gets or sets the blue componentcolor.a: gets or sets the alpha componentMethods
color:toRGBA(): converts the Color to an RGBA integer in little-endiancolor:fromRGBA(int): fills the Color with an RGBA integer in little-endianStatic Functions
DateTime.utc(): gets the current UTC time
sec (0-based), min (0-based), hr (0-based, since midnight), mday (1-based, day of the month), mo (1-based), yr (since C.E.), wday (1-based, days since Sun.), yday (1-based, days since 1, Jan.), isdst (daylight saving time flag, always 0 for UTC)DateTime.now(): gets the current local time
sec (0-based), min (0-based), hr (0-based, since midnight), mday (1-based, day of the month), mo (1-based), yr (since C.E.), wday (1-based, days since Sun.), yday (1-based, days since 1, Jan.), isdst (daylight saving time flag)DateTime.ticks(): gets a high precision timestamp
DateTime.toMilliseconds(ticks): converts nanoseconds to milliseconds
ticks: nanosecondsDateTime.fromMilliseconds(ms): converts milliseconds to nanoseconds
ms: millisecondsDateTime.toSeconds(ticks): converts nanoseconds to seconds
ticks: nanosecondsDateTime.fromSeconds(sec): converts seconds to nanoseconds
sec: secondsDateTime.sleep(ms): sleeps for the specific milliseconds
ms: millisecondsStatic Functions
Base64.encode(bytes): encodes the specific Bytes to Base64 string
bytes: the Bytes to encode from start till end, its cursor won’t be movedBase64.decode(txt): decodes the specific Base64 string to Bytes
txt: Base64 string to decodeBytes, its cursor will be at the endStatic Functions
Lz4.encode(bytes): encodes the specific Bytes to LZ4 encoded Bytes
bytes: the Bytes to encode from start till end, its cursor won’t be movedBytesLz4.decode(bytes): decodes the specific LZ4 Bytes to Bytes
bytes: LZ4 Bytes to decodeBytes, its cursor will be at the endBeing the same as Lua list, a File’s index starts from 1. Implements a Stream protocol as file on disk.
Constructors
File.new(): constructs a file objectOperators
file:__len(): gets the length in bytesMethods
file:open(path, access = Stream.Read): opens a File for reading or writing
path: the File pathaccess: can be one in Stream.Read, Stream.Write, Stream.Append, Stream.ReadWrite, for reading, truncated writing, non-truncated writing, reading and writing respectivelytrue for success, otherwise falsefile:close() closes an opened File
true for success, otherwise falsefile:peek(): peeks the reading/writing cursor
file:poke(index): pokes the reading/writing cursor
index: starts from 1true for success, otherwise falsefile:count(): gets the length in bytes
file:empty(): gets whether the File is empty
true for empty, otherwise falsefile:endOfStream(): gets whether the cursor is at the end
true for end, otherwise falsefile:readByte(): reads a byte and moves the cursor forward
file:readInt16(): reads a 16-bit signed integer and moves the cursor forward
file:readUInt16(): reads a 16-bit unsigned integer and moves the cursor forward
file:readInt32(): reads a 32-bit signed integer and moves the cursor forward
file:readUInt32(): reads a 32-bit unsigned integer and moves the cursor forward
file:readInt64(): reads a 64-bit signed integer and moves the cursor forward
file:readSingle(): reads a single precision real number and moves the cursor forward
file:readDouble(): reads a double precision real number and moves the cursor forward
file:readBytes([expSize[, bytes]]): reads some Bytes and moves the cursor forward
expSize: optional, the expected size in bytes to read; omit to read till endbytes: optional, Bytes to receive, its content will be cleared; omit to return a new BytesBytes, its cursor will be at the endfile:readString([expSize]): reads some text and moves the cursor forward
expSize: optional, the expected size in bytes to read; omit to read till endfile:readLine(): reads a line of text and moves the cursor forward
file:writeByte(): writes a byte and moves the cursor forward
val: the byte to writefile:writeInt16(): writes a 16-bit signed integer and moves the cursor forward
val: the 16-bit signed integer to writefile:writeUInt16(): writes a 16-bit unsigned integer and moves the cursor forward
val: the 16-bit unsigned integer to writefile:writeInt32(): writes a 32-bit signed integer and moves the cursor forward
val: the 32-bit signed integer to writefile:writeUInt32(): writes a 32-bit unsigned integer and moves the cursor forward
val: the 32-bit unsigned integer to writefile:writeInt64(): writes a 64-bit signed integer and moves the cursor forward
val: the 64-bit signed integer to writefile:writeSingle(): writes a single precision real number and moves the cursor forward
val: the single precision real number to writefile:writeDouble(): writes a double precision real number and moves the cursor forward
val: the double precision real number to writefile:writeBytes(bytes[, expSize]): writes some Bytes and moves the cursor forward
bytes: the Bytes to write from start till end, its cursor won’t be movedexpSize: optional, the expected size in bytes to write; omit to write till bytes’s endfile:writeString(val): writes some text and moves the cursor forward
val: the string to writefile:writeLine(val): writes a line of text and moves the cursor forward
val: the line to writeNote that when open a file as Stream.Append, it always writes data at the end of the file, expanding it, and file:poke(...) are ignored.
Static Functions
Path.combine(...): combines a number of paths
Path.split(full): splits the specific path into parts
name, ext, parentPath.existsFile(path): gets whether the specific file exists
path: the file pathtrue for exists, otherwise falsePath.existsDirectory(path): gets whether the specific directory exists
path: the directory pathtrue for exists, otherwise falsePath.copyFile(src, dst): copies the specific file to a new path
src: the source pathdst: the destination pathtrue for success, otherwise falsePath.copyDirectory(src, dst): copies the specific directory to a new path recursively
src: the source pathdst: the destination pathtrue for success, otherwise falsePath.moveFile(src, dst): moves the specific file to a new path
src: the source pathdst: the destination pathtrue for success, otherwise falsePath.moveDirectory(src, dst): moves the specific directory to a new path recursively
src: the source pathdst: the destination pathtrue for success, otherwise falsePath.removeFile(path, toTrashBin): removes the specific file
path: the file pathtoTrashBin: true to remove to the trash bin, otherwise remove permanentlytrue for success, otherwise falsePath.removeDirectory(path, toTrashBin): removes the specific directory recursively
path: the directory pathtoTrashBin: true to remove to the trash bin, otherwise remove permanentlytrue for success, otherwise falsePath.touchFile(path): tries to create a file at the specific path, will touch its ancestors
path: the file pathtrue for success, otherwise falsePath.touchDirectory(path): tries to create a directory at the specific path, will touch its ancestors
path: the directory pathtrue for success, otherwise falseStatic Variables
Path.executableFile: readonly, gets the executable file pathPath.documentDirectory: readonly, gets the documents directory pathPath.writableDirectory: readonly, gets the writable directory pathPath.savedGamesDirectory: readonly, gets the “Saved Games” directory path on Windows, or same as Path.writableDirectory on other platformsConstructors
FileInfo.new(path): constructs a file information object with the specific path
path: the file pathDirectoryInfo.new(path): constructs a directory information object with the specific path
path: the directory pathMethods
fileInfo:fullPath(): gets the full path
fileInfo:parentPath(): gets the path of the parent directory
fileInfo:fileName(): gets the file name
fileInfo:extName(): gets the extension name
fileInfo:empty(): gets whether the file represented by the FileInfo is empty
true if empty, otherwise falsefileInfo:exists(): gets whether the file represented by the FileInfo exists
true for exists, otherwise falsefileInfo:make(): makes a file represented by the FileInfo if it doesn’t exist, fails if its ancestors don’t exist
true for success, otherwise falsefileInfo:copyTo(dst): copies the file represented by the FileInfo to a new path
dst: the destination pathtrue for success, otherwise falsefileInfo:moveTo(dst): moves the file represented by the FileInfo to a new path
dst: the destination pathtrue for success, otherwise falsefileInfo:remove(toTrashBin): removes the file represented by the FileInfo
toTrashBin: true to remove to the trash bin, otherwise remove permanentlytrue for success, otherwise falsefileInfo:rename(newName[, newExt]): renames the file represented by the FileInfo
newName: the new file namenewExt: the new extension name; omit to keep the oldtrue for success, otherwise falsefileInfo:parent(): gets the DirectoryInfo of the FileInfo’s parent
DirectoryInfo of its parentfileInfo:readAll(): reads all content of the file represented by the FileInfo as string
directoryInfo:fullPath(): gets the full path
directoryInfo:parentPath(): gets the path of the parent directory
directoryInfo:dirName(): gets the directory name
directoryInfo:empty(): gets whether the directory represented by the DirectoryInfo is empty
true if empty, otherwise falsedirectoryInfo:exists(): gets whether the directory represented by the DirectoryInfo exists
true for exists, otherwise falsedirectoryInfo:make(): makes a directory represented by the DirectoryInfo if it doesn’t exist, fails if its ancestors don’t exist
true for success, otherwise falsedirectoryInfo:copyTo(dst): copies the directory represented by the DirectoryInfo to a new path
dst: the destination pathtrue for success, otherwise falsedirectoryInfo:moveTo(dst): moves the directory represented by the DirectoryInfo to a new path
dst: the destination pathtrue for success, otherwise falsedirectoryInfo:remove(toTrashBin): removes the directory represented by the DirectoryInfo
toTrashBin: true to remove to the trash bin, otherwise remove permanentlytrue for success, otherwise falsedirectoryInfo:rename(newName): renames the directory represented by the DirectoryInfo
newName: the new directory nametrue for success, otherwise falsedirectoryInfo:getFiles(pattern = '*.*', recursive = false): gets sub-files under the directory represented by the DirectoryInfo
pattern: lookup pattern, supports wildcards, eg. "*.txt;*.json"recursive: whether lookup its sub-directoriesFileInfo objectsdirectoryInfo:getDirectories(recursive = false): gets sub-directories under the directory represented by the DirectoryInfo
recursive: whether lookup its sub-directoriesDirectoryInfo objectsdirectoryInfo:parent(): gets the DirectoryInfo of this DirectoryInfo’s parent
DirectoryInfo of its parentConstructors
Image.new(palette): constructs an image object with the specific Palette asset
palette: the Palette loaded by Resources.load(...)Image.new(): constructs a true-color image objectObject Fields
image.channels: readonly, gets the channels of the Image, 1 for paletted, 4 for true-colorimage.width: readonly, gets the width of the Imageimage.height: readonly, gets the height of the ImageMethods
image:resize(width, height, stretch = true): resizes the Image with the specific size
width: the widthheight: the heightstretch: true to stretch the Image, otherwise to cliptrue for success, otherwise falseimage:get(x, y): gets the Color or Palette index at the specific index
x: starts from 0y: starts from 0Color or palette indeximage:set(x, y, val): sets the Color or Palette index at the specific index
x: starts from 0y: starts from 0val: Color or Palette indextrue for success, otherwise falseimage:blit(dst, x, y[, w, h[, sx, sy]]): blits the Image to another one
dst: the specific destination Imagex: the destination xy: the destination yw: the destination widthh: the destination heightsx: the source xsy: the source ytrue for success, otherwise falseimage:fromImage(img): loads content from another Image
img: the specific Image to loadtrue for success, otherwise falseimage:fromBlank(width, height, paletted = 0): loads blank content
width: the specific widthheight: the specific heightpaletted: 0 for true-color, non-zero for palettedtrue for success, otherwise falseimage:toBytes(bytes, type = 'png'): encodes the Image to Bytes
bytes: the Bytes to receive, its cursor will be at the endtype: can be one in “png”, “jpg”, “bmp”, “tga”, “img”bytes for success, otherwise nilimage:fromBytes(bytes): decodes the specific Bytes
bytes: the Bytes to retrieve from start till end, its cursor won’t be movedtrue for success, otherwise falseConstants
Json.NullConstructors
Json.new(): constructs a JSON objectMethods
json:toString(pretty = true): serializes the Json to string
pretty: whether to serialize in a friendly to read formatjson:fromString(txt): parses Json data from the specific string
txt: the text to parsetrue for success, otherwise falsejson:toTable(allowNull = false): serializes the Json to Lua table
allowNull: true to convert Json null to Json.Null, otherwise to Lua niljson:fromTable(tbl): parses Json data from the specific Lua table, ignores incompatible data types
tbl: the table to parsetrue for success, otherwise falseConstants
Vec2
Vec2.Zero: equals to Vec2.new(0, 0)Vec2.One: equals to Vec2.new(1, 1)Vec2.Left: equals to Vec2.new(-1, 0)Vec2.Right: equals to Vec2.new(1, 0)Vec2.Up: equals to Vec2.new(0, -1)Vec2.Down: equals to Vec2.new(0, 1)Vec3
Vec3.Zero: equals to Vec3.new(0, 0, 0)Vec3.One: equals to Vec3.new(1, 1, 1)Vec4
Vec4.Zero: equals to Vec4.new(0, 0, 0, 0)Vec4.One: equals to Vec4.new(1, 1, 1, 1)Static Functions
Rect
Rect.byXYWH(x, y, w, h): constructs a rectangle object in real numbers by position and sizeRecti
Recti.byXYWH(x, y, w, h): constructs a rectangle object in integers by position and sizeConstructors
Vec2
Vec2.new([x, y]): constructs a vector object in 2 dimensionsVec3
Vec3.new([x, y, z]): constructs a vector object in 3 dimensionsVec4
Vec4.new([x, y, z, w]): constructs a vector object in 4 dimensionsRect
Rect.new([x0, y0, x1, y1]): constructs a rectangle object in real numbers by pointsRecti
Recti.new([x0, y0, x1, y1]): constructs a rectangle object in integers by pointsRot
Rot.new([s, c]): constructs a rotation objectOperators
Vec2
vec2:__add(vec2_): adds with another Vec2 componentwiselyvec2:__sub(vec2_): subtracts by another Vec2 componentwiselyvec2:__mul(num): multiplies with another numbervec2:__mul(vec2_): multiplies with another Vec2 componentwiselyvec2:__unm(): takes the opposite Vec2 componentwiselyvec2:__len(): gets the length of the Vec2vec2:__eq(vec2_): compares with another Vec2 for equalityVec3
vec3:__add(vec3_): adds with another Vec3 componentwiselyvec3:__sub(vec3_): subtracts by another Vec3 componentwiselyvec3:__mul(num): multiplies with another numbervec3:__mul(vec3_): multiplies with another Vec3 componentwiselyvec3:__unm(): takes the opposite Vec3 componentwiselyvec3:__len(): gets the length of the Vec3vec3:__eq(vec3_): compares with another Vec3 for equalityVec4
vec4:__add(vec4_): adds with another Vec4 componentwiselyvec4:__sub(vec4_): subtracts by another Vec4 componentwiselyvec4:__mul(num): multiplies with another numbervec4:__mul(vec4_): multiplies with another Vec4 componentwiselyvec4:__unm(): takes the opposite Vec4 componentwiselyvec4:__eq(vec4_): compares with another Vec4 for equalityRot
rot:__add(rot_): adds with another Rot in anglerot:__sub(rot_): subtracts by another Rot in anglerot:__mul(vec2): rotates another Vec2rot:__mul(rot_): rotates another Rotrot:__unm(): takes the opposite Rot in anglerot:__eq(rot_): compares with another Rot for equalityRect
rect:__eq(rect_): compares with another Rect for equalityRectirecti:__eq(recti_): compares with another Recti for equalityObject Fields
Vec2
vec2.x: gets or sets the x componentvec2.y: gets or sets the y componentvec2.normalized: readonly, gets the normalized Vec2vec2.length: readonly, gets the lengthvec2.angle: readonly, gets the rotated angle in radians as a vectorVec3
vec3.x: gets or sets the x componentvec3.y: gets or sets the y componentvec3.z: gets or sets the z componentvec3.normalized: readonly, gets the normalized Vec3vec3.length: readonly, gets the lengthVec4
vec4.x: gets or sets the x componentvec4.y: gets or sets the y componentvec4.z: gets or sets the z componentvec4.w: gets or sets the w componentRot
rot.s: gets or sets the sine componentrot.c: gets or sets the cosine componentrot.angle: gets or sets the angle in radians denoted by the RotRect
rect.x0: gets or sets the first x componentrect.y0: gets or sets the first y componentrect.x1: gets or sets the second x componentrect.y1: gets or sets the second y componentRecti
recti.x0: gets or sets the first x componentrecti.y0: gets or sets the first y componentrecti.x1: gets or sets the second x componentrecti.y1: gets or sets the second y componentMethods
Vec2
vec2:normalize(): normalizes the Vec2
vec2:distanceTo(vec2_): gets the distance between this and another Vec2
vec2:dot(vec2_): applies a dot multiplication
vec2:cross(num): applies a cross multiplication
Vec2vec2:cross(vec2_): applies a cross multiplication
vec2:angleTo(vec2_): gets the angle between this and another Vec2 as vectors
vec2:rotated(angle[, pivot]): gets the rotated Vec2
angle: the angle to rotatepivot: the pivot Vec2 to rotate aroundVec2vec2:rotated(rot[, pivot]): gets the rotated Vec2
rot: the Rot to rotatepivot: the pivot Vec2 to rotate aroundVec2Vec3
vec3:normalize(): normalizes the Vec3
vec3:dot(vec3_): applies a dot multiplication
Rect
rect:xMin(): gets the minimum x componentrect:yMin(): gets the minimum y componentrect:xMax(): gets the maximum x componentrect:xMax(): gets the maximum y componentrect:width(): gets the width, equals to rect:xMax() - rect:xMin()rect:height(): gets the height, equals to rect:yMax() - rect:yMin()Recti
recti:xMin(): gets the minimum x componentrecti:yMin(): gets the minimum y componentrecti:xMax(): gets the maximum x componentrecti:xMax(): gets the maximum y componentrecti:width(): gets the width, equals to rect:xMax() - rect:xMin() + 1recti:height(): gets the height, equals to rect:yMax() - rect:yMin() + 1Static Functions
Math.intersects(shapeA, shapeB): detects whether two shapes intersects with each other
shapeA: the first shapeshapeB: the second shapetrue for intersects, otherwise falseBoth shape parameters can be:
Vec2Vec4, x, y for first point, z, w for secondVec3, x, y for center, z for radiusRect; Recti is supported as well, but converted to Rect internally to determine against other shapes except for another RectiConstants
Network.NoneNetwork.UdpNetwork.TcpConstructors
Network.new(onRecv[, onEstb[, onDisc]]): constructs a network object
onRecv: callback on receivedonEstb: callback on connection establishedonDisc: callback on connection disconnectedThe callback of received event is an invokable in form of function (data, size, addr) end, which accepts three parameters respectively represent for the data has been just received, the data size corresponding to specific types, and the remote adress string. The type of the first parameter is determined by the “data_type” option.
The callback of connection established is an invokable in form of function (addr) end, which accepts a parameter represents for the remote address string; nil for failure for outcoming connection. It’s invoked when either incoming or outcoming connection established; ignored by UDP.
The callback of disconnected is an invokable in form of function (addr) end, which accepts a parameter represents for the remote address string. It’s invoked when either incoming or outcoming connection disconnected; ignored by UDP.
Object Fields
network.ready: readonly, gets whether the Network is readyMethods
network:getOption(key): gets the option value of the specific key
key: the option key to getnetwork:setOption(key, val): sets option value of the specific key
key: the option key to setval: the value to setCurrently there is only one available option:
| Key | Value | Note |
|---|---|---|
| “data_type” | Can be one in “stream”, “bytes”, “string”, “json”, defaults to “json” | Data type for transmission/datagram |
network:open(addr[, protocal]): opens a Network as either server or client
addr: the addressprotocal: can be one in Network.Udp, Network.Tcptrue for success, otherwise falsenetwork:close(): closes a Network, clears all options; will neither be impossible to send nor receive anything after closing
true for success, otherwise falseAn addr argument is combined with four parts, direction, protocol, address and port:
| Part | Value |
|---|---|
| Direction | > for connecting, < for listening |
| Protocol | udp://, tcp:// |
| Address | IP address |
| Port | Port number |
For example:
| Address string | Connectivity |
|---|---|
| “>tcp://192.168.0.1:12000” | As client, connects to 192.168.0.1 port 12000 via TCP |
| “<udp://127.0.0.1:12000” | As server, listens from local host port 12000 via UDP |
| “udp://192.168.0.1:12000” | As client, sends to 192.168.0.1 port 12000 via UDP |
| “tcp://12000” | As server, listens from port 12000 via TCP |
| “192.168.0.1:12000” | As client, connects to 192.168.0.1 port 12000, protocal determined by the explicit protocal parameter |
| “12000” | As server, listens from port 12000, protocal determined by the explicit protocal parameter |
network:poll([timeoutMs]): polls pending Network events manually; do not need to call this function if a program already entered the update(delta) loop
timeoutMs: the timeout valuenetwork:disconnect(): disconnects from remote peersnetwork:send(bytes): sends the specific Bytes
bytes: the Bytes to sendtrue for success, otherwise falsenetwork:send(txt): sends the specific string
txt: the string to sendtrue for success, otherwise falsenetwork:send(json): sends the specific Json
json the Json to sendtrue for success, otherwise falsenetwork:send(tbl): sends the specific Lua table as Json
tbl the Lua table to sendtrue for success, otherwise falsenetwork:broadcast(bytes): broadcasts the specific Bytes
bytes: the Bytes to broadcasttrue for success, otherwise falsenetwork:broadcast(txt): broadcasts the specific string
txt: the string to broadcasttrue for success, otherwise falsenetwork:broadcast(json): broadcasts the specific Json
json: the Json to broadcasttrue for success, otherwise falsenetwork:broadcast(tbl): broadcasts the specific Lua table as Json
tbl: the Lua table to broadcasttrue for success, otherwise falseA single transmission or datagram cannot be longer than 512KB.
Consider closing and setting a Network object to nil as soon as it’s no longer in use.
For “stream”, it sends and receives raw Bytes, you are free parsing and serializing for your own protocol.
For “bytes”, an extra 32-bit unsigned integer will be automatically packed at head of Bytes before sending, the size head itself also counts; Bytes parameter in the received callback doesn’t contain that head. In short words, it’s transparent between Bitty Engine projects, but it’s helpful to communicate with other endpoints to distinguish different messages, and you have to adapt the rule for other Network endpoints.
For both “string” and “json”, the underneath data flow always end up with a zero byte, vice versa, received string and Json must end up with a terminal zero byte.
Static Functions
Platform.surf(url): surfs the Internet via browser
url: the URL address to surfPlatform.browse(dir): browses the filesystem via explorer
dir: the directory path to browsePlatform.hasClipboardText(): gets whether there is text content in the clipboard
true for nonempty, otherwise falsePlatform.getClipboardText(): gets the text content in the clipboard
Platform.setClipboardText(txt): sets the text content in the clipboard
txt: the text to setPlatform.execute(cmd): executes the specific system command; this function invokes native command on desktops, and JavaScript function in browser
cmd: the command to executePlatform.openFile([title[, filter[, multiselect]]]): popups an open-file-dialog
title: the title textfilter: the file filter, eg. "Text files (*.txt);*.txt;All files (*.*);*"multiselect: true for multiselect, false for single file selectnil for canceledPlatform.saveFile([title[, filter]]): popups a save-file-dialog
title: the title textfilter: the file filternil for canceledPlatform.selectDirectory([title]): popups a select-directory-dialog
title: the title textnil for canceledStatic Variables
Platform.os: readonly, gets the current running OSPlatform.endian: readonly, gets the current endian
This module declares a minimal protocol to handle asynchronization.
Constants
Promise.PendingPromise.ResolvedPromise.RejectedObject Fields
promise.state: gets the state of the Promise object, can be one in Promise.Pending, Promise.Resolved, Promise.Rejectedpromise.value: gets the fulfilled value of the Promise object, or nilMethods
promise:thus(handler): sets the specific callback to handle on succeeded
handler: in form of function (...) end, an invokable object which accepts optional argumentsPromise itselfpromise:catch(handler): sets the specific callback to handle on failed
handler: in form of function ([err]) end, an invokable objectPromise itselfpromise:finally(handler): sets the specific callback to handle on finished
handler: in form of function () end, an invokable objectPromise itselfThis module contains constants indicating accessibilities for other modules.
Constants
Stream.ReadStream.WriteStream.AppendStream.ReadWriteExperimental feature. This module offers fetching via HTTP.
Functions
Implements a Promise protocol for HTTP accessing and manipulating.
fetch(url[, options]): requests the specific HTTP resource
url: the URL to requestoptions: the option Json or Lua tablePromise objectThe thus handler of the returned Promise object takes an invokable object in form of function (rsp) end which accepts the responded content. The catch handler of the returned Promise object takes an invokable object in form of function (err) end. The finally handler of the returned Promise object takes an invokable object in form of function () end.
For example:
fetch('https://github.com', {
method = 'GET',
headers = {
['Content-Type'] = 'text/html',
['User-Agent'] = 'Mozilla/5.0 Gecko/20100101 Firefox/83.0'
}
})
:thus(function (rsp)
print(rsp)
end)
:catch(function (err)
print('Error.')
end)
:finally(function ()
print('Finished.')
end)
| Option | Values | Description |
|---|---|---|
method |
“GET”, “POST”, “PUT”, “DELETE”, etc. | Specific method to perform HTTP request |
headers |
Valid HTTP headers | Optional. Header data |
body |
Request body | Optional. Body data |
hint |
“bytes”, “string”, “json” | Optional, defaults to “string”. Prefers how to interpret respond data |
allow_insecure_connection_for_https |
true, false |
Optional, defaults to false, for desktop only. Specifies whether to allow insecure connection for HTTPS |
Static Functions
Resources.load(entry[, hint]): loads a resource from the specific asset entry
entry: the entry name to loadhint: the type hintnilResources.load(path[, hint]): loads a resource from the specific file path
path: the file path to loadhint: the type hintnilResources.load(bytes[, hint]): loads a resource from the specific Bytes; available for Texture, Sfx, Music
bytes: the Bytes to load, its cursor won’t be movedhint: the type hintnilResources.load(str[, hint]): loads a resource from the specific asset content as string
str: the asset content as string to loadhint: the type hintnilResources.load(json[, hint]): loads a resource from the specific Json object
json: the Json to loadhint: the type hintnilResources.load(tbl[, hint]): loads a resource from the specific Lua table; similar to the Json version, but in table form
tbl: the Lua table to loadhint: the type hintnilResources.load(img[, hint]): loads a resource from the specific Image object
img: the Image to loadhint: the type hintnilResources.wait(res): waits until the resource is loaded or timeout
res: the resource to wait fortrue for ready to use, otherwise falseResources.unload(res): unloads a resource
res: the resource to unloadResources.collect(): collects all unused resourcesThe hint can be one in Palette, Texture, Sprite, Map, Sfx, Music. Bitty Engine can infer asset types from extension or content most of the time. However hint is necessary if there is yet insufficient information to tell a type, or to distinguish as either Sfx or Music when loading an audio asset.
For example:
foo = Resources.load('bar.pal') -- Load a palette.
foo = Resources.load({ width = 128, height = 128 }) -- Load a blank texture.
local data = {
width = 8, height = 8,
count = 2,
data = {
{
x = 16, y = 0, width = 8, height = 8,
interval = 0.25,
key = 'idle'
},
{
x = 24, y = 0, width = 8, height = 8,
interval = 0.25,
key = ''
}
},
ref = baz -- Ref by object.
}
foo = Resources.load(data) -- Load a sprite.
local data = {
tiles = {
count = { 8, 8 }
},
width = 60, height = 40,
data = { ... },
ref = 'baz.png' -- Ref by asset name.
}
foo = Resources.load(data) -- Load a map.
foo = Resources.load('bar.mp3', Sfx) -- Load an SFX.
foo = Resources.load('bar.mp3', Music) -- Load a piece of music.
The asynchronous Resources.load(...) returns a resource handle immediately. It is lazy evaluated, loading is deferred until specific reading and writing access happens. The synchronous Resources.wait(...) also loads it, it returns immediately if the specific resource is already loaded, otherwise it waits until loaded or timeout.
Consider using Resources.unload(...) or Resources.collect() to unload unused resources (loaded by Resources.load(...)) periodically and properly, or there would be memory leak. One possible practice is to call Lua’s GC then collect resources after loading a new level, since the old one is no longer in use:
collectgarbage()
Resources.collect()
Can be loaded by Resources.load(...), only happens when Bitty Engine cannot determine specific sub asset type.
Can be loaded by Resources.load(...).
Constructors
Font.new(entry, size = 14 | Vec2.new(8, 8), permeation = 1): constructs a font object from the specific (TrueType or Bitmap) font asset with the specific size and permeation
entry: the entry name to loadsize: can be either a number for TrueType, or a Vec2 for Bitmappermeation: indicates how to blur glyph edges with the alpha channel, with range of values from 0 to 255Font.new(path, size = 14 | Vec2.new(8, 8), permeation = 1): constructs a font object from the specific (TrueType or Bitmap) font file with the specific size and permeation
path: the file path to loadsize: can be either a number for TrueType, or a Vec2 for Bitmappermeation: indicates how to blur glyph edges with the alpha channel, with range of values from 0 to 255Font.new(img, size = Vec2.new(8, 8), permeation = 1): constructs a font object from the specific (Bitmap) Image with the specific size and permeation
img: the Image to loadsize: the size as Vec2 for a characterpermeation: indicates how to blur glyph edges with the alpha channel, with range of values from 0 to 255Font.new(nil, size = 14, permeation = 1): constructs a font object from the default font with the specific size and permeation
size: the size as numberpermeation: indicates how to blur glyph edges with the alpha channel, with range of values from 0 to 255Font is constructed like regular object and managed by GC, do not need to unload it manually. The permeation parameter indicates how to handle font transparency, zero means using values from a font file, while non-zero means a specified threshold for whether a pixel shall pass (non-transparent) or be blocked (transparent).
Can be loaded by Resources.load(...).
Object Fields
texture.width: readonly, gets the Texture widthtexture.height: readonly, gets the Texture heightMethods
texture:blend(mode): sets the blend state of the Texture with the specific mode
mode: the blend mode to set; refer to the blend modes of Canvastrue for success, otherwise falseCan be loaded by Resources.load(...).
Object Fields
sprite.count: readonly, gets the Sprite frame countsprite.width: readonly, gets the Sprite width of every framesprite.height: readonly, gets the Sprite height of every frame
sprite.hFlip: gets or sets whether the Sprite is flipped horizontallysprite.vFlip: gets or sets whether the Sprite is flipped verticallyMethods
sprite:play(beginIndex = -1, endIndex = -1, reset = true, loop = true, async = false): plays the specific animation, use -1 for both begin and end indices to play through all frames
beginIndex: the begin frame index, starts from 0endIndex: the end frame index, starts from 0reset: whether resets to the initial animation frameloop: true for loop, otherwise plays onceasync: true for asynchronously playing, otherwise plays synchronouslytrue for success, otherwise false, and a secondary value for estimated duration if plays synchronously; the secondary value would be always -1 if plays asynchronouslysprite:play(beginStr, reset = true, loop = true, async = false): plays the specific animation
beginStr: the animation name stringreset: whether resets to the initial animation frameloop: true for loop, otherwise plays onceasync: true for asynchronously playing, otherwise plays synchronouslytrue for success, otherwise false, and a secondary value for estimated duration if plays synchronously; the secondary value would be always -1 if plays asynchronouslysprite:pause(): pauses playing
true for success, otherwise falsesprite:resume(): resumes playing
true for success, otherwise falsesprite:stop(): stops playing
true for success, otherwise falseIt communicates across internal threads when play a sprite animation synchronously, this might take lots of time if there are lots of sprites. Consider playing it asynchronously if this matters in your actual project.
Can be loaded by Resources.load(...).
Object Fields
map.width: readonly, gets the Map widthmap.height: readonly, gets the Map heightCan be loaded by Resources.load(...).
Can be loaded by Resources.load(...).
The coordinate definition in Bitty Engine is as follow:

The zero point is to the top-left corner, the x, y axises increase in right, bottom respectively.
Functions
cls([col]): clears the screen with the specific Color
col: optional, defaults to the previous passed value to this functionColorcolor(col): sets the active Color with a specific value
col: the Color to setColorcolor(): resets the active Color to whitesync(): synchronizes commands to graphics manually, also updates Network and Web links
Functions
plot(x, y[, col]): draws a point
x: the x positiony: the y positioncol: omit to use the active Colorline(x0, y0, x1, y1[, col]): draws a line
x0: the first x positiony0: the first y positionx1: the second x positiony1: the second y positioncol: omit to use the active Colorcirc(x, y, r, fill = false[, col]): draws a cicle
x: the x positiony: the y positionr: the radiusfill: true for fillcol: omit to use the active Colorellipse(x, y, rx, ry, fill = false[, col]): draws an ellipse
x: the x positiony: the y positionrx: the x radiusry: the y radiusfill: true for fillcol: omit to use the active Colorpie(x, y, r, startAngle, endAngle, fill = false[, col]): draws a pie
x: the x positiony: the y positionr: the radiusstartAngle: the start angle in radiansendAngle: the end angle in radiansfill: true for fillcol: omit to use the active Colorrect(x0, y0, x1, y1, fill = false[, col[, rad]]): draws a rectangle
x0: the first x positiony0: the first y positionx1: the second x positiony1: the second y positionfill: true for fillcol: omit to use the active Colorrad: the radius of the corner arcs of the rectangletext(txt, x, y[, col, margin = 1, scale = 1]): draws text
txt: the text to drawx: the x positiony: the y positioncol: omit to use the active Colormargin: the margin distancescale: the scale factortri(p0, p1, p2, fill = false[, col]): draws a triangle
p0: Vec2 for the first pointp1: Vec2 for the second pointp2: Vec2 for the third pointfill: true for fillcol: omit to use the active ColorFunctions
pget(res, index): gets the Color from the specific Palette resource
res: the Palette resourceindex: starts from 0Colorpset(res, index, col): sets the Color to the specific Palette resource
res: the Palette resourceindex: starts from 0col: the Color to setFunctions
font(font_): sets the active Font for the text(...) function
font_: the Font resourcefont(): resets the active Font to defaultmeasure(txt, font, margin = 1, scale = 1): measures the size of the specific text
txt: the text to measurefont: the Font to measure with, nil to use defaultmargin: the margin distancescale: the scale factorwidth, height for both dimensions respectivelyFunctions
tex(res, x, y[, w, h[, sx, sy[, sw, sh[, rotAngle, rotCenter = Vec2.new(0.5, 0.5), hFlip = false, vFlip = false, col = Color.new(255, 255, 255, 255)]]]]): draws the specific Texture resource
res: the Texture resourcex: the destination x positiony: the destination y positionw: the destination width; omit to use the resource widthy: the destination height; omit to use the resource heightsx: the source x position to sample, defaults to 0sy: the source y position to sample, defaults to 0sw: the source width to sample, defaults to the resource widthsh: the source height to sample, defaults to the resource heightrotAngle: the rotation angle in radiansrotCenter: the rotation centerhFlip: whether to flip horizontallyvFlip: whether to flip verticallycol: additional Color multiplied to render the TextureFunctions
spr(res, x, y[, w, h[, rotAngle, rotCenter = Vec2.new(0.5, 0.5), col = Color.new(255, 255, 255, 255)]]): draws the specific Sprite resource
res: the Sprite resourcex: the destination x positiony: the destination y positionw: the destination widthy: the destination heightrotAngle: the rotation angle in radiansrotCenter: the rotation centercol: additional Color multiplied to render the SpriteFunctions
map(res, x, y, col = Color.new(255, 255, 255, 255), scale = 1): draws the specific Map resource
res: the Map resourcex: the destination x positiony: the destination y positioncol: additional Color multiplied to render the Mapscale: positive integer, the scale factormget(res, x, y): gets the tile index from the specific Map resource
res: the Map resourcex: starts from 0y: starts from 0mset(res, x, y, cel): sets the tile index to the specific Map resource
res: the Map resourcex: starts from 0y: starts from 0cel: the tile indexFunctions
volume(sfxVol[, musicVol]): sets the audio volume
sfxVol: volume for all SFX channels, with range of values from 0.0 to 1.0musicVol: with range of values from 0.0 to 1.0volume({ sfxVol1, sfxVol2, sfxVol3, sfxVol4 }[, musicVol]): sets the audio volume
{ sfxVol1, sfxVol2, sfxVol3, sfxVol4 }: volume for SFX channels respectively, with range of values from 0.0 to 1.0 at each, -1 to leave as ismusicVol: with range of values from 0.0 to 1.0Functions
play(sfx, loop = false[, fade[, channel]]): plays the specific Sfx resource
sfx: the Sfx resourceloop: true for loop, otherwise plays oncefade: the fade in time in secondschannel: the specific channel to play this sound, starts from 1; omit to pick an available automaticallystop(sfx[, fade]): stops the specific Sfx resource
sfx: the Sfx resourcefade: the fade out time in secondsFunctions
play(music, loop = false[, fade[, pos]]): plays the specific Music resource
music: the Music resourceloop: true for loop, otherwise plays oncefade: the fade in time in secondspos: real number, the specific position in seconds to start from; affects MP3, OGG, WAV, FLAC, and some MOD formatsstop(music[, fade]): stops the specific Music resource
music: the Music resourcefade: the fade out time in secondsA gamepad is a virtual entity, its buttons are binded to a keyboard or an actual gamepad hardware.
Functions
btn([button[, index]]): gets whether the specific gamepad button is pressed
button: the button index; omit to get any keyindex: the gamepad index, starts from 1true for pressed, otherwise falsebtnp([button[, index]]): gets whether the specific gamepad button is released from pressing
button: the button index; omit to get any keyindex: the gamepad index, starts from 1true for released, otherwise falserumble(index, lowHz = 100[, hiHz, ms = 100]): rumbles the specific gamepad, if an actual hardware is binded to any key of the gamepad entity
index: the gamepad index, starts from 1For the button parameter, 0, 1, 2, 3, 4, 5 are for Left, Right, Up, Down, A, B respectively. Seealso the “Gamepad” example under the “Primitives” category.
Functions
key(code): gets whether the specific key is pressed
code: the key code on keyboardtrue for pressed, otherwise falsekeyp(code): gets whether the specific key is released from pressing
code: the key code on keyboardtrue for released, otherwise falseSee keycodes for more readable presentation. Seealso the “Keyboard” example under the “Primitives” category.
Functions
mouse([index]): gets the current mouse (or touch) states
index: always 1 for the mouse, or the finger index with touch screens, starts from 1x, y, b1, b2, b3, wheel for the mouse position and the LMB, RMB, MMB, wheel state respectively, x and y could be NaN if the mouse is outside the canvas, wheel can be negative, positive or zeroSeealso the “Mouse” example under the “Primitives” category.
Functions
camera(x, y): sets the camera offset, affects all coordinate-based primitives
x: the x offsety: the y offsetx, y, or both nil for non-offsetcamera(): resets the camera offset to 0, 0
x, y, or both nil for non-offsetFunctions
clip(x, y, w, h): sets the clip area
x: the x offset to clipy: the y offset to clipw: the clip widthh: the clip heightx, y, w, h, or all nil for non-clipclip(): resets the clip area to none
x, y, w, h, or all nil for non-clipFunctions
blend(mode): sets the blend state with the specific mode
mode: the blend mode to set; refer to the blend modes of Canvasblend(): resets the blend state to alpha blendDue to space limitation in the page, read Physics for details.
Invoke.call(func, ...): invokes a function in the host environment with the specific arguments, this feature is available with HTML build only
func: the function name to invokeThe Invoke.call(func, ...) invokes from Lua to the host environment (for HTML build only). It supports up to 16 parameters.
Bitty Engine supports callback from the host environment to Lua (for HTML build only). To use this feature, you need to define a function on the Lua side with the name call, and the function will be called when the host environment invokes the callback. The function accepts variadic arguments, and the arguments are passed as strings. In JavaScript, call Module.call(arg1, arg2, ..., arg16) to invoke the callback with up to 16 arguments.
To call from JavaScript to Lua, make a “ccall” to call1, call2, etc. i.e.
Module.ccall(
'call2',
'number',
[ 'number', 'number' ],
[ stringToNewUTF8('Hello'), stringToNewUTF8('World') ]
);
Static Functions
Application.setOption(key, ...): sets option value of the specific key
key: the option key to setAvailable options:
| Key | Value | Note | |
|---|---|---|---|
| “title” | String, title |
Sets the title of the application window | |
| “minimum_size” | Integers, width, height |
Sets the minimum size of the application window | |
| “maximum_size” | Integers, width, height |
Sets the maximum size of the application window | |
| “bordered” | Boolean, bordered |
Sets whether the application window is bordered | |
| “resizable” | Boolean, resizable |
Sets whether the application window is resizable | |
| “position” | Integers, x, y |
Sets the position of the application window | |
| “display_index” | Integers, index |
Sets the index where the application window will be displayed on that device | |
| “transparent_color” | Color | nil, color |
Experimental, sets the transparent color key of the application window |
The “transparent_color” option is an experimental feature, it supports Windows 10 and above. Note that it affects the whole application window.
Application.setCursor(img[, x, y]): sets the mouse cursor
img: the specific Image to set, nil to resetx: the spot x, with range of values from 0.0 to 1.0y: the spot y, with range of values from 0.0 to 1.0Application.size(): gets the application window size
width, heightApplication.resize(w, h): resizes the application window; use canvas:resize(...) to resize canvas (the rendering area)
w: the expected widthh: the expected heightApplication.resize(size): resizes the application window
size: can be one in “fullscreen”, “windowed”Application.raise(): raises the application windowConstants
Canvas.BlendModeNoneCanvas.BlendModeBlendCanvas.BlendModeAddCanvas.BlendModeModCanvas.BlendModeMul
Canvas.BlendFactorZeroCanvas.BlendFactorOneCanvas.BlendFactorSrcColorCanvas.BlendFactorOneMinusSrcColorCanvas.BlendFactorSrcAlphaCanvas.BlendFactorOneMinusSrcAlphaCanvas.BlendFactorDstColorCanvas.BlendFactorOneMinusDstColorCanvas.BlendFactorDstAlphaCanvas.BlendFactorOneMinusDstAlpha
Canvas.BlendOperationAddCanvas.BlendOperationSubCanvas.BlendOperationRevSubCanvas.BlendOperationMinCanvas.BlendOperationMaxStatic Functions
Canvas.compose(srcColFactor, dstColFactor, colOp, srcAlphaFactor, dstAlphaFactor, alphaOp): composes a blend value from the specific parameters
srcColFactor: the specific source color factordstColFactor: the specific destination color factorcolOp: the specific color operationsrcAlphaFactor: the specific source alpha factordstAlphaFactor: the specific destination alpha factoralphaOp: the specific alpha operationStatic Variables
Canvas.main: readonly, gets the main CanvasObject Fields
canvas.target: gets or sets the render target of the Canvas, nil for the main canvascanvas.autoCls: gets or sets whether to clear the canvas automatically, either true or falseMethods
canvas:size(): gets the Canvas size
width, heightcanvas:resize(width, height): resizes the Canvas; use Application.resize(...) to resize the whole application
width: the specific width, 0 to adapt automaticallyheight: the specific height, 0 to adapt automaticallytrue for success, otherwise falseProject accepts strategies, add a “strategies” field in “info.json” to enable specific options, eg.
{
...
"strategies": [
"batch_map"
]
}
Currently there is only one available strategy, change and try if it’s needed:
| Strategy | Description | Note |
|---|---|---|
| “batch_map” | Hints to batch map for better rendering performance, but occupies more memory | Always on for HTML build |
| “linear_canvas” | Hints to set canvas filtering as linear | |
| “anisotropic_canvas” | Hints to set canvas filtering as anisotropic |
Constants
Project.new(): constructs a project objectStatic Variables
Project.main: readonly, gets the main ProjectMethods
project:fullPath(): gets the full path of the Project
Project, or nilproject:getAssets([pattern]): gets all asset names in the Project
pattern: lookup pattern, supports wildcardsnilproject:load(path): loads this Project from the specific path; for user constructed Project only
path: the specific path to load fromtrue for success, otherwise falseproject:save(path): saves this Project to the specific path; for user constructed Project only
path: the specific path to save totrue for success, otherwise falseproject:exists(name): gets whether the specific asset exists in the Project
name: the asset name to look fortrue for exists, otherwise falseproject:read(name): reads the content of the specific asset; this method can read all asset types except for code
name: the asset name to readBytes and its cursor will be at the end, or nilproject:write(name, bytes, overwrite = true): writes the specific Bytes to the Project; for user constructed Project only
name: the asset name to writebytes: the Bytes to writeoverwrite: true to overwritetrue for success, otherwise falseproject:remove(name): removes the specific asset from the Project; for user constructed Project only
name: the asset name to removetrue for success, otherwise falseproject:strategies(): gets all effective strategies
nilThis module is used for debugging purposes.
Static Functions
Debug.setBreakpoint(src, ln, brk = true): sets or unsets a breakpoint programmingly
src: the source fileln: the line numberbrk: whether to set or unsettrue for success, otherwise falseDebug.clearBreakpoints([src]): clears breakpoints programmingly
src: the source file to clear; omit to clear all in projecttrue for success, otherwise falseDebug.clearConsole(): clears the console output programminglyDebug.getTimeout(): gets the invoking timeout value
Debug.setTimeout(val): sets the invoking timeout value to the specific seconds
val: the timeout value in seconds, 0 to disable timeoutDebug.setTimeout(): resets the invoking timeout value to default (10 seconds)Debug.trace([message[, level]]): gets the stack trace
Click “Project”, “Import…” to browse and import some assets from a “.bit”, “.txt”, “*.zip” archive. This operation doesn’t overwrite conflictions in your editing project.
Click “Project”, “Export…” to select and export some assets to a “.bit”, “.txt”, “*.zip” archive.
Click “Project”, “Build”, then “Windows”/”MacOS”/”Linux” to make an executable for Windows/MacOS/Linux respectively with the current opened project.
It might require execution permission to launch an exported desktop binary, to apply that permission:
Click “Project”, “Build”, then “HTML” to make an executable for browser with the current opened project. It requires a WebAssembly capable browser.
You can upload it to cloud or host it on your own server for others to play.