Core Concepts /Program Structure

Core Concepts

Program Structure

How a Codetoy program is put together. Setup code runs once, the update loop runs every frame, and events fire on input.

Every Codetoy program has the same three parts:

  1. Setup is code at the top level of your file. It runs once when the program starts.
  2. The update loop is your export function update()Screen.OnUpdate()def update(). It runs every frame, about 60 times a second.
  3. Events fire once when something happens, like a key press or a click.
import { fill, rect, circle } from "codetoy/canvas"
import * as screen from "codetoy/screen"
import { deltaTime } from "codetoy/time"

// 1. Setup: runs once
let x: f64 = 0
let speed: f64 = 200
console.log("Program started")

// 2. Update loop: runs every frame
export function update(): void {
  x += speed * deltaTime()
  if (x > screen.width()) x = 0

  fill(20, 20, 30)
  rect(0, 0, screen.width(), screen.height())
  fill(120, 200, 255)
  circle(x, screen.centerY(), 20)
}

// 3. Events: run once per action
export function onKeyDown(key: string): void {
  if (key == " ") speed = -speed
}
// 1. Setup: runs once
double x = 0;
double speed = 200;
Console.Log("Program started");

// 2. Update loop: runs every frame
Screen.OnUpdate(() => {
    x += speed * Screen.DeltaTime;
    if (x > Screen.Width) x = 0;

    Canvas.Fill(20, 20, 30);
    Canvas.Rect(0, 0, Screen.Width, Screen.Height);
    Canvas.Fill(120, 200, 255);
    Canvas.Circle(x, Screen.CenterY, 20);
});

// 3. Events: run once per action
Input.OnKeyDown((string key) => {
    if (key == " ") speed = -speed;
});
from codetoy.canvas import fill, rect, circle
from codetoy.screen import width, height, centerY
from codetoy.time import deltaTime

# 1. Setup: runs once
x = 0.0
speed = 200.0
print("Program started")

# 2. Update loop: runs every frame
def update():
    global x
    x += speed * deltaTime()
    if x > width():
        x = 0

    fill(20, 20, 30)
    rect(0, 0, width(), height())
    fill(120, 200, 255)
    circle(x, centerY(), 20)

# 3. Events: run once per action
def keyDown(key):
    global speed
    if key == " ":
        speed = -speed

#How Codetoy finds your code

In AssemblyScript, Codetoy calls functions you export from your file by name. An unexported update is never called, so don't forget export.

In C#, you register callbacks. Pass a lambda to Screen.OnUpdate for the update loop and to Input.OnKeyDown, Input.OnMouseDown and the other Input.On… methods for events. Registering again replaces the previous callback.

You can use top-level statements (as in these docs) or a classic static void Main. Codetoy works either way.

In Python, Codetoy looks for top-level functions with specific names after your script runs. Define the ones you need and leave out the rest. You never register anything.

AssemblyScript C# Python
Every frame export function update(): void Screen.OnUpdate(Action) def update()
Canvas resized export function resize(w: f64, h: f64): void Not available def resize(w, h)
Key pressed / released onKeyDown(key: string) / onKeyUp Input.OnKeyDown(Action<string>) / OnKeyUp def keyDown(key) / keyUp
Mouse button pressed / released onMouseDown(button: i32) / onMouseUp Input.OnMouseDown(Action<int>) / OnMouseUp def mouseDown(button) / mouseUp
Touch started / moved onTouchStart(id, x, y) / onTouchMove Input.OnTouchStart(Action<int, double, double>) / OnTouchMove def touchStart(id, x, y) / touchMove
Touch ended onTouchEnd(id: i32) Input.OnTouchEnd(Action<int>) def touchEnd(id)

All events are optional. Details for each are in the Input API and Screen API.

#Keeping state

There are no game objects or components. Your game's state is just variables at the top level of your file, read and changed by export function update()Screen.OnUpdate()def update() and your events.

Python needs a global statement to assign to a module-level variable from inside a function. Without it, Python creates a new local variable instead:

Python
score = 0

def update():
    global score  # required, or `score += 1` raises UnboundLocalError
    score += 1

Declare variables before types

With top-level statements, put all top-level variables and statements above any class, struct or enum declarations. A statement after a type declaration is a compile error.

Give top-level variables an explicit type when the inferred one isn't what you want. let x = 0 is an integer (i32), so write let x: f64 = 0 for a position that moves by fractions of a pixel.

#The frame lifecycle

Each frame, Codetoy:

  1. Delivers any input events that happened since the last frame.
  2. Calls export function update()Screen.OnUpdate()def update().
  3. Shows what you drew.

The canvas is not cleared automatically. Anything you drew last frame is still there, so most programs start export function update()Screen.OnUpdate()def update() by painting a full-screen background. Skipping that is how you get trails and paint effects. See Drawing.

Esc