A Processing library for teaching Object-Oriented Programming through game development.
SpriteGame gives beginner programmers a concrete, visual context for learning the core ideas of OOP — classes, objects, inheritance, encapsulation, and polymorphism — by building sprite-based games in Processing. It is designed around an Objects First curriculum philosophy: students encounter and use objects from their very first lesson, and extend the library's own classes to create their own sprites long before they understand every detail of how the machinery works.
- Philosophy
- Requirements
- Installation
- Quick Start
- Class Reference
- Writing Your Own Sprite
- Included Examples
- Building from Source
- Credits
The traditional approach to teaching programming starts with variables, then control flow, then functions, and finally — weeks or months later — objects. By the time students reach OOP the syntax feels abstract and the motivation is unclear.
Objects First inverts this. Students write code that creates and talks to objects on day one. They observe the behavior before they understand the implementation. Curiosity about how it works is the bridge to reading and writing class definitions themselves.
SpriteGame is designed to support this progression:
| Stage | What the student does | OOP concept encountered |
|---|---|---|
| 1 — Use | Create Blob and Block objects, call move() and drawSprite() |
Objects, method calls, constructors |
| 2 — Observe | See that different objects share behavior but look different | Polymorphism in practice |
| 3 — Extend | Write class MySprite extends Sprite in a .pde file |
Inheritance, super(), overriding |
| 4 — Design | Add new fields and methods to their subclass | Encapsulation, abstraction |
| 5 — Compose | Build a CompoundSprite from multiple parts |
Composition vs. inheritance |
The library intentionally keeps its own source code readable and well-documented so that students who are ready to look under the hood can do so without being overwhelmed.
- Processing 4 (4.0 or later)
- Java 17 (bundled with Processing 4 — no separate install needed)
- Download SpriteGame.zip.
- Copy the unzipped folder into your Processing libraries directory:
- Windows:
Documents\Processing\libraries\ - macOS:
~/Documents/Processing/libraries/ - Linux:
~/sketchbook/libraries/
- Windows:
- Restart Processing, if you have it running.
- Verify the install: Sketch → Import Library → SpriteGame should appear in the menu.
Add the import at the top of your sketch, create some sprites, and call move() and drawSprite() inside draw():
import coxprogramming.processing.sprites.*;
ArrayList<Blob> blobs;
void setup() {
fullScreen();
blobs = new ArrayList<Blob>();
for (int i = 0; i < 10; i++) {
blobs.add(new Blob(this,
random(width), random(height), // position
random(10, 30), // radius
random(-5, 5), random(-5, 5), // velocity
color(random(255), random(255), random(255))
));
}
}
void draw() {
background(255);
for (Blob blob : blobs) {
blob.move();
blob.drawSprite();
}
}Every sprite automatically wraps around the screen edges when move() is called — no boundary-checking code required.
Sprite (abstract)
├── Blob
│ └── Block
├── ImageSprite
└── CompoundSprite
└── AnimatedSprite
Vector2D — 2D vector math
Event — event / listener system
The base class for everything in the library. A Sprite knows its position (pos) and velocity (vel) as Vector2D objects, knows how to move itself, and declares drawSprite() as abstract — meaning every concrete subclass must decide how it looks.
Key methods
| Method | Description |
|---|---|
move() |
Advances position by velocity; wraps at screen edges |
moveTo(x, y) |
Teleports to a new position |
setVelocity(dx, dy) |
Sets the velocity |
getPosition() |
Returns current position as Vector2D |
getVelocity() |
Returns current velocity as Vector2D |
followMouse() |
Moves toward the mouse at the current speed |
keyboardControl() |
Maps arrow keys to velocity; call from keyPressed() |
distanceTo(Sprite) |
Returns pixel distance to another sprite |
drawSprite() |
Abstract — subclasses must implement this |
Every constructor requires this as the first argument so the sprite can access the sketch's drawing functions and screen dimensions:
Blob b = new Blob(this, 200, 300, 25, color(255, 0, 0));A circular sprite with a radius and a fill color. The most common building block for quick prototypes.
// Stationary blob
Blob dot = new Blob(this, 100, 200, 30, color(0, 120, 255));
// Moving blob
Blob ball = new Blob(this, 100, 200, 30, 3, -2, color(255, 80, 0));
// Collision detection
if (ball.collidesWith(dot)) {
// circles are touching
}A rectangular sprite. Extends Blob so it has the same collision and movement methods, but drawSprite() draws a rectangle instead of a circle. The position marks the top-left corner of the rectangle.
Block wall = new Block(this, 0, 300, width, 20, color(80));A sprite that displays a picture file instead of a drawn shape. Place the image in your sketch's data/ folder. By default, the image is drawn 100 × 100 pixels and centered on the sprite's position. You can also set a custom display size and rotate the image in radians.
ImageSprite hero = new ImageSprite(this, 200, 300, "hero.png");
ImageSprite boss = new ImageSprite(this, 400, 300, "boss.png", 180, 120);
boss.setRotation(PI / 4); // turn to 45 degrees
boss.rotate(0.03); // add a little more rotation each frameA container that groups multiple sprites so they move together as one unit. Children can still have their own independent velocity on top of the group velocity — useful for animated characters made of several parts.
Blob body = new Blob(this, 200, 300, 40, color(30, 100, 200));
Blob head = new Blob(this, 200, 250, 20, color(255, 220, 180));
CompoundSprite player = new CompoundSprite(this, 200, 300)
.addSprite(body)
.addSprite(head);
// The whole character walks right
player.setVelocity(3, 0);
// In draw():
player.move();
player.drawSprite();addSprite() and removeSprite() return this for builder-style chaining.
A CompoundSprite that uses its child sprites as animation frames and draws
one frame at a time. frameRate means game frames per animation frame: a
value of 8 holds each animation frame for 8 calls to drawSprite().
AnimatedSprite cloud = AnimatedSprite.FromSprite(frame0)
.AddFrameSprite(frame1)
.AddFrameSprite(frame2)
.setFrameRate(8);
cloud.setVelocity(1, 0);
// In draw():
cloud.move();
cloud.drawSprite();Use getFrameNumber(), setFrameNumber(n), getFrameRate(), and
setFrameRate(n) to inspect or control the animation.
A 2D vector class used internally by Sprite for position and velocity. Also available directly for students who want to do their own vector math.
Vector2D a = new Vector2D(3, 4);
Vector2D b = Vector2D.FromPolar(5, PI / 4); // from magnitude + angle
float speed = a.mag(); // length of the vector
Vector2D dir = a.unitVector(); // same direction, length = 1
Vector2D sum = a.add(b);
Vector2D diff = a.subtract(b);
Vector2D rot = a.rotate(PI / 6); // rotate 30 degreesStatic factory methods
| Method | Description |
|---|---|
Vector2D.FromXY(x, y) |
Creates a vector from rectangular coordinates |
Vector2D.FromPolar(r, theta) |
Creates a vector from magnitude and angle (radians) |
A reflection-based event and listener system for connecting game events to response functions without tight coupling. Useful once students are comfortable with OOP and want to explore the Observer pattern.
// Declare an event that passes no arguments
Event onCoinCollected = new Event();
// Attach a listener (the method must exist on the object)
onCoinCollected.bind(scoreBoard, "incrementScore");
// Fire the event when something happens
onCoinCollected.trigger();
// Detach when no longer needed
onCoinCollected.unbind(scoreBoard, "incrementScore");The most important feature of SpriteGame is that it is designed to be extended. Students create their own sprite types by writing a class that extends Sprite directly in a .pde file alongside their sketch.
The only requirement is implementing drawSprite(). Everything else — position, velocity, move(), followMouse(), keyboardControl() — is inherited automatically.
// In MySketch/Asteroid.pde
class Asteroid extends Sprite {
float radius;
float rotationAngle;
float rotationSpeed;
Asteroid(PApplet p, float x, float y, float r) {
super(p, x, y, random(-3, 3), random(-3, 3));
radius = r;
rotationAngle = 0;
rotationSpeed = random(-0.05, 0.05);
}
void drawSprite() {
rotationAngle += rotationSpeed;
parent.pushMatrix();
parent.translate(pos.x, pos.y);
parent.rotate(rotationAngle);
parent.fill(160, 140, 120);
parent.stroke(100);
parent.beginShape();
for (int i = 0; i < 8; i++) {
float angle = parent.TWO_PI / 8 * i;
float r = radius * parent.random(0.8, 1.2);
parent.vertex(parent.cos(angle) * r, parent.sin(angle) * r);
}
parent.endShape(CLOSE);
parent.popMatrix();
}
}A few things to note when writing sprite subclasses in .pde files:
- Pass
thisas the first constructor argument so the sprite can reach the sketch's drawing functions through theparentfield. - Call all Processing drawing functions as
parent.fill(...),parent.ellipse(...), etc., because inside a class that extendsSprite(notPApplet) they need the explicit reference. - Processing constants like
CLOSE,TWO_PI, andCENTERare available directly in.pdeinner classes, or asPApplet.TWO_PIetc. if needed.
Open any example via File → Examples → Contributed Libraries → SpriteGame.
Ten randomly colored Blob objects bounce around a full-screen window and wrap at the edges. The simplest possible introduction to the library.
Concepts: Blob, ArrayList, move(), drawSprite()
A sky-and-ground scene with a drifting sun, animated clouds, and placeholder trees. Cloud and Sun are complete working sprites; Tree is a commented shell for students to fill in.
Concepts: Extending Sprite, drawSprite() implementation, draw-order layering, the size scaling pattern
The Tree class is intentionally left incomplete — drawing the tree is the student's assignment.
A variation on SceneExample that uses AnimatedSprite for drifting clouds
and a shimmering sun. Each cloud animation is built from several CloudFrame
sprites with slightly different shapes and grey values; the sun animation uses
several SunFrame sprites with changing ray lengths.
Concepts: AnimatedSprite, sprite frames, frame rate, builder-style
animation setup, grouped movement
A playable Asteroids-style arcade game with a rotating ship, thrust, bullets, splitting asteroids, scoring, lives, waves, invincibility after respawn, and restart after game over.
Concepts: Custom Sprite subclasses, Vector2D velocity math, sprite
lists, collision checks, game state, and screen wrapping
A fully functional four-function calculator where each key is a Button sprite wired to a lambda via onClicked().
Concepts: Strategy pattern, lambda expressions, Action functional interface, builder-style chaining, the Observer pattern
// Each button is told what to do via a lambda.
// The button itself never knows what digitPressed() or opPressed() do.
new Button(this, x, y, 75, 75, "7", grey, white)
.onClicked(() -> digitPressed("7"));
new Button(this, x, y, 75, 75, "+", orange, white)
.onClicked(() -> opPressed("+"));The build script looks for Processing's bundled Java compiler and core.jar
automatically on macOS, Linux, and Windows Bash environments such as Git Bash,
MSYS2, Cygwin, or WSL.
# From the repository root
bash build.shOutput: library/SpriteGame.jar
If Processing is installed in an unusual location, pass explicit paths:
PROCESSING_HOME="/path/to/Processing" bash build.sh
CORE_JAR="/path/to/core.jar" JAVAC="/path/to/javac" bash build.shThe script compiles all sources in src/coxprogramming/processing/sprites/
against Processing's core.jar and packages the result. Native Windows
PowerShell cannot run .sh files directly; use Git Bash/WSL or add a small
PowerShell wrapper if native Windows builds become a regular workflow.
After building, deploy.sh installs the library directly into your local
Processing sketchbook so Processing can load it immediately — no manual copying
required. build.sh calls deploy.sh automatically, so a single
bash build.sh both compiles and deploys.
You can also run it on its own after a successful build:
bash deploy.shThe script resolves the sketchbook location by platform:
| Platform | Default sketchbook path |
|---|---|
| macOS | ~/Documents/Processing |
| Linux | ~/sketchbook (falls back to ~/Documents/Processing) |
| Windows (Git Bash / MSYS2 / Cygwin) | %USERPROFILE%\Documents\Processing |
If your sketchbook is in a non-standard location, override it:
PROCESSING_SKETCHBOOK="/path/to/sketchbook" bash deploy.shNote: if Processing has the library open when you deploy, the copy may
fail. Close Processing first, then re-run bash deploy.sh. The compiled JAR
is always available at library/SpriteGame.jar regardless.
- Library design and implementation — Jason Cox, Winsor School
Eventclass — originally by Stephcraft, adapted for this library- Built for Processing 4
SpriteGame is free to use in educational settings. If you use it in your classroom, the author would love to hear about it.