Chapter 6: Real Art

Example Assets Needed:
To follow along with this chapter's examples, you'll need these image files:

  • player.png — 32x32 character sprite (or 128x32 spritesheet with 4 frames)
  • hero.png — 32x32 character spritesheet (4+ frames for animation)
  • coin.png — 16x16 collectible sprite
  • enemy.png — 32x32 enemy sprite
  • background.png — A simple background image
  • icon.png, powerup.png, ghost.png, arrow.png, title.png — Various UI/game sprites

You can draw these yourself (see Chapter 5!), use free assets from sites like OpenGameArt.org or itch.io, or use simple colored rectangles as placeholders.

Circles and lines are great for learning, but let's be honest—you want your games to look GOOD. You want sprites! Characters! Backgrounds! Explosions that look like actual explosions instead of expanding circles!

Good news: Crash BASIC makes it super easy to use real images in your games. And once you see how simple it is, you'll never want to go back to drawing everything with primitives.

Let's turn your games into works of art!


Before we can use images in our code, we need to get them INTO Crash BASIC. That's what the Resources widget is for.

Look at the Crash BASIC IDE. See that panel with the folder icon? That's the Resources widget. It's where all your game's assets live—images, sounds, everything.

To add an image:

  1. Click the Resources tab in the IDE
  2. Click the Upload button (or drag and drop files directly!)
  3. Select your image file (PNG, JPG, or GIF)
  4. Done! The image is now part of your project

Pro tip: PNG files are best for game sprites because they support transparency. That means the background of your sprite can be see-through, so your character doesn't have an ugly rectangle around them!


Loading Images: LOADPNG

Once your image is in the Resources widget, you need to tell your program to load it. That's what LOADPNG does:

SCREEN 13
LOADPNG "player.png", "player"

Let's break that down:

  • "player.png" — The filename (exactly as it appears in Resources)
  • "player" — The name you'll use to refer to this image in your code

The second name can be anything you want! You could load "my_super_cool_character_sprite_v3_final_FINAL.png" and call it just "hero". Much easier to type!

You can also use LOADIMG—it does exactly the same thing:

LOADIMG "enemy.png", "badguy"

Displaying Images: PUTIMAGE

Now for the fun part—putting images on screen!

SCREEN 13
LOADPNG "player.png", "player"

PUTIMAGE (100, 50), "player"

PAUSE

That's it! The image appears at coordinates (100, 50). The position is where the top-left corner of the image goes.

Let's make it move:

SCREEN 13
LOADPNG "player.png", "player"

x = 0
DO
    BEGIN FRAME
    CLS
    PUTIMAGE (x, 100), "player"
    END FRAME
    x = x + 2
    IF x > 320 THEN x = 0
    DELAY 16
LOOP

Your character glides across the screen! Same animation principle as before—erase, draw, repeat—but now with REAL art instead of circles.


Transparency: The Magic of PNG

Here's why PNG files are magical: they can have transparent pixels.

Imagine you have a character sprite. The character is drawn on a canvas, but the area around them? That's transparent. When you PUTIMAGE, only the character shows up—not an ugly colored rectangle.

This just works automatically with PNG files that have transparency. No special code needed!

If you're making your own sprites, use any image editor (like GIMP, Photoshop, or even free online tools) and save as PNG with transparency enabled. The transparent pixels will stay transparent in Crash BASIC.


Sprite Sheets: Animation Made Easy

Real games don't use separate files for every animation frame—that would be hundreds of files! Instead, they use sprite sheets: one image with all the frames arranged in a grid.

+-------+-------+-------+-------+
| Frame | Frame | Frame | Frame |
|   0   |   1   |   2   |   3   |
+-------+-------+-------+-------+
| Frame | Frame | Frame | Frame |
|   4   |   5   |   6   |   7   |
+-------+-------+-------+-------+

To load a sprite sheet, tell Crash BASIC the size of each frame:

SCREEN 13
LOADPNG "hero.png", "hero" AS SPRITESHEET(32, 32)

This tells Crash BASIC: "This image contains frames that are each 32x32 pixels." It automatically figures out how many frames there are based on the image size.

Frame numbering: Frames start at 0 in the top-left, go left-to-right, then wrap to the next row. So in a 4x2 grid, frames are numbered 0-3 on top, 4-7 on bottom.

Now you can show specific frames:

SCREEN 13
LOADPNG "hero.png", "hero" AS SPRITESHEET(32, 32)

PUTIMAGE (100, 100), "hero", 0    ' Frame 0
PUTIMAGE (150, 100), "hero", 1    ' Frame 1
PUTIMAGE (200, 100), "hero", 2    ' Frame 2

PAUSE

Animation: Bringing Sprites to Life

Let's animate! We'll cycle through frames to create movement:

SCREEN 13
LOADPNG "hero.png", "hero" AS SPRITESHEET(32, 32)

frame = 0
x = 100

DO
    BEGIN FRAME
    CLS
    PUTIMAGE (x, 100), "hero", frame
    END FRAME

    ' Advance to next frame
    frame = frame + 1
    IF frame >= FRAMECOUNT("hero") THEN frame = 0

    DELAY 100    ' Slower delay so animation is visible
LOOP

FRAMECOUNT("hero") returns how many frames the sprite sheet has. This way, your code works no matter how many frames the artist adds later!

Let's combine movement with animation:

SCREEN 13
LOADPNG "hero.png", "hero" AS SPRITESHEET(32, 32)

frame = 0
x = 0
frameTimer = 0

DO
    BEGIN FRAME
    CLS

    ' Draw the hero
    PUTIMAGE (x, 100), "hero", frame
    END FRAME

    ' Move
    x = x + 2
    IF x > 320 THEN x = -32

    ' Animate (change frame every 5 game loops)
    frameTimer = frameTimer + 1
    IF frameTimer >= 5 THEN
        frameTimer = 0
        frame = frame + 1
        IF frame >= FRAMECOUNT("hero") THEN frame = 0
    END IF

    DELAY 16
LOOP

Now your character walks across the screen with proper animation!


Scaling: Bigger and Smaller

Want to make an image bigger or smaller? Use the SCALE modifier:

SCREEN 13
LOADPNG "icon.png", "icon"

' Original size
PUTIMAGE (10, 50), "icon"

' Scaled to 64x64 pixels
PUTIMAGE (100, 50), "icon", SCALE(64, 64)

' Scaled to 128x128 pixels
PUTIMAGE (200, 50), "icon", SCALE(128, 128)

PAUSE

SCALE takes the target width and height in pixels. The image stretches or shrinks to fit.

This is great for:

  • Making items grow when collected
  • Zoom effects
  • Using the same sprite at different sizes
SCREEN 13
LOADPNG "powerup.png", "star"

size = 16
growing = 1

DO
    BEGIN FRAME
    CLS
    PUTIMAGE (144, 84), "star", SCALE(size, size)
    END FRAME

    IF growing THEN
        size = size + 1
        IF size >= 64 THEN growing = 0
    ELSE
        size = size - 1
        IF size <= 16 THEN growing = 1
    END IF

    DELAY 16
LOOP

A pulsing power-up effect!


Transparency Effects: ALPHA

Want a ghost that's see-through? A fading explosion? Use ALPHA:

SCREEN 13
LOADPNG "ghost.png", "ghost"

' Fully opaque (solid)
PUTIMAGE (50, 100), "ghost", ALPHA(1.0)

' 50% transparent
PUTIMAGE (150, 100), "ghost", ALPHA(0.5)

' Almost invisible
PUTIMAGE (250, 100), "ghost", ALPHA(0.2)

PAUSE

ALPHA goes from 0.0 (completely invisible) to 1.0 (completely solid).

Let's make a fade-in effect:

SCREEN 13
LOADPNG "title.png", "title"

' Fade in
FOR alpha = 0 TO 10
    BEGIN FRAME
    CLS
    PUTIMAGE (80, 80), "title", ALPHA(alpha / 10)
    END FRAME
    DELAY 100
NEXT alpha

PAUSE

Flipping: Mirror Images

Need your character to face left AND right, but only have sprites facing one direction? Use FLIPX and FLIPY:

SCREEN 13
LOADPNG "hero.png", "hero" AS SPRITESHEET(32, 32)

' Normal (facing right)
PUTIMAGE (50, 100), "hero", 0

' Flipped horizontally (facing left)
PUTIMAGE (150, 100), "hero", 0, FLIPX

' Flipped vertically (upside down)
PUTIMAGE (250, 100), "hero", 0, FLIPY

PAUSE

Here's a character that faces the direction they're moving:

SCREEN 13
LOADPNG "hero.png", "hero" AS SPRITESHEET(32, 32)

x = 160
facingRight = 1

DO
    k$ = INKEY$

    IF k$ = "a" THEN
        x = x - 3
        facingRight = 0
    ELSEIF k$ = "d" THEN
        x = x + 3
        facingRight = 1
    END IF

    BEGIN FRAME
    CLS
    IF facingRight THEN
        PUTIMAGE (x, 100), "hero", 0
    ELSE
        PUTIMAGE (x, 100), "hero", 0, FLIPX
    END IF
    END FRAME

    DELAY 16
LOOP

One sprite, two directions!


Rotation: Spinning Things Around

Want to rotate an image? Use ROTATE:

SCREEN 13
LOADPNG "arrow.png", "arrow"

angle = 0
DO
    BEGIN FRAME
    CLS
    PUTIMAGE (144, 84), "arrow", ROTATE(angle)
    END FRAME
    angle = angle + 3
    IF angle >= 360 THEN angle = 0
    DELAY 16
LOOP

By default, ROTATE spins the image around its top-left corner. But usually you want to rotate around the CENTER. Use the optional origin parameters:

' ROTATE(angle, originX, originY)
' originX and originY are 0-1, where 0.5 = center

PUTIMAGE (144, 84), "arrow", ROTATE(angle, 0.5, 0.5)
  • (0, 0) = top-left corner
  • (0.5, 0.5) = center (most common!)
  • (1, 1) = bottom-right corner
  • (0.5, 1) = bottom-center (good for characters pivoting on their feet)

Here's a spinning power-up that rotates around its center:

SCREEN 13
LOADPNG "coin.png", "coin"

angle = 0
DO
    BEGIN FRAME
    CLS
    PUTIMAGE (144, 84), "coin", ROTATE(angle, 0.5, 0.5)
    END FRAME
    angle = (angle + 5) MOD 360
    DELAY 16
LOOP

Combining Modifiers

The best part? You can combine all these modifiers together!

SCREEN 13
LOADPNG "ghost.png", "ghost"

angle = 0
alpha = 0.7

DO
    BEGIN FRAME
    CLS

    ' A semi-transparent, scaled, rotating ghost facing left
    PUTIMAGE (144, 84), "ghost", ALPHA(alpha), SCALE(64, 64), ROTATE(angle, 0.5, 0.5), FLIPX
    END FRAME

    angle = (angle + 2) MOD 360

    DELAY 16
LOOP

Modifiers can be in any order. Go wild!


Putting It All Together: A Sprite-Based Game

Let's make a simple game using everything we learned:

SCREEN 13

' Load our sprites
LOADPNG "player.png", "player" AS SPRITESHEET(32, 32)
LOADPNG "coin.png", "coin"
LOADPNG "background.png", "bg"

' Game state
playerX = 144
playerY = 150
playerFrame = 0
facingRight = 1
frameTimer = 0

coinX = INT(RND * 280) + 20
coinY = INT(RND * 150) + 20
coinAngle = 0

score = 0

DO
    k$ = INKEY$

    ' Player movement
    moving = 0
    IF k$ = "a" AND playerX > 0 THEN
        playerX = playerX - 3
        facingRight = 0
        moving = 1
    ELSEIF k$ = "d" AND playerX < 288 THEN
        playerX = playerX + 3
        facingRight = 1
        moving = 1
    END IF

    ' Animate player when moving
    IF moving THEN
        frameTimer = frameTimer + 1
        IF frameTimer >= 5 THEN
            frameTimer = 0
            playerFrame = playerFrame + 1
            IF playerFrame >= FRAMECOUNT("player") THEN playerFrame = 0
        END IF
    ELSE
        playerFrame = 0
    END IF

    ' Spin the coin
    coinAngle = (coinAngle + 5) MOD 360

    ' Check coin collection
    dx = (playerX + 16) - (coinX + 8)
    dy = (playerY + 16) - (coinY + 8)
    dist = SQR(dx * dx + dy * dy)
    IF dist < 20 THEN
        score = score + 10
        coinX = INT(RND * 280) + 20
        coinY = INT(RND * 150) + 20
    END IF

    ' Draw everything
    BEGIN FRAME
    CLS
    PUTIMAGE (0, 0), "bg"
    PUTIMAGE (coinX, coinY), "coin", ROTATE(coinAngle, 0.5, 0.5)

    IF facingRight THEN
        PUTIMAGE (playerX, playerY), "player", playerFrame
    ELSE
        PUTIMAGE (playerX, playerY), "player", playerFrame, FLIPX
    END IF

    LOCATE 1, 1
    PRINT "Score: "; score
    END FRAME

    DELAY 16
LOOP

This game has:

  • A background image
  • An animated player that faces the direction they're moving
  • A spinning coin to collect
  • Score tracking

All with REAL art instead of circles!


Quick Reference

Command What It Does
LOADPNG "file", "name" Load an image
LOADPNG "file", "name" AS SPRITESHEET(w, h) Load as sprite sheet
PUTIMAGE (x, y), "name" Display image
PUTIMAGE (x, y), "name", frame Display specific frame
ALPHA(0.0-1.0) Set transparency
SCALE(width, height) Resize image
FLIPX Mirror horizontally
FLIPY Mirror vertically
ROTATE(angle) Rotate (from top-left)
ROTATE(angle, 0.5, 0.5) Rotate around center
FRAMECOUNT("name") Get number of frames

But What If I'm Not an Artist?

Here's a secret: neither am I! And neither are a LOT of game developers. But that doesn't have to stop you.

First: Try anyway. Seriously! Open up any image editor—even MS Paint—and just START drawing. Your first sprites will probably look terrible. That's okay! Everyone's first sprites look terrible. The important thing is that YOUR game has YOUR art, and there's something special about that.

Start simple:

  • Stick figures are valid game characters
  • Colored squares can be enemies
  • A yellow circle with two dots is a face
  • Simple shapes with bold outlines read well at small sizes

Second: Let AI help you level up.

We live in an amazing time. AI art tools can take your rough sketches and transform them into something polished. Here's the workflow I recommend:

  1. Draw your best attempt — Even if it's messy, get your idea down
  2. Use AI to enhance it — Tools like:
  3. Edit the results — AI gives you a starting point, then you tweak it

You can also describe your game to AI: "16x16 pixel art sprite sheet of a knight character, 4 walking frames, transparent background, retro game style" — and get something usable!

The key insight: AI is a tool, not a replacement. Use it to bridge the gap between what you can imagine and what you can draw. As you practice, you'll need it less and less. But there's no shame in using every tool available to bring your vision to life.

Your game with "AI-assisted art that you directed" is infinitely better than "a game you never made because you couldn't draw."


Tips for Great Game Art

  1. Use PNG for sprites — Transparency is your friend!
  2. Keep sprite sheets organized — Same-size frames, consistent spacing
  3. Start small — 16x16 or 32x32 pixels is plenty for retro games
  4. Free resources exist! — Sites like OpenGameArt.org have tons of free sprites
  5. SCALE lets you cheat — One small sprite can be multiple sizes
  6. AI is your friend — Use it to enhance your rough sketches into polished art

Try It Yourself!

  1. Find or create a simple sprite sheet and make it walk across the screen
  2. Make an object that fades in, spins, then fades out
  3. Create a "face the mouse" effect using ROTATE (hint: ATN from Chapter 4!)
  4. Build a scene with a background and multiple characters

Your games are about to look SO much better!

See you in Chapter 7!


Next Chapter: We'll learn how to talk to our players—keyboard, mouse, touch, and more!