Week 3 – OOP

Concept:
This generative artwork was inspired by kaleidoscopes, with specific regard to the shifting patterns they display as you rotate it. I used the OOP principles we covered to make a Hexagon class and relevant properties/methods for it, and combined it with a 2D array to create multiple layers of hexagonal grids. I implemented randomness by randomly setting the colour and opacity of each hexagon, with the latter being constrained between 30 and 80 to allow for some clear overlap and blending between layers. I initially planned to have three layers, being controlled by mouse/arrows/wasd respectively, but I ended up scrapping the mouse movement since I liked the imagery of peeling back the upper two layers to reveal the remaining one, plus using keys allowed me to set a specific speed value instead of being at the whim of the cursor’s movement.

Highlight:

// // Fill a specified layer with hexagons
function fillLayer(index) {
  // // Loops to populate layer
  let offsetCol = false;
  for (let x = -(width/2); x < width*1.5; x += 1.5*hexSize) {
    for (let y = -(height/2); y < height*1.5; y += 2*hexSize) {
      // // Offset every other column --> interlocking pattern
      if (offsetCol && y === -(height/2)) {
        y += hexSize;
      }
      layers[index].push(new Hexagon(x, y, hexSize));
    }
    offsetCol = !offsetCol;
  }
}

Embed:

Reflection:
I’m pretty happy with how this piece turned out, in both the creative and programmatic aspects. I felt that I had a clear vision going in this time, and was able to actually realize it. My code itself was better contained after compartmentalizing and encapsulating into functions and methods, and I was successful in cutting down on needlessly making functions. On the creative side, I ran into a number of happy little accidents that ended up improving my end result, which was a breath of fresh air.

Despite this specific improvement, I still definitely need to plan things out more, since I found myself having to constantly readjust my code in order to deal with things like messing up the math for my hexagons or implementing the movement functionality with keyIsPressed() instead of keyIsDown().

Week 3 – Functions, Arrays, and Object-Oriented Programming

Concept

In this p5.js sketch, my main objective was to practice the use of classes and arrays. In my sketch, little objects called “walkers” wander randomly across the canvas, leaving behind the trail that slowly fades away. Each walker has its properties (see below in Code Highlight part), which are determined randomly at the moment of creation (user click).

Demo (Click on canvas)

Code Highlight:

The core of this sketch is the Walker class. It encapsulates everything each walker needs to function:

// Walker class definition
class Walker {
  constructor(x, y) {
    this.x = x;
    this.y = y;
    // Give each Walker a random color
    this.col = color(random(255), random(255), random(255));
    // Control how quickly it moves around
    this.stepSize = random(1, 3);
  }

  update() {
    // Randomly move the walker in x & y directions
    this.x += random(-this.stepSize, this.stepSize);
    this.y += random(-this.stepSize, this.stepSize);

    // Keep the walker within the canvas boundaries
    this.x = constrain(this.x, 0, width);
    this.y = constrain(this.y, 0, height);
  }

  show() {
    noStroke();
    fill(this.col);
    ellipse(this.x, this.y, 8, 8);
  }
}

Inside this class, the update() method adjusts the walker’s position in small random increments, while show() draws a small ellipse at its current location.

The background(0, 13) call in the draw() loop is also important because it uses transparency to slowly erase the walkers’ paths, creating the glowing trails of each walker (I think it looks kinda cool).

Reflection & Improvements for Future Work

First of all, it was really entertaining to watch each walker wander around, leaving a trail. By simply changing parameters like number of walkers, their step size, or fade value in the background, one could produce unique versions of this piece.

In the future, I would love to make sure that the walkers of the same color would interact with each other (mixing together and creating a bigger walker). Another interesting idea would be to incorporate music in this piece (maybe 90s like Jungle beat) -> this way each walker would change its size/movement speed/direction based on the song.

If one would think long enough, the possibilities for making this piece more immersive and dynamic are essentially limitless.

Maybe one could make a game out of this piece, who knows?

Reading Response 2 – What Exactly Is Interactivity? (Week 3)

Chris Crawford’s idea of interactivity as a conversation between two participants came as a novelty to me. Before reading this, I assumed that any program that reacted to user input was interactive in its nature, but after reading this I was convinced that an interactive system must possess these three elements; listening, thinking and responding/speaking. 

I feel like Crawford’s example of the refrigerator light was brilliant, it made me rethink what it means for a system to be truly interactive. I began examining the apps and websites I use every day and noticed that many of them only react to user input without actually processing information in a meaningful way. They operate on predefined rules, responding to clicks and taps but not truly engaging with the user. This made me question whether these systems, despite their responsiveness, can really be considered interactive in the way Crawford describes. 

This reading also made me reflect on how I can make my own p5 sketches feel more interactive. Right now, they mostly respond to simple inputs like mouse clicks, but what if I could design interactions that feel more like a two-way conversation?

Instead of just reacting instantly, the system could analyze patterns in user input, adapt its responses based on context, or even introduce an element of unpredictability to keep the interaction dynamic. For example, it could recognize different drawing styles over time and subtly adjust its behavior to match the user’s preferences. Of course, achieving this level of interactivity would likely require more advanced tools than p5.js (Maybe use of LLMs/AI).

I would love to create something beyond basic cause-and-effect responses and explore ways to create a more engaging.

Week 2 – Reading response

How are you planning to incorporate random elements into your work?

Well, I myself have am not used to the idea of producing something random, although there is beauty in the idea of randomness it’s not as alluring as the idea of systematic approach. When it’s random, it’s likely only to be produced once like that and twice if you can beat the odds. Although Casey, with in the video showed how these random elements can prove to not only provide an unique appearance, he also presents its limitations on how once done can’t be done agin, the idea of having to repeat a process to hopefully create something similar can be infuriating, but also fascinating as the random elements could go beyond expectation or never reach the expectations sent. I intend to incorporate this kind of thinking into future works, I might not be happy in the beginning due to my rigid thinking but over time I could change and will change in how to balance the randomness that can only produced once and the control of the scope in which it happens.

Where do you feel is the optimum balance between total randomness and complete control?

I think that when theres a start of a systematic approach too randomness. All randomness has to be born with in a confined space, whether by the laws of science that govern the way things move or how systems have an algorithm that will produce a random sequence based off the a equation thats been written before hand. You can’t escape, it but you can confine it with in a space. Like a science experiment you might have the tools, and test it out and then an outcome that works. You have your controlled variables and uncontrolled variables. Sometimes we are the uncontrolled variables but our way of thinking is the controlled variable. The way we move and do things, the laws of the universe these are controlled, set in stone in that moment, but once we release it without being able to calculate or speculate the outcome it then becomes random.

Week 2 Assignment

Introduction:

While looking through the same art, I thought that its actually far from what I could create at least at this point. I wanted it to simple yet something that reminds me of home. I ended up then thinking about what makes home, home? Was it the people that I missed? Was it the seas and mountains? Was it the seasons? Well, it was a bit of everything, the way the mountain changed its vegetation across the seasons, the way I’d travel to those mountains with those very precious people. The way the seasons or the feel of the seasons could not be replicated here with in the UAE.

Concept:

My concept for the post had to do with mountains and seasons. The reflection on something not season as clearly or with in the country as abundantly as my own country. I didn’t really use any references from the document but it’s essence rather gave me something I’d rather implement.

 

Production and Completion:

Although I had to go through many trials, like getting the color scheme, the clouds, the sun and moon, the mountains, as well as the time switch to show the seasons. I wasn’t satisfied, because I had a dream of how it should have made me felt. I hadn’t gotten close but I had gotten somewhere, starting with what can represent the seasons? the time? The way things change. If you look at the code you will notice that the frame rate changes at about every 3 seconds like the months. The sun changes into the after 1.6 seconds and the moon to the sun at 0.8 seconds, match 16 hours of sun and 8 hours of moon.

 

let sunAngle = 0;
let showMoon = false;
let seasonProgress = 0;
let currentSeason = "spring";
let mountainProgress = 0;
let seasons = ["spring", "summer", "autumn", "winter"];
let brushColors;
let icons = [];
let clouds = [];

function setup() {
    createCanvas(800, 600);
    brushColors = [
        color(139, 69, 19),  // Brown (Autumn)
        color(34, 139, 34),  // Green (Spring)
        color(255, 165, 0),  // Yellow-orange (Summer)
        color(173, 216, 230) // **Distinctive icy blue for Winter**
    ];
    frameRate(30);
    generateIcons();
    generateClouds();
}

function draw() {
    if (currentSeason === "spring") {
        background(144, 238, 144);
    } else if (currentSeason === "summer") {
        background(255, 223, 186);
    } else if (currentSeason === "autumn") {
        background(255, 165, 0);
    } else if (currentSeason === "winter") {
        background(100, 150, 200); // **Deeper Frost Blue for Winter**
    }

    drawMountain();
    drawClouds();
    if (!showMoon) {
        drawSun();
    } else {
        drawMoon();
    }
    displayIcons();
    updateIcons();
    updateClouds();

    if (frameCount % 90 === 0) {
        changeSeason();
        generateIcons();
    }
}

function drawMountain() {
    let layerHeight = 50;
    let numLayers = 6;
    for (let i = 0; i < numLayers; i++) {
        let layerColor = getMountainColor(i);
        stroke(layerColor);
        strokeWeight(15 + (sin(mountainProgress + i * 0.5) * 5));
        noFill();
        beginShape();
        for (let x = 0; x < width; x++) {
            let y = sin(x * 0.02 + mountainProgress + i * 0.5) * (100 + i * layerHeight) + 400;
            vertex(x, y);
        }
        endShape();
    }
    mountainProgress += 0.02;
}

function getMountainColor(layerIndex) {
    let seasonIndex = seasons.indexOf(currentSeason);
    if (currentSeason === "spring") {
        return lerpColor(brushColors[1], color(255, 255, 255), layerIndex * 0.1);
    } else if (currentSeason === "summer") {
        return lerpColor(brushColors[2], color(255, 255, 255), layerIndex * 0.1);
    } else if (currentSeason === "autumn") {
        return lerpColor(brushColors[0], color(255, 255, 255), layerIndex * 0.1);
    } else if (currentSeason === "winter") {
        return lerpColor(brushColors[3], color(255, 255, 255), layerIndex * 0.2); // **Stronger white contrast for winter**
    }
}

function drawSun() {
    fill(255, 204, 0, 150);
    noStroke();
    let size = 100 + sin(sunAngle) * 30;
    ellipse(650, 100, size, size);
    sunAngle += 0.02;

    if (sunAngle > TWO_PI) {
        sunAngle = 0;
        showMoon = true;
    }
}

function drawMoon() {
    let moonSize = map(sin(frameCount * 0.1), -1, 1, 50, 100);
    fill(255, 255, 255, 150);
    noStroke();
    ellipse(650, 100, moonSize, moonSize);
    if (frameCount % 24 === 0) {
        showMoon = false;
    }
}

function changeSeason() {
    let nextSeasonIndex = (seasons.indexOf(currentSeason) + 1) % seasons.length;
    currentSeason = seasons[nextSeasonIndex];
    generateClouds();
}

function generateIcons() {
    icons = [];
    let iconSymbol = "";
    if (currentSeason === "spring") {
        iconSymbol = "🌸";
    } else if (currentSeason === "summer") {
        iconSymbol = "☀️";
    } else if (currentSeason === "autumn") {
        iconSymbol = "🍂";
    } else if (currentSeason === "winter") {
        iconSymbol = "❄️";
    }
    for (let i = 0; i < 5; i++) {
        icons.push({
            x: random(width),
            y: random(100, 300),
            speed: random(0.2, 0.5),
            symbol: iconSymbol
        });
    }
}

function updateIcons() {
    for (let icon of icons) {
        icon.y += icon.speed;
        if (icon.y > height) {
            icon.y = random(100, 300);
        }
    }
}

function displayIcons() {
    textSize(32);
    textAlign(CENTER, CENTER);
    for (let icon of icons) {
        text(icon.symbol, icon.x, icon.y);
    }
}

function generateClouds() {
    clouds = [];
    for (let i = 0; i < 6; i++) {
        clouds.push({
            x: random(width),
            y: random(50, 200),
            size: random(60, 100),
            opacity: random(100, 200),
            speed: random(0.5, 1.5)
        });
    }
}

function drawClouds() {
    for (let cloud of clouds) {
        fill(255, 255, 255, cloud.opacity);
        noStroke();
        ellipse(cloud.x, cloud.y, cloud.size, cloud.size * 0.6);
        ellipse(cloud.x + 30, cloud.y, cloud.size * 0.8, cloud.size * 0.5);
        ellipse(cloud.x - 30, cloud.y, cloud.size * 0.9, cloud.size * 0.6);
    }
}

function updateClouds() {
    for (let cloud of clouds) {
        cloud.x += cloud.speed;
        cloud.size += sin(frameCount * 0.01) * 0.5;
        cloud.opacity = map(sin(frameCount * 0.01), -1, 1, 100, 200);
        if (cloud.x > width + 50) {
            cloud.x = -50;
            cloud.y = random(50, 200);
        }
    }
}

Sketch:

Improvements:

I think I can improve a lot with more dynamic visuals and smoother transitions. I will try to include more user interaction that can allow them to do more than just have a ‘watch’ experience. They should be able to have ‘active’ experience as a participant. I could include sounds that mimic the ambiance achieved in  places in South African to make it further immersive.

 

Reading Reflection: Week #3

In “The Art of Interactive Design” interactivity is defined as “a cyclic process in which two actors alternately listen, think, and speak”.  This approach suggests that the quality of interaction depends on the effectiveness of each subtask. It seems to me then that a strongly interactive system is great in perceiving input, processing it meaningfully, and providing feedback right on time, creating a conversation between user and system.

In my opinion, to create a better user interaction involvement, the artist should be designing elements that not only react to user inputs but also adapt and evolve based on user behavior. For example, incorporating real-time feedback mechanisms can make the interaction feel more engaging.

Apart from that, allowing for user customization and providing clear and simple visual cues can guide users through the interactive experience. This aligns with Crawford’s vision of interactive design as an art form creating meaningful digital exchanges, where the interaction feels like a real conversation between the user and the digital environment.

Week 2 – Reading Response

After watching Casey Reas talk about randomness, it got me thinking about how I usually approach design. When working I’ve always been about control, and making sure every element has a purpose and fits just right. But Reas kind of pushed me to reflect on how it’s not about giving up control but rather just letting a little unpredictability into the process to keep things from becoming flat and boring. When things are too ordered, they lose their spark and this idea made me realize that maybe I’ve been too focused on precision and could benefit from creating space for randomness to breathe a little life into the work im making. I’m now thinking of ways to incorporate small random elements, like little shifts in color, shape, or spacing, so that my designs feel alive without losing the structured feel I love.

As for the balance between randomness and control, I think it’s about finding that perfect place where the two can interact with each other.  Things that are too rigid can become very static, while too much randomness can feel directionless. In my opinion the perfect balance happens when you have a solid structure but let randomness subtly influence the details. Whether it’s adjusting spacing, throwing in a surprise texture, or letting a color shift unexpectedly, it makes the work feel slightly more dynamic. The goal isn’t to pick one or the other but to let control and randomness work together to create something that keeps the viewer engaged and constantly evolving.

Week 2 – Reading Reflections

The talk by Casey was truly enlightening. His opening remarks about artists and designers being the key players in maintaining order in today’s society—after the chaos (the Big Bang) that led to our creation—really struck me. The rendered animations had an element of randomness to them, but unlike the art where pieces of paper were dropped onto the floor, or the machine that caught fire (intended to destroy itself), these were post-World War demonstrations by the artist. However, hidden within that seemingly destructive surface was an element of randomness, which is what made it so interesting. Once computing became feasible, algorithmic works like those of Keith Tyson could be visualized and fabricated. Whether it’s the ‘role the dice’ algorithm or something of that sort, I believe art cannot truly exist without interpretive bias, complemented by mistakes and uncertainties. This also reminded me of how some painters splash buckets of paint onto the canvas to sometimes set the foundation for their work.

How are you planning to incorporate random elements into your work?

I’m passionate about creating practical solutions—solutions that not only integrate into existing fields but also introduce entirely new possibilities. The word ‘random’ itself is open to interpretation, but in my view, it’s a mix of an artist’s little inattentiveness and human uncertainties. Like I did in this week’s assignment, where I used random color selection, I plan to incorporate different mapping functions that produce unexpected results. It’s true that the internal ‘random’ function built into most programming languages isn’t entirely random, but the influence of the programmer’s choices still adds a layer of uncertainty. Much like Casey, I want the numerical models that form the foundation of my program and its elements to remain random and stay that way. In life, randomness doesn’t equate to mess—it’s simply how things work. The animation Game of Life also visualizes this phenomenon. So, my plan is to innovate artistically while still maintaining a degree of control, such as setting certain parameters.

Where do you feel is the optimum balance between total randomness and complete control?

I believe the balance is subjective and depends on the context. For works that involve transformation and less precision, it’s often better to let things spin out of control. The variation not only eliminates some of the artist’s personal bias, but it also allows for new ideas and inspirations to emerge when the art ‘flows.’ That said, there are also scenarios where the information being used is constrained to specific parameters, and in these cases, the balance depends on the context and how much ‘variance’ is considered acceptable.

Week 2

Concept

This sketch explores the interaction between two screen squares, incorporating movement and “emotional” behavior. The squares are initially placed randomly on the canvas, and they shrink and change color when they overlap, representing a form of “embarrassment.” The goal is to create a simple yet dynamic visual experience where the squares react to user interaction (mouse clicks) and their proximity. When clicked, the squares move toward the mouse position, and if they get too close, they start shrinking and changing color. This sketch is an experiment with combining basic geometric shapes and dynamic behavior in p5.js.

Code Highlight

One section of code I’m particularly proud of is the implementation of the shrink-and-color-change behavior. Here’s the part where the squares react when they “feel embarrassed”:

 

// Check for "embarrassment" (if squares overlap)
let distance = dist(square1.x, square1.y, square2.x, square2.y);
if (distance < (square1.size / 2 + square2.size / 2)) {
  square1.shrink = true;
  square2.shrink = true;
}

// If embarrassed, shrink and change color
if (square1.shrink) {
  square1.size -= 0.5;
  square1.color = color(random(255), random(255), random(255)); // Random color
  if (square1.size < 10) {
    square1.shrink = false; // Start over
    square1.size = 50; // Reset size
  }
}

if (square2.shrink) {
  square2.size -= 0.5;
  square2.color = color(random(255), random(255), random(255)); // Random color
  if (square2.size < 10) {
    square2.shrink = false; // Start over
    square2.size = 50; // Reset size
  }
}

 This logic triggers the shrinking and color change when the distance between the two squares becomes small enough (i.e., they overlap). It creates a fun dynamic where the squares seem to react in real time, making the sketch feel more alive.

Embedded Sketch

You can view and interact with the sketch directly in the p5.js editor, or here’s an embedded link to the live sketch:

Reflection and Future Work

This project started with a simple concept of square interaction, but it quickly became more dynamic by adding emotional “reactions” like shrinking and changing color. The interaction of movement toward the mouse creates an element of control, while the “embarrassment” response adds unpredictability.

For future improvements, I’d consider the following:

  1. Adding sound effects to accompany the “embarrassment” reaction, like a shriek or a sound that corresponds with the color change. This would enhance the multisensory aspect of the experience.
  2. More complex behaviors: Perhaps, when the squares get too small, they could “reproduce” into smaller squares, creating a chain reaction, or they could break apart into multiple pieces.
  3. Interactivity: Instead of just reacting to the mouse, I could add additional interaction methods, such as keyboard inputs or random events that change the behavior of the squares.
  4. Visual effects: Adding gradient colors or animations when the squares change could make the transition smoother and more visually engaging.

This sketch could evolve into a larger concept where geometric shapes and their “emotions” become central to the user interaction, possibly forming the foundation of a game or interactive artwork.

Week 2 – Reading Reflection

One thing that stood out to me from the video was how randomness can be used to generate complexity. Casey talked about how simple rules together with random elements, can give results that feel natural and unexpected. I personally like using randomness in my work because it makes things feel more natural, rather than too structured or predictable. I also found it  interesting how randomness isn’t just about making things look chaotic—it actually reflects real-life patterns from the biological to the mathematical world. Just like in nature, nothing is perfectly placed, and randomness can help simulate that. However, I believe it is best to allow randomness to do its thing in artwork but while still maintaining some control over the whole structure to some extent. Having control or knowledge over art makes me feel more connected to the final structure.  If everything is completely random, it can feel messy, but if there’s no randomness at all, it feels artificial. I choose to settle for balance between the two . A great example Casey mentioned was a piece that incorporated randomness but became more structured when symmetry was introduced. This showed how even a small amount of control can bring order to something that initially seems chaotic. 

Another point that resonated with me was on the use of random numbers in art. He mentioned how random numbers can serve as a tool to introduce variation, but they also rely on a system of rules to guide the outcome. Without some guiding principles, the randomness would lose its purpose. I think this aligns with my approach to using randomness in my work—it’s not just about throwing chaos into the mix, but about using it in a controlled way to show creativity while still achieving a somewhat desired result. In my week two project, I was able to maintain order for the most part of the artwork, while also adding randomness in aspects like the color choices.