Concept
This assignment is mainly based on the text patterns of early games like “Space Invaders” or “Tetris,” where the text and images were made out of square pixels. The way the blocks move and respond to user input is like the jumpy, random effects we see in old games where graphics were powered by simple hardware.
The key interactions involve entering any word which you want to display, and pressing “Generate” forms the word in the grid. The grid can be toggled on/off with a separate “Toggle Grid” button. When the mouse hovers over the text, the blocks near the cursor change color and become more diverse. When we hold down the “Enter” key, it causes the blocks representing the text to scatter randomly, simulating random jumpy movements. As soon as the key is let go, the boxes come back to their original positions.
Sketch
Code I am proud of
// Setup Function function setup() { // Create the canvas createCanvas(600, 400); cols = floor(width / gridSize); rows = floor(height / gridSize); // Taking the input and generating the other buttons input = createInput(); input.position(20, height + 20); button = createButton('Generate'); button.position(input.x + input.width + 10, height + 20); button.mousePressed(startAnimation); toggleButton = createButton('Toggle Grid'); toggleButton.position(button.x + button.width + 10, height + 20); toggleButton.mousePressed(toggleGrid); textSize(fontSize); textAlign(CENTER, CENTER); pg = createGraphics(width, height); pg.pixelDensity(1); } // Function to show/hide the grid function toggleGrid() { showGrid = !showGrid; } // Draw function function draw() { // Smooth background blending bgColor.r = lerp(bgColor.r, targetBgColor.r, 0.01); bgColor.g = lerp(bgColor.g, targetBgColor.g, 0.01); bgColor.b = lerp(bgColor.b, targetBgColor.b, 0.01); background(bgColor.r, bgColor.g, bgColor.b); if (showGrid) { drawGrid(); } if (animating && word.length > 0) { fillLetterPixels(); } for (let i = 0; i < pixelIndex; i++) { let px = letterPixels[i].x * gridSize; let py = letterPixels[i].y * gridSize; // Jumpy explosion effect if (exploding) { // Randomize position for the explosion effect px += random(-10, 10); py += random(-10, 10); } else { // Smooth return to original positions px = lerp(px, originalPositions[i].x * gridSize, 0.1); py = lerp(py, originalPositions[i].y * gridSize, 0.1); } let d = dist(mouseX, mouseY, px + gridSize / 2, py + gridSize / 2); if (d < gridSize * 4) { let blockColor = blockColors[i]; fill(blockColor.r, blockColor.g, blockColor.b, map(d, 0, gridSize * 4, 255, 50)); } else { fill(0); } noStroke(); rect(px, py, gridSize, gridSize); if (random(1) < sparkleChance) { fill(random(255), random(255), random(255)); rect(px, py, gridSize, gridSize); } } }
- Setup() function sets up the canvas, makes the Graphics buffer and initializes the canvas color to white.
- Draw() function is the function which is the main loop that runs continuously. It controls the background color blending, sparkle effect, jumpy explosion effect, stores which keys are pressed, checks grid is toggled on/off, and so on.
// Startup animation after the generate button is clicked function startAnimation() { word = input.value(); pixelIndex = 0; animating = true; getLetterPixels(); blockColors = letterPixels.map(() => { return { r: random(255), g: random(255), b: random(255) }; }); originalPositions = letterPixels.map((p) => ({ ...p })); // Store original positions targetBgColor = { r: random(255), g: random(255), b: random(255) }; }
– This function is responsible for the short simulation of making the letters of the word when “Generate button” is pressed.
function getLetterPixels() { letterPixels = []; // Use the off-screen buffer (pg) to render the text pg.background(255); pg.textSize(fontSize); pg.textAlign(CENTER, CENTER); pg.fill(0); pg.text(word, pg.width / 2, pg.height / 2); pg.loadPixels(); for (let y = 0; y < pg.height; y += gridSize) { for (let x = 0; x < pg.width; x += gridSize) { let index = (x + y * pg.width) * 4; let r = pg.pixels[index]; if (r < 128) { let gridX = floor(x / gridSize); let gridY = floor(y / gridSize); letterPixels.push({ x: gridX, y: gridY }); } } } }
- This function uses the off-screen buffer (pg) to render the input text and identifies the grid positions where the pixels are black (indicating a letter).
function fillLetterPixels() { if (pixelIndex < letterPixels.length) { let px = letterPixels[pixelIndex].x * gridSize; let py = letterPixels[pixelIndex].y * gridSize; fill(0); noStroke(); rect(px, py, gridSize, gridSize); pixelIndex++; } else { animating = false; } }
- This function simulates the pixels that form the letters. It gradually reveals the blocks one by one.
// Run the function if ENTER key is pressed function keyPressed() { if (keyCode === ENTER) { exploding = true; // Start the explosion effect } } // Run the function if ENTER key is released function keyReleased() { if (keyCode === ENTER) { exploding = false; // Stop the explosion and return to original positions } }
- When the Enter key is pressed or released, it starts or stops the jumpy explosion effect. When the Enter key is pressed, the exploding flag is set to true, causing the blocks to scatter randomly. When the Enter key is released, the exploding flag is set to false, and the blocks return to their original positions.
Challenges/ Future Improvements
Some of the major challenges I had faced were:
- Creating the random “jumpy” explosion effect and making sure that the boxes making up the letters stay in place after key is released.
- The “sparkle” effect was another challenge as it required creating intermittent flashes of random color across specific blocks.
- The color changing due to the “hovering mouse” was another one. However, by measuring the distance (dist()) between the mouse and the block’s center, the program smoothly blends colors based on proximity to the cursor, giving the effect of interaction with the text.
However, the code can be further improved upon by introducing some collission, introducing different layers to create a 3D pixelated text feel, and so on.