Keyboard shortcuts

Press ← or → to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

A whole game

Time to put it together! Stars fall from the sky. Catch them in your basket for a point each, and let three hit the ground and the game’s over.

Every piece of it is something from an earlier lesson:

  • the basket and the stars are sprites, showing images drawn in a MEMORYBUFFER;
  • the stars fall by themselves, with a behavior;
  • ONCOLLISION tells a star it’s been caught, or that it hit the ground;
  • the keys move the basket, and COOLDOWN keeps the loop’s time;
  • CALL RENDER draws the score every frame, under the sprites;
  • BEEP and SOUND say what happened.
SCREEN 320, 240
RANDOMIZE

// --- What things look like ---------------------------------------------
MEMORYBUFFER "basket", 40, 12
    LINE (0, 4) -> (39, 11), 6 !! box fill
END MEMORYBUFFER

MEMORYBUFFER "star", 11, 11
    POLYGON [(5, 0), (6, 4), (10, 4), (7, 6), (8, 10), (5, 8), (2, 10), (3, 6), (0, 4), (4, 4)], 14, 14
END MEMORYBUFFER

// The ground: a star that reaches it is lost.
BOUNDARY ADD "ground", (0, 236) -> (320, 240)

// --- The score ---------------------------------------------------------
ATOMIC caught = 0
ATOMIC missed = 0

FUNCTION draw()
    FRAME
        CLS
        LOCATE 1, 1
        PRINT "caught", caught, "   missed", missed, "of 3"
        IF missed >= 3
            LOCATE 14, 16
            PRINT "GAME OVER"
        END IF
    END FRAME
END FUNCTION
CALL RENDER draw, "score"

// --- Falling stars ------------------------------------------------------
BEHAVIOR "fall"
    VELOCITY 0, PARAM("speed", 1)
    ONCOLLISION
        // A star touching something touches it every tick until it's gone:
        // count it only the first time, and not once the game's over.
        IF spriteenabled(me) AND missed < 3
            IF other_tag = "basket"
                caught = caught + 1
                DISABLE SPRITE me
            ELSE IF other_tag = "ground"
                missed = missed + 1
                DISABLE SPRITE me
            END IF
        END IF
    END ONCOLLISION
END BEHAVIOR

FUNCTION drop_star()
    id = reserve_sprite()
    IF id < 0 THEN RETURN
    speed = 1 + rnd * 1.5 + caught / 10
    SET SPRITE id !! image("star") x(10 + rnd * 290) y(0)
        !! tag("star") behavior("fall") behavior_params({speed: speed})
    SHOW SPRITE id
END FUNCTION

// --- The basket, and the game ------------------------------------------
basket = reserve_sprite()
x = 140
SET SPRITE basket !! image("basket") x(x) y(220) tag("basket")
SHOW SPRITE basket

DO WHILE missed < 3
    // Sixty times a second: move the basket.
    IF COOLDOWN(1)
        IF keydown("Left") AND x > 0 THEN x = x - 4
        IF keydown("Right") AND x < 280 THEN x = x + 4
        SET SPRITE basket !! x(x)
    END IF
    // Every 45 ticks, three quarters of a second: another star.
    IF COOLDOWN(45) THEN drop_star()
LOOP
SOUND 220, 0.5

Click the screen, then use the arrow keys.

The score is drawn on layer 0, the bottom one, and the sprites are drawn above it. A layer of its own would have to be cleared to see-through rather than to black, or it would hide the sprites under it.

Make it yours

It’s yours now. Some things to try:

  • Faster. Drop a star every 30 ticks instead of 45, or make them fall faster as the score goes up.
  • A sound for a catch. Put a BEEP in the ONCOLLISION where a star is caught.
  • Bad stars. Drop a red one now and then, with a tag of its own, that costs you a point if you catch it.
  • A best score. When the game’s over, save caught with SAVETEXT if it’s better than what loadtext gives back.
  • A sky. Draw something on layer 0 before the game starts: it stays put under everything, the way the sun did in Drawing on the screen.