Luau Guide
What is Luau?
Luau is a fast, small, safe, gradually typed embeddable scripting language derived from Lua. It's developed by Roblox and used in Like2D for game scripting.
Getting Started with Luau
Hello World
print("Hello, Like2D!")
Variables
-- Local variable (recommended)
local x = 10
-- Global variable
y = 20
-- Multiple assignment
local a, b = 1, 2
-- Type annotations (Luau feature)
local name: string = "Player"
local health: number = 100
local isAlive: boolean = true
Data Types
- nil: Represents no value
- boolean: true or false
- number: Double-precision floating point
- string: Text values
- function: Callable functions
- table: Associative arrays (objects, arrays, dictionaries)
Tables
Tables are the only data structure in Luau. They can be used as arrays, dictionaries, or objects:
Array-style tables
local fruits = {"apple", "banana", "cherry"}
print(fruits[1]) -- apple (indices start at 1!)
Dictionary-style tables
local player = {
name = "John",
health = 100,
x = 400,
y = 300
}
print(player.name) -- John
print(player.health) -- 100
Object-oriented style
local Player = {}
Player.__index = Player
function Player.new(name, x, y)
local self = setmetatable({}, Player)
self.name = name
self.x = x
self.y = y
self.health = 100
return self
end
function Player:move(dx, dy)
self.x = self.x + dx
self.y = self.y + dy
end
function Player:takeDamage(amount)
self.health = self.health - amount
end
-- Usage
local player1 = Player.new("Player1", 400, 300)
player1:move(10, 0)
player1:takeDamage(20)
print(player1.health) -- 80
Functions
-- Basic function
function add(a, b)
return a + b
end
-- Local function (recommended)
local function multiply(a, b)
return a * b
end
-- Multiple return values
local function getNameAndAge()
return "Alice", 30
end
local name, age = getNameAndAge()
-- Variable arguments
local function sum(...)
local total = 0
for i, v in ipairs({...}) do
total = total + v
end
return total
end
print(sum(1, 2, 3, 4)) -- 10
Control Flow
If statements
local x = 10
if x > 0 then
print("x is positive")
elseif x < 0 then
print("x is negative")
else
print("x is zero")
end
For loops
-- Numeric for
for i = 1, 10 do
print(i)
end
-- Numeric for with step
for i = 10, 1, -1 do
print(i)
end
-- Generic for (ipairs for arrays)
local fruits = {"apple", "banana", "cherry"}
for i, fruit in ipairs(fruits) do
print(i, fruit)
end
-- Generic for (pairs for dictionaries)
local player = {name = "John", health = 100}
for key, value in pairs(player) do
print(key, value)
end
While loops
local i = 1
while i <= 10 do
print(i)
i = i + 1
end
Repeat-until loops
local i = 1
repeat
print(i)
i = i + 1
until i > 10
String Manipulation
local str = "Hello, Like2D!"
-- Length
print(#str) -- 14
-- Concatenation
local greeting = str .. " How are you?"
-- String functions
print(string.upper(str)) -- HELLO, LIKE2D!
print(string.lower(str)) -- hello, like2d!
print(string.sub(str, 1, 5)) -- Hello
print(string.find(str, "Like2D")) -- 8
Math Library
print(math.pi) -- 3.14159...
print(math.abs(-5)) -- 5
print(math.floor(3.7)) -- 3
print(math.ceil(3.2)) -- 4
print(math.sqrt(16)) -- 4
print(math.random()) -- Random number between 0 and 1
print(math.random(1, 10)) -- Random integer between 1 and 10
-- Set random seed
math.randomseed(os.time())
Table Library
local t = {3, 1, 4, 1, 5}
-- Insert
table.insert(t, 6) -- t becomes {3, 1, 4, 1, 5, 6}
table.insert(t, 2, 9) -- t becomes {3, 9, 1, 4, 1, 5, 6}
-- Remove
table.remove(t, 2) -- t becomes {3, 1, 4, 1, 5, 6}
-- Sort
table.sort(t) -- t becomes {1, 1, 3, 4, 5, 6}
-- Get length
print(#t) -- 6
Luau in Like2D
In Like2D, you write your game logic in Luau. The framework provides callback functions that you implement and a special function for including other files:
Including Other Files (dofile)
To keep your project organized, you can split your code into multiple .luau files and include them using dofile() at the top of your main.luau:
-- main.luau
dofile("anim.luau")
dofile("scripts/utils.luau")
Note: This is much better than having a single 5,000-line file!
Callback Functions
Like2D calls these global functions automatically. Implement them in your main.luau:
-- Called once at startup — load assets and set up state
function onInit()
setWindowTitle("My Game")
setWindowSize(800, 600)
loadImage("assets/player.png")
loadSound("bgm", "assets/music.mp3")
playSound("bgm", true)
end
-- Called every frame BEFORE onDraw() — game logic, input, physics
function onUpdate(dt)
-- dt = seconds since last frame (~0.016 at 60 FPS)
if isKeyDown("Right") then
playerX = playerX + 200 * dt
end
end
-- Called every frame for rendering — draw everything here
function onDraw()
clearScreen(20, 20, 30)
renderImage("assets/player.png", playerX, playerY, 64, 64)
drawTextDirect("Score: " .. score, 10, 10, 24, 255, 255, 255, 255)
end
-- Called once when closing — cleanup and save
function onCleanup()
unloadSound("bgm")
print("Game ended")
end
Best Practices
- Use
localvariables whenever possible (faster and safer) - Load assets in
onInit(), never inonDraw()oronUpdate() - Put game logic and input in
onUpdate(dt), rendering inonDraw() - Use
dt(delta time) for all movement to ensure smooth, frame-rate-independent gameplay - Unload sounds in
onCleanup()to prevent memory leaks - Use meaningful variable and function names
- Comment your code for clarity
- Keep functions small and focused
- Use tables to organize related data
Learning More
- Official Luau Documentation
- Lua 5.1 Manual (Luau is compatible with Lua 5.1)