Sprite Engine Basics
Welcome to Unit 4 — Building Games! HyperXTalk includes a powerful built-in sprite engine that lets you create 2D games with moving characters, collision detection, and smooth animation. In this lesson you'll learn the fundamentals: placing sprites, making them move, tracking keyboard input, and detecting when sprites collide.
- Set up the Sprite Canvas widget on a card
- Create, position, and size sprites
- Set velocity to make sprites move automatically each tick
- Use the
spriteTickhandler as your game loop - Track which keys are held down for smooth movement
- Detect collisions between sprites
- Read sprite position and size with
spriteInfo
🎮 Overview
The HyperXTalk sprite engine revolves around three things: a Sprite Canvas widget that does the rendering, a set of commands for creating and controlling sprites, and a tick loop that calls your card script many times per second so you can update game state.
The engine script is included with HyperXTalk. Add it to your stack once and all the sprite commands become available everywhere. The basic structure of any sprite game looks like this:
resumeSprites at the very end of openCard, after all your sprites are created and configured. Starting the tick loop before everything is set up can cause errors.
🖼️ The Sprite Canvas
The Sprite Canvas is a widget — add it to your card from the Tools palette just like any other control. Resize it to fill whatever area you want your game to occupy. Give it a memorable name in the Property Inspector (e.g. GameCanvas) then tell the engine about it at the start of openCard:
If you only have one Sprite Canvas on the card you can skip this — the engine will find it automatically. But calling it explicitly is good practice and avoids confusion if you ever add a second canvas.
You can also set the canvas background colour:
🧩 Creating Sprites
A sprite is a named image that lives on the canvas. Create one with createSprite, passing its name, image source, and optionally its starting position and size:
The image source can be a file path or the name of a HyperXTalk image object stored in the stack. If you don't provide an image, a magenta placeholder rectangle is drawn instead — useful for testing layout before your art is ready.
You can show and hide sprites, swap their images, and remove them:
🏃 Movement and Velocity
The most natural way to make sprites move is to set their velocity — the number of pixels to move each tick. The engine adds this to the sprite's position automatically on every tick:
Positive X moves right, negative X moves left. Positive Y moves down, negative Y moves up — the canvas coordinate system has (0,0) at the top left.
⏱️ The Tick Loop
The tick loop is the heartbeat of your game. Every tick (about 60 times per second), the engine sends a spriteTick message to your card. Handle it to update game logic — check for collisions, apply physics, respond to input:
You can pause and resume the tick loop at any time:
⌨️ Key Tracking
For smooth player movement you need to know which keys are currently held down, not just which key was last pressed. The standard pattern is to track this yourself using rawKeyDown and rawKeyUp handlers in your card script, storing held keys in local variables:
Key codes for common game keys:
| Key | Code | Key | Code |
|---|---|---|---|
| A | 97 | D | 100 |
| W | 119 | S | 115 |
| ↑ Up arrow | 65362 | ↓ Down arrow | 65364 |
| ← Left arrow | 65361 | → Right arrow | 65363 |
| Space | 32 | Return | 13 |
rawKeyDown and rawKeyUp in your card script, not a button script. The card receives key events naturally when no other control has focus. If the Sprite Canvas takes focus, it forwards key events back to the card automatically.
💥 Collision Detection
The engine checks for sprite collisions automatically every tick and sends a spriteCollision message to your card whenever two sprites overlap. Handle it to react to collisions:
You can also check for collision manually at any point using spritesCollide:
For precise collision with complex sprites, you can define a custom hitbox — a rectangle smaller than the visible sprite that's used for collision testing. This avoids false collisions at the transparent edges of an image:
📊 Reading Sprite State
spriteInfo returns a comma-delimited string with everything you need to know about a sprite. There are also convenience functions for reading individual values:
Build a simple game where the player chases a star around the canvas using the A and D keys. When they collide, the star jumps to a new random position and the score increases.
-
Create a new stack. Add a Sprite Canvas widget from the Tools palette and name it
GameCanvas. Size it to fill most of the card. Add a Label above it namedScoreLabel. -
Add this to the card script:
local gKeyRight, gKeyLeft, gScore on openCard put 0 into gScore setSpriteCanvas "GameCanvas" createSprite "player", empty, 200, 200, 40, 40 createSprite "star", empty, 350, 150, 30, 30 resumeSprites end openCard on spriteTick if gKeyRight then setSpriteVelocity "player", 4, 0 else if gKeyLeft then setSpriteVelocity "player", -4, 0 else setSpriteVelocity "player", 0, 0 if spritesCollide("player", "star") then add 1 to gScore setSpritePosition "star", random(550), random(350) set the text of field "ScoreLabel" to "Score: " & gScore end if end spriteTick on rawKeyDown pKey if pKey is 100 then put true into gKeyRight if pKey is 97 then put true into gKeyLeft end rawKeyDown on rawKeyUp pKey if pKey is 100 then put false into gKeyRight if pKey is 97 then put false into gKeyLeft end rawKeyUp
- Switch to Browse mode and press A and D to chase the magenta star. Each time you catch it, it jumps to a random new position and your score goes up.
Bonus challenges: Add W and S keys so the player can also move up and down. Add a second star that moves on its own by setting its velocity in openCard and bouncing it off the canvas edges in spriteTick.
resumeSprites — call it at the very end of openCard, after all sprites have been created and configured. Starting the loop before everything is set up can cause errors.rawKeyDown/rawKeyUp rather than just checking key state inside spriteTick?rawKeyDown/rawKeyUp to track held keys in boolean variables gives you smooth, frame-perfect movement — the sprite moves every tick the key is held. Checking inside spriteTick alone would miss the key being held between ticks, causing stuttery movement.item 3 of spriteInfo("player") return?spriteInfo string is formatted as name,x,y,w,h,vx,vy,visible,group — so item 1 = name, item 2 = x, item 3 = y, item 4 = width, item 5 = height, and so on.