Example Assets Needed:
This chapter builds a complete game! You'll need:Sprites:
- player.png — 32x32 character spritesheet (4 frames for animation)
- coin.png — 16x16 collectible spritesheet (4 frames for spin animation)
Sound Effects (.wav):
- coin.wav — Collect sound
- miss.wav — Miss/fail sound
- gameover.wav — Game over jingle
Music (.mp3):
- music.mp3 — Loopable background music
If you've been following along, you already have most of these from earlier chapters!
You've learned variables, loops, conditionals, graphics, sprites, sound, saving, behaviors, collisions... that's a LOT of ingredients!
But here's the thing about soup: having all the ingredients doesn't mean you have soup. You need to combine them, let them simmer, taste-test, adjust the seasoning...
Is YOUR game soup yet?
This chapter is about putting it all together. We'll build a complete game from scratch, and along the way, I'll share the secrets to making your game feel FINISHED—not just functional.
The Game Development Recipe
Every good game follows a recipe. Here's mine:
1. Start With the Core Loop
What does the player DO? Over and over? That's your core loop.
- Platformer: Jump, avoid obstacles, reach the goal
- Shooter: Move, shoot, dodge
- Puzzle: Think, move pieces, solve
Get this working FIRST. No fancy graphics, no sound, no menus. Just the core loop with rectangles and placeholder art.
2. Add Juice (Feedback)
"Juice" is game developer slang for all the little things that make actions feel GOOD:
- Screen shake when you get hit
- Particles when you collect coins
- Sound effects for EVERYTHING
- Brief pauses on big impacts
- Sprite scaling/flashing on damage
3. Add Structure
- Title screen
- Game over screen
- Score/lives display
- Maybe levels or progression
4. Polish and Test
- Fix bugs
- Balance difficulty
- Add final art and sound
- Test on friends!
5. Ship It
Done is better than perfect. At some point, you have to call it soup and serve it!
Let's Make Some Soup!
Time to build a complete game using EVERYTHING we've learned. We're making Coin Catcher—a simple but polished arcade game.
The concept: Coins fall from the sky. Catch them to score points. Miss too many and it's game over. As you play, coins fall faster!
Step 1: Project Setup
' ================================================
' COIN CATCHER
' A complete game example
' ================================================
SCREEN 13 ' 320x200, 256 colors
' ================================================
' LOAD ALL RESOURCES UPFRONT
' ================================================
LOADPNG "player.png", "player" AS SPRITESHEET(32, 32)
LOADPNG "coin.png", "coin" AS SPRITESHEET(16, 16)
LOADWAV "coin.wav", "coinSound"
LOADWAV "miss.wav", "missSound"
LOADWAV "gameover.wav", "gameoverSound"
LOADMP3 "music.mp3", "bgm"Lesson from Chapter 12: Load ALL resources at the start. No stuttering mid-game!
Step 2: Define Behaviors
' ================================================
' DEFINE BEHAVIORS (Chapter 14)
' ================================================
BEHAVIOR "playerIdle"
ANIMATE "player", 0, 1 FRAMERATE 5
END BEHAVIOR
BEHAVIOR "playerLeft"
ANIMATE "player", 2, 3 FRAMERATE 10
BFLIPX ON
END BEHAVIOR
BEHAVIOR "playerRight"
ANIMATE "player", 2, 3 FRAMERATE 10
BFLIPX OFF
END BEHAVIOR
BEHAVIOR "coinFall"
ANIMATE "coin", 0, 1, 2, 3 FRAMERATE 8
BOSCILLATE AMPLITUDE 3, 0 ' Wobble side to side
END BEHAVIOR
BEHAVIOR "coinCollected"
BSCALE 1, 1 TO 2, 2 DURATION 10
BALPHA 1 TO 0 DURATION 10
END BEHAVIORLesson from Chapter 14: Define behaviors once, use everywhere!
Step 3: Define Patterns
' ================================================
' DEFINE PATTERNS (Chapter 14)
' ================================================
PATTERN "playerControl" LOOP
"playerIdle"
"playerLeft" WHEN KEYDOWN("LEFT")
"playerRight" WHEN KEYDOWN("RIGHT")
END PATTERN
PATTERN "coinDeath"
"coinCollected"
DISABLE
END PATTERNStep 4: Game State (Using Custom Types!)
' ================================================
' GAME STATE (Chapter 11 - Custom Types)
' ================================================
TYPE GameState
score AS INTEGER
lives AS INTEGER
level AS INTEGER
coinsSpawned AS INTEGER
coinSpeed AS SINGLE
gameOver AS INTEGER
paused AS INTEGER
END TYPE
DIM game AS GameStateStep 5: Initialize Game
' ================================================
' INITIALIZE GAME
' ================================================
SUB InitGame()
game.score = 0
game.lives = 3
game.level = 1
game.coinsSpawned = 0
game.coinSpeed = 2
game.gameOver = FALSE
game.paused = FALSE
' Clear any existing sprites
FOR i = 0 TO 99
DISABLE SPRITE i
NEXT i
' Create player (sprite 0)
ENABLE SPRITE 0
SET SPRITE 0, 160, 170, "player" TAG "player"
SET SPRITE 0 PATTERN "playerControl"
' Set up boundaries (Chapter 14)
BOUNDARY CLEAR
BOUNDARY ADD "left", (0, 0)-(10, 200) SOLID
BOUNDARY ADD "right", (310, 0)-(320, 200) SOLID
BOUNDARY ADD "floor", (0, 190)-(320, 200) ' Not solid - coins pass through
' Start music
PLAYMP3 "bgm", 1
END SUBStep 6: Spawn Coins
' ================================================
' SPAWN COINS
' ================================================
SUB SpawnCoin()
s = NEXTFREESPRITE()
IF s > 0 AND s < 50 THEN ' Reserve sprites 50+ for effects
ENABLE SPRITE s
SET SPRITE s, INT(RND * 280) + 20, -20, "coin" TAG "coin"
SET SPRITE s BEHAVIOR "coinFall"
' Speed increases with level
SET SPRITE s SPEED game.coinSpeed
game.coinsSpawned = game.coinsSpawned + 1
END IF
END SUBStep 7: Update Game Logic
' ================================================
' UPDATE GAME
' ================================================
SUB UpdateGame()
IF game.paused OR game.gameOver THEN EXIT SUB
' Move player with keyboard
px = SPRITEX(0)
IF KEYDOWN("LEFT") AND px > 20 THEN
MOVE SPRITE 0, px - 4, SPRITEY(0)
END IF
IF KEYDOWN("RIGHT") AND px < 300 THEN
MOVE SPRITE 0, px + 4, SPRITEY(0)
END IF
' Move coins down
FOR SPRITES s, "coin"
MOVE SPRITE s, SPRITEX(s), SPRITEY(s) + game.coinSpeed
NEXT SPRITE
' Check for coins that fell off screen
FOR SPRITES s, "coin"
IF SPRITEY(s) > 200 THEN
DISABLE SPRITE s
game.lives = game.lives - 1
PLAYWAV "missSound"
IF game.lives <= 0 THEN
game.gameOver = TRUE
STOPMP3 "bgm"
PLAYWAV "gameoverSound"
END IF
END IF
NEXT SPRITE
' Collision detection
FOR COLLISIONS a, b
tagA$ = SPRITETAG$(a)
tagB$ = SPRITETAG$(b)
IF (tagA$ = "player" AND tagB$ = "coin") OR (tagB$ = "player" AND tagA$ = "coin") THEN
' Find which one is the coin
IF tagA$ = "coin" THEN
coinSprite = a
ELSE
coinSprite = b
END IF
' Collect it!
SET SPRITE coinSprite PATTERN "coinDeath"
SET SPRITE coinSprite TAG "collected" ' Prevent double-collection
game.score = game.score + 10
PLAYWAV "coinSound"
' Level up every 100 points
IF game.score MOD 100 = 0 THEN
game.level = game.level + 1
game.coinSpeed = game.coinSpeed + 0.5
END IF
END IF
NEXT COLLISION
' Spawn new coins periodically
IF TIMER MOD 30 = 0 THEN
SpawnCoin
END IF
END SUBStep 8: Draw UI
' ================================================
' DRAW UI (Chapters 5 & 9)
' ================================================
SUB DrawUI()
' Score
LOCATE 1, 1
COLOR 15
PRINT "Score: "; game.score
' Lives (draw hearts)
LOCATE 1, 30
FOR i = 1 TO game.lives
PRINT CHR$(3); ' Heart character
NEXT i
' Level
LOCATE 1, 15
PRINT "Level "; game.level
END SUB
SUB DrawGameOver()
' Darken the screen
LINE (60, 60)-(260, 140), 0, BF
LINE (60, 60)-(260, 140), 15, B
WINDOW (70, 70)-(250, 130)
COLOR 15
LOCATE 3, 5
PRINT "GAME OVER"
LOCATE 5, 3
PRINT "Final Score: "; game.score
LOCATE 8, 2
PRINT "Press SPACE to restart"
WINDOW ' Reset window
END SUB
SUB DrawPaused()
LINE (100, 80)-(220, 120), 0, BF
LINE (100, 80)-(220, 120), 15, B
LOCATE 12, 13
COLOR 15
PRINT "PAUSED"
END SUBStep 9: Title Screen
' ================================================
' TITLE SCREEN
' ================================================
SUB ShowTitle()
CLS 1 ' Dark blue background
' Title
LOCATE 5, 10
COLOR 14
PRINT "COIN CATCHER"
LOCATE 8, 8
COLOR 7
PRINT "Catch the coins!"
LOCATE 10, 6
PRINT "Miss 3 and it's over!"
LOCATE 14, 7
COLOR 15
PRINT "Press SPACE to start"
' Wait for space
DO
DELAY 16
LOOP UNTIL KEYDOWN("SPACE")
' Wait for release
DO
DELAY 16
LOOP UNTIL NOT KEYDOWN("SPACE")
END SUBStep 10: Main Game Loop
' ================================================
' MAIN GAME LOOP
' ================================================
ShowTitle
InitGame
DO
' Handle pause
IF KEYDOWN("P") THEN
game.paused = NOT game.paused
DELAY 200 ' Debounce
END IF
' Update
UpdateGame
' Render
BEGIN FRAME
CLS 9 ' Light blue sky
' Draw ground
LINE (0, 180)-(319, 199), 2, BF
' Draw UI
DrawUI
IF game.paused THEN
DrawPaused
END IF
IF game.gameOver THEN
DrawGameOver
END IF
END FRAME
DELAY 16
' Restart?
IF game.gameOver AND KEYDOWN("SPACE") THEN
InitGame
END IF
LOOP UNTIL KEYDOWN("ESCAPE")
STOPMP3 "bgm"
ENDThe Checklist: Is It Soup Yet?
Before you call your game "done," run through this checklist:
Core Gameplay
- Can the player DO the main thing? (move, jump, shoot, etc.)
- Is there a goal or win condition?
- Is there a fail state or challenge?
- Does difficulty increase over time?
Feedback & Juice
- Does every action have a sound?
- Do important events have visual feedback?
- Are there animations (not just static sprites)?
- Does the game "feel" good to play?
Structure
- Is there a title screen?
- Is there a game over screen?
- Can the player restart without closing the game?
- Is the score/progress visible?
Polish
- Are there any obvious bugs?
- Is the difficulty fair (not too hard at the start)?
- Have you tested it on someone else?
- Does it run smoothly (no stuttering)?
Technical
- Are all resources loaded at startup?
- Are sprites properly disabled when not needed?
- Is music stopped when it should be?
- Does the game clean up properly on restart?
Common Bugs and How to Fix Them
"My sprites are disappearing randomly!"
You're probably running out of sprite slots. Use NEXTFREESPRITE() to check for available slots, and make sure you DISABLE SPRITE when sprites are no longer needed.
s = NEXTFREESPRITE()
IF s >= 0 THEN
' Safe to use sprite s
ELSE
' No sprites available!
END IF"Collisions are triggering multiple times!"
Re-tag collected items immediately so they don't trigger again:
FOR COLLISIONS a, b
IF SPRITETAG$(a) = "coin" AND SPRITETAG$(b) = "player" THEN
SET SPRITE a TAG "collected" ' Change tag immediately!
score = score + 10
END IF
NEXT COLLISION"My game slows down over time!"
You're probably not cleaning up old sprites. Make sure disabled sprites are really disabled:
' When a coin goes off-screen:
DISABLE SPRITE coinSprite
SET SPRITE coinSprite BEHAVIOR NONE
SET SPRITE coinSprite PATTERN NONE"Sound effects are overlapping weirdly!"
Limit how often a sound can play:
DIM lastSoundTime AS INTEGER
IF shouldPlaySound AND TIMER - lastSoundTime > 100 THEN
PLAYWAV "effect"
lastSoundTime = TIMER
END IF"My game is too hard/too easy!"
Playtest! Watch someone else play. If they're frustrated in the first 30 seconds, it's too hard. If they're bored after a minute, it's too easy.
Start easy and ramp up gradually:
' Level 1: Slow coins, lots of lives
' Level 5: Medium coins, fewer mistakes allowed
' Level 10: Fast coins, you really need to focus!
coinSpeed = 1 + (level * 0.3)Sharing Your Game
Once your soup is ready, it's time to serve it! Crash BASIC lets you bundle your game into a single file that others can play.
Creating a Bundle
Your game and all its resources get packaged into a .cbundle file:
- Make sure your game runs correctly in the IDE
- Use the Bundles widget to create a new bundle
- All your code files and resources are included automatically
- Give your bundle a name and export it!
What Goes in a Bundle?
mygame.cbundle/
main.bas <- Your main program
helpers.bas <- Any imported modules
resources/
player.png <- All your images
coin.png
music.mp3 <- All your sounds
coin.wav
data/
highscore.sav <- Saved data (if any)The Bundle is Self-Contained
When someone opens your .cbundle, they get everything they need. No missing files, no "works on my machine" problems!
Final Tips
Start Small
Your first game should be Pong, not Skyrim. Small games teach you more than unfinished big games.
Finish Things
A finished bad game is better than an unfinished masterpiece. You learn the most from the last 10% of a project.
Steal Like an Artist
Remake classic games! Pong, Breakout, Space Invaders, Snake. Understanding WHY those games work teaches you design.
Show People
Watch someone else play your game. Don't help them. Don't explain. Just watch. You'll learn SO much about what's confusing or unclear.
Have Fun
If you're not having fun making games, something's wrong. Games are about joy—including the joy of making them!
Quick Reference: Complete Game Checklist
| Category | Check |
|---|---|
| Resources | All loaded at startup? |
| Behaviors | Defined before use? |
| Sprites | Properly enabled/disabled? |
| Collision | Tagged correctly? |
| Sound | Playing at right moments? |
| Music | Starts/stops correctly? |
| UI | Score/lives visible? |
| Flow | Title → Game → Game Over → Restart? |
| Input | Responsive and debounced? |
| Performance | Runs at steady 60 FPS? |
You Did It!
Congratulations! You've learned everything you need to make games with Crash BASIC:
- Variables to store data
- Conditionals to make decisions
- Loops to repeat actions
- Functions to organize code
- Graphics to draw worlds
- Sprites to bring characters to life
- Sound to create atmosphere
- Saving to preserve progress
- Behaviors to automate movement
- Collisions to create interaction
The only thing left is to MAKE GAMES!
Start simple. Finish what you start. Show people. Learn from feedback. Make another one. Get better.
Your soup is ready. Time to serve it!
Thank you for reading "Crash-tan Teaches BASIC!" Now go make something amazing!