Progress and Regress // ICM W2

Sep 16, 2024

Exploring Opposites

In this blog I'll go through how I explored the ideas of representing a pair of opposite concepts using P5.js. Inspired by Casey Neistat's video, I chose to explore the ideas of progress and regress through interactive motion. Although I found the messaging a little reductive, I really appreciated the way he illustrated the concept in motion.


Concept Overview

My sketch revolves around a circle that moves across the canvas, representing three states:

  1. Staying put

  2. Progressing forward

  3. Regressing backward

The circle's movement is controlled by user interaction, creating a simple yet engaging visualization of progress and regress.

Initial Sketches

I started with low-fidelity paper sketches to flesh out my idea. These sketches helped me visualize:

  • The circle's movement

  • A "floor" element to ground the visual

  • Basic layout and interaction zones

Higher Fidelity Design

Using Figma, I created a more refined version of my concept, focusing on: Circle positioning, Movement, Color palette and Overall visual feel. This step helped me simplify the design for my MVP, ensuring I could focus on core functionality.

MVP Approach

To create a functional prototype quickly, I decided to focus on three key components:

  1. Circle movement based on mouse interaction

  2. Handling different movement states

  3. Conditions for mouse interaction with the canvas

I opted to leave out more complex features like fading trails for this initial version. Although I do have some idea of how we can achieve this by playing around with the alpha value of the circles and having it decrease in relation to speed, I will likely explore this in the next version of the idea or perhaps come back to this blog and update it.

Pseudocode Development

To clarify my logic, I developed pseudocode, which I refined through discussion with my classmate, Nick.

// Round 1 pseudo code 
Main:
Global Variables: circleX, speed, height, width, circleoffsetY=140

Setup:
Create Canvas(window.width, window.height);

function draw():
    render background (colour, opacity)
    render square (size, colour)

    if mouse is in frame & pressed:
        circleX = circleX + speed
    else if mouseX + mouseY is in range (0-height & 0-width):
        circleX = circleX
    else:
        circleX = circleX + speed * (-1)

    no stroke - fill
    render circle (circleX, height-heightOffset, 50)

We noted that there was a way to simplify the code further and focus on the variable speed as the primary parameter thats changing so the code was edited to reflect that.

Main:
Global Variables: circleX, speed = 0, height, width  // Initialized speed to 0
                  circleOffsetY = 140

Setup:
Create Canvas(window.width, window.height);

function draw():
    render background (colour, opacity)
    render square (size, colour)

    // Simplified movement logic using speed variable
    if mouse is in frame & pressed:
        speed = 5  // Move right
    else if mouse is outside:
        speed = -5  // Move left
    else:
        speed = 0  // Stay in place

    circleX += speed  // Single update to circle position

    no stroke - fill
    render circle (circleX, height-heightOffset, 50)

// Note: This approach centralizes movement logic in the speed variable

Describing the conditions for position of mouse over and over in the code also was quite tedious so a function was created called inFrame, that would be called on when going through the conditionals. since calling on the function inFrame() would only check if its true, I learned that by adding an exclamation mark you can also check to see if the function is false.

Global Variables: circleX, speed = 0, height, width  // Initialized speed to 0
                  circleOffsetY = 140

// Function to check if mouse is within the frame
function inFrame():
    return mouseX >= 0 && mouseX <= width && mouseY >= 0 && mouseY <= height;

Setup:
    Create Canvas(window.width, window.height);

function draw():
    render background (colour, opacity)
    render square (size, colour)

    // Check if the mouse is in the frame or not
    if inFrame() && mouse is pressed:
        speed = 5  // Move right
    else if !inFrame():
        speed = -5  // Move left
    else:
        speed = 0  // Stay in place

    circleX += speed  // Single update to circle position

    no stroke - fill
    render circle (circleX, height - circleOffsetY, 50)

Code Implementation

Translating our pseudocode into P5.js, here's the core of our sketch:

// We set up global variales, here
let height;
let width;
let circleX;
let circleOffsetY;
let circleY;
let speed = 0;

function setup() {
  // since windowWidth and windowHeight are unavailable outside setup
  // we attribute them here
  height = windowHeight;
  width = windowWidth;
  circleX = width / 2;
  circleOffsetY = 140;
  circleY = height / 2 + circleOffsetY;
  // call on the global variables for height and width
  createCanvas(height, width);
}
// Intially I had written out the conditions for inFrame and outFrame seperately but I learned from Nik that if your conditions are Binary then you can declare them as a funciton and then just call on the true value of the function by refernecing it and then !function() to call on the false value this made my code cleaner and also much more succicnt 
function inFrame() {
  return mouseX > 0 && mouseX < width && mouseY > 0 && mouseY < height;
}

// this is our conditional that checks for the thing thats changing constantly which is speed or the position of change of the x cordinate of the circle 
function draw() {
  background(244, 242, 239);
  noStroke();
  fill(151, 169, 150);
  rect(0, (height * 3) / 4, width, height / 4);

  if (inFrame() && mouseIsPressed) {
    speed = 5;
  }  else if (!inFrame()){
    speed = -5;
    
  } else {
    
    speed = 0;
    
  }
  // this last part draws the circle over and over again based on the updated value of the x cordinate of the circle based on the conditional logice we have above 
  
  circleX += speed;
  noStroke();
  fill(238,136,56);
  circle(circleX,circleY,50)
}

Final Sketch

Final Sketch

References
  1. Nik's Blog
  2. Casey Neistat YouTube Channel

©2019-2025 SURYA NARREDDI.

©2019-2025 SURYA NARREDDI.