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 API Reference

Complete reference for all EktuPy classes, methods, and functions.

Table of Contents


Stage Class

The Stage is the canvas where all sprites live and move. The stage has a fixed size of 960x720 pixels.

Constructor

Stage(background_color="#ffffff")
ParameterTypeDefaultDescription
background_colorstr“#ffffff”Background color (CSS color)
# Create a stage with default white background
stage = Stage()

# Create a stage with a custom background color
stage = Stage("#1a1a2e")

Properties

PropertyTypeDescription
widthintStage width (always 960)
heightintStage height (always 720)

Coordinate System

EktuPy uses a Scratch-like coordinate system with the origin at the center:

                    (0, 360) Top
                        |
                        |
(-480, 0) Left -----(0, 0)-----> (480, 0) Right
                        |
                        |
                   (0, -360) Bottom
AxisRangeDescription
X-480 to 480Horizontal position (negative = left, positive = right)
Y-360 to 360Vertical position (negative = down, positive = up)

Direction angles:

  • 0 = Up
  • 90 = Right
  • 180 (or -180) = Down
  • -90 = Left

Methods

set_background(color)

Set the stage background color.

stage.set_background("#87CEEB")  # Sky blue
stage.set_background("red")      # Named color

set_background_image(name_or_path)

Set a background image by asset name or path.

# Using an asset name
stage.set_background_image("sky-and-clouds")

# Using a path
stage.set_background_image("/static/assets/backdrops/jungle.svg")

Available backdrops:

  • jungle - Dense jungle forest scene
  • mountain-sunrise - Mountains with rising sun
  • paddy-field - Sun over rice paddy fields
  • race-track - Racing track scene
  • sky-and-clouds - Blue sky with fluffy clouds

set_cursor_sprite(sprite)

Set a sprite to use as a custom mouse cursor. The sprite will follow the mouse position and render on top of everything. The default cursor is hidden while inside the stage area.

# Create a custom cursor
hammer = Sprite("hammer")
hammer.size = 50
stage.set_cursor_sprite(hammer)

# Restore default cursor
stage.set_cursor_sprite(None)
ParameterTypeDescription
spriteSprite or NoneSprite to use as cursor, or None to restore default

Example: Whack-a-Mole with hammer cursor

stage = Stage()
hammer = Sprite("hammer")
hammer.size = 60
stage.set_cursor_sprite(hammer)

# The hammer now follows the mouse automatically

add_sprite(sprite)

Add a sprite to the stage.

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

add_egg(egg)

Add an egg (special display element) to the stage. See Eggs for available egg types.

from ektupy import SegmentDisplay

display = SegmentDisplay(cells=8, color="#00FF00")
stage.add_egg(display)

start()

Start the game loop. Usually called automatically.

stop()

Stop the game loop.


Sprite Class

Sprites are the visual objects that move and interact on the stage.

Constructor

Sprite(image_path=None)
ParameterTypeDefaultDescription
image_pathstrNoneAsset name or path to sprite image (SVG, PNG, etc.)

You can create sprites using either an asset name (simpler) or a full path:

# Using asset name (recommended)
snake = Sprite("snake")    # Looks up "snake" in the asset map
paddle = Sprite("paddle")  # Looks up "paddle" in the asset map

# Using full path (also works)
snake = Sprite("/static/assets/sprites/snake.svg")

Asset names are easier to use and will show a warning in the editor if the name doesn’t exist. See Asset Map for more details.

Sprite Properties

All properties can be read and written:

PropertyTypeDescription
xfloatX position (0 = center)
yfloatY position (0 = center)
directionfloatDirection in degrees (0=up, 90=right)
sizefloatSize as percentage (100 = normal)
costume_numberintCurrent costume number (read-only)
costume_namestrCurrent costume name (read-only)
is_cloneboolTrue if this sprite is a clone (read-only)
sprite.x = 100
sprite.y = -50
sprite.direction = 90  # Face right
sprite.size = 150      # 150% size
print(sprite.x)        # Read position

Motion Methods

move(steps)

Move in the current direction.

sprite.move(10)  # Move 10 steps forward

turn_right(degrees) / turn_left(degrees)

Rotate the sprite.

sprite.turn_right(90)  # Turn 90 degrees clockwise
sprite.turn_left(45)   # Turn 45 degrees counter-clockwise

go_to(x, y)

Instantly move to a position.

sprite.go_to(0, 0)      # Go to center
sprite.go_to(-100, 50)  # Go to specific position

set_x(x) / set_y(y)

Set just the x or y position.

sprite.set_x(100)
sprite.set_y(-50)

change_x(amount) / change_y(amount)

Change position by an amount.

sprite.change_x(10)   # Move 10 pixels right
sprite.change_y(-5)   # Move 5 pixels down

go_to_random_position()

Move to a random position on the stage.

sprite.go_to_random_position()

go_to_mouse()

Move to the mouse pointer position.

sprite.go_to_mouse()

go_to_sprite(other)

Move to another sprite’s position.

cat.go_to_sprite(dog)

glide_to(x, y, seconds)

Smoothly glide to a position over time.

sprite.glide_to(100, 50, 2)  # Glide over 2 seconds

glide_to_random_position(seconds)

Glide to a random position.

sprite.glide_to_random_position(1.5)

glide_to_mouse(seconds)

Glide to the mouse pointer.

sprite.glide_to_mouse(1)

glide_to_sprite(other, seconds)

Glide to another sprite.

cat.glide_to_sprite(dog, 2)

point_towards(x, y)

Point toward a position.

sprite.point_towards(100, 100)

point_towards_mouse()

Point toward the mouse pointer.

sprite.point_towards_mouse()

point_towards_sprite(other)

Point toward another sprite.

cat.point_towards_sprite(dog)

set_rotation_style(style)

Set how the sprite rotates visually.

StyleDescription
"all around"Rotate freely in all directions
"left-right"Only flip horizontally (default)
"don't rotate"Never rotate visually
sprite.set_rotation_style("all around")

bounce_if_on_edge()

If touching edge, bounce (reverse direction).

@on_forever
def move():
    sprite.move(5)
    sprite.bounce_if_on_edge()

Looks Methods

say(text, seconds=None)

Show a speech bubble.

sprite.say("Hello!")           # Show until changed
sprite.say("Hi!", 2)           # Show for 2 seconds
sprite.say("")                 # Clear bubble

think(text, seconds=None)

Show a thought bubble (cloud shape).

sprite.think("Hmm...")
sprite.think("I wonder...", 3)

show() / hide()

Show or hide the sprite.

sprite.hide()
wait(1)
sprite.show()

change_size(amount)

Change size by amount.

sprite.change_size(10)   # Grow by 10%
sprite.change_size(-20)  # Shrink by 20%

set_ghost_effect(value)

Set transparency (0=visible, 100=invisible).

sprite.set_ghost_effect(50)  # 50% transparent

change_ghost_effect(amount)

Change transparency by amount.

sprite.change_ghost_effect(10)  # More transparent

clear_graphic_effects()

Reset all visual effects.

sprite.clear_graphic_effects()

switch_costume(name_or_index)

Switch to a different costume.

sprite.switch_costume(0)       # By index
sprite.switch_costume("walk1") # By name

next_costume()

Switch to the next costume (wraps around).

sprite.next_costume()

add_costume(image_path, name)

Add a new costume from an image.

sprite.add_costume("/static/assets/walk2.png", "walk2")

Layer Methods

sprite.go_to_front_layer()    # Move to front
sprite.go_to_back_layer()     # Move to back
sprite.go_forward_layers(2)   # Move forward 2 layers
sprite.go_backward_layers(1)  # Move backward 1 layer

Rotation and Flip Methods

These methods let you visually rotate and flip sprites independently of their movement direction. Unlike direction (which controls which way the sprite moves), these methods only affect how the sprite looks.

set_rotation(degrees)

Set the visual rotation of the sprite in degrees. This rotates the sprite’s image without changing its movement direction.

sprite.set_rotation(45)   # Rotate 45 degrees clockwise
sprite.set_rotation(0)    # Reset to no rotation
sprite.set_rotation(-90)  # Rotate 90 degrees counter-clockwise
ParameterTypeDescription
degreesfloatRotation angle in degrees (positive = clockwise)

Example: Spinning coin animation

coin = Sprite("coin")

@on_forever
def spin_coin():
    coin.change_rotation(5)  # Continuously spin

change_rotation(degrees)

Change the visual rotation by a relative amount.

sprite.change_rotation(10)   # Rotate 10 degrees more clockwise
sprite.change_rotation(-15)  # Rotate 15 degrees counter-clockwise
ParameterTypeDescription
degreesfloatAmount to change rotation (positive = clockwise)

Example: Tilt on key press

spaceship = Sprite("spaceship")

@on_key_press("left arrow")
def tilt_left():
    spaceship.change_rotation(-15)

@on_key_press("right arrow")
def tilt_right():
    spaceship.change_rotation(15)

flip_horizontal()

Toggle the horizontal flip state. If the sprite is normal, it flips horizontally (mirror image). If already flipped, it returns to normal.

sprite.flip_horizontal()  # Flip left-right

Example: Face direction of movement

player = Sprite("robot")

@on_key_press("left arrow")
def move_left():
    if not player.is_flipped_horizontally:
        player.flip_horizontal()  # Face left
    player.change_x(-10)

@on_key_press("right arrow")
def move_right():
    if player.is_flipped_horizontally:
        player.flip_horizontal()  # Face right
    player.change_x(10)

flip_vertical()

Toggle the vertical flip state. If the sprite is normal, it flips vertically (upside down). If already flipped, it returns to normal.

sprite.flip_vertical()  # Flip upside-down

Example: Flip when hit

enemy = Sprite("alien")

def on_hit():
    enemy.flip_vertical()  # Turn upside down when defeated

set_flipped_horizontally(flipped)

Explicitly set whether the sprite is horizontally flipped.

sprite.set_flipped_horizontally(True)   # Force flip
sprite.set_flipped_horizontally(False)  # Force normal
ParameterTypeDescription
flippedboolTrue to flip horizontally, False for normal

Example: Always face the mouse

cat = Sprite("cat")

@on_forever
def face_mouse():
    # Flip based on mouse position
    cat.set_flipped_horizontally(mouse_x() < cat.x)

set_flipped_vertically(flipped)

Explicitly set whether the sprite is vertically flipped.

sprite.set_flipped_vertically(True)   # Force upside-down
sprite.set_flipped_vertically(False)  # Force normal
ParameterTypeDescription
flippedboolTrue to flip vertically, False for normal

Note: You can also read the current flip state using:

  • sprite.is_flipped_horizontally - Returns True if horizontally flipped
  • sprite.is_flipped_vertically - Returns True if vertically flipped

Pen Methods

Draw lines on the stage as the sprite moves.

pen_down() / pen_up()

Start or stop drawing.

sprite.pen_down()
sprite.move(100)   # Draws a line
sprite.pen_up()
sprite.move(50)    # No line drawn

set_pen_color(color)

Set the pen color.

sprite.set_pen_color("red")
sprite.set_pen_color("#FF5500")
sprite.set_pen_color("rgb(255, 100, 0)")

set_pen_size(size)

Set the pen width in pixels.

sprite.set_pen_size(5)

stamp()

Stamp the sprite’s image onto the stage.

sprite.stamp()

clear()

Erase all pen drawings.

sprite.clear()

Sensing Methods

touching(other)

Check if touching another sprite.

if cat.touching(dog):
    cat.say("Ouch!")

touching_edge()

Check if touching the stage edge.

if sprite.touching_edge():
    sprite.bounce_if_on_edge()

touching_mouse()

Check if touching the mouse pointer.

if sprite.touching_mouse():
    sprite.say("You're on me!")

distance_to(other)

Get distance to another sprite.

dist = cat.distance_to(dog)
if dist < 50:
    cat.say("Too close!")

distance_to_mouse()

Get distance to the mouse pointer.

dist = sprite.distance_to_mouse()
if dist < 100:
    sprite.say("Getting close!")

Clone Methods

Create copies of sprites at runtime.

clone()

Create a clone of this sprite.

new_clone = sprite.clone()

on_clone_start(callback)

Register a function to run when this sprite is cloned.

def on_cloned():
    # 'sprite' here refers to the new clone
    sprite.go_to_random_position()

sprite.on_clone_start(on_cloned)

delete_clone()

Delete this clone (only works on clones).

if sprite.is_clone:
    sprite.delete_clone()

Per-Sprite Event Decorators

Each sprite can have its own event handlers, just like Scratch.

@sprite.on_start

Runs when the program starts (for this sprite only).

@cat.on_start
def cat_setup():
    cat.go_to(-100, 0)
    cat.say("I'm the cat!")

@sprite.on_forever

Runs every frame (for this sprite only).

@cat.on_forever
def cat_loop():
    cat.turn_right(1)

@sprite.on_key_press(key)

Runs when a key is pressed (for this sprite only).

@cat.on_key_press("space")
def cat_jump():
    cat.change_y(50)

@sprite.on_message(message)

Runs when a broadcast is received (for this sprite only).

@cat.on_message("game_over")
def cat_dies():
    cat.say("Oh no!")
    cat.hide()

sprite.on_clicked(callback)

Runs when this sprite is clicked.

def on_cat_click():
    cat.say("You clicked me!")

cat.on_clicked(on_cat_click)

Eggs

Eggs are special visual components that can be added to the stage but aren’t sprites. Unlike sprites, eggs don’t have movement, costumes, or collision detection - they’re specialized display elements.

SegmentDisplay

A 14-segment LED display for showing text, numbers, and scrolling messages. Perfect for scoreboards, clocks, timers, and retro-style game displays.

Constructor

SegmentDisplay(cells=4, color="#00FF00", bg_color=None, scale=1.0, panel_color="#0a0a0a")
ParameterTypeDefaultDescription
cellsint4Number of character cells in the display
colorstr“#00FF00”Color of lit segments (CSS color)
bg_colorstrNoneColor of unlit segments (auto-calculated if None)
scalefloat1.0Scale factor for the display size
panel_colorstr“#0a0a0a”Background panel color
from ektupy import Stage, SegmentDisplay

stage = Stage()
stage.set_background("#0d1117")

# Create a green 8-cell display
score_display = SegmentDisplay(cells=8, color="#00FF00", scale=1.0)
stage.add_egg(score_display)
score_display.go_to(0, 200)
score_display.show("SCORE")

Methods

show(text)

Display static text on the segment display.

display.show("HELLO")      # Show text
display.show("12345")      # Show numbers
display.show("HI:00")      # Colons work too
display.show("99.5")       # Decimal points supported
ParameterTypeDescription
textstrText to display (uppercase letters, numbers, some symbols)

Supported characters:

  • Letters: A-Z (uppercase, displayed as uppercase)
  • Numbers: 0-9
  • Symbols: . : - _ + = / \ * ! ? ' " ( ) [ ] < > @ # $ % ^ &
  • Space:
scroll(text, speed=0.1)

Start scrolling text across the display automatically.

# Scroll a message (adds padding automatically)
display.scroll("WELCOME TO THE GAME", 0.15)

# Faster scrolling
display.scroll("BREAKING NEWS", 0.05)
ParameterTypeDefaultDescription
textstr-Text to scroll
speedfloat0.1Seconds between scroll steps (smaller = faster)

The scroll loops continuously until you call show() or stop_scroll().

stop_scroll()

Stop scrolling and clear the display.

display.stop_scroll()
go_to(x, y)

Position the display on the stage (uses Scratch-style coordinates).

display.go_to(0, 200)      # Center-top
display.go_to(-300, -200)  # Bottom-left area
ParameterTypeDescription
xfloatX position (-480 to 480)
yfloatY position (-360 to 360)
hide() / show_display()

Hide or show the display.

display.hide()        # Make invisible
display.show_display()  # Make visible again

Example: Digital Clock

from ektupy import Stage, SegmentDisplay, on_start, on_forever
from ektupy import current_hour, current_minute, current_second

stage = Stage()
stage.set_background("#0d1117")

# Red clock display (like alarm clocks)
clock = SegmentDisplay(cells=8, color="#FF2222", scale=1.2)
stage.add_egg(clock)
clock.go_to(0, 0)

@on_forever
def update_clock():
    h = current_hour()
    m = current_minute()
    s = current_second()
    clock.show(f"{h:02d}:{m:02d}:{s:02d}")

Example: Game Score with Multiple Displays

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

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

# Title display - green
title = SegmentDisplay(cells=10, color="#00FF00", scale=1.0)
stage.add_egg(title)
title.go_to(0, 250)
title.show("HIGH SCORE")

# Score display - amber/orange
score_display = SegmentDisplay(cells=8, color="#FFAA00", scale=1.2)
stage.add_egg(score_display)
score_display.go_to(0, 150)

# Lives display - red
lives_display = SegmentDisplay(cells=6, color="#FF0000", scale=0.8)
stage.add_egg(lives_display)
lives_display.go_to(0, 50)

score = 0
lives = 3

@on_start
def setup():
    score_display.show(f"{score:08d}")
    lives_display.show(f"LIVES:{lives}")

@on_key_press("space")
def add_points():
    global score
    score += 100
    score_display.show(f"{score:08d}")

Example: Scrolling Message

from ektupy import Stage, SegmentDisplay, on_start

stage = Stage()
stage.set_background("#0d1117")

# Cyan scrolling display
news = SegmentDisplay(cells=16, color="#00FFFF", scale=0.9)
stage.add_egg(news)
news.go_to(0, 0)

@on_start
def setup():
    # Text scrolls automatically and loops
    news.scroll("    WELCOME TO EKTUPY - CREATE AMAZING GAMES WITH PYTHON    ", 0.12)

Global Event Decorators

These decorators register handlers that aren’t tied to a specific sprite.

@on_start

Runs once when the program starts.

@on_start
def setup():
    print("Game started!")

@on_forever

Runs every frame (approximately 60 times per second).

@on_forever
def game_loop():
    # Update game state
    pass

@on_key_press(key)

Runs when a specific key is pressed.

Key names: "a" to "z", "0" to "9", "space", "up arrow", "down arrow", "left arrow", "right arrow", "any" (any key)

@on_key_press("space")
def jump():
    player.change_y(50)

@on_key_press("any")
def any_key(key):
    print(f"Pressed: {key}")

@on_mouse_click

Runs when the mouse is clicked on the stage.

@on_mouse_click
def click_handler(x, y):
    print(f"Clicked at ({x}, {y})")
    sprite.go_to(x, y)

@on_message(message)

Runs when a broadcast message is received.

@on_message("level_complete")
def next_level():
    print("Loading next level...")

Control Functions

wait(seconds)

Pause execution without freezing the program.

@on_start
def setup():
    sprite.say("Hello!")
    wait(2)
    sprite.say("Goodbye!")

wait_until(condition)

Wait until a condition becomes true.

@on_start
def setup():
    sprite.say("Waiting for you to press space...")
    wait_until(lambda: key_pressed("space"))
    sprite.say("Thanks!")

stop() / stop_all()

Stop the game/program.

if game_over:
    stop()

Input Functions

key_pressed(key)

Check if a key is currently held down.

if key_pressed("right arrow"):
    sprite.change_x(5)

mouse_x() / mouse_y()

Get the mouse position on the stage.

x = mouse_x()
y = mouse_y()
sprite.go_to(x, y)

mouse_down()

Check if the mouse button is pressed.

if mouse_down():
    sprite.stamp()

Sensing Functions

Global functions for sensing time, date, and environment.

Timer

timer()

Get the time in seconds since the program started (or since the last reset).

t = timer()
if t > 30:
    sprite.say("30 seconds passed!")

reset_timer()

Reset the timer back to 0.

reset_timer()
# timer() now returns 0

Date and Time

current_year()

Get the current year.

year = current_year()  # e.g., 2025

current_month()

Get the current month (1-12).

month = current_month()  # 1=January, 12=December

current_date()

Get the current day of the month (1-31).

day = current_date()

current_day_of_week()

Get the current day of the week (1-7, where 1=Sunday).

day_of_week = current_day_of_week()
if day_of_week == 1:
    sprite.say("It's Sunday!")

current_hour()

Get the current hour (0-23).

hour = current_hour()
if hour < 12:
    sprite.say("Good morning!")

current_minute()

Get the current minute (0-59).

minute = current_minute()

current_second()

Get the current second (0-59).

second = current_second()

days_since_2000()

Get the number of days since January 1, 2000 (including fractional days).

days = days_since_2000()
sprite.say(f"{int(days)} days since Y2K!")

Ask and Answer

Get user input through an on-screen text box, just like Scratch’s “ask [] and wait” block.

ask(prompt)

Show a text input box at the bottom of the stage with a prompt, wait for the user to type and submit an answer, then return the answer as a string.

@on_start
def setup():
    name = ask("What is your name?")
    sprite.say(f"Hello, {name}!")

The input box appears at the bottom of the stage with:

  • The prompt text displayed above the input field
  • A text input where the user can type
  • A submit button (or press Enter to submit)

The program pauses until the user submits their answer.

answer()

Get the most recent answer from ask(). This is useful when you need to access the last answer later in your code.

@on_start
def setup():
    ask("What is your name?")
    name = answer()  # Get the answer that was just entered

    ask("How old are you?")
    age = answer()   # Get this new answer

    sprite.say(f"Hi {name}, you are {age} years old!")

Example: Multiple questions

@on_start
def quiz():
    score = 0

    ask("What is 5 + 3?")
    if answer() == "8":
        score += 1
        sprite.say("Correct!")
    else:
        sprite.say("Wrong! It's 8")
    wait(1)

    ask("What color is the sky?")
    if answer().lower() == "blue":
        score += 1
        sprite.say("Correct!")
    else:
        sprite.say("Wrong!")
    wait(1)

    sprite.say(f"You scored {score}/2!")

Messaging

broadcast(message, data=None)

Send a message to all listeners.

broadcast("game_over")
broadcast("score_changed", {"score": 100})

Receive with @on_message or @sprite.on_message:

@on_message("score_changed")
def update_score(data):
    print(f"New score: {data['score']}")

broadcast_and_wait(message, data=None)

Send a message and wait for all handlers to complete before continuing.

# Send message and wait for all handlers to finish
broadcast_and_wait("prepare_level")
# This line runs after ALL @on_message("prepare_level") handlers complete
print("Level ready!")

Useful for synchronization:

@cat.on_key_press("space")
def start_animation():
    cat.say("Ready...")
    broadcast_and_wait("all_sprites_ready")  # Wait for everyone
    cat.say("Go!")  # Only runs after all handlers finish

@dog.on_message("all_sprites_ready")
def dog_prepare():
    dog.go_to(0, 0)
    wait(1)  # This delay is waited for by broadcast_and_wait

Console Output

Use standard Python print() for debugging:

print("Hello!")           # Appears in white
print(f"Position: {x}")   # String formatting works

import sys
sys.stderr.write("Error!\n")  # Appears in red

Sound Functions

Play sounds and music in your projects, just like Scratch’s Sound blocks.

Loading and Playing Sounds

load_sound(name)

Load a sound by name and return a Sound object. The name is looked up in the asset map.

# Load a sound - returns a Sound object
poweron = load_sound("sfx_sound_poweron")
coin = load_sound("sfx_coin_single1")
ParameterTypeDescription
namestrAsset name to look up in the sound library

Returns: Sound - A Sound object to use with start_sound(), stop_sound(), etc.

Asset names will show a warning in the editor if the name doesn’t exist. See Asset Map for available sounds.

start_sound(sound)

Start playing a sound (like Scratch’s “play sound” block). The sound plays in the background while your code continues running.

meow = load_sound("sfx_sound_meow")
start_sound(meow)    # Plays and continues immediately
sprite.say("Meow!")  # Runs right away
ParameterTypeDescription
soundSoundA Sound object returned by load_sound()

play_sound_until_done(sound)

Play a sound and wait until it finishes (like Scratch’s “play sound until done” block).

meow = load_sound("sfx_sound_meow")

@on_start
def setup():
    sprite.say("Listen...")
    play_sound_until_done(meow)  # Waits for sound to finish
    sprite.say("Done!")          # Only runs after sound ends

stop_all_sounds()

Stop all currently playing sounds.

stop_all_sounds()

Volume Control

Control the global volume of all sounds (0-100, like Scratch).

set_volume(value)

Set the volume (0-100).

set_volume(50)   # 50% volume
set_volume(100)  # Full volume
set_volume(0)    # Muted

change_volume(amount)

Change the volume by an amount.

change_volume(10)   # Volume up by 10
change_volume(-20)  # Volume down by 20

get_volume()

Get the current volume level (0-100).

vol = get_volume()
sprite.say(f"Volume: {vol}%")

Sound Effects

Apply effects to sounds like pitch and stereo panning.

set_pitch_effect(value)

Set the pitch effect (like Scratch). Range is approximately -360 to 360.

  • 0 = normal pitch
  • Positive values = higher pitch (faster playback)
  • Negative values = lower pitch (slower playback)
set_pitch_effect(60)   # Higher pitch
set_pitch_effect(-60)  # Lower pitch
set_pitch_effect(0)    # Normal

change_pitch_effect(amount)

Change the pitch effect by an amount.

change_pitch_effect(10)   # Increase pitch
change_pitch_effect(-20)  # Decrease pitch

set_pan_effect(value)

Set the stereo pan (like Scratch’s “set pan left/right” effect).

  • -100 = full left speaker
  • 0 = center (both speakers)
  • 100 = full right speaker
set_pan_effect(-100)  # Full left
set_pan_effect(0)     # Center
set_pan_effect(100)   # Full right

change_pan_effect(amount)

Change the pan effect by an amount.

change_pan_effect(50)  # Pan more to the right

clear_sound_effects()

Reset all sound effects (pitch and pan) to normal.

clear_sound_effects()  # Reset to normal pitch and center pan

Example: Playing Sounds with Effects

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

# Load sounds - each returns a Sound object
coin_sound = load_sound("sfx_coin_single1")
fanfare_sound = load_sound("sfx_sounds_fanfare1")

@on_start
def setup():
    set_volume(70)  # 70% volume
    start_sound(fanfare_sound)  # Play a fanfare

@on_key_press("space")
def coin():
    cat.say("Coin!")
    start_sound(coin_sound)

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

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

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

Asset Map

EktuPy includes an asset map that makes it easy to use sprites and sounds by name instead of remembering full paths.

How It Works

The asset map is a JSON file (asset_map.json) that maps asset names to their full paths. This is generated from the static/assets/sprites and static/assets/sounds directories.

When you use an asset name (without slashes), EktuPy automatically looks it up in the asset map and uses the full path.

Using Asset Names

Sprites:

# Instead of using the full path:
snake = Sprite("/static/assets/sprites/snake.svg")

# You can use the asset name:
snake = Sprite("snake")

Sounds:

# Load a sound by name - returns a Sound object
hit_sound = load_sound("sfx_sound_neutral1")

# Then use it to play the sound
start_sound(hit_sound)

Benefits

  1. Shorter code: No need to type long paths
  2. Editor validation: The editor shows a warning if you use a name that doesn’t exist
  3. Easier to remember: Use descriptive names instead of file paths

Helper Functions

get_available_sprites()

Get a list of all available sprite asset names.

sprites = get_available_sprites()
print(sprites)  # ['snake', 'paddle', 'ball-solid', ...]

get_available_sounds()

Get a list of all available sound asset names.

sounds = get_available_sounds()
print(sounds)  # ['sfx_sound_neutral1', 'sfx_sound_neutral2', ...]

get_available_backdrops()

Get a list of all available backdrop asset names.

backdrops = get_available_backdrops()
print(backdrops)  # ['jungle', 'mountain-sunrise', 'paddy-field', 'race-track', 'sky-and-clouds']

Naming Conflicts

If two files have the same basename but different extensions (e.g., ball.svg and ball.png), they are differentiated by adding the extension to the name:

  • ball-svg for ball.svg
  • ball-png for ball.png