Keep your place in this quest

Log in or sign up for free to subscribe, follow lesson progress, and access more learning content.

Example: Complete Game

This lesson builds a small collection game. The player moves around a scene, bumps into walls, collects coins, and prints a final score when the game ends.

Instead of pasting the whole script at once, the example is split into the same parts you will use in most Tiniest2D projects:

  • asset and state variables
  • start()
  • onUpdate(dt)
  • onCollision(objA, objB)
  • end()

1. Assets and Game State

The first section creates the assets and variables the rest of the script will use. Sprites are images, the scene is the level, the player is an object placed into that scene, and the score/speed variables store simple game state.

// Create assets
var playerImg = Sprite(16, 16)
var wallImg = Sprite(16, 16)
var coinImg = Sprite(8, 8)
var level = Scene()

// Create player object
var player = Object("Player")

// Game state
var score = 0
var speed = 100

At this point, the variables exist, but the game has not placed anything into the scene yet. That setup happens in start().

2. The start() Function

start() runs once when the game begins. Use it to configure objects, set the first scene, position the camera, and prepare any starting values.

func start() {
    // Setup player
    setSprite(player, playerImg)
    setCollisionType(player, COLLISION_DYNAMIC())
    setX(player, 50)
    setY(player, 50)
    addObject(level, player)

    // Set starting scene
    setScene(level)

    // Center camera on player
    setCameraX(level, getX(player))
    setCameraY(level, getY(player))
    setCameraZoom(level, 3)

    print("Collect the coins!")
}

The player uses COLLISION_DYNAMIC() because it should collide and be pushed out of walls. The camera starts centered on the player so the level view begins in the right place.

3. The onUpdate(dt) Function

onUpdate(dt) runs every frame. This is where the player reads input, moves, updates the camera, and checks for reset keys.

dt means "delta time": the amount of time since the previous frame. Multiplying movement by dt makes movement speed more consistent across different frame rates.

func onUpdate(dt) {
    // Player movement
    var moveX = 0
    var moveY = 0

    if (isKeyHeld(KEY_LEFT()) || isKeyHeld(KEY_A())) {
        moveX = -1
    }
    if (isKeyHeld(KEY_RIGHT()) || isKeyHeld(KEY_D())) {
        moveX = 1
    }
    if (isKeyHeld(KEY_UP()) || isKeyHeld(KEY_W())) {
        moveY = -1
    }
    if (isKeyHeld(KEY_DOWN()) || isKeyHeld(KEY_S())) {
        moveY = 1
    }

    // Apply movement
    setX(player, getX(player) + moveX * speed * dt)
    setY(player, getY(player) + moveY * speed * dt)

    // Camera follows player
    setCameraX(level, getX(player))
    setCameraY(level, getY(player))

    // Reset level with R key
    if (isKeyPressed(KEY_R())) {
        resetScene(level)
        setX(player, 50)
        setY(player, 50)
        score = 0
        print("Level reset!")
    }
}

The movement code builds a direction from keyboard input. Then it adds that direction to the player's current position. The camera is updated after movement so it follows the new position.

4. The onCollision(objA, objB) Function

onCollision(objA, objB) runs when two objects collide. In this example, coins should use COLLISION_TRIGGER(). Trigger objects report overlaps, but they do not block movement.

func onCollision(objA, objB) {
    var nameB = getName(objB)
    var typeB = getCollisionType(objB)

    // Coin collection (coins should be TRIGGER type in scene editor)
    if (typeB == COLLISION_TRIGGER()) {
        removeObject(level, objB)
        score = score + 1
        print("Score: " + score)
    }
}

When the player touches a trigger, the script removes that object from the scene and increases the score. This is the basic pattern for pickups, keys, powerups, and checkpoints.

5. The end() Function

end() runs when the game stops. This example only prints the final score, but larger games can use this function for cleanup or final debug messages.

func end() {
    print("Final score: " + score)
}

Setting Up the Example

  1. Create the sprites:
  2. Ctrl+Click on playerImg, draw a character (for example, a simple stick figure)
  3. Ctrl+Click on wallImg, draw a solid block
  4. Ctrl+Click on coinImg, draw a small circle or diamond

  5. Design the scene:

  6. Ctrl+Click on level
  7. Select wallImg in the left panel, set collision to "Static"
  8. Paint walls around the edges and create a maze
  9. Select coinImg, set collision to "None" for decorative coin tiles
  10. Place coins around the level as visual guides

  11. Create trigger coin objects:

Sprites stamped into the scene are useful for tiles and decoration, but collectible coins should be objects so collision callbacks can remove them. Add coin objects like this:

var coin1 = Object("Coin1")
var coin2 = Object("Coin2")

func start() {
    // ... player setup ...

    // Setup coins as triggers
    setSprite(coin1, coinImg)
    setCollisionType(coin1, COLLISION_TRIGGER())
    setX(coin1, 100)
    setY(coin1, 80)
    addObject(level, coin1)

    setSprite(coin2, coinImg)
    setCollisionType(coin2, COLLISION_TRIGGER())
    setX(coin2, 150)
    setY(coin2, 120)
    addObject(level, coin2)

    // ... rest of start ...
}

This same pattern can be expanded for more coins, enemies, doors, or any object that needs script behavior.