🚀 Stage 4: Source Code Showcase

Same rocket. SketchWave objects. A flickering flame and a pulsing porthole — in under 10 new lines.

📂 The Stage 4 Files

Stage 4 replaces every raw p5.js drawing call with a SketchWave object. The rocket looks identical to Stage 3 — same position, same colors, same scrolling stars — but its internal structure is completely different. Three files make up the Stage 4 build:

File What it does Stage 4 changes
rocketStg4.html HTML shell Six new <script> tags load the SW class library
rocketStg4Sketch.js The p5.js sketch colorMode(HSB); SW objects built in setup(); sinusoid animations; draw() calls .draw()
rocket4Styles.css Minimal CSS reset Unchanged from Stages 2 & 3

SketchWave classes loaded for this stage:

Class File Used for
SWColor swColor.js All six named colors; HSB palette
SWPoint swPoint.js Vertices and center positions for every shape
SWSinusoid swSinusoid.js Flame flicker & porthole pulse animations
SWRectangle swRectangle.js Rocket body
SWTriangle swTriangle.js Nose cone, left fin, right fin, flame
SWDisk swDisk.js Porthole (with breathe() animation)
💡 What actually changed?

In setup(), each rocket part is constructed as an SW object and stored in a named variable (rocketBody, noseCone, flame, …). draw() shrinks to:

drawBackground();  drawStars();  animateFlame(t);  animatePorthole(t);  drawRocket();

And drawRocket() is simply:

leftFin.draw();  rightFin.draw();  rocketBody.draw();  …

Each shape knows how to draw itself. draw() is a pure table of contents.
🔥 Flame Flicker + 💡 Porthole Pulse

Flame: flame.vC is the SWPoint at the flame tip. Each frame:
flame.vC.y = flameSin.getValue(t);
One line. The sinusoid oscillates the tip between 325 px and 385 px below the canvas top (a 60 px range) at ~3 cycles per second. SWTriangle.draw() always reads the current vertex positions, so the flame automatically draws at the right length every frame.

Porthole: porthole.breathe(portholeBreatheSin, t);
SWDisk.breathe() sets this.radius to the sinusoid value. The radius oscillates between 14 px and 16 px over 2.5 seconds — a slow, glowing pulse.
⚠ Trade-off: Flexibility vs Complexity

Stage 4 adds six <script> tags and a longer setup(). That is real cost.

The payoff: every future animation is one sinusoid + one property update. Want the nose cone to wobble? Add a sinusoid, update noseCone.vC.x in draw(). Want the body to breathe? Call rocketBody.breathe(s, t). No new drawing functions. No restructuring.

In software engineering, this principle is called Open/Closed: open for extension, closed for modification. SW objects make animation open for extension.
rocketStg4.html — running live inside an <iframe>

📊 Stage 3 vs Stage 4: Same Look, Different Structure

Both stages render an identical rocket on an identical scrolling star field. The difference is entirely in how the drawing code is organized.

Aspect Stage 3 — Raw p5.js Stage 4 — SketchWave
Rocket body rect(BODY_X, BODY_Y, BODY_W, BODY_H) rocketBody.draw()
Color definition const CLR_ACCENT = [255, 100, 100] clrRocketRed = new SWColor(0, 61, 100, 100, "rocketRed")
Color mode Default RGB (p5 auto-detects) colorMode(HSB, 360, 100, 100, 100) — required for SWColor
Flame animation Not possible without redesigning drawFlame() flame.vC.y = flameSin.getValue(t); — one line
Porthole animation Not possible without a new radius variable and redraw logic porthole.breathe(portholeBreatheSin, t); — one line
draw() length Calls multiple drawing sub-functions directly Calls 5 high-level functions; each part calls .draw()
Script tags 2 (p5 + sketch) 8 (p5 + 6 SW classes + sketch)
Stars Identical plain JS objects — deliberately not converted to SW
📌 Why didn't the stars become SWDisk objects?

Converting 100 plain JS star objects to SWDisk instances would create 100 SWColor objects, 100 SWPoint center objects, plus all their internal copies — for dots that are 1–3 px wide and completely opaque half the time. The visual result would be identical but the memory and construction cost would be significant.

Stage 4 keeps stars as plain JS objects deliberately. This is a real engineering decision: use the right tool for the right job. SW classes shine for complex, named, animatable shapes. They are overkill for 100 tiny identical dots.

📜 Source Code

rocketStg4.html HTML5
Loading rocketStg4.html…
sketches/rocketStg4Sketch.js JavaScript
Loading rocketStg4Sketch.js…
styles/rocket4Styles.css CSS
Loading rocket4Styles.css…

💪 Try It Yourself

Use the Copy buttons above to grab the files, then:

  1. Copy the shapeClasses/ folder from the project (you need swColor.js, swPoint.js, swSinusoid.js, swRectangle.js, swTriangle.js, and swDisk.js).
  2. Open rocketStg4.html from a web server (VS Code Live Server, or localhost) — the SW class console.log messages confirm every file loaded.
  3. Flame speed challenge: change FLAME_PERIOD from 0.35 to 1.5. How does the flicker feel different? What happens if you set it to 0.1?
  4. Porthole glow challenge: change PORT_R_MIN and PORT_R_MAX to exaggerate the pulse (e.g., 8 and 30). Does it still look like a porthole?
  5. New animation challenge: add a sinusoid that makes the nose cone wobble left and right. Store the original noseCone.vC.x (= BODY_CX = 300) and add a sinusoid value to it each frame. What period and amplitude feel natural?
  6. Stars with depth challenge (from Stage 3): give each star a speed property in generateStars() scaled by its size so larger stars scroll faster. This creates a parallax depth effect.

⚠️ 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 Open Full Size link above and choose “View Page Source” instead.