Recording the refactoring to Stage 2 with configurable parameters and tilt effects.
Let's refactor movieCreditsSim1.html as movieCreditsSim2.html with these improvements:
tiltAngle in a range of [-15, 15] degrees since in the original movie credits, some of the names were slightly tiltedmovieCreditsSim2.html - Enhanced version with configuration and tiltchatLog2.html - This chat log documenting Stage 2 changesAdded three configuration constants at the top of the code for easy customization:
// ============================================
// CONFIGURATION VARIABLES (NEW IN STAGE 2!)
// ============================================
// *** NUMBER OF STARS ***
// Controls how many background stars appear in the starfield
const NUM_STARS = 100;
// *** INITIAL FONT SIZE ***
// How large the student names appear when they first show up
const INITIAL_FONT_SIZE = 64;
// *** CREDIT APPEARANCE DELAY ***
// Time between each student name appearing (in milliseconds)
const CREDIT_DELAY_MS = 3000;
Added tiltAngle property to each credit for authentic movie credits feel:
// In initializeCredits() function:
// *** NEW: Generate random tilt angle for this credit ***
// In the original Superman movie, text appeared at slight angles
// Range: -15 to +15 degrees
let tiltAngle = random(-15, 15);
let credit = {
name: studentNames[i],
x: width / 2,
y: height / 2,
size: INITIAL_FONT_SIZE, // *** Uses config variable ***
opacity: 100,
hue: (i * 50) % 360,
active: false,
startTime: i * CREDIT_DELAY_MS, // *** Uses config variable ***
tiltAngle: tiltAngle // *** NEW property ***
};
Modified displayCredit() to apply rotation transformation:
function displayCredit(credit) {
if (credit.active && credit.opacity > 0) {
// *** STAGE 2 ADDITION: Apply rotation transformation ***
push(); // Save current drawing state
translate(credit.x, credit.y); // Move origin to text position
// *** NEW: Rotate by the tilt angle ***
rotate(radians(credit.tiltAngle));
fill(credit.hue, 80, 100, credit.opacity);
textSize(credit.size);
// Draw at origin (0,0) since we translated
text(credit.name, 0, 0);
pop(); // Restore previous drawing state
}
}
Added configuration constants section with NUM_STARS, INITIAL_FONT_SIZE, and CREDIT_DELAY_MS
Changed hardcoded 100 to NUM_STARS variable
// Before (Stage 1):
for (let i = 0; i < 100; i++) {
// After (Stage 2):
for (let i = 0; i < NUM_STARS; i++) {
Multiple changes in this function:
Completely refactored to use transformation matrix:
We used const for configuration variables because they shouldn't change
during the program. Use const for values that stay the same, and
let for values that will change (like credit.size or credit.opacity).
"Magic numbers" are unexplained numbers scattered through code (like 100, 64, 3000). They make code hard to understand and modify. Configuration variables give these numbers meaningful names and a single place to change them.
Instead of calculating rotated positions mathematically, we let p5.js do it with transformations. This is more intuitive and less error-prone. Think of it like moving and tilting your drawing paper instead of calculating where each point goes.
The random() function makes each credit unique. Without it, all credits
would tilt the same way, looking mechanical. Random tilts create a more organic,
authentic feel - just like in the original 1978 Superman credits!
NUM_STARS = 200 for a denser starfieldINITIAL_FONT_SIZE = 80 for more dramaCREDIT_DELAY_MS = 1500 for quicker pacingrandom(-15, 15) to random(-30, 30)credit.tiltAngle += 0.5; to make text spin!hue: map(tiltAngle, -15, 15, 0, 360) for tilt-based colorsThe Stage 2 version now shows student names appearing at slight angles, creating a more authentic movie credits effect. Each name has its own unique tilt between -15 and +15 degrees, and all the animation parameters are easy to adjust at the top of the code.
Good code is configurable (easy to customize), readable (easy to understand), and maintainable (easy to modify later). By extracting configuration variables and adding the tilt effect, we've made the code better on all three counts!
Let's make this modest change in each of the files here. As the student name fades into the background, straighten it so that as it disappears, it is horizontal, and explain where this update takes place and how it is done.
Added code to gradually reduce the tilt angle to 0 (horizontal) as credits fade out.
The update is in the updateCredit() function, which is called every frame
for each active credit. This is where all the animation properties are updated
(size, opacity, position, and now tilt angle).
// Inside the updateCredit() function, added after opacity update:
// *** NEW: Gradually straighten the text as it fades ***
// Multiply tiltAngle by 0.95 each frame to slowly reduce it toward 0
// This makes the text become horizontal as it disappears
// 0.95 means it keeps 95% of its tilt each frame, losing 5%
credit.tiltAngle *= 0.95;
function updateCredit(credit) {
// Calculate how much time has passed since THIS animation started
let timeSinceStart = millis() - animationStartTime;
// Check if it's time for this credit to appear
if (!credit.active && timeSinceStart > credit.startTime) {
credit.active = true;
}
// If the credit is active, animate it
if (credit.active) {
// Gradually shrink the text
if (credit.size > 12) {
credit.size -= 0.5;
}
// Gradually fade out
if (credit.opacity > 0) {
credit.opacity -= 0.3;
}
// *** NEW: Gradually straighten the text as it fades ***
credit.tiltAngle *= 0.95;
// Move slightly upward (like credits scrolling)
credit.y -= 0.2;
}
}
This technique is called exponential decay and is very useful in animation:
value *= factor (where factor < 1)credit.tiltAngle -= 0.5 but this:
Now when you watch the animation, each student name starts at a random tilt angle, and as it shrinks and fades away, it also gradually straightens to horizontal. This creates a more polished, professional-looking animation where the text "settles" as it disappears into the starfield background.
Let's also update the 'magic number' tilt size of 15 to a variable, maxTilt and update chatlog2.html with this improvement.
Replaced the hardcoded value 15 with a configuration constant for maximum tilt angle.
In Interaction #3, we learned that "magic numbers" make code hard to understand and modify.
The value 15 was still hardcoded in the random(-15, 15) call. By extracting it
to a configuration variable, we complete the refactoring and make the code more maintainable.
Added to the configuration section at the top of the script:
// *** MAXIMUM TILT ANGLE ***
// The maximum angle (in degrees) that text can tilt from horizontal
// Text will randomly tilt between -MAX_TILT and +MAX_TILT degrees
// Smaller values (5-10) = subtle tilt, Larger values (20-30) = dramatic tilt
const MAX_TILT = 15;
Replaced hardcoded values with the MAX_TILT variable:
// Before:
let tiltAngle = random(-15, 15);
// After:
let tiltAngle = random(-MAX_TILT, MAX_TILT);
MAX_TILT = 5 for barely noticeable tiltMAX_TILT = 30 for wild anglesMAX_TILT = 0 to disable tilting entirelyMAX_TILT = 45 for artistic effectNow all animation parameters are configurable in one place:
// ============================================
// CONFIGURATION VARIABLES
// ============================================
const NUM_STARS = 100; // Number of background stars
const INITIAL_FONT_SIZE = 64; // Starting text size in pixels
const CREDIT_DELAY_MS = 3000; // Delay between credits (milliseconds)
const MAX_TILT = 15; // Maximum tilt angle (degrees)
Refactoring means improving code structure without changing what it does. This is an important practice in software development:
Similarly, let's make the .95 adjustment a constant: TILT_DECAY; update the chatlog2.html accordingly.
Replaced the hardcoded value 0.95 with a configuration constant for the tilt decay rate.
Just like with the MAX_TILT variable in Interaction #5, we're identifying another magic number (0.95) and extracting it to a configuration constant. This demonstrates the iterative nature of code refactoring - keep improving as you notice opportunities!
Added to the configuration section after MAX_TILT:
// *** TILT DECAY RATE ***
// Controls how quickly the tilt angle returns to horizontal (0 degrees)
// Each frame, tiltAngle is multiplied by this value
// Closer to 1.0 = slower straightening, Closer to 0.0 = faster straightening
// Typical range: 0.90 (fast) to 0.98 (slow)
const TILT_DECAY = 0.95;
Replaced hardcoded value with the TILT_DECAY constant:
// Before:
credit.tiltAngle *= 0.95;
// After:
credit.tiltAngle *= TILT_DECAY;
The TILT_DECAY value is a decay factor in exponential decay:
This means at 60 frames per second, the angle is almost horizontal after just 1 second!
TILT_DECAY = 0.90 for faster straighteningTILT_DECAY = 0.98 for slower, gentler straighteningTILT_DECAY = 0.80 for quick snap to horizontalTILT_DECAY = 1.0 to disable straightening entirelyAll five animation parameters are now configurable:
// ============================================
// CONFIGURATION VARIABLES
// ============================================
const NUM_STARS = 100; // Number of background stars
const INITIAL_FONT_SIZE = 64; // Starting text size in pixels
const CREDIT_DELAY_MS = 3000; // Delay between credits (milliseconds)
const MAX_TILT = 15; // Maximum tilt angle (degrees)
const TILT_DECAY = 0.95; // Tilt straightening speed (0-1)
Notice how TILT_DECAY and MAX_TILT work together:
Notice the naming convention for our constants:
These practices make code "self-documenting" - you can understand what it does just by reading it!
We've now eliminated all magic numbers from the animation code. Every important value is configurable, documented, and easy to find. This is production-quality code organization!
Next Steps: Could add sound effects, different animation patterns, user controls, or export to video!