Assignment Week 08: Unusual Switch ft Aloevera

Concept:
The idea for creating an unusual switch with my arm actually struck me while I was at the gym. As I was practicing with dumbbells, I thought, “Why not use the motion of my arm to activate a switch?” When I was doing bicep curls — you know, the exercise where you pull the dumbbells up toward your shoulders, maybe called as bicep curls— it clicked. I needed some conductors that could connect the wires and pass electricity when my arm moved upward. I initially thought of using aluminum foil, but that felt too common. I wanted to do something different, so I decided to go with aloe vera gel instead. It seemed like a more unique choice, and I was curious to see how well it would conduct electricity.

Hardware Used:

  • Arduino
  • LED
  • 330 ohm resistor
  • Jumper wires
  • Breadboard
  • Aloe vera gel (as a conductor)
  • Aluminum foil (optional, used for wrapping, but didn’t use)
  • Glue to attach the aloe vera slices with a decorative plant that can be wrapped around my arm

Process:

  1. Prepare the Aloe Vera Gel: I first applied some aloe vera gel to the inside of my elbow, creating a path for electricity when my arm bends during the bicep curl motion. This would serve as a conductor, allowing the current to flow when I made contact. But, it did not work. So, I used this decorative plant to wrap my arm and put the aloe vera slices glued on to it.
  2. Set Up the LED Circuit:
    • I placed the LED on the breadboard, with the shorter leg (cathode) on one row and the longer leg (anode) on another.
    • I connected a 330 ohm resistor to the same row as the shorter leg of the LED. The other end of the resistor was connected to one of the Arduino’s GND pins.
    • Then, I took a jumper wire and connected the row with the longer leg of the LED (anode) to digital pin 13 on the Arduino.
  3. Integrate the Aloe Vera Gel as the Switch:
    • I connected a jumper wire from the Arduino’s 5V pin to one piece of aloe vera that was in contact with my elbow.
    • Another jumper wire went from the same piece of aloe vera to pin 2 on the Arduino (set up as an input pin).
    • I then placed the second piece of aloe vera on the outer part of my elbow, completing the circuit when my arm was bent.
  4. Coding the Arduino:
    • In the code, I used digitalRead() to check if there was a connection between the two pieces of aloe vera (when the gel completed the circuit during the bicep curl).
    • If the circuit was closed, the LED would turn on. When I relaxed my arm, breaking the connection, the LED would turn off.
  5. Testing: I tried different amounts of aloe vera gel and even experimented with wrapping aluminum foil around the gel for better conductivity. Eventually, I found a sweet spot where the gel was conductive enough to switch the LED on and off based on my arm movement.

Pictures From The Process:

The circuit:
This is the circuit with aloe vera slices and decor plant  on my arm.

 

Unfortunately, the decor plant did not work properly. So, I used a black rope ( does not look good) to tie aloe vera with my arm directly. Here is the final one!

 

Video of the switch:

Reflection and Future Implementation:

  1. Need to find a way to adjust the aloe vera properly on my arm as I tried to use glue on a decor plant which did not work and gave me burning sensation  on my elbow area instead.
  2. Overall, I find it amusing to work with aloe vera and electronics. It was fun!

 

 

 

Reading Response: Week 08

I began my reading with the piece about Margaret Hamilton, feeling a strong curiosity to learn more about her. It resonated deeply when she mentioned being “one of the guys,” as it reminded me of how, in many cultures, there is a stereotype that only men excel in mathematics, coding, and engineering. When a woman shows talent in these fields, it is often seen as “unusual.” Her story was truly inspiring, highlighting not only her achievements but also the consistency and persistence that made her a role model in engineering. Even though it’s not the first time I’ve encountered gender disparity in STEM, her approach to tackling “imposter syndrome”—which I believe many women in STEM have faced—was a particularly powerful lesson. It’s a reminder to everyone, regardless of gender, to stay focused on their goals and remain committed to what they want to achieve. Her story also brought to mind the movie *Hidden Figures*, which is a great watch for anyone interested in the experiences of women in STEM.

For the second reading, I’ve been brainstorming ideas related to cognitive science and human adaptability. This reading showed how design, when informed by cognitive science, can significantly impact our experiences. For instance, when I visit stores like Miniso, I often find myself drawn to items that are aesthetically pleasing and easy to use. Of course, the definition of “aesthetic” may vary from person to person; for me, it means a sleek, minimal design with soothing colors and user-friendly features. While aesthetic preferences differ, there must be some fundamental principles that apply to everyone. In this context, it’s important to explore the concept of affect and design to understand how we shape our environments and how these designs impact our daily lives. Striking a balance between beauty and usability is indeed the key factor in innovating effective designs and products.

Midterm Project

Concept and Inspiration:

I wanted to share the inspiration behind my game. It all started when I delved into the captivating world of folklore, specifically the stories of Sindbad the Sailor and Behula from Bangladeshi culture. Sindbad’s adventurous spirit, sailing through the vast oceans, I mean, who doesn’t love a good tale of adventure on the high seas?

Then there’s Behula, a fierce and determined woman who braves the ocean’s challenges to bring back her husband. Her journey is filled with trials and tribulations, showcasing strength, love, and resilience. These stories are so rich and deep, and I wanted to weave that essence into my game.

As I started to brainstorm, I thought, “Why not create a surfer game set against this backdrop?” The ocean is such a dynamic environment, and surfing adds an exciting twist. I wanted to capture the thrill of riding the waves while subtly nodding to these legendary tales.

Of course, I realized that not everyone might connect with the heavier themes of folklore, especially younger audiences. So, I decided to give the game a fun, cartoonish vibe. This way, it can appeal to all ages while still honoring those timeless stories. It’s all about adventure, overcoming challenges, and having a great time on the waves!

Code Explanation:

In my game, I’ve focused on creating an engaging surfing experience, and the wave mechanics play a crucial role in bringing that to life. There are some key elects that I would like to mention, especially how I generate those smooth, dynamic waves that define the gameplay.

1. Wave Creation

One of the standout features of my game is how I create the waves. I use a combination of beginShape() and endShape()to draw the wave’s outline:

beginShape();
let xOffset = waveXOffset;
for (let x = 0; x <= width; x += 10) {
    let y = map(noise(xOffset, yOffset), 0, 1, height / 2 - waveAmplitude, height / 2 + waveAmplitude);
    vertex(x, y);
    xOffset += waveFrequency;
}
endShape(CLOSE);
  • Creating Vertex Points: Inside this loop, I utilize the vertex() function to establish a series of points that define the wave’s shape. By iterating across the entire width of the canvas, I can create a flowing wave profile that enhances the surfing experience.
  • Using Perlin Noise: The magic happens with the noise() function. I chose Perlin noise because it generates smooth, natural variations, making the waves look more realistic. Unlike random values that can create jarring changes, Perlin noise ensures that the wave transitions are fluid, which adds to the game’s aesthetic appeal.
  • Mapping Values: I then use the map() function to rescale the noise output, allowing me to set the wave height within specific bounds. By centering the waves around the middle of the canvas (height / 2), I ensure they oscillate up and down, making the gameplay more visually engaging.2.

    2. Player Interaction with Waves

    The way the waves interact with the swimmer is equally important. I calculate the wave’s height and adjust the swimmer’s position accordingly:

    if (isJumping) {
        verticalVelocity += gravity;
        swimmerY += verticalVelocity;
        if (swimmerY >= waveY - swimmerHeight / 2) {
            swimmerY = waveY - swimmerHeight / 2;
            isJumping = false;
            verticalVelocity = 0;
        }
    } else {
        swimmerY = waveY - swimmerHeight / 2;
    }
    • Jump Mechanics: I implement a jumping mechanic where the swimmer’s vertical position changes based on gravity and jump forces. When the swimmer is in the air, I adjust their position based on the wave height, allowing them to ride the wave realistically.
    • Wave Height Adjustment: By ensuring the swimmer’s position is linked to the wave’s current height, I can create a seamless experience where the player feels like they are truly surfing on the waves.3. Window Resizing and Obstacles: 
      • The windowResized() function allows the canvas to resize dynamically if the window size changes, maintaining the game’s responsiveness.
        • Instantiation of Obstacles: Every time spawnObstacle() is called, a new instance of the Obstacle class is created and added to the obstacles array. This ensures that there are multiple obstacles on the screen for players to avoid, making the gameplay more challenging.
        • Continuous Challenge: By calling this function regularly within the main game loop (in the playGame function), I ensure that obstacles keep appearing as the player progresses. This continuous spawning simulates a moving ocean environment, where new challenges arise as players navigate the waves.
        • P5.js Sketch:

      Features  and Game Mechanics:

      • The game kicks off with an engaging start screen featuring the title “Surfer Game”, inviting players to click to begin their surfing.
      • Players control a lively surfer character using intuitive keyboard commands, specifically the spacebar to jump over incoming obstacles like sharks, enhancing the gameplay’s interactivity.
      • As players navigate through the waves, they encounter a dynamic wave system that adjusts in amplitude and frequency, creating a realistic surfing experience. This effect is achieved through Perlin noise, giving the waves a smooth, natural movement.
      • Collectible coins are scattered throughout the waves, adding an exciting layer of challenge. When the player collides with a coin, it disappears, contributing to the score, which is displayed on the screen.
      • The game includes a health mechanic where if the surfer collides with an obstacle, such as a shark, the game transitions to a “Game Over” state, prompting players to either restart or return to the main menu.
      • Upon reaching specific milestones, such as collecting a set number of coins, players are rewarded with a “Level Up” screen that highlights their achievements and encourages them to continue.
      • Players can easily restart the game after it ends by clicking anywhere on the screen, offering a seamless transition between attempts.

      Additional AudioVisual:

      • Sound effects enhance the immersive experience, with cheerful tunes playing when coins are collected and exciting sound bites when the surfer jumps over obstacles.
      • Background music plays continuously throughout the game, creating an engaging atmosphere. Players can enjoy a unique soundtrack that fits the theme of the game, enriching their adventure.
      • The graphics have a cartoonish style, making it appealing for all age groups while still paying homage to the folklore inspirations behind the game.

Reflection and Challenges

When I first set out to create a game, my vision was to develop something based on neuroscience, exploring complex concepts in an engaging way. However, as I delved deeper into that idea, I realized it was more challenging than I anticipated. I then pivoted to creating a 2048 game, but that also didn’t quite hit the mark for me. I felt it lacked the excitement needed to captivate players of all ages.

This experience taught me a valuable lesson: sometimes, taking a step back can provide clarity. Rather than getting bogged down in intricate designs, I opted for a simpler concept that would appeal to a wider audience. Thus, I decided to create an ocean-themed surfing game, inspired by folklore like Sindbad the Sailor and the tale of Behula from Bangladeshi culture.

I see a lot of potential for upgrading this game. Adding a storyline could further engage young players and introduce them to fascinating narratives from folklore. Additionally, I plan to enhance the wave mechanics by incorporating realistic gravity effects, making the surfing experience more immersive. These improvements could really elevate the gameplay and provide an enjoyable adventure for everyone.

Week 05: Midterm Initial Project

Concept :

I’ve always found the brain fascinating, especially how neurons fire and communicate. It’s like this intricate dance of connections that sparks thoughts and actions. Interestingly, voices also make our neurons fire. So, I thought, why not combine that with a game I love? I decided to merge the concept of neuron firing with the mechanics of the classic 2048 game.

Instead of numbers merging, it’s all about neurons connecting and lighting up, almost like a visual representation of a neural network in action. It’s exciting to see how each move can mimic real-life brain activity. The main goal is to keep merging neurons to reach the ultimate neuron—represented as a “Super Neuron”—while continuously creating connections to maintain an active and vibrant neural network. Players can aim for high scores, challenging themselves to beat their previous records or compete with others.

 

Game Design: 

The main goal of the game is to keep building neuron connections. Among all the neuron like particles, there are some target particles (super neuron) that are shown as neuron spark. Player needs to click on the glowing/target particle to create a connection with sparking neuron and the neurons near the area. The neurons merges and more connections keeps building as apart of the simulation. If the player is able to make 05 connections, the player will pass the level.

Codes I’m Proud of: 

Still, the code is in a beginning level and requires lots of modifications to finish the game. The first thing I liked is how the neurons look like which I created using particles as function.

// Start simulation with neurons
function startSimulation() {
  background(0);
  orbitControl();  // Allow mouse control to rotate

  // Analyze the audio amplitude and spectrum
  let spectrum = fft.analyze();
  let level = amp.getLevel();

  // Set lighting
  ambientLight(20, 20, 30);
  pointLight(255, 255, 255, 0, 0, 300);

  // Slowly rotate the scene
  rotateY(frameCount * 0.001);
  rotateX(frameCount * 0.0015);

  // Draw neurons (with sparkle effect)
  for (let i = 0; i < particles.length; i++) {
    let p = particles[i];
    p.move(level);
    p.display();
    
    // Draw lines between nearby particles (neurons)
    for (let j = i + 1; j < particles.length; j++) {
      let d = dist(p.pos.x, p.pos.y, p.pos.z, particles[j].pos.x, particles[j].pos.y, particles[j].pos.z);
      if (d < 120) {
        strokeWeight(map(d, 0, 120, 4, 0.1));
        stroke(150, 150, 255);
        line(p.pos.x, p.pos.y, p.pos.z, particles[j].pos.x, particles[j].pos.y, particles[j].pos.z);
      }
    }
  }

  // Draw the target particle (glowing neuron)
  targetParticle.move();
  targetParticle.display();
  
  // Handle interactions with the target particle
  if (mouseIsPressed) {
    let d = dist(targetParticle.pos.x, targetParticle.pos.y, targetParticle.pos.z, mouseX - width / 2, mouseY - height / 2, 0);
    if (d < 50) {
      fireNeurons();
      connectToNearestNeuron();  // Connect the glowing neuron to the nearest neuron
      score++;  // Increase score when a neuron is clicked
    }
  }

I also tried to make the particles change positions according to the audio amplitude.

fft = new p5.FFT();
amp = new p5.Amplitude();

// Analyze the audio amplitude and spectrum
let spectrum = fft.analyze();
let level = amp.getLevel();

I tried to implement another  cool feature that creates dynamic connections between neurons when they come near each other. This mimics real neural networks and adds a layer of interaction. But, the code might have some flaws.

// Draw lines between nearby particles (neurons)
for (let j = i + 1; j < particles.length; j++) {
  let d = dist(p.pos.x, p.pos.y, p.pos.z, particles[j].pos.x, particles[j].pos.y, particles[j].pos.z);
  if (d < 120) {
    strokeWeight(map(d, 0, 120, 4, 0.1));
    stroke(150, 150, 255);
    line(p.pos.x, p.pos.y, p.pos.z, particles[j].pos.x, particles[j].pos.y, particles[j].pos.z);
  }
}

P5.js Sketch:

Future Works:

  • Need to find a proper background with the name visible for players.
  • Need to add descriptions on the Read part and fix the settings on the Settings Page.
  • Regarding the game design part, it requires to fix the game mechanics as the game flow is not implemented yet.
  • Need to monitor the performance and use techniques like frame rate. 
  • Need to work on the sound. Create a sound experience that reacts dynamically to what’s happening in the game. For example, as neurons connect, the music could change in tempo or complexity

Reading Reflection: Week 05

I read about Myron Kruger’s “Videoplace” from another article and I think Myron W Krueger’s philosophical approach to make an interaction between Arts and Computer Science is a pioneering idea in the 60’s that made him a first generation virtual reality and augmented reality researcher. His examples of creating art on the hands of his friend and visual aesthetics reminded me of the times when I used to draw just lines and patterns on the “Paint” software of windows computer and sometimes it would come out pretty aesthetically, but he took this simple idea to generate something out of the box. From this paper, as I read more about the VIDEOPLACE, I felt it was more advanced than the technologies of that time and surely created a path for today’s AR and VR tech. I felt this paper works as a stepping stone for students interested in Computer Vision and Artificial Intelligence.

I also felt very curious to know more about Messa di Voce, created by Golan Levin in collaboration with Zachary Lieberman. The concept of what can be done in the field of Human-Computer Interaction expanded more through this project. Previously, image or pattern recognition would come to my mind while talking about HCI, but now I see how our voice, can be an excellent element for interacting with audiovisual installations. I agree on the fact that algorithms play a key role in this field and I wonder do we all need to keep rebuilding new algorithms to explore more opportunities in HCI? The idea of building machine vision techniques “from first principles” resonates with my desire to understand how these systems work under the hood. While many environments provide off-the-shelf solutions, the challenge of implementing vision algorithms from scratch seems like a rewarding process that deepens one’s understanding of the mechanics of vision systems.

After reading this paper, I want to explore how vision-based systems can interact with audio, visuals, and physical devices to create immersive, interactive experiences. Tools like Myron, Rozin’s TrackThemColors, and especially Max/MSP/Jitter with CV.Jit seem like powerful platforms for experimenting with art and performance which I haven’t used till now.

Reading Reflection: Week 04

From the readings, when I came across the issues with door handling, it immediately reminded me of the doors at NYUAD, especially in D2. They’re supposed to be semi-automatic with sensors, but I often find myself having to pull them with all my strength just to get them to open. It’s incredibly frustrating, especially when I’m carrying something heavy or have my hands full. Struggling with these doors can be really annoying.

What really drives me crazy is that we live in a world that talks about inclusivity and accessibility, yet my own university isn’t fully disability-friendly. I can’t understand how a person in a wheelchair can access the dining halls when the doors require someone else to pull them open. Drawing from Don Norman’s ideas, I really connect with his emphasis on human-centered design to create better usability. He points out that “Engineers are trained to think logically,” which is something I’ve noticed over the years. However, I believe there’s been a shift in recent times.

As someone aspiring to be an engineer, I resonate with this statement. We often focus more on mathematical modeling rather than on accessibility and the psychological aspects of human behavior. Many engineering projects—like billboards and airport dashboards—do help by displaying information clearly, but they often overlook people with dyslexia. For example, using fonts like Sansa can make reading difficult for them.

Norman also talks about cognitive load, which refers to the mental effort required to use a device. In our fast-paced world, having a high cognitive load can be overwhelming. Take, for instance, a multifunctional printer with tons of buttons and features. If I have to remember multiple steps just to print a document, it can be exhausting. A better design would simplify the process, reducing the steps and making controls more intuitive. This aligns perfectly with Norman’s argument that good design should minimize cognitive load, letting users focus on their tasks instead of trying to figure out how to use the device.

Overall, this reading has been the most enlightening for me in the past four weeks.

Week 04: Data Visualisation

Inspiration:

As someone who believes in the transformative power of data visualization, I see it as an essential tool for making complex information accessible and understandable. Visualizing data allows us to grasp patterns, trends, and insights that would otherwise remain hidden in raw numbers. In the context of healthcare, especially with something as critical as blood pressure, effective visualization can significantly impact how we interpret and respond to health data.

One of my inspirations for this project comes from the recent work of renowned data artist, Giorgia Lupi, a renowned information designer known for her innovative approach to data visualization. I loved how she turned data visualisation in an artistic human connector engaging us with tales, emotions, informations through data.

Concept: The blood pressure dataset, originally from Stata, serves as a crucial resource for understanding the impacts of various factors on blood pressure among different demographic groups. I have taken the dataset from the Github Open Source For Data Science account. The idea came into my mind after remembering how blood pressure runs into families and sometimes we don’t care about it. Though the dataset is pretty small and not too complex, I enjoyed creating a visualisation for the first time.

Codes which I’m proud of:

I had trouble with managing datasets so I used the console.log technique that we learned in the class to check if  the CSV data loads correctly before any processing occurs or not. This is crucial because if the data is not available, the subsequent calculations will fail. I created two charts as the dataset had more columns, so I made two error handling for each chart.

    function preload() {
    data = loadTable('blood_pressure.csv', 'csv', 'header');
}

else {
        console.error("Data not loaded properly"); // Error handling if data isn't loaded
    }

I couldn’t find it possible nto fit the data in one chart. To make it easy to understand I created two charts which are connected based on the parameters. Here is the snippet for dynamically creating two separate charts for age and sex while keeping the layout clear. It required careful organization of data and chart settings.

function createAgeGroupChart() {
    const ageGroups = {}; // Object to hold blood pressure data by age group
    
    // Ensure the data is loaded
    if (data) {
        // Iterate through each row of data
        data.rows.forEach(row => {
            const agegrp = row.getString('agegrp'); // Get age group
            const bp_before = row.getNum('bp_before'); // Get blood pressure before
            const bp_after = row.getNum('bp_after'); // Get blood pressure after

            // Initialize arrays for this age group if it doesn't exist
            if (!ageGroups[agegrp]) {
                ageGroups[agegrp] = { before: [], after: [] };
            }
            // Add blood pressure data to the respective arrays
            ageGroups[agegrp].before.push(bp_before);
            ageGroups[agegrp].after.push(bp_after);
        });

        // Extract labels and average values for the chart
        const labels = Object.keys(ageGroups);
        const avgBefore = labels.map(label => avg(ageGroups[label].before)); // Average BP before
        const avgAfter = labels.map(label => avg(ageGroups[label].after)); // Average BP after

        // Get context for the first chart
        const ctx1 = document.getElementById('chart1').getContext('2d');
        chart1 = new Chart(ctx1, {
            type: 'bar', // Bar chart type
            data: {
                labels: labels, // X-axis labels (age groups)
                datasets: [
                    {
                        label: 'BP Before', // Dataset label
                        data: avgBefore, // Data for BP before
                        backgroundColor: 'rgba(75, 192, 192, 0.6)', // Fill color
                        borderColor: 'rgba(75, 192, 192, 1)', // Border color
                        borderWidth: 1 // Border width
                    },
                    {
                        label: 'BP After', // Dataset label
                        data: avgAfter, // Data for BP after
                        backgroundColor: 'rgba(153, 102, 255, 0.6)', // Fill color
                        borderColor: 'rgba(153, 102, 255, 1)', // Border color
                        borderWidth: 1 // Border width
                    }
                ]

Similarly, I did another chart for the average counts according to sex.

function avg(array) {
    return array.reduce((a, b) => a + b, 0) / array.length;
}

Lastly, I tried to ensure that the charts adjust to different screen sizes while keeping everything readable and visually appealing. I used this part of code to implement it. I used Inspiration from Bar_Chart_in_P5.js video.

options: {
    responsive: true,
    scales: {
        y: { beginAtZero: true, title: { display: true, text: 'Blood Pressure' } },
        x: { title: { display: true, text: 'Age Group' } }
    }
}

 

p5.js Sketch:

Challenges and further improvements: 

The main challenge was to find a proper dataset. I tried to use different data sets from Google Dataset Search, Kaggle, Data.gov etc but they were not showing into charts, sometimes error was coming or the dataset was too big to use for this project. I took help from chatgpt to give me resources for fine datatsets but it didn’t give me any dataset or link, suggested me to check on Github so I used the idea and searched github.

 

 

Assignment 03: River Flow

Concept: I wanted to create a view of my home country, Bangladesh, which is filled with. hundreds of rivers, and with time the rivers are shrinking. So, I used this assignment to create something that represents the rivers from Bangladesh in a sunset light.

Code:

I’m particularly proud of the FluidSimulation and FlowingMotif parts of my code because they exemplify a thoughtful blend of creativity and technical skill. The FluidSimulation class captures the essence of fluid dynamics with its elegant use of vectors and noise functions to simulate realistic flow patterns. The display() method, with its precise rendering of flow lines, transforms abstract concepts into a visually engaging experience. This method doesn’t just draw; it visually narrates the movement of fluid in a way that is both aesthetically pleasing and scientifically intriguing.

Similarly, the getForceAt() method provides a crucial interface for interaction with the fluid simulation, enabling dynamic elements like particles to seamlessly integrate with the simulated environment. This capability is pivotal in creating a responsive and immersive visual experience.

The FlowingMotif class adds a touch of artistic flair to the simulation. By using dynamic shapes that evolve over time, it introduces an additional layer of visual interest and complexity. The carefully crafted constructor ensures that each motif is unique, with properties that allow for smooth and captivating motion. The motifs enhance the overall aesthetic of the simulation, bringing a sense of life and movement to the scene.

display() {
    noFill();
    strokeWeight(1);
    for (let y = 0; y < this.rows; y++) {
      for (let x = 0; x < this.cols; x++) {
        let v = this.field[y][x];
        let px = x * this.gridSize;
        let py = y * this.gridSize;
        stroke(255, 100);
        line(px, py, px + v.x * this.gridSize, py + v.y * this.gridSize);
      }
    }
  }

  getForceAt(x, y) {
    let col = floor(x / this.gridSize);
    let row = floor(y / this.gridSize);
    col = constrain(col, 0, this.cols - 1);
    row = constrain(row, 0, this.rows - 1);
    return this.field[row][col].copy();
  }
}

// FlowingMotif class definition
class FlowingMotif {
  constructor(x, y, size) {
    this.x = x;
    this.y = y;
    this.size = size;
    this.angleOffset = random(TWO_PI);
    this.frequency = random(0.01, 0.05);
  }

P5.js Sketch:

Week 03: Reading Reflection

In the first chapter of Chris Crawford’s The Art of Interactive Design, I found myself engaged with the foundational ideas presented. From Crawford’s exploration into the nature of interaction as the core of design, one of the key takeaways for me was Crawford’s emphasis on interaction being the core of design. Before reading this, I often saw interactivity as an added feature rather than the fundamental aspect of the user experience. It was like a light bulb went off when he explained that interaction isn’t just about adding clickable elements but about making the whole design process revolve around the user’s actions and reactions. This perspective has made me question my approach to design—am I truly focusing on how users interact with my work, or am I just ticking off boxes?

I agree with him on the definition of interactivity. If I am creating an interactive device/art/product, I should always remember how four parameters, aka listening, speaking, thinking, and responding, work on my idea. I really enjoyed how he explained interactivity with examples, making it easier to even teach my 7-year-old brother about interactivity in technology.

Lastly, on the notion of traditional entertainment like movies being non-interactive, I think that might get shifted with emerging technologies. Digital media, including interactive films, virtual reality experiences, and even interactive web-based stories, demonstrate that interactivity can be a fundamental aspect of various media forms. The rise of these new media formats challenges the traditional notion that interactivity is limited to games or other explicitly interactive experiences.

Assignment 02: Flower Artistry

Concept:  My interactive media class starts just at the end of the day and when I was sitting in the class, brainstorming what I do with loops, I randomly started to draw some simple flowers on P5.js to relieve some stress from having a long day. Then the idea came to my head that having a flower bouquet can make me feel so good, if I don’t have one, then why not create a virtual one? So, here it is!

Proud Moment: I initially sketched some basic flower-like shapes using circles in P5.js, but they didn’t turn out as expected. To achieve the variety and complexity I wanted, I decided to use loops directly as we discussed in class, as manually coding each flower would have been impractical. My main challenge was ensuring that all the flowers had distinct appearances. To address this, I designed each flower type, reusing a base code and adjusting parameters to create different flower variations.

Code Snippet:

function drawDaisy(x, y, size, rotation) {
  let petalCount = 9;
  let petalLength = size;
  let petalWidth = size / 3;
  
  stroke(0);
  fill('#D9E4E6');
  push();
  translate(x, y);
  rotate(rotation);
  for (let i = 0; i < petalCount; i++) {
    push();
    rotate(TWO_PI / petalCount * i);
    ellipse(0, -size / 2, petalWidth, petalLength);
    pop();
  }
  pop();
  
  fill('#F2F2F2');
  noStroke();
  ellipse(x, y, size / 2);
}


function drawTulip(x, y, size, rotation) {
  let petalCount = 6;
  let petalWidth = size / 2;
  
  stroke(0);
  fill('#AEB7FE');
  push();
  translate(x, y);
  rotate(rotation);
  for (let i = 0; i < petalCount; i++) {
    push();
    rotate(TWO_PI / petalCount * i);
    ellipse(0, -size / 2, petalWidth, size);
    pop();
  }
  pop();
  
  fill('#EDEAE6');
  noStroke();
  ellipse(x, y, size / 3);
}

It made the design part of my work easier, but I initially struggled with making the flowers continuously generate as the mouse cursor moves and ensuring they didn’t cluster in one spot. To address this, I turned to various YouTube videos on Mouse Trails, such as the p5.js | Mouse Trail (Quick Code) tutorial. However, I needed to adapt some parameters and functions to fit my specific goals, which differed slightly from those demonstrated in the videos. This aspect of the project was particularly challenging as I had to first grasp the underlying logic before implementing the necessary code to achieve the desired functionality.

In mouseMoved() Function, I’m implementing the logic to generate new flowers as the mouse moves across the canvas. Here’s a breakdown:

function mouseMoved() {
  let currentTime = millis();
  if (currentTime - lastGenerationTime > flowerGenerationInterval) {
    lastGenerationTime = currentTime;
    generateFlowers(mouseX, mouseY);
  }
}

function updateFlower(flower) {
  let dx = mouseX - flower.x;
  let dy = mouseY - flower.y;
  let distance = dist(flower.x, flower.y, mouseX, mouseY);
  
  if (distance > 1) {
    flower.x += (dx / distance) * followSpeed;
    flower.y += (dy / distance) * followSpeed;
  }
  
  flower.x += random(-0.5, 0.5);
  flower.y += random(-0.5, 0.5);
}
I use millis() to get the current time in milliseconds since the sketch started. By comparing it to lastGenerationTime, I ensure that new flowers are only generated after a specified interval (flowerGenerationInterval). This prevents an overwhelming number of flowers from being created all at once.

 

When the time condition is met, I update lastGenerationTime and call generateFlowers() with the current mouse position (mouseX, mouseY). This function creates flowers around the mouse cursor, adding to the visual interest as I move the mouse.

Then, I calculate the distance between the flower and the mouse cursor using dx and dy. If the distance is greater than 1 pixel, the flower moves towards the mouse position. The followSpeed controls how quickly the flower moves. By dividing dx and dy by the distance, I ensure that the flower moves in the correct direction and scales its speed relative to the distance. While there might be other efficient ways to implement this, I chose this manual approach by carefully considering the underlying logic.

After watching the video “Eyeo2012 – Casey Reas,” I decided to introduce some randomness into the flower movement. I added the last two lines of code to make the movement more natural and less mechanical by including a small random offset to the flower’s position. This randomness results in a more organic and unpredictable motion, enhancing the overall visual appeal.

However, I was confused about which version to use as my final submission because each offers a unique vibe that I find appealing. To showcase the contrast, I am also including my first draft as a media file. This allows for a comparison between the two iterations, each with its distinct style and feel.

First Draw: 

Floral Artistry First Draft

 

Reflection and Ideas for Future Work or Improvements:

By using loops and arrays, I was able to efficiently generate and manage an infinite number of flowers, ensuring that the animation remained dynamic and engaging. The code successfully used these loops to update the positions of the flowers and arrays to store and retrieve flower properties, which was crucial for managing the large number of elements and their interactions. Here is what I think can be done in the future:

Performance Optimization: I encountered performance issues when increasing the number of flowers. For instance, trying to use infinitely many flowers caused the webpage to lag, highlighting the need for optimization to handle more elements smoothly. Addressing this performance challenge would help in making the animation more fluid and responsive.

Color Combinations: The current color scheme for the flowers and background could be improved. Some color combinations might not be as visually appealing or harmonious as they could be. Experimenting with different palettes could enhance the overall aesthetic and make the animation more striking.

User Interface and Interactivity: I initially experimented with aligning flowers based on input words, but this approach did not work as intended. Consequently, I simplified the project to focus solely on basic typography and the interactive aspect of the flowers following the mouse cursor. Future iterations could benefit from refining this concept or incorporating new interactive features to give users more control.

Conclusion: Despite these areas for improvement, I am pleased with the overall vibe of the project. The use of rotation to animate the flowers adds a dynamic touch, enhancing the visual interest of the animation. I enjoy the lively and engaging feel it provides and look forward to further refining and expanding upon this project in the future.