EktuPy Examples
This page contains example programs demonstrating EktuPy features. Each example includes a code walkthrough explaining the key concepts.
Hello World
The simplest EktuPy program - display a sprite with a speech bubble.
What you’ll learn:
- Creating a stage and sprite
- Using the
@on_startdecorator - Basic sprite positioning and speech bubbles
View Code
# Hello Snake - Simple greeting example
from ektupy import Stage, Sprite, on_start
stage = Stage()
stage.set_background("#2d5a27")
snake = Sprite("snake")
stage.add_sprite(snake)
@on_start
def setup():
snake.go_to(0, 0)
snake.say("Hello, I'm Py the Snake!", 5)
Code Breakdown
Imports and Setup
from ektupy import Stage, Sprite, on_start
Import the core classes and the @on_start decorator.
Stage Creation
stage = Stage()
stage.set_background("#2d5a27") # Dark green color
Create a 960x720 pixel stage with a custom background color using CSS hex notation.
Sprite Creation
snake = Sprite("snake")
stage.add_sprite(snake)
Create a sprite using the asset name “snake” and add it to the stage. The sprite won’t be visible until added.
Event Handler
@on_start
def setup():
snake.go_to(0, 0)
snake.say("Hello, I'm Py the Snake!", 5)
The @on_start decorator runs this function once when the program starts. say() displays a speech bubble for 5 seconds.
Arrow Key Movement
Move a sprite around the stage using arrow keys.
What you’ll learn:
- Using
@on_foreverfor continuous checking - Reading keyboard input with
key_pressed() - Sprite direction and movement
- Edge bouncing
View Code
# Arrow Key Movement Example
# Use arrow keys to move the snake
from ektupy import Stage, Sprite, on_start, on_forever, key_pressed
stage = Stage()
snake = Sprite("snake")
stage.add_sprite(snake)
speed = 5
@on_start
def setup():
snake.go_to(0, 0)
snake.say("Use arrow keys to move!", 3)
@on_forever
def game_loop():
if key_pressed("right arrow"):
snake.direction = 90
snake.move(speed)
if key_pressed("left arrow"):
snake.direction = -90
snake.move(speed)
if key_pressed("up arrow"):
snake.direction = 0
snake.move(speed)
if key_pressed("down arrow"):
snake.direction = 180
snake.move(speed)
snake.bounce_if_on_edge()
Code Breakdown
Game Variables
speed = 5
Store movement speed in a variable for easy adjustment.
The Forever Loop
@on_forever
def game_loop():
This function runs every frame (~60 times per second), perfect for checking continuous input.
Key Checking
if key_pressed("right arrow"):
snake.direction = 90 # Point right (90 degrees)
snake.move(speed) # Move forward
key_pressed() returns True while a key is held. Direction uses Scratch-style angles: 0=up, 90=right, 180=down, -90=left.
Boundary Handling
snake.bounce_if_on_edge()
Prevents the sprite from leaving the stage by reversing direction at edges.
Bouncing Ball
A sprite that bounces around the stage continuously.
What you’ll learn:
- Random initial direction
- Continuous movement with bouncing
- Using Python’s
randommodule
View Code
# Bouncing Ball Example
# Watch the snake bounce around the stage
from ektupy import Stage, Sprite, on_start, on_forever
import random
stage = Stage()
stage.set_background("#1a1a2e")
snake = Sprite("snake")
stage.add_sprite(snake)
speed = 8
@on_start
def setup():
snake.go_to(0, 0)
snake.direction = random.randint(30, 60)
snake.say("Wheee!", 2)
@on_forever
def game_loop():
snake.move(speed)
snake.bounce_if_on_edge()
Code Breakdown
Random Direction
import random
snake.direction = random.randint(30, 60)
Python’s standard library works in EktuPy! Set a random diagonal direction at startup.
Continuous Motion
@on_forever
def game_loop():
snake.move(speed)
snake.bounce_if_on_edge()
The sprite moves forward continuously and bounces off walls automatically.
Drawing with Pen
Use the pen to draw on the stage as the sprite moves.
What you’ll learn:
- Pen down/up for drawing
- Pen color and size
- Following mouse position
- Clearing drawings
View Code
# Drawing with Pen Example
# Click and drag to draw, press 'c' to clear
from ektupy import Stage, Sprite, on_start, on_forever
from ektupy import mouse_x, mouse_y, mouse_down, key_pressed
stage = Stage()
pen = Sprite("snake")
pen.size = 30
stage.add_sprite(pen)
@on_start
def setup():
pen.pen_up()
pen.set_pen_color("#00ff00")
pen.set_pen_size(3)
pen.say("Click to draw, 'c' to clear", 3)
@on_forever
def draw():
pen.go_to(mouse_x(), mouse_y())
if mouse_down():
pen.pen_down()
else:
pen.pen_up()
# Press 'c' to clear
if key_pressed("c"):
pen.clear()
# Color keys
if key_pressed("1"):
pen.set_pen_color("#ff0000") # Red
if key_pressed("2"):
pen.set_pen_color("#00ff00") # Green
if key_pressed("3"):
pen.set_pen_color("#0000ff") # Blue
Code Breakdown
Pen Setup
pen.pen_up() # Start with pen up
pen.set_pen_color("#00ff00") # Green color
pen.set_pen_size(3) # 3 pixel line width
Configure pen before drawing. Use CSS colors (hex, rgb, or named).
Mouse Tracking
pen.go_to(mouse_x(), mouse_y())
Move sprite to current mouse position every frame.
Drawing Logic
if mouse_down():
pen.pen_down()
else:
pen.pen_up()
Only draw when mouse button is pressed.
Color Switching
if key_pressed("1"):
pen.set_pen_color("#ff0000")
Change colors with number keys for variety.
Two Sprites
Each sprite can have its own scripts, just like in Scratch!
What you’ll learn:
- Per-sprite event decorators (
@sprite.on_start,@sprite.on_key_press) - Multiple sprites with independent controls
- Collision detection
- Broadcasting messages between sprites
View Code
# Two Sprites Example - Cat and Dog
# This shows how each sprite can have its own scripts, just like Scratch!
# Create the stage
stage = Stage()
stage.set_background("#87CEEB") # Sky blue background
# Create our two sprites
cat = Sprite("cat")
dog = Sprite("dog")
# Add sprites to the stage
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 - Check if they touch
# ============================================
@cat.on_forever
def check_collision():
if cat.touching(dog):
cat.say("Hey!")
dog.say("Hi friend!")
Code Breakdown
Per-Sprite Decorators
@cat.on_start # Only for cat
@dog.on_key_press("w") # Only for dog
Each sprite has its own event handlers, keeping code organized.
Different Control Schemes
- Cat uses arrow keys
- Dog uses WASD keys Both can move simultaneously!
Message Broadcasting
broadcast("woof") # Dog sends message
@cat.on_message("woof") # Cat receives it
def cat_hears_woof():
cat.say("Meow back!")
Sprites can communicate through broadcast messages.
Collision Detection
if cat.touching(dog):
cat.say("Hey!")
Check if two sprites are overlapping using bounding box collision.
Many Sprites
Click on sprites to select them, then move with arrow keys.
What you’ll learn:
- Managing multiple sprites
- Click handlers with
on_clicked() - Global state for selection
- Dynamic behavior based on selection
View Code
# Many Sprites Example
# Click on a sprite to select it, then use arrow keys to move it!
from ektupy import Stage, Sprite, on_start, on_key_press
import random
stage = Stage()
stage.set_background("#1a1a2e")
# Create all the sprites
lion = Sprite("lion")
fish = Sprite("fish")
cat = Sprite("cat")
shark = Sprite("shark")
snake = Sprite("snake")
# Add them to the stage
stage.add_sprite(lion)
stage.add_sprite(fish)
stage.add_sprite(cat)
stage.add_sprite(shark)
stage.add_sprite(snake)
# Track which sprite is selected
selected_sprite = None
def select_sprite(sprite, name):
"""Select a sprite and make it say its name."""
global selected_sprite
selected_sprite = sprite
# Clear speech from all sprites
lion.say("")
fish.say("")
cat.say("")
shark.say("")
snake.say("")
# Selected sprite says its name
sprite.say(f"I'm {name}!")
@on_start
def setup():
# Place sprites at random positions
for sprite in [lion, fish, cat, shark, snake]:
x = random.randint(-350, 350)
y = random.randint(-250, 250)
sprite.go_to(x, y)
sprite.size = 80
print("Click on a sprite to select it!")
print("Use arrow keys to move the selected sprite.")
# Click handlers for each sprite
def click_lion():
select_sprite(lion, "Lion")
def click_fish():
select_sprite(fish, "Fish")
def click_cat():
select_sprite(cat, "Cat")
def click_shark():
select_sprite(shark, "Shark")
def click_snake():
select_sprite(snake, "Snake")
# Register click handlers
lion.on_clicked(click_lion)
fish.on_clicked(click_fish)
cat.on_clicked(click_cat)
shark.on_clicked(click_shark)
snake.on_clicked(click_snake)
# Arrow key movement
@on_key_press("up arrow")
def move_up():
if selected_sprite:
selected_sprite.change_y(20)
@on_key_press("down arrow")
def move_down():
if selected_sprite:
selected_sprite.change_y(-20)
@on_key_press("left arrow")
def move_left():
if selected_sprite:
selected_sprite.change_x(-20)
@on_key_press("right arrow")
def move_right():
if selected_sprite:
selected_sprite.change_x(20)
Code Breakdown
Click Handler Registration
lion.on_clicked(click_lion)
Register a callback function to run when this sprite is clicked.
Selection State
selected_sprite = None
def select_sprite(sprite, name):
global selected_sprite
selected_sprite = sprite
Use a global variable to track the currently selected sprite.
Conditional Movement
if selected_sprite:
selected_sprite.change_y(20)
Only move if a sprite is selected (not None).
Costume Animation
Watch the snake change costumes as it moves!
What you’ll learn:
- Costume system
- Frame-based animation timing
- Accessing costume properties
View Code
# Costume Animation Example
# Watch the snake change colors as it moves!
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.set_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}")
Code Breakdown
Costume Access
print("Available costumes:", snake.costumes)
Sprites can have multiple costumes. Access the list via the costumes property.
Frame Counting
frame_count += 1
if frame_count % 20 == 0:
snake.next_costume()
Use modulo (%) to trigger actions periodically. At 60fps, % 20 triggers ~3 times per second.
Costume Properties
snake.costume_name # Current costume name
snake.costume_number # Current costume index
Mouse Tracker
A sprite that follows and reacts to the mouse.
What you’ll learn:
- Distance calculations
- Mouse sensing
- Point-towards behavior
- Conditional responses based on distance
View Code
# Mouse Tracker - Sensing Mouse Position
# Demonstrates distance_to_mouse and touching_mouse
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)
Code Breakdown
Distance Sensing
dist = snake.distance_to_mouse()
Get the pixel distance between sprite center and mouse position.
Conditional Responses
if snake.touching_mouse():
snake.say("You caught me!")
elif dist < 80:
snake.say("Too close!")
Create zones of different behavior based on distance.
Following Behavior
snake.point_towards_mouse()
if dist > 10:
snake.move(2)
Point toward mouse and move only if not already there (prevents jittering).
Ask Name
Get user input through an on-screen text box.
What you’ll learn:
- Using
ask()for user input - Working with the returned answer
- Sequential prompts
View Code
# Ask Your Name - User Input Example
# Demonstrates the ask() and answer() functions
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}"')
Code Breakdown
Getting Input
name = ask("What's your name?")
Shows an input box at the bottom of the stage. Program pauses until user submits.
Using the Answer
snake.say(f"Hello, {name}!")
The returned value is a string you can use immediately.
Multiple Questions
name = ask("What's your name?")
color = ask("What's your favorite color?")
Each ask() waits for its own response before continuing.
Digital Clock
Display the current time and date using sensing functions.
What you’ll learn:
- Date/time functions
- Timer functions
- String formatting
- Creating a live display
View Code
# Digital Clock - Sensing Time Example
# Demonstrates timer and date/time functions
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")
Code Breakdown
Time Functions
h = current_hour() # 0-23
m = current_minute() # 0-59
s = current_second() # 0-59
Get current time from the user’s system.
Day of Week
days = ["", "Sunday", "Monday", ...]
day = days[current_day_of_week()] # 1=Sunday
Convert numeric day (1-7) to a name using a lookup list.
String Formatting
f"{h:02d}:{m:02d}:{s:02d}" # "09:05:03"
Python f-strings with format specifiers for leading zeros.
Timer
reset_timer() # Start at 0
elapsed = int(timer()) # Seconds since reset
Track time elapsed since program started.
Background Images
Use backdrop images and cycle through them.
What you’ll learn:
- Setting background images
- Discovering available assets
- Cycling through options
View Code
# Background Image Example
# Demonstrates using backdrop images with sprites
from ektupy import Stage, Sprite, on_start, on_forever, key_pressed
from ektupy import get_available_backdrops
stage = Stage()
stage.set_background_image("mountain-sunrise")
snake = Sprite("snake")
stage.add_sprite(snake)
# Track current backdrop index
backdrops = ["mountain-sunrise", "jungle", "paddy-field", "sky-and-clouds"]
current_backdrop = 0
@on_start
def setup():
snake.go_to(0, -200)
snake.say("Press SPACE to change backdrop!", 3)
print("Available backdrops:", get_available_backdrops())
@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)
Code Breakdown
Setting Background Image
stage.set_background_image("mountain-sunrise")
Use asset names for backgrounds, just like sprites.
Asset Discovery
print("Available backdrops:", get_available_backdrops())
Runtime function to list available backdrop names.
Cycling with Modulo
current_backdrop = (current_backdrop + 1) % len(backdrops)
Wrap around to 0 when reaching the end of the list.
Pong Game
A complete two-player Pong game with sound effects.
What you’ll learn:
- Game state management
- Two-player controls
- Ball physics with bouncing
- Score tracking
- Sound effects
View Code
# Pong Game Example
# Classic two-player Pong game
# Player 1 (Left): W/S keys
# Player 2 (Right): Up/Down arrow keys
# Press SPACE to start/restart the ball
# Game variables (scaled for 960x720 stage)
ball_speed_x = 0
ball_speed_y = 0
paddle_speed = 10
score1 = 0
score2 = 0
ball_moving = False
# Create the stage with dark background
stage = Stage()
stage.set_background("#1a1a2e")
# Load sound effects
load_sound("hit", "sfx_sound_neutral1")
load_sound("score", "sfx_sound_neutral5")
# Create sprites
paddle1 = Sprite("paddle")
paddle2 = Sprite("paddle")
ball = Sprite("ball")
# Add sprites to stage
stage.add_sprite(paddle1)
stage.add_sprite(paddle2)
stage.add_sprite(ball)
@on_start
def setup():
global ball_speed_x, ball_speed_y, score1, score2, ball_moving
# Position paddles on left and right sides
paddle1.go_to(-440, 0)
paddle2.go_to(440, 0)
# Center the ball
ball.go_to(0, 0)
ball.size = 80
# Reset scores and ball state
score1 = 0
score2 = 0
ball_speed_x = 0
ball_speed_y = 0
ball_moving = False
# Show instructions
ball.say("Press SPACE to start!")
@on_key_press("space")
def start_ball():
global ball_speed_x, ball_speed_y, ball_moving
if not ball_moving:
ball_speed_x = 6
ball_speed_y = 4
ball_moving = True
ball.say("")
@on_forever
def game_loop():
global ball_speed_x, ball_speed_y, score1, score2, ball_moving
# Player 1 controls (W/S)
if key_pressed("w"):
if paddle1.y < 280:
paddle1.change_y(paddle_speed)
if key_pressed("s"):
if paddle1.y > -280:
paddle1.change_y(-paddle_speed)
# Player 2 controls (Up/Down arrows)
if key_pressed("up arrow"):
if paddle2.y < 280:
paddle2.change_y(paddle_speed)
if key_pressed("down arrow"):
if paddle2.y > -280:
paddle2.change_y(-paddle_speed)
# Only move ball if game is active
if not ball_moving:
return
# Move the ball
ball.change_x(ball_speed_x)
ball.change_y(ball_speed_y)
# Ball bounces off top and bottom walls
if ball.y > 330 or ball.y < -330:
ball_speed_y = -ball_speed_y
# Ball bounces off paddles
if ball.touching(paddle1) and ball_speed_x < 0:
ball_speed_x = -ball_speed_x
ball_speed_y += (ball.y - paddle1.y) * 0.1
start_sound("hit")
if ball.touching(paddle2) and ball_speed_x > 0:
ball_speed_x = -ball_speed_x
ball_speed_y += (ball.y - paddle2.y) * 0.1
start_sound("hit")
# Limit vertical speed
if ball_speed_y > 16:
ball_speed_y = 16
if ball_speed_y < -16:
ball_speed_y = -16
# Score when ball goes past paddles
if ball.x < -480:
score2 += 1
reset_ball()
if ball.x > 480:
score1 += 1
reset_ball()
def reset_ball():
global ball_speed_x, ball_speed_y, ball_moving
start_sound("score")
ball.go_to(0, 0)
ball_speed_x = 0
ball_speed_y = 0
ball_moving = False
ball.say(f"{score1} - {score2} Press SPACE")
Code Breakdown
Game State
ball_speed_x = 0
ball_speed_y = 0
ball_moving = False
score1 = 0
score2 = 0
Track all game state in global variables.
Sound Effects
load_sound("hit", "sfx_sound_neutral1")
start_sound("hit") # Play when ball hits paddle
Load sounds with asset names, play them at appropriate moments.
Paddle Movement with Bounds
if key_pressed("w"):
if paddle1.y < 280: # Don't go off top
paddle1.change_y(paddle_speed)
Check bounds before moving to keep paddles on screen.
Ball Physics
# Bounce off walls
if ball.y > 330 or ball.y < -330:
ball_speed_y = -ball_speed_y
# Bounce off paddle with angle
if ball.touching(paddle1) and ball_speed_x < 0:
ball_speed_x = -ball_speed_x
ball_speed_y += (ball.y - paddle1.y) * 0.1 # Add spin
Simple physics with direction reversal and spin based on hit position.
Scoring
if ball.x < -480:
score2 += 1
reset_ball()
Check if ball passes paddles to award points.
Racing Game
Avoid traffic in this endless racing game.
What you’ll learn:
- Object pooling for traffic
- Lane-based movement
- Collision detection
- Background music with looping
- Progressive difficulty
View Code
"""
Racing Down - Avoid the Traffic!
Use LEFT and RIGHT arrow keys to move your red car
Avoid the oncoming traffic. Don't crash!
Press SPACE to restart after game over
"""
from ektupy import (
Stage, Sprite, on_start, on_forever, on_key_press,
load_sound, start_sound, set_sound_loop, set_sound_volume
)
import random
# Create stage with race track background
stage = Stage()
stage.set_background_image("race-track")
# Player's red car
player = Sprite("car")
player.switch_costume("red")
player.size = 80
stage.add_sprite(player)
# Traffic vehicles pool
traffic_types = [
("car", "blue", 70),
("car", "green", 70),
("car", "default", 70),
("truck", "yellow", 80),
("truck", "default", 80),
]
traffic = []
# Create pool of traffic vehicles
for i in range(6):
sprite_name, costume_name, size = traffic_types[i % 3]
car = Sprite(sprite_name)
car.switch_costume(costume_name)
car.size = size
car.hide()
stage.add_sprite(car)
traffic.append(car)
# Lane positions (x coordinates for 3 lanes)
LANES = [-130, 0, 130]
# Game state
game_over = False
score = 0
speed = 5
# Load sounds
load_sound("crash", "sfx_damage_hit1")
load_sound("music", "boss_battle")
@on_start
def setup():
global game_over, score, speed
game_over = False
score = 0
speed = 5
player.go_to(0, -280)
player.show()
for car in traffic:
car.hide()
car.go_to(0, 500)
# Start background music
set_sound_loop("music", True)
set_sound_volume("music", 30)
start_sound("music")
def spawn_traffic():
for car in traffic:
if not car.visible:
lane = random.choice(LANES)
car.go_to(lane, 400)
car.show()
return
def check_collision(car):
px, py = player.x, player.y
cx, cy = car.x, car.y
player_w, player_h = 30, 50
car_w, car_h = 30, 50
if abs(px - cx) < (player_w + car_w) / 2:
if abs(py - cy) < (player_h + car_h) / 2:
return True
return False
@on_forever
def game_loop():
global game_over, score, speed
if game_over:
return
for car in traffic:
if car.visible:
car.change_y(-speed)
if check_collision(car):
game_over = True
start_sound("crash")
player.say("GAME OVER!")
return
if car.y < -400:
car.hide()
score += 1
# Spawn new traffic (max 3 at a time)
if count_active_traffic() < 3:
if random.random() < 0.03:
spawn_traffic()
# Gradually increase speed
if score > 0 and score % 10 == 0:
speed = min(12, 5 + score // 10)
@on_key_press("left arrow")
def move_left():
if not game_over:
current_x = player.x
for i, lane in enumerate(LANES):
if abs(current_x - lane) < 50:
if i > 0:
player.set_x(LANES[i - 1])
break
@on_key_press("right arrow")
def move_right():
if not game_over:
current_x = player.x
for i, lane in enumerate(LANES):
if abs(current_x - lane) < 50:
if i < len(LANES) - 1:
player.set_x(LANES[i + 1])
break
@on_key_press("space")
def restart_game():
global game_over, score, speed
if game_over:
game_over = False
score = 0
speed = 5
player.go_to(0, -280)
player.say("")
for car in traffic:
car.hide()
Code Breakdown
Object Pooling
traffic = []
for i in range(6):
car = Sprite(sprite_name)
car.hide()
traffic.append(car)
Pre-create sprites and reuse them instead of creating new ones. Improves performance.
Lane-Based Movement
LANES = [-130, 0, 130]
for i, lane in enumerate(LANES):
if abs(current_x - lane) < 50:
if i > 0:
player.set_x(LANES[i - 1])
Snap player to discrete lanes instead of free movement.
Background Music
set_sound_loop("music", True) # Loop the music
set_sound_volume("music", 30) # 30% volume
start_sound("music") # Start playing
Configure and play looping background music.
Progressive Difficulty
if score > 0 and score % 10 == 0:
speed = min(12, 5 + score // 10)
Increase traffic speed every 10 points, capped at 12.
Summary
These examples demonstrate the core features of EktuPy:
| Category | Examples |
|---|---|
| Basics | Hello World, Movement |
| Animation | Bouncing Ball, Costumes |
| Input | Arrow Keys, Mouse Tracker, Ask Name |
| Drawing | Pen Drawing |
| Multiple Sprites | Two Sprites, Many Sprites |
| Sensing | Clock, Mouse Tracker |
| Games | Pong, Racing |
Try modifying these examples to learn more. Experiment with:
- Changing colors and speeds
- Adding more sprites
- Creating new game mechanics
- Combining features from different examples