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

EktuPy Examples

This page contains example programs demonstrating EktuPy features. Each example shows a different aspect of the API.


Hello World

The simplest EktuPy program - display a sprite with a speech bubble.

from ektupy import Stage, Sprite, on_start

stage = Stage()
snake = Sprite("snake")
stage.add_sprite(snake)

@on_start
def setup():
    snake.go_to(0, 0)
    snake.say("Hello! Use arrow keys to move me!", 3)

Key concepts: Stage(), Sprite(), @on_start, say()

Hello World


Arrow Key Movement

Move a sprite around the stage using arrow keys.

from ektupy import Stage, Sprite, on_start, on_forever, key_pressed

stage = Stage()
snake = Sprite("snake")
stage.add_sprite(snake)

@on_start
def setup():
    snake.go_to(0, 0)
    snake.say("Hello! Use arrow keys to move me!", 3)

@on_forever
def game_loop():
    if key_pressed("right arrow"):
        snake.direction = 90
        snake.move(5)
    if key_pressed("left arrow"):
        snake.direction = -90
        snake.move(5)
    if key_pressed("up arrow"):
        snake.direction = 0
        snake.move(5)
    if key_pressed("down arrow"):
        snake.direction = 180
        snake.move(5)

Key concepts: @on_forever, key_pressed(), direction, move()

Movement


Bouncing Ball

A sprite that bounces around the stage continuously.

from ektupy import Stage, Sprite, on_start, on_forever

stage = Stage()
snake = Sprite("snake")
stage.add_sprite(snake)

@on_start
def setup():
    snake.go_to(0, 0)
    snake.direction = 45
    snake.set_rotation_style("all around")

@on_forever
def game_loop():
    snake.move(5)
    snake.bounce_if_on_edge()

Key concepts: set_rotation_style(), bounce_if_on_edge()

Bounce


Drawing with Pen

Use the pen to draw shapes as the sprite moves.

from ektupy import Stage, Sprite, on_start, on_forever, key_pressed

stage = Stage()
stage.set_background("#222222")

pen = Sprite("snake")
stage.add_sprite(pen)

@on_start
def setup():
    pen.go_to(0, 0)
    pen.set_pen_color("#00FF00")
    pen.set_pen_size(3)
    pen.pen_down()

@on_forever
def draw():
    if key_pressed("right arrow"):
        pen.direction = 90
        pen.move(3)
    if key_pressed("left arrow"):
        pen.direction = -90
        pen.move(3)
    if key_pressed("up arrow"):
        pen.direction = 0
        pen.move(3)
    if key_pressed("down arrow"):
        pen.direction = 180
        pen.move(3)
    if key_pressed("c"):
        pen.clear()
    if key_pressed("space"):
        pen.pen_up()
        pen.go_to(0, 0)
        pen.pen_down()

Key concepts: pen_down(), pen_up(), set_pen_color(), set_pen_size(), clear()

Drawing


Sound Effects

Play sounds with volume and pitch control.

from ektupy import Stage, Sprite, on_start, on_key_press
from ektupy import load_sound, start_sound, stop_all_sounds
from ektupy import set_volume, change_volume, get_volume
from ektupy import set_pitch_effect, clear_sound_effects

stage = Stage()
stage.set_background("#2d3436")

snake = Sprite("snake")
stage.add_sprite(snake)

@on_start
def setup():
    snake.go_to(0, 0)
    snake.size = 100

    # Load sounds using asset names
    load_sound("sfx_coin_single1")
    load_sound("sfx_movement_jump1")
    load_sound("sfx_menu_select1")

    # Set initial volume
    set_volume(70)

    snake.say("Press: C=coin J=jump\nUP/DOWN=volume")

@on_key_press("c")
def play_coin():
    start_sound("sfx_coin_single1")
    snake.say(f"Coin! Vol: {get_volume()}%")

@on_key_press("j")
def play_jump():
    start_sound("sfx_movement_jump1")
    snake.say(f"Jump! Vol: {get_volume()}%")

@on_key_press("up arrow")
def volume_up():
    change_volume(10)
    snake.say(f"Volume: {get_volume()}%")

@on_key_press("down arrow")
def volume_down():
    change_volume(-10)
    snake.say(f"Volume: {get_volume()}%")

@on_key_press("p")
def pitch_up():
    set_pitch_effect(60)
    snake.say("High pitch!")

@on_key_press("n")
def pitch_normal():
    clear_sound_effects()
    snake.say("Normal pitch")

@on_key_press("s")
def stop_sounds():
    stop_all_sounds()
    snake.say("Stopped!")

Key concepts: load_sound(), start_sound(), set_volume(), change_volume(), get_volume(), set_pitch_effect(), clear_sound_effects(), stop_all_sounds()

Sound Effects


Costume Animation

Switch between costumes to create animation effects.

from ektupy import Stage, Sprite, on_start, on_forever

stage = Stage()
stage.set_background("#2d3436")

# Create a snake sprite - automatically loads all costumes
snake = Sprite("snake")
stage.add_sprite(snake)

frame_count = 0

@on_start
def setup():
    snake.go_to(0, 0)
    snake.size = 150
    # Show available costumes
    print("Available costumes:", snake.costumes)
    snake.say("I can change colors!", 2)

@on_forever
def animate():
    global frame_count
    frame_count += 1

    # Move in a circle
    snake.turn_right(3)
    snake.move(5)

    # Change costume every 20 frames
    if frame_count % 20 == 0:
        snake.next_costume()
        print(f"Now wearing: {snake.costume_name}")

Key concepts: costumes, next_costume(), costume_name, switch_costume()

Costume Animation


Ghost Effect (Transparency)

Make sprites fade in and out using the ghost effect.

from ektupy import Stage, Sprite, on_start, on_forever, on_key_press

stage = Stage()
stage.set_background("#1a1a2e")

ghost = Sprite("snake")
stage.add_sprite(ghost)

fade_direction = 1  # 1 = fading out, -1 = fading in
ghost_value = 0

@on_start
def setup():
    ghost.go_to(0, 0)
    ghost.size = 150
    ghost.say("I fade in and out!\nPress SPACE to reset", 3)

@on_forever
def animate():
    global fade_direction, ghost_value

    # Change ghost effect (transparency)
    ghost_value += fade_direction * 2

    # Reverse direction at limits
    if ghost_value >= 80:
        fade_direction = -1
    elif ghost_value <= 0:
        fade_direction = 1

    ghost.set_ghost_effect(ghost_value)

    # Move in a circle
    ghost.turn_right(2)
    ghost.move(3)
    ghost.bounce_if_on_edge()

@on_key_press("space")
def reset():
    ghost.set_ghost_effect(0)
    ghost.clear_graphic_effects()
    ghost.go_to(0, 0)
    ghost.say("Reset!")

Key concepts: set_ghost_effect(), change_ghost_effect(), clear_graphic_effects()

Ghost Effect


Sprite Layers

Control which sprites appear in front of others.

from ektupy import Stage, Sprite, on_start, on_key_press, wait

stage = Stage()
stage.set_background("#87CEEB")

# Create three overlapping sprites
red = Sprite("snake")
green = Sprite("snake")
blue = Sprite("snake")

stage.add_sprite(red)
stage.add_sprite(green)
stage.add_sprite(blue)

@on_start
def setup():
    # Position sprites overlapping
    red.go_to(-50, 0)
    red.size = 150

    green.go_to(0, 0)
    green.size = 150

    blue.go_to(50, 0)
    blue.size = 150

    red.say("R=front")
    green.say("G=front")
    blue.say("B=front")

@on_key_press("r")
def red_front():
    red.go_to_front_layer()
    red.say("I'm in front!")
    green.say("")
    blue.say("")

@on_key_press("g")
def green_front():
    green.go_to_front_layer()
    green.say("I'm in front!")
    red.say("")
    blue.say("")

@on_key_press("b")
def blue_front():
    blue.go_to_front_layer()
    blue.say("I'm in front!")
    red.say("")
    green.say("")

@on_key_press("space")
def reset_order():
    red.go_to_back_layer()
    green.go_forward_layers(1)
    blue.go_to_front_layer()
    red.say("Back")
    green.say("Middle")
    blue.say("Front")

Key concepts: go_to_front_layer(), go_to_back_layer(), go_forward_layers(), go_backward_layers()

Sprite Layers


Stamping Patterns

Use stamp() to leave copies of the sprite on the stage.

from ektupy import Stage, Sprite, on_start, on_key_press

stage = Stage()
stage.set_background("#1a1a2e")

snake = Sprite("snake")
stage.add_sprite(snake)

@on_start
def setup():
    snake.go_to(0, 0)
    snake.size = 30
    snake.say("Press S=spiral G=grid C=clear", 3)

@on_key_press("s")
def draw_spiral():
    snake.go_to(0, 0)
    snake.direction = 0
    snake.size = 20

    # Draw a spiral pattern using stamps
    for i in range(36):
        snake.stamp()
        snake.move(10 + i * 2)
        snake.turn_right(30)
        snake.size = 20 + i

    snake.say("Spiral complete!")

@on_key_press("c")
def clear_stamps():
    snake.clear()
    snake.go_to(0, 0)
    snake.size = 30
    snake.say("Cleared!")

@on_key_press("g")
def draw_grid():
    snake.size = 20

    # Draw a grid pattern
    for row in range(-4, 5):
        for col in range(-6, 7):
            snake.go_to(col * 60, row * 60)
            snake.stamp()

    snake.go_to(0, 0)
    snake.say("Grid complete!")

Key concepts: stamp(), clear()

Stamping


Mouse Tracking

Follow the mouse and detect proximity.

from ektupy import Stage, Sprite, on_start, on_forever
from ektupy import mouse_x, mouse_y

stage = Stage()
stage.set_background("#2d5a27")

snake = Sprite("snake")
stage.add_sprite(snake)

@snake.on_start
def setup():
    snake.go_to(0, 0)
    snake.size = 80

@snake.on_forever
def track_mouse():
    # Calculate distance to mouse
    dist = snake.distance_to_mouse()

    # Check if touching mouse pointer
    if snake.touching_mouse():
        snake.say("You caught me!")
    elif dist < 80:
        snake.say("Too close!")
    elif dist < 150:
        snake.say("Getting warmer...")
    else:
        snake.say(f"Distance: {int(dist)}")

    # Slowly move toward mouse
    snake.point_towards_mouse()
    if dist > 10:
        snake.move(2)

Key concepts: distance_to_mouse(), touching_mouse(), point_towards_mouse(), mouse_x(), mouse_y()

Mouse Tracking


User Input (Ask and Answer)

Get text input from the user.

from ektupy import Stage, Sprite, on_start, on_key_press
from ektupy import ask, answer, wait

stage = Stage()
stage.set_background("#4a90d9")

snake = Sprite("snake")
stage.add_sprite(snake)

@snake.on_start
def greet():
    snake.go_to(0, 100)
    snake.size = 100

    # Ask for the user's name
    name = ask("What's your name?")

    # Use the answer
    snake.say(f"Hello, {name}! Nice to meet you!")
    wait(2)

    # Ask another question
    color = ask("What's your favorite color?")
    snake.say(f"{color} is a great color!")
    wait(2)

    snake.say("Press SPACE to ask again!")

@snake.on_key_press("space")
def ask_again():
    response = ask("Tell me something interesting:")
    snake.say(f'You said: "{response}"')

Key concepts: ask(), answer() - the input box appears at the bottom of the stage

User Input


Timer and Clock

Use sensing functions for time.

from ektupy import Stage, Sprite, on_start, on_forever
from ektupy import timer, reset_timer
from ektupy import current_hour, current_minute, current_second, current_day_of_week

stage = Stage()
stage.set_background("#1a1a2e")

clock = Sprite("snake")
stage.add_sprite(clock)

days = ["", "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"]

@clock.on_start
def setup():
    clock.go_to(0, 100)
    clock.size = 100
    reset_timer()

@clock.on_forever
def update_clock():
    h = current_hour()
    m = current_minute()
    s = current_second()
    day = days[current_day_of_week()]

    # Format time with leading zeros
    time_str = f"{h:02d}:{m:02d}:{s:02d}"
    elapsed = int(timer())

    clock.say(f"{day}\n{time_str}\nRunning: {elapsed}s")

Key concepts: timer(), reset_timer(), current_hour(), current_minute(), current_second(), current_day_of_week()

Timer and Clock


Two Sprites with Independent Controls

Each sprite has its own scripts and responds to different keys.

from ektupy import Stage, Sprite, wait, broadcast

stage = Stage()
stage.set_background("#87CEEB")

cat = Sprite("cat")
dog = Sprite("dog")

stage.add_sprite(cat)
stage.add_sprite(dog)

# ============================================
# CAT'S SCRIPTS - Use arrow keys to move
# ============================================

@cat.on_start
def cat_setup():
    cat.go_to(-100, 0)
    cat.say("I'm the cat! Use arrow keys to move me.")
    wait(3)
    cat.say("")

@cat.on_key_press("up arrow")
def cat_up():
    cat.change_y(10)

@cat.on_key_press("down arrow")
def cat_down():
    cat.change_y(-10)

@cat.on_key_press("left arrow")
def cat_left():
    cat.change_x(-10)

@cat.on_key_press("right arrow")
def cat_right():
    cat.change_x(10)

@cat.on_message("woof")
def cat_hears_woof():
    cat.say("Meow back!")
    wait(1)
    cat.say("")

# ============================================
# DOG'S SCRIPTS - Use WASD keys to move
# ============================================

@dog.on_start
def dog_setup():
    dog.go_to(100, 0)
    dog.say("I'm the dog! Use WASD to move me.")
    wait(3)
    dog.say("")

@dog.on_key_press("w")
def dog_up():
    dog.change_y(10)

@dog.on_key_press("s")
def dog_down():
    dog.change_y(-10)

@dog.on_key_press("a")
def dog_left():
    dog.change_x(-10)

@dog.on_key_press("d")
def dog_right():
    dog.change_x(10)

@dog.on_key_press("space")
def dog_bark():
    dog.say("Woof!")
    broadcast("woof")
    wait(1)
    dog.say("")

# ============================================
# COLLISION DETECTION
# ============================================

@cat.on_forever
def check_collision():
    if cat.touching(dog):
        cat.say("Hey!")
        dog.say("Hi friend!")

Key concepts: Per-sprite decorators (@sprite.on_start, @sprite.on_key_press, @sprite.on_message), touching(), broadcast()

Two Sprites


Cloning

Create multiple copies of a sprite at runtime.

from ektupy import Stage, Sprite, on_start, on_key_press
import random

stage = Stage()
stage.set_background("#1a1a2e")

star = Sprite("snake")
stage.add_sprite(star)

@star.on_start
def star_setup():
    star.hide()
    star.size = 30

def on_clone_created():
    star.show()
    star.go_to_random_position()
    star.set_ghost_effect(random.randint(0, 50))

star.on_clone_start(on_clone_created)

@on_start
def setup():
    print("Press SPACE to create stars!")

@on_key_press("space")
def create_star():
    star.clone()
    print("Created a star!")

Key concepts: clone(), on_clone_start(), is_clone, delete_clone(), go_to_random_position()

Cloning


Click to Move

Click anywhere on the stage to move the sprite there smoothly.

from ektupy import Stage, Sprite, on_start, on_mouse_click

stage = Stage()
sprite = Sprite("snake")
stage.add_sprite(sprite)

@on_start
def setup():
    sprite.go_to(0, 0)
    sprite.say("Click anywhere!")

@on_mouse_click
def move_to_click(x, y):
    sprite.glide_to(x, y, 0.5)
    sprite.say(f"({int(x)}, {int(y)})")

Key concepts: @on_mouse_click, glide_to()

Click to Move


Broadcasting Messages

Use broadcasts to coordinate between sprites.

from ektupy import Stage, Sprite, on_start, on_key_press, on_message, broadcast, wait

stage = Stage()

button = Sprite("snake")
responder = Sprite("cat")

stage.add_sprite(button)
stage.add_sprite(responder)

@button.on_start
def button_setup():
    button.go_to(-100, 0)
    button.say("Press SPACE!")

@responder.on_start
def responder_setup():
    responder.go_to(100, 0)

@on_key_press("space")
def send_message():
    button.say("Sending...")
    broadcast("hello")
    wait(0.5)
    button.say("Press SPACE!")

@responder.on_message("hello")
def receive_message():
    responder.say("Got it!")
    responder.change_y(20)
    wait(0.5)
    responder.change_y(-20)
    responder.say("")

Key concepts: broadcast(), @on_message, broadcast_and_wait()

Broadcasting


Background Images

Use backdrop images for your stage.

from ektupy import Stage, Sprite, on_start, on_forever, key_pressed

stage = Stage()
stage.set_background_image("mountain-sunrise")

snake = Sprite("snake")
stage.add_sprite(snake)

# Available backdrops: mountain-sunrise, jungle, paddy-field, race-track, sky-and-clouds
backdrops = ["mountain-sunrise", "jungle", "paddy-field", "race-track", "sky-and-clouds"]
current_backdrop = 0

@on_start
def setup():
    snake.go_to(0, -200)
    snake.say("Press SPACE to change backdrop!", 3)

@on_forever
def game_loop():
    global current_backdrop

    # Move with arrow keys
    if key_pressed("right arrow"):
        snake.direction = 90
        snake.move(5)
    if key_pressed("left arrow"):
        snake.direction = -90
        snake.move(5)
    if key_pressed("up arrow"):
        snake.direction = 0
        snake.move(5)
    if key_pressed("down arrow"):
        snake.direction = 180
        snake.move(5)

    # Change backdrop with space
    if key_pressed("space"):
        current_backdrop = (current_backdrop + 1) % len(backdrops)
        stage.set_background_image(backdrops[current_backdrop])
        snake.say(backdrops[current_backdrop], 1)

Key concepts: set_background_image(), available backdrops: jungle, mountain-sunrise, paddy-field, race-track, sky-and-clouds

Background Images