Guides /Examples

Guides

Examples

Complete, copy-paste programs, from a cursor follower to a small game, each in AssemblyScript, C# and Python.

Every example is a whole program. Paste it into a new codetoy, press ▶ Play and start changing numbers.

#Follow the cursor

A circle that chases the mouse smoothly and logs clicks.

import { fill, rect, circle } from "codetoy/canvas"
import * as screen from "codetoy/screen"
import * as input from "codetoy/input"
import { deltaTime } from "codetoy/time"

let x: f64 = 0
let y: f64 = 0

export function update(): void {
  const k = 1.0 - Math.exp(-8.0 * deltaTime())
  x += (input.mouseX() - x) * k
  y += (input.mouseY() - y) * k

  fill(20, 20, 30)
  rect(0, 0, screen.width(), screen.height())
  fill(0, 150, 255)
  circle(x, y, 30)
}

export function onMouseDown(button: i32): void {
  console.log("Clicked at " + input.mouseX().toString() + ", " + input.mouseY().toString())
}
double x = 0, y = 0;

Screen.OnUpdate(() => {
    double k = 1.0 - Math.Exp(-8.0 * Screen.DeltaTime);
    x += (Input.MouseX - x) * k;
    y += (Input.MouseY - y) * k;

    Canvas.Fill(20, 20, 30);
    Canvas.Rect(0, 0, Screen.Width, Screen.Height);
    Canvas.Fill(0, 150, 255);
    Canvas.Circle(x, y, 30);
});

Input.OnMouseDown((int button) => {
    Console.Log($"Clicked at {Input.MouseX}, {Input.MouseY}");
});
import math
from codetoy.canvas import fill, rect, circle
from codetoy.screen import width, height
from codetoy.time import deltaTime
from codetoy._input import mouseX, mouseY

x, y = 0.0, 0.0

def update():
    global x, y
    k = 1.0 - math.exp(-8.0 * deltaTime())
    x += (mouseX() - x) * k
    y += (mouseY() - y) * k

    fill(20, 20, 30)
    rect(0, 0, width(), height())
    fill(0, 150, 255)
    circle(x, y, 30)

def mouseDown(button):
    print(f"Clicked at {mouseX():.0f}, {mouseY():.0f}")

#Responsive grid

A grid that always fills the screen, whatever its size.

import { fill, rect, noStroke } from "codetoy/canvas"
import * as screen from "codetoy/screen"

const cols = 6
const rows = 4

export function update(): void {
  noStroke()
  fill(30, 30, 30)
  rect(0, 0, screen.width(), screen.height())

  const cw = screen.width() / (cols as f64)
  const ch = screen.height() / (rows as f64)

  for (let row = 0; row < rows; row++) {
    for (let col = 0; col < cols; col++) {
      fill(80 + col * 30, 90 + row * 35, 210)
      rect(col * cw + 4, row * ch + 4, cw - 8, ch - 8, 8)
    }
  }
}
int cols = 6, rows = 4;

Screen.OnUpdate(() => {
    Canvas.NoStroke();
    Canvas.Fill(30, 30, 30);
    Canvas.Rect(0, 0, Screen.Width, Screen.Height);

    double cw = Screen.Width / cols;
    double ch = Screen.Height / rows;

    for (int row = 0; row < rows; row++) {
        for (int col = 0; col < cols; col++) {
            Canvas.Fill(80 + col * 30, 90 + row * 35, 210);
            Canvas.Rect(col * cw + 4, row * ch + 4, cw - 8, ch - 8, 8);
        }
    }
});
from codetoy.canvas import fill, rect, noStroke
from codetoy.screen import width, height

cols, rows = 6, 4

def update():
    noStroke()
    fill(30, 30, 30)
    rect(0, 0, width(), height())

    cw = width() / cols
    ch = height() / rows

    for row in range(rows):
        for col in range(cols):
            fill(80 + col * 30, 90 + row * 35, 210)
            rect(col * cw + 4, row * ch + 4, cw - 8, ch - 8, 8)

#Click to spawn

Every click adds a dot with a random size and color. The dots live in a list, since there are no game objects.

import { fill, rect, circle, noStroke } from "codetoy/canvas"
import * as screen from "codetoy/screen"
import * as input from "codetoy/input"

class Dot {
  constructor(public x: f64, public y: f64, public r: f64, public hue: f64) {}
}

const dots = new Array<Dot>()

export function onMouseDown(button: i32): void {
  dots.push(new Dot(input.mouseX(), input.mouseY(), 6 + Math.random() * 18, Math.random() * 360))
}

export function update(): void {
  noStroke()
  fill(15, 15, 25)
  rect(0, 0, screen.width(), screen.height())

  for (let i = 0; i < dots.length; i++) {
    const d = dots[i]
    fill(128 + Math.cos(d.hue) * 127, 128 + Math.sin(d.hue) * 127, 200)
    circle(d.x, d.y, d.r)
  }
}
var dots = new List<(double X, double Y, double R, int Red, int Green)>();
var rng = new Random();

Input.OnMouseDown((int button) => {
    dots.Add((Input.MouseX, Input.MouseY, 6 + rng.NextDouble() * 18, rng.Next(80, 256), rng.Next(80, 256)));
});

Screen.OnUpdate(() => {
    Canvas.NoStroke();
    Canvas.Fill(15, 15, 25);
    Canvas.Rect(0, 0, Screen.Width, Screen.Height);

    foreach (var d in dots) {
        Canvas.Fill(d.Red, d.Green, 220);
        Canvas.Circle(d.X, d.Y, d.R);
    }
});
import random
from codetoy.canvas import fill, rect, circle, noStroke
from codetoy.screen import width, height
from codetoy._input import mouseX, mouseY

dots = []

def mouseDown(button):
    color = (random.randint(80, 255), random.randint(80, 255), 220)
    dots.append((mouseX(), mouseY(), random.uniform(6, 24), color))

def update():
    noStroke()
    fill(15, 15, 25)
    rect(0, 0, width(), height())

    for x, y, r, (red, green, blue) in dots:
        fill(red, green, blue)
        circle(x, y, r)

#Sine wave

A path that follows a moving sine wave across the screen.

import { fill, rect, stroke, lineWidth, beginPath, moveTo, lineTo, strokePath } from "codetoy/canvas"
import * as screen from "codetoy/screen"
import { elapsedTime } from "codetoy/time"

export function update(): void {
  const t = elapsedTime()
  fill(15, 15, 30)
  rect(0, 0, screen.width(), screen.height())

  stroke(100, 200, 255)
  lineWidth(3)
  beginPath()
  for (let x: f64 = 0; x <= screen.width(); x += 4) {
    const y = screen.centerY() + Math.sin(x * 0.02 + t * 3) * 80
    if (x == 0) moveTo(x, y)
    else lineTo(x, y)
  }
  strokePath()
}
double t = 0;

Screen.OnUpdate(() => {
    t += Screen.DeltaTime;
    Canvas.Fill(15, 15, 30);
    Canvas.Rect(0, 0, Screen.Width, Screen.Height);

    Canvas.Stroke(100, 200, 255);
    Canvas.LineWidth(3);
    Canvas.BeginPath();
    for (double x = 0; x <= Screen.Width; x += 4) {
        double y = Screen.CenterY + Math.Sin(x * 0.02 + t * 3) * 80;
        if (x == 0) Canvas.MoveTo(x, y);
        else Canvas.LineTo(x, y);
    }
    Canvas.StrokePath();
});
import math
from codetoy.canvas import fill, rect, stroke, lineWidth, beginPath, moveTo, lineTo, strokePath
from codetoy.screen import width, height, centerY
from codetoy.time import elapsedTime

def update():
    t = elapsedTime()
    fill(15, 15, 30)
    rect(0, 0, width(), height())

    stroke(100, 200, 255)
    lineWidth(3)
    beginPath()
    for i in range(0, int(width()) + 1, 4):
        y = centerY() + math.sin(i * 0.02 + t * 3) * 80
        if i == 0:
            moveTo(i, y)
        else:
            lineTo(i, y)
    strokePath()

#Orbits

Transforms and push()Canvas.Push()push()/pop()Canvas.Pop()pop(): a moon orbits a planet that orbits a sun.

import { fill, rect, circle, noStroke, push, pop, translate, rotate } from "codetoy/canvas"
import * as screen from "codetoy/screen"
import { elapsedTime } from "codetoy/time"

export function update(): void {
  const t = elapsedTime()
  noStroke()
  fill(10, 10, 20)
  rect(0, 0, screen.width(), screen.height())

  push()
  translate(screen.centerX(), screen.centerY())
  fill(255, 200, 60)
  circle(0, 0, 40)            // sun

  rotate(t * 0.8)
  translate(150, 0)
  fill(80, 160, 255)
  circle(0, 0, 18)            // planet

  rotate(t * 3)
  translate(36, 0)
  fill(220, 220, 230)
  circle(0, 0, 6)             // moon
  pop()
}
double t = 0;

Screen.OnUpdate(() => {
    t += Screen.DeltaTime;
    Canvas.NoStroke();
    Canvas.Fill(10, 10, 20);
    Canvas.Rect(0, 0, Screen.Width, Screen.Height);

    Canvas.Push();
    Canvas.Translate(Screen.CenterX, Screen.CenterY);
    Canvas.Fill(255, 200, 60);
    Canvas.Circle(0, 0, 40);          // sun

    Canvas.Rotate(t * 0.8);
    Canvas.Translate(150, 0);
    Canvas.Fill(80, 160, 255);
    Canvas.Circle(0, 0, 18);          // planet

    Canvas.Rotate(t * 3);
    Canvas.Translate(36, 0);
    Canvas.Fill(220, 220, 230);
    Canvas.Circle(0, 0, 6);           // moon
    Canvas.Pop();
});
from codetoy.canvas import fill, rect, circle, noStroke, push, pop, translate, rotate
from codetoy.screen import width, height, centerX, centerY
from codetoy.time import elapsedTime

def update():
    t = elapsedTime()
    noStroke()
    fill(10, 10, 20)
    rect(0, 0, width(), height())

    push()
    translate(centerX(), centerY())
    fill(255, 200, 60)
    circle(0, 0, 40)            # sun

    rotate(t * 0.8)
    translate(150, 0)
    fill(80, 160, 255)
    circle(0, 0, 18)            # planet

    rotate(t * 3)
    translate(36, 0)
    fill(220, 220, 230)
    circle(0, 0, 6)             # moon
    pop()

#Multi-touch paint

Each finger paints in its own color, and old strokes slowly fade. Try it on a phone or tablet.

import { fill, rect, circle, noStroke } from "codetoy/canvas"
import * as screen from "codetoy/screen"
import * as input from "codetoy/input"

const ids = new Array<i32>()

export function onTouchStart(id: i32, x: f64, y: f64): void { ids.push(id) }

export function onTouchEnd(id: i32): void {
  const i = ids.indexOf(id)
  if (i >= 0) ids.splice(i, 1)
}

export function update(): void {
  noStroke()
  fill(20, 20, 30, 0.08)                 // translucent background leaves trails
  rect(0, 0, screen.width(), screen.height())

  for (let i = 0; i < ids.length; i++) {
    const id = ids[i]
    fill(120 + (id * 70) % 135, 255 - (id * 50) % 155, 200)
    circle(input.touchX(id), input.touchY(id), 24)
  }
}
var colors = new Dictionary<int, (int R, int G)>();
var rng = new Random();

Input.OnTouchStart((int id, double x, double y) => colors[id] = (rng.Next(100, 256), rng.Next(100, 256)));
Input.OnTouchEnd((int id) => colors.Remove(id));

Screen.OnUpdate(() => {
    Canvas.NoStroke();
    Canvas.Fill(20, 20, 30, 0.08);         // translucent background leaves trails
    Canvas.Rect(0, 0, Screen.Width, Screen.Height);

    foreach (var (id, c) in colors) {
        if (!Input.IsTouchDown(id)) continue;
        Canvas.Fill(c.R, c.G, 220);
        Canvas.Circle(Input.TouchX(id), Input.TouchY(id), 24);
    }
});
import random
from codetoy.canvas import fill, rect, circle, noStroke
from codetoy.screen import width, height
from codetoy._input import isTouchDown, touchX, touchY

touches = {}  # id -> color

def touchStart(id, x, y):
    touches[id] = (random.randint(100, 255), random.randint(100, 255), 220)

def touchEnd(id):
    touches.pop(id, None)

def update():
    noStroke()
    fill(20, 20, 30, 0.08)                # translucent background leaves trails
    rect(0, 0, width(), height())

    for id, (r, g, b) in list(touches.items()):
        if isTouchDown(id):
            fill(r, g, b)
            circle(touchX(id), touchY(id), 24)

#Catch the stars

A complete mini-game: move the paddle with the arrow keys (or A/D), catch falling stars and don't miss three.

import { fill, rect, circle, text, font, measureText, noStroke } from "codetoy/canvas"
import * as screen from "codetoy/screen"
import * as input from "codetoy/input"
import { deltaTime } from "codetoy/time"

let paddleX: f64 = 200
let starX: f64 = 100
let starY: f64 = -20
let starSpeed: f64 = 180
let score = 0
let lives = 3

function dropStar(): void {
  starX = 20 + Math.random() * (screen.width() - 40)
  starY = -20
}

export function onKeyDown(key: string): void {
  if (lives == 0 && key == " ") { score = 0; lives = 3; starSpeed = 180; dropStar() }
}

export function update(): void {
  const dt = deltaTime()
  const w = screen.width(), h = screen.height()

  if (lives > 0) {
    if (input.isKeyDown("ArrowLeft") || input.isKeyDown("a")) paddleX -= 420 * dt
    if (input.isKeyDown("ArrowRight") || input.isKeyDown("d")) paddleX += 420 * dt
    paddleX = Math.max(50, Math.min(w - 50, paddleX))

    starY += starSpeed * dt
    if (starY > h - 40 && starY < h - 20 && Math.abs(starX - paddleX) < 60) {
      score++
      starSpeed += 15
      dropStar()
    } else if (starY > h + 20) {
      lives--
      dropStar()
    }
  }

  noStroke()
  fill(15, 18, 35)
  rect(0, 0, w, h)
  fill(255, 220, 80)
  circle(starX, starY, 12)
  fill(120, 200, 255)
  rect(paddleX - 50, h - 30, 100, 14, 7)

  fill(255, 255, 255)
  font("Arial", 18, "bold")
  text("Score " + score.toString() + "   Lives " + lives.toString(), 12, 12)

  if (lives == 0) {
    font("Arial", 28, "bold")
    const msg = "Game over! Press Space"
    text(msg, w / 2 - measureText(msg) / 2, h / 2 - 14)
  }
}
double paddleX = 200, starX = 100, starY = -20, starSpeed = 180;
int score = 0, lives = 3;
var rng = new Random();

void DropStar() {
    starX = 20 + rng.NextDouble() * (Screen.Width - 40);
    starY = -20;
}

Input.OnKeyDown((string key) => {
    if (lives == 0 && key == " ") { score = 0; lives = 3; starSpeed = 180; DropStar(); }
});

Screen.OnUpdate(() => {
    double dt = Screen.DeltaTime, w = Screen.Width, h = Screen.Height;

    if (lives > 0) {
        if (Input.IsKeyDown("ArrowLeft") || Input.IsKeyDown("a")) paddleX -= 420 * dt;
        if (Input.IsKeyDown("ArrowRight") || Input.IsKeyDown("d")) paddleX += 420 * dt;
        paddleX = Math.Clamp(paddleX, 50, w - 50);

        starY += starSpeed * dt;
        if (starY > h - 40 && starY < h - 20 && Math.Abs(starX - paddleX) < 60) {
            score++;
            starSpeed += 15;
            DropStar();
        } else if (starY > h + 20) {
            lives--;
            DropStar();
        }
    }

    Canvas.NoStroke();
    Canvas.Fill(15, 18, 35);
    Canvas.Rect(0, 0, w, h);
    Canvas.Fill(255, 220, 80);
    Canvas.Circle(starX, starY, 12);
    Canvas.Fill(120, 200, 255);
    Canvas.Rect(paddleX - 50, h - 30, 100, 14, 7);

    Canvas.Fill(255, 255, 255);
    Canvas.Font("Arial", 18, "bold");
    Canvas.Text($"Score {score}   Lives {lives}", 12, 12);

    if (lives == 0) {
        Canvas.Font("Arial", 28, "bold");
        string msg = "Game over! Press Space";
        Canvas.Text(msg, w / 2 - Canvas.MeasureText(msg) / 2, h / 2 - 14);
    }
});
import random
from codetoy.canvas import fill, rect, circle, text, font, measureText, noStroke
from codetoy.screen import width, height
from codetoy.time import deltaTime
from codetoy._input import isKeyDown

paddle_x, star_x, star_y, star_speed = 200.0, 100.0, -20.0, 180.0
score, lives = 0, 3

def drop_star():
    global star_x, star_y
    star_x = random.uniform(20, width() - 20)
    star_y = -20

def keyDown(key):
    global score, lives, star_speed
    if lives == 0 and key == " ":
        score, lives, star_speed = 0, 3, 180
        drop_star()

def update():
    global paddle_x, star_y, star_speed, score, lives
    dt, w, h = deltaTime(), width(), height()

    if lives > 0:
        if isKeyDown("ArrowLeft") or isKeyDown("a"): paddle_x -= 420 * dt
        if isKeyDown("ArrowRight") or isKeyDown("d"): paddle_x += 420 * dt
        paddle_x = max(50, min(w - 50, paddle_x))

        star_y += star_speed * dt
        if h - 40 < star_y < h - 20 and abs(star_x - paddle_x) < 60:
            score += 1
            star_speed += 15
            drop_star()
        elif star_y > h + 20:
            lives -= 1
            drop_star()

    noStroke()
    fill(15, 18, 35)
    rect(0, 0, w, h)
    fill(255, 220, 80)
    circle(star_x, star_y, 12)
    fill(120, 200, 255)
    rect(paddle_x - 50, h - 30, 100, 14, 7)

    fill(255, 255, 255)
    font("Arial", 18, "bold")
    text(f"Score {score}   Lives {lives}", 12, 12)

    if lives == 0:
        font("Arial", 28, "bold")
        msg = "Game over! Press Space"
        text(msg, w / 2 - measureText(msg) / 2, h / 2 - 14)

Make it a Discord game

The AssemblyScript version of Catch the stars is ready to publish. Capture a build and follow the Discord Activities guide to play it with friends.

Esc