🚀 Stage 3: Source Code Showcase

Same rocket. Scrolling stars. A classic parallax illusion — in 4 new lines of code.

📂 The Stage 3 Files

Stage 3 adds a single new idea on top of Stage 2: the star field scrolls downward each frame, creating the illusion that the rocket is flying upward. The rocket itself never moves. Three files make up the Stage 3 build:

File What it does Stage 3 changes
rocketStg3.html HTML shell — loads p5.js, CSS, and the sketch Title updated; stylesheet and sketch pointers updated
rocketStg3Sketch.js The p5.js sketch — all drawing logic One new constant (STAR_SPEED); drawStars() now advances and wraps each star’s y
rocket3Styles.css Minimal CSS reset — canvas flush, no margin Unchanged from Stage 2 (intentionally minimal)
💡 What actually changed? The entire visual difference between Stage 2 and Stage 3 lives in two lines inside drawStars():

s.y += STAR_SPEED;
if (s.y > CANVAS_H) { s.y = 0; s.x = random(CANVAS_W); }

That’s it. One line moves the star. One line wraps it when it exits the canvas. Everything else — the rocket, the colors, the constants — is identical to Stage 2.
🌃 The Parallax Illusion

The rocket never moves. It is drawn at exactly the same coordinates every frame. Only the star field moves — downward at STAR_SPEED pixels per frame.

The brain interprets “background moving down” as “foreground (rocket) moving up.” This is the same trick used in side-scrolling arcade games since the 1980s, and in cinematic backgrounds in film long before that.

Wrapping loop: when a star’s y exceeds CANVAS_H, it resets to y = 0 with a fresh random x. This makes the star field appear infinite — the rocket is always “flying through” new space, never running out of stars.
⚠ Trade-off: Static Data vs Mutable State

In Stage 2, each star object was created once in setup() and never changed. The stars array was pure read-only data.

In Stage 3, each star’s y property is updated every single frame. The array is now mutable state — it changes over time.

Mutable state is not wrong; it’s often necessary. But it comes with a cost: the program is harder to reason about, because an object’s value depends on when you look at it, not just where it was created. In larger programs, uncontrolled mutable state is one of the most common sources of bugs. Stage 3 is a gentle introduction to that trade-off.
rocketStg3.html — running live inside an <iframe>

⚡ Performance: Stage 1 vs Stage 3

Stage 3 does more than Stage 1 — the stars actually move — yet it is measurably more efficient. The difference is entirely in how the stars are handled each frame.

Operation Stage 1 — per frame Stage 3 — per frame
random() calls (stars) 300 — x, y, and size × 100 stars 100 — alpha only; size is fixed
Object allocations 100 new objects created and discarded 0 — array created once in setup()
Garbage collection Yes — 100 abandoned objects per frame None — no objects abandoned
Per-star update work 3 × random() calls 1 × random() + 1 × += + 1 × if
Star positions Fully re-randomized — random drift as a side-effect Controlled scroll — intentional motion only
Rocket drawing Identical — same 7 shapes, same coordinates
📊 At 60fps, those numbers scale up fast. Stage 1 makes 18,000 random() calls per second for stars alone, and allocates then immediately discards 6,000 objects per second. The JavaScript engine's garbage collector has to silently clean that up between frames. Stage 3 makes 6,000 random() calls per second (alpha only) and allocates zero new objects.

The lesson: Stage 1's star approach is one of the least efficient patterns possible in any animation loop — allocate, draw, discard, repeat. Stage 3 demonstrates the standard game-programming alternative: allocate once, mutate cheaply, reuse forever.

📜 Source Code

rocketStg3.html HTML5
Loading rocketStg3.html…
sketches/rocketStg3Sketch.js JavaScript
Loading rocketStg3Sketch.js…
styles/rocket3Styles.css CSS
Loading rocket3Styles.css…

💪 Try It Yourself

Use the Copy button above to grab any file, then:

  1. Create a new project folder with sketches/ and styles/ sub-folders.
  2. Paste each file into VS Code and save it with the matching filename.
  3. Open rocketStg3.html in your browser — watch the stars scroll!
  4. Change STAR_SPEED from 1 to 3. How does the illusion feel different? At what speed does it start to feel unrealistic?
  5. Parallax depth challenge: give each star a speed property in generateStars() set to random(0.5, 2.5). Then change s.y += STAR_SPEED to s.y += s.speed. Larger stars should probably move faster. Why?
  6. Separation-of-concerns challenge: move the star position update into its own updateStars() function, and call it from draw() before drawStars(). How does this change the structure? Is it worth it at this scale?

⚠️ The Copy button requires a secure context (https:// or localhost). If you’re viewing this file directly from your file system (file://), right-click the Run link above and choose “View Page Source” instead.