Sketch 2026-02-14 08:55

This sketch creates an unsettling interactive creature that appears to escape the digital canvas. A dark blob-like entity with five glowing yellow eyes that track your mouse movements is accompanied by eerie ambient sounds (white noise with reverb and a low-frequency hum). Semi-transparent red bars peek from the canvas edges, and the webpage background flickers with a glitchy dark effect, blurring the boundary between the sketch and the webpage.

🧪 Try This!

Experiment with the code by making these changes:

  1. Make the entity glow brighter — Changing the entity's color to a brighter red makes it more visible and threatening against the dark background
  2. Make the blob spikier — Doubling the noise scale by changing 0.5 to 1.0 makes the blob's edges more jagged and distorted, amplifying the alien appearance
  3. Add more eyes — Increasing numEyes makes the entity have more glowing eyes that track your mouse, multiplying the creepy factor
  4. Make the sound louder — Increasing both sound amplitudes makes the white noise hiss and low hum much more prominent and unsettling
  5. Speed up the background flicker — Lowering the flicker interval from 60 to 20 frames makes the webpage background change color much faster, intensifying the glitchy effect
  6. Make the edge bars brighter — Increasing the red channel from 100 to 200 makes the semi-transparent bars peeking from the edges more vivid and threatening
Prefer the full editor? Open it there →

📖 About This Sketch

This sketch creates a genuinely creepy experience by combining visual and audio elements to suggest something breaking out of the digital canvas. The entity is a dark, Perlin-noise-distorted blob with five glowing eyes whose pupils follow your mouse position in real time. Ambient sounds—white noise with reverb and a low-frequency sine wave with delay—fade in at startup to create an unsettling atmosphere. The sketch uses p5.sound's Noise, Oscillator, Reverb, and Delay classes to generate these effects from scratch, rather than loading audio files.

The code is organized into preload() (reserved for future use), setup() (which initializes the canvas, eyes array, and sound objects), draw() (which updates the creature's appearance and adds glitchy background flashes), and windowResized() (which keeps the sketch responsive). By studying it, you will learn how to generate procedural shapes with Perlin noise, make visual elements track the mouse, synthesize scary sounds with p5.sound, and use p5.js's select() function to manipulate the webpage DOM for immersive effects.

⚙️ How It Works

  1. When the sketch loads, setup() creates a fullscreen canvas (using windowWidth and windowHeight), initializes an array of five eyes with random positions and sizes, and fades in two sound generators: white noise with reverb for a hissing, spacious feel, and a low sine wave with delay for a deep, unsettling hum.
  2. Every frame, draw() clears the canvas with a very dark background (RGB 20, 20, 20) and redraws the entity body using beginShape() and vertex() to trace a distorted circle whose radius is modulated by Perlin noise—this creates an organic, breathing blob effect.
  3. For each eye, the sketch draws a yellowish ellipse (the iris) and then a black ellipse (the pupil) whose position is mapped from the current mouseX and mouseY values, so the pupils follow your cursor around the canvas.
  4. Every 60 frames (once per second), the code uses select('body').style() to change the webpage's background color to a random dark red—creating the illusion that the entity is flickering the page itself.
  5. Semi-transparent red rectangles are drawn partially off the left and right edges of the canvas, suggesting that something dark and unknown is lurking just outside the visible area.
  6. When the window is resized, windowResized() regenerates the canvas and re-randomizes the eyes' positions and sizes, maintaining the creepy aesthetic at any screen resolution.

🎓 Concepts You'll Learn

Perlin noise and procedural generationMouse tracking and coordinate mappingp5.sound synthesis and audio effectsDOM manipulation with p5.jsCanvas boundaries and drawing outsideResponsive canvas with windowResized()Conditional logic and frame-based timing

📝 Code Breakdown

preload()

preload() is reserved for loading external assets. In this sketch it's empty because the sounds are generated in setup() using p5.sound's Noise and Oscillator classes.

function preload() {
  // Use preload() to load external assets if needed, but for sound generation, setup() is fine.
  // For example, if you had a specific scary sound file:
  // scarySoundFile = loadSound('path/to/your/scary_sound.mp3');
}
Line-by-line explanation (1 lines)
function preload() {
preload() is a special p5.js function that runs before setup()—use it to load external files like sounds, images, or fonts

setup()

setup() runs once when the sketch starts. It initializes your canvas size, creates all the eyes with random properties, and chains together p5.sound objects to generate the unsettling audio. Notice how disconnect() and then process() are used to route sounds through effects—this is how you build audio chains in p5.sound.

🔬 This loop creates eyes at random positions within the central half of the screen. What happens if you change 'width / 4' to '0' and '3 * width / 4' to 'width'—spreading eyes across the entire width?

  for (let i = 0; i < numEyes; i++) {
    eyes.push({
      x: random(width / 4, 3 * width / 4),
      y: random(height / 4, 3 * height / 4),
      size: random(30, 80),

🔬 These two lines control how loud each sound becomes. What happens if you change 0.1 to 0.3 and 0.05 to 0.15—making both sounds much louder?

  scaryNoise.amp(0.1, 2); // Fade in noise to 0.1 amplitude over 2 seconds
  lowHum.amp(0.05, 3); // Fade in hum to 0.05 amplitude over 3 seconds
function setup() {
  createCanvas(windowWidth, windowHeight);
  // Tip: Use windowWidth/windowHeight for responsive canvas

  entityColor = color(50, 0, 0); // Dark red/brown for the entity's body

  // Create some glowing eyes
  for (let i = 0; i < numEyes; i++) {
    eyes.push({
      x: random(width / 4, 3 * width / 4), // Eyes within the central area
      y: random(height / 4, 3 * height / 4),
      size: random(30, 80), // Size of the eye
      eyeColor: color(255, 200, 0), // Yellowish for the eye's glow
      pupilColor: color(0), // Black pupil
      pupilSize: random(0.2, 0.5) // Pupil size relative to eye size
    });
  }

  // --- Initialize p5.sound elements for an unsettling atmosphere ---

  // White noise for a static/hissing sound
  scaryNoise = new p5.Noise('white');
  scaryNoise.amp(0); // Start quietly
  scaryNoise.start();
  scaryNoise.disconnect(); // Disconnect to apply reverb without direct output
  let reverb = new p5.Reverb();
  reverb.process(scaryNoise, 3, 2); // Add reverb: wetness 3, delay 2 seconds
  reverb.drywet(0.5); // Mix 50% dry signal with 50% reverberated signal

  // Low-frequency sine wave for a subtle, deep hum
  lowHum = new p5.Oscillator('sine');
  lowHum.freq(random(30, 60)); // Very low frequency (30-60 Hz)
  lowHum.amp(0);
  lowHum.start();
  lowHum.disconnect(); // Disconnect to apply delay without direct output
  let delay = new p5.Delay();
  delay.process(lowHum, 0.75, 0.5, 2300); // Delay: 0.75s, feedback 0.5, filter 2300Hz
  delay.drywet(0.3); // Mix 70% dry signal with 30% delayed signal

  // Fade in the sounds over a few seconds
  scaryNoise.amp(0.1, 2); // Fade in noise to 0.1 amplitude over 2 seconds
  lowHum.amp(0.05, 3); // Fade in hum to 0.05 amplitude over 3 seconds
}
Line-by-line explanation (22 lines)

🔧 Subcomponents:

calculation Fullscreen Canvas Creation createCanvas(windowWidth, windowHeight);

Creates a canvas that fills the entire browser window, making the sketch immersive and borderless

for-loop Eyes Array Initialization for (let i = 0; i < numEyes; i++) { eyes.push({...});

Populates the eyes array with random positions, sizes, and colors so the entity has multiple tracking eyes

calculation White Noise Synthesis with Reverb scaryNoise = new p5.Noise('white'); scaryNoise.amp(0); scaryNoise.start(); scaryNoise.disconnect(); let reverb = new p5.Reverb(); reverb.process(scaryNoise, 3, 2); reverb.drywet(0.5);

Generates white noise, adds spacious reverb to it, and chains it for playback—creating a hissing, echoing sound

calculation Low-Frequency Sine Wave with Delay lowHum = new p5.Oscillator('sine'); lowHum.freq(random(30, 60)); lowHum.amp(0); lowHum.start(); lowHum.disconnect(); let delay = new p5.Delay(); delay.process(lowHum, 0.75, 0.5, 2300); delay.drywet(0.3);

Generates a very low sine wave (30–60 Hz), adds delay/feedback to it, and chains it for playback—creating an unsettling hum

calculation Gradual Sound Fade-In scaryNoise.amp(0.1, 2); lowHum.amp(0.05, 3);

Fades the noise in over 2 seconds and the hum in over 3 seconds, gradually building the creepy atmosphere

createCanvas(windowWidth, windowHeight);
Creates a p5.js canvas that fills the entire browser window—windowWidth and windowHeight are built-in p5.js variables that store the browser dimensions
entityColor = color(50, 0, 0);
Sets the entity's body color to a very dark reddish-brown (RGB 50, 0, 0)—almost black with a hint of red
for (let i = 0; i < numEyes; i++) {
Loops 5 times (numEyes = 5), creating and storing an object for each eye in the eyes array
x: random(width / 4, 3 * width / 4),
Places each eye's x position randomly in the middle half of the canvas (between 25% and 75% from the left)
y: random(height / 4, 3 * height / 4),
Places each eye's y position randomly in the middle half of the canvas (between 25% and 75% from the top)
size: random(30, 80),
Gives each eye a random diameter between 30 and 80 pixels, so they vary in size
eyeColor: color(255, 200, 0),
Sets each eye's iris to a bright yellowish color (RGB 255, 200, 0), giving them a glowing appearance
pupilSize: random(0.2, 0.5)
Makes each pupil between 20% and 50% of the eye's size, so pupils are proportional but vary
scaryNoise = new p5.Noise('white');
Creates a white noise generator—white noise sounds like static or TV hiss and has equal loudness across all frequencies
scaryNoise.amp(0);
Sets the noise's initial amplitude (volume) to 0 so it doesn't play yet
scaryNoise.start();
Starts the noise generator—it's now running internally, but inaudible because amplitude is 0
scaryNoise.disconnect();
Disconnects the noise from direct output so it can be routed through the reverb effect instead of playing raw
let reverb = new p5.Reverb();
Creates a reverb effect object that will add spacious, echo-like qualities to the white noise
reverb.process(scaryNoise, 3, 2);
Applies reverb to the white noise with wetness 3 (how much the effect is applied) and delay 2 seconds (how long the echo lasts)
reverb.drywet(0.5);
Mixes the reverbed signal 50/50 with the original (dry) signal—this blends the effect so it's present but not overwhelming
lowHum = new p5.Oscillator('sine');
Creates a sine wave oscillator—sine waves are smooth, musical tones; they're the foundation of all synthesized sound
lowHum.freq(random(30, 60));
Sets the oscillator's frequency to a random value between 30 and 60 Hz—far below normal hearing range (20 Hz is the lowest humans typically hear), creating a subsonic rumble
let delay = new p5.Delay();
Creates a delay effect object that will repeat the low hum in echoes, adding spaciousness and unease
delay.process(lowHum, 0.75, 0.5, 2300);
Applies delay to the hum: 0.75s delay time, 0.5 feedback (each echo is 50% as loud), and 2300 Hz filter to smooth the echoes
delay.drywet(0.3);
Mixes the delayed signal 30% wet (delayed) and 70% dry (original)—keeps the hum intelligible while adding echo texture
scaryNoise.amp(0.1, 2);
Fades the white noise's volume to 0.1 (10% of maximum) over 2 seconds—gradual fade-in for a creeping sound
lowHum.amp(0.05, 3);
Fades the low hum's volume to 0.05 (5% of maximum) over 3 seconds—even more subtle, building unsettling dread

draw()

draw() runs 60 times per second, continuously updating the canvas. This is where the entity's blob animates (via Perlin noise and frameCount), the eyes track your mouse (via map and mouseX/mouseY), and the webpage glitches (via select and DOM manipulation). The repeated background() call each frame prevents trails from persisting.

🔬 This loop traces a distorted circle by plotting ~63 vertices around the center. What happens if you change 'i += 0.1' to 'i += 0.05'—doubling the number of vertices and making the blob outline smoother?

  for (let i = 0; i < TWO_PI; i += 0.1) {
    let r = map(noise(cos(i) * 0.5, sin(i) * 0.5, frameCount * 0.01), 0, 1, width * 0.1, width * 0.3);
    let x = width / 2 + r * cos(i);
    let y = height / 2 + r * sin(i);
    vertex(x, y);
  }

🔬 These lines make the pupil follow your mouse by mapping your position to an offset. What happens if you change the second 'mouseX' to 'width - mouseX'—inverting the pupil tracking?

    let pupilX = map(mouseX, 0, width, -eye.size * eye.pupilSize * 0.5, eye.size * eye.pupilSize * 0.5);
    let pupilY = map(mouseY, 0, height, -eye.size * eye.pupilSize * 0.5, eye.size * eye.pupilSize * 0.5);
    ellipse(eye.x + pupilX, eye.y + pupilY, eye.size * eye.pupilSize);
function draw() {
  background(20); // Very dark background

  // --- Draw the scary entity's body ---
  noStroke();
  fill(entityColor);
  beginShape();
  // Use noise() to create a distorted, organic blob shape
  for (let i = 0; i < TWO_PI; i += 0.1) {
    let r = map(noise(cos(i) * 0.5, sin(i) * 0.5, frameCount * 0.01), 0, 1, width * 0.1, width * 0.3);
    let x = width / 2 + r * cos(i);
    let y = height / 2 + r * sin(i);
    vertex(x, y);
  }
  endShape(CLOSE);

  // --- Draw the glowing eyes that follow the mouse ---
  for (let eye of eyes) {
    fill(eye.eyeColor);
    ellipse(eye.x, eye.y, eye.size); // The main glowing part of the eye
    fill(eye.pupilColor);
    // Calculate pupil position based on mouseX and mouseY
    let pupilX = map(mouseX, 0, width, -eye.size * eye.pupilSize * 0.5, eye.size * eye.pupilSize * 0.5);
    let pupilY = map(mouseY, 0, height, -eye.size * eye.pupilSize * 0.5, eye.size * eye.pupilSize * 0.5);
    ellipse(eye.x + pupilX, eye.y + pupilY, eye.size * eye.pupilSize); // The pupil
  }

  // --- "Coming out of its game" effects ---

  // 1. Draw shapes partially outside the canvas boundaries
  // These semi-transparent red bars appear at the edges, suggesting something lurking beyond.
  fill(100, 0, 0, 150); // Semi-transparent red
  rect(-50, height / 3, 100, height / 3); // Left edge
  rect(width - 50, height / 3, 100, height / 3); // Right edge

  // 2. Manipulate DOM elements (e.g., change body background for a glitchy effect)
  // This uses p5.js's select() function to access the HTML body and change its style.
  if (frameCount % 60 === 0) { // Every second (60 frames)
    let r = random(10, 50);
    let g = random(0, 10);
    let b = random(0, 10);
    select('body').style('background-color', `rgb(${r}, ${g}, ${b})`); // Glitchy dark background
  }
  // The cursor is already hidden via style.css, which is another "out of game" effect.
}
Line-by-line explanation (25 lines)

🔧 Subcomponents:

calculation Canvas Clear background(20);

Clears the canvas to a very dark color every frame, preventing motion trails and ensuring a clean redraw

for-loop Procedural Blob Shape for (let i = 0; i < TWO_PI; i += 0.1) { let r = map(noise(cos(i) * 0.5, sin(i) * 0.5, frameCount * 0.01), 0, 1, width * 0.1, width * 0.3); let x = width / 2 + r * cos(i); let y = height / 2 + r * sin(i); vertex(x, y); }

Traces a distorted circle around the center of the canvas using Perlin noise to vary the radius—creating an organic, breathing blob

for-loop Eyes Drawing and Pupil Tracking for (let eye of eyes) { fill(eye.eyeColor); ellipse(eye.x, eye.y, eye.size); fill(eye.pupilColor); let pupilX = map(mouseX, 0, width, -eye.size * eye.pupilSize * 0.5, eye.size * eye.pupilSize * 0.5); let pupilY = map(mouseY, 0, height, -eye.size * eye.pupilSize * 0.5, eye.size * eye.pupilSize * 0.5); ellipse(eye.x + pupilX, eye.y + pupilY, eye.size * eye.pupilSize); }

Draws each eye's iris and pupil, with the pupil position calculated from the mouse position so it follows your cursor

calculation Semi-Transparent Edge Bars fill(100, 0, 0, 150); rect(-50, height / 3, 100, height / 3); rect(width - 50, height / 3, 100, height / 3);

Draws semi-transparent red rectangles partially off the canvas edges, suggesting something lurking just beyond the screen

conditional Glitchy Background Color Flicker if (frameCount % 60 === 0) { let r = random(10, 50); let g = random(0, 10); let b = random(0, 10); select('body').style('background-color', `rgb(${r}, ${g}, ${b})`); }

Every 60 frames (once per second), changes the webpage background to a random dark reddish color, creating a glitchy 'out of game' effect

background(20);
Clears the entire canvas to a very dark gray (RGB 20, 20, 20), erasing the previous frame so new content can be drawn fresh
noStroke();
Disables outlines on shapes—all future shapes drawn will have no border, only fill colors
fill(entityColor);
Sets the fill color to entityColor (dark reddish-brown), so the blob body will be colored with this
beginShape();
Starts defining a custom polygon shape by collecting vertex points—you'll add many vertices and then close the shape
for (let i = 0; i < TWO_PI; i += 0.1) {
Loops around a full circle (TWO_PI ≈ 6.28 radians = 360°), incrementing by 0.1 radians each step—this traces ~63 points around the circle
let r = map(noise(cos(i) * 0.5, sin(i) * 0.5, frameCount * 0.01), 0, 1, width * 0.1, width * 0.3);
Uses 3D Perlin noise to create a value between 0 and 1, then maps it to a radius between width*0.1 (10% of canvas width) and width*0.3 (30% of canvas width). frameCount changes every frame, animating the blob.
let x = width / 2 + r * cos(i);
Calculates the x position of this vertex using polar coordinates: the canvas center plus the radius r times the cosine of the angle i
let y = height / 2 + r * sin(i);
Calculates the y position of this vertex using polar coordinates: the canvas center plus the radius r times the sine of the angle i
vertex(x, y);
Adds this point to the shape being drawn—after all vertices are added, they form the blob's outline
endShape(CLOSE);
Completes the shape by connecting the last vertex back to the first one with a line, creating a closed blob
for (let eye of eyes) {
Loops through each eye object in the eyes array, drawing it one at a time
fill(eye.eyeColor);
Sets the fill color to this particular eye's color (yellowish) so the iris will be drawn in that color
ellipse(eye.x, eye.y, eye.size);
Draws a circle (ellipse with equal width and height) at the eye's x and y position with diameter eye.size—this is the glowing iris
fill(eye.pupilColor);
Changes the fill color to black (the pupil color) so the next ellipse will be dark
let pupilX = map(mouseX, 0, width, -eye.size * eye.pupilSize * 0.5, eye.size * eye.pupilSize * 0.5);
Maps the mouseX position (0 to width) to a pupil offset (-half-pupil-radius to +half-pupil-radius)—the pupil shifts left/right based on where your mouse is
let pupilY = map(mouseY, 0, height, -eye.size * eye.pupilSize * 0.5, eye.size * eye.pupilSize * 0.5);
Maps the mouseY position (0 to height) to a pupil offset (-half-pupil-radius to +half-pupil-radius)—the pupil shifts up/down based on where your mouse is
ellipse(eye.x + pupilX, eye.y + pupilY, eye.size * eye.pupilSize);
Draws the black pupil at the eye's position plus the mouse-tracking offsets, creating the illusion that the pupil is following your cursor
fill(100, 0, 0, 150);
Sets the fill color to a semi-transparent dark red (RGB 100, 0, 0 with alpha 150 out of 255)—mostly opaque but slightly see-through
rect(-50, height / 3, 100, height / 3);
Draws a rectangle at x=-50 (off the left edge), y=height/3, with width 100 and height=height/3—this bar peeks in from the left, suggesting something lurking beyond
rect(width - 50, height / 3, 100, height / 3);
Draws a rectangle at x=width-50 (off the right edge), y=height/3, with width 100 and height=height/3—this bar peeks in from the right
if (frameCount % 60 === 0) {
Checks if frameCount is divisible by 60 (every 60 frames, or once per second at 60 fps)—this triggers the background color change infrequently
let r = random(10, 50);
Generates a random red channel value between 10 and 50 (very dark red)
let g = random(0, 10);
Generates a random green channel value between 0 and 10 (almost no green)
let b = random(0, 10);
Generates a random blue channel value between 0 and 10 (almost no blue)
select('body').style('background-color', `rgb(${r}, ${g}, ${b})`);
Uses p5.js's select() to grab the HTML <body> element, then sets its background-color CSS property to the random dark red—this flickers the webpage background

windowResized()

windowResized() is a p5.js lifecycle function that triggers whenever the browser window size changes. By resizing the canvas and regenerating the eyes array, you ensure the sketch scales gracefully to any screen size and the entity always remains visually coherent.

function windowResized() {
  resizeCanvas(windowWidth, windowHeight);
  // Re-calculate eye positions when the window is resized to keep them centered
  eyes = [];
  for (let i = 0; i < numEyes; i++) {
    eyes.push({
      x: random(width / 4, 3 * width / 4),
      y: random(height / 4, 3 * height / 4),
      size: random(30, 80),
      eyeColor: color(255, 200, 0),
      pupilColor: color(0),
      pupilSize: random(0.2, 0.5)
    });
  }
}
Line-by-line explanation (6 lines)

🔧 Subcomponents:

calculation Canvas Resize resizeCanvas(windowWidth, windowHeight);

Adjusts the p5.js canvas size to match the current browser window dimensions

for-loop Eyes Array Recreation eyes = []; for (let i = 0; i < numEyes; i++) { eyes.push({...});

Clears the old eyes array and regenerates new eyes with random properties so they reposition and resize on the new canvas dimensions

function windowResized() {
This is a special p5.js function that automatically runs whenever the browser window is resized—use it to keep your sketch responsive
resizeCanvas(windowWidth, windowHeight);
Resizes the p5.js canvas to match the new browser dimensions (windowWidth and windowHeight update automatically when you resize)
eyes = [];
Clears the eyes array completely, discarding all old eye objects so we can create new ones
for (let i = 0; i < numEyes; i++) {
Recreates the same number of eyes (numEyes = 5) with new random positions and sizes suited to the resized canvas
x: random(width / 4, 3 * width / 4),
Places each new eye at a random x position within the new canvas's central half, keeping eyes centered relative to the new dimensions
y: random(height / 4, 3 * height / 4),
Places each new eye at a random y position within the new canvas's central half, proportional to the new height

📦 Key Variables

entityColor p5.Color

Stores the dark reddish-brown color of the entity's blob body, set once in setup() and used in draw()

let entityColor = color(50, 0, 0);
eyes array

Stores an array of eye objects, each with x, y, size, eyeColor, pupilColor, and pupilSize properties—allows the sketch to draw and track multiple eyes

let eyes = [];
numEyes number

Controls how many eyes the entity has—used in loops in setup() and windowResized() to create and recreate the eyes array

let numEyes = 5;
scaryNoise p5.Noise

Stores the white noise generator object, initialized in setup() with reverb effects and faded in for atmospheric sound

let scaryNoise;
lowHum p5.Oscillator

Stores the low-frequency sine wave oscillator object, initialized in setup() with delay effects and faded in for a deep, unsettling hum

let lowHum;

🔧 Potential Improvements (6)

Here are some ways this code could be enhanced:

BUG draw() pupil tracking

The pupil mapping uses mouseX/mouseY directly mapped to pupil offset, but doesn't account for the actual eye position—pupils can visually jump if an eye is far from center

💡 Calculate pupil offset based on the angle from each eye to the mouse: use atan2(mouseY - eye.y, mouseX - eye.x) to make pupils track toward the actual mouse position instead of globally

PERFORMANCE draw() Perlin noise and DOM manipulation

Every frame calls noise() 63 times (in the blob loop) and every second calls select('body').style() which causes a DOM reflow; repeatedly selecting and modifying DOM elements can impact performance

💡 Cache the body element as a global variable in setup() and reuse it in draw(); also consider caching the eye array reference to avoid repeated lookups

STYLE setup() eye object creation

The eye object is created inline in the loop with hard-coded colors and ranges, making it hard to tweak visual properties globally

💡 Create a helper function like createEye() that returns a new eye object with consistent properties, centralizing eye creation logic

FEATURE draw() blob shape

The blob's breathing animation is driven only by frameCount * 0.01, which is linear and predictable; the entity could feel more alive with varied, organic motion

💡 Use multiple layers of Perlin noise or sine waves with different frequencies to create complex, shifting deformations—e.g., add a time-varying scale factor based on noise(frameCount * 0.002)

FEATURE draw() and setup() sounds

The white noise and low hum are constant once faded in; they don't respond to user interaction or visual events, missing an opportunity for deeper immersion

💡 Map mouse distance from the entity center to sound amplitude, so the sounds get louder as you move closer or softer as you move away—creating dynamic audio feedback

STYLE windowResized()

Eye positions are regenerated with completely new randomness when the window resizes, rather than preserving their relative positions or scaling gracefully

💡 Instead of recreating eyes, scale each eye's position and size proportionally to the new canvas dimensions (e.g., multiply x by newWidth / oldWidth) to maintain spatial consistency

🔄 Code Flow

Code flow showing preload, setup, draw, windowresized

💡 Click on function names in the diagram to jump to their code

graph TD start[Start] --> setup[setup] setup --> createcanvas[create-canvas] setup --> eyesloop[eyes-loop] setup --> scarynoisesetup[scary-noise-setup] setup --> lowhumsetup[low-hum-setup] setup --> fadeinsounds[fade-in-sounds] setup --> draw[draw loop] click setup href "#fn-setup" click createcanvas href "#sub-create-canvas" click eyesloop href "#sub-eyes-loop" click scarynoisesetup href "#sub-scary-noise-setup" click lowhumsetup href "#sub-low-hum-setup" click fadeinsounds href "#sub-fade-in-sounds" draw --> backgroundclear[background-clear] draw --> blobloop[blob-loop] draw --> eyesloop2[eyes-loop] draw --> edgebars[edge-bars] draw --> glitchbackground[glitch-background] draw --> windowresized[windowresized] click draw href "#fn-draw" click backgroundclear href "#sub-background-clear" click blobloop href "#sub-blob-loop" click eyesloop2 href "#sub-eyes-loop" click edgebars href "#sub-edge-bars" click glitchbackground href "#sub-glitch-background" windowresized --> canvasresize[canvas-resize] windowresized --> eyesresetloop[eyes-reset-loop] click windowresized href "#fn-windowresized" click canvasresize href "#sub-canvas-resize" click eyesresetloop href "#sub-eyes-reset-loop"

❓ Frequently Asked Questions

What visual elements are featured in the p5.js sketch titled 'Sketch 2026-02-14 08:55'?

The sketch features a dark red/brown entity with glowing yellow eyes randomly positioned within the canvas, creating an eerie and atmospheric visual effect.

Is there any user interaction available in this creative coding sketch?

The sketch does not currently include user interaction; it is primarily a visual and auditory experience meant to evoke a spooky atmosphere.

What creative coding concepts does this sketch illustrate using p5.js?

This sketch demonstrates the use of randomness in positioning and sizing, as well as sound manipulation techniques like reverb and oscillation to enhance the eerie ambiance.

Preview

Sketch 2026-02-14 08:55 - p5.js creative coding sketch preview
Sketch Preview
Code flow diagram showing the structure of Sketch 2026-02-14 08:55 - Code flow showing preload, setup, draw, windowresized
Code Flow Diagram