Raya Tabassum: Unusual Switch Project

Concept & Usage: My idea was to build a distance-sensitive security system. The system is designed to be sensitive to distance, using the HC-SR04 ultrasonic sensor paired with an Arduino board to trigger an audible alarm. The closer the object is to the sensor, the faster the alarm—or buzzer—will beep, which serves as an intuitive indicator of proximity.

The ultrasonic sensor-based alarm acts not only as a simple security device but can also be an interactive element for various applications. By emitting ultrasonic waves, the sensor can determine the distance to an object based on the time it takes for the waves to return. In the context of security, this setup can detect potential intruders or unauthorized access by sensing motion within a predefined range.

The versatility of the alarm allows it to be adapted for different purposes, such as:

  • Intruder detection for personal properties, alerting homeowners to possible trespassers
  • Industrial safety, where restricted areas can be monitored to ensure personnel safety
  • Public events, to manage crowd control and prevent attendees from accessing sensitive areas

Implementation:

When the system senses an object within a specified distance (less than 50 cm in your code), it activates the buzzer. The alarm’s operation is controlled by the code which defines the pins for the sensor and the buzzer, measures the distance by calculating the time interval of the echo’s return, and dynamically adjusts the beeping speed based on this distance.

Code:

//Security Alarm with Ultrasonic Sensor//

#define trigPin 6  
#define echoPin 5
#define buzzer 2
float new_delay; 


void setup() 
{
  Serial.begin (9600); 
  pinMode(trigPin, OUTPUT); 
  pinMode(echoPin, INPUT);
  pinMode(buzzer,OUTPUT);
  
}


void loop() 
{
  long duration, distance;
  digitalWrite(trigPin, LOW);        
  delayMicroseconds(2);              
  digitalWrite(trigPin, HIGH);
  delayMicroseconds(10);           
  digitalWrite(trigPin, LOW);
  duration = pulseIn(echoPin, HIGH);
  distance = (duration/2) / 29.1;
  new_delay= (distance *3) +30;
  Serial.print(distance);
  Serial.println("  cm");
  if (distance < 50)
  {
   digitalWrite(buzzer,HIGH);
   delay(new_delay);
   digitalWrite(buzzer,LOW);
 
  }
  else
  {
    digitalWrite(buzzer,LOW);

  }
  
 delay(200);
}
  • trigPin and echoPin are defined for sending and receiving the ultrasonic signals.
  • buzzer is defined for the alarm sound.
  • In the loop function, the program triggers the ultrasonic sensor and listens for the echo. The distance is calculated based on the time it takes for the echo to return.
  • The new_delay is calculated based on the measured distance. The closer the object, the smaller the delay, resulting in a faster beep.
  • The buzzer is activated if the object is within 50 cm of the sensor, with the beeping speed proportional to the object’s proximity.

References:

I used several Youtube tutorials for executing the project using the tools.

-https://youtu.be/HynLoCtUVtU?si=zHnjgYTF8wYnlOKp

-https://youtu.be/0Lhgd8PQmn0?si=OXr1fvTP4b9X0pPW

Raya Tabassum: Reading Response 5

The concept that “attractive things work better” suggests that when users find an object attractive, they tend to perceive it as more user-friendly, which can enhance their overall interaction with it. It argues for a balance between functionality and beauty in design, suggesting that products should not only be practical and easy to use but also evoke positive emotions to enhance user experience. The reflection on personal experiences with teapots suggests a deeper, perhaps unspoken critique: that the essence of design transcends its physical form or function, tapping into the user’s emotional and situational contexts. This perspective invites us to reconsider the role of affect in design, not as a secondary aspect but as a central component of usability.
The narrative around three distinct teapots illustrates varied design priorities — usability, aesthetics, and practicality — and how these elements impact user preference depending on context and mood. It raises implicit questions about the prevailing biases in design philosophy — do we undervalue the emotional impact of aesthetics due to a hyperfocus on functionality? This challenges us to think beyond traditional design paradigms, advocating for a more nuanced approach that incorporates affect as a fundamental aspect of design thinking.

The second reading of Margaret Hamilton’s journey from a young MIT programmer to a pioneer of software engineering for the Apollo missions encapsulates a story of groundbreaking achievement amidst societal and professional challenges. Her innovative work in developing flight software was pivotal in landing men on the moon, highlighting her role in transforming software development into a critical component of modern technological endeavors. Hamilton’s perseverance and ingenuity not only broke gender barriers in a male-dominated field but also laid the foundational principles of software engineering, influencing countless future innovations and establishing her legacy as a trailblazer in both technology and gender equality in STEM.

Raya Tabassum: Midterm Project

Link to the fullscreen version

Concept: My midterm project is a game I’ve named “Gold Rush”. It’s inspired from the Super Mario games’ design. The game features a character Super Onion boy that the player controls to jump over and walk to dodge enemies and collect coins to increase their score. The main character, an adventurer with a knack for treasure hunting, traverses a dynamically scrolling landscape filled with gold coins for him to collect. The game introduces a unique enemy, the “GOMBA,” a mysterious creature with a purple body, tentacles, and light-flickering eyes, adding a layer of intrigue and challenge to the player’s journey. Dodging the enemy gains the player +5 points and collecting each coin gains them +10 points, and the score system is displayed on top of the screen while the game is playing. If the player collides with the enemy GOMBA, the game over screen appears and to play again – the player needs to press SHIFT key and the game will restart.

User Experience: The game is structured around a loop where the player’s character is continuously moving forward, with the background scrolling to simulate progression through the game world. This effect is achieved through an implementation of looping background images that reset once they scroll past the view, creating an endless moving landscape. The characters, including the player, the coin, and the enemy, are animated using sprites, which are sequences of images that create the illusion of motion when displayed in rapid succession.


One aspect of the project I’m particularly proud of is the collision detection mechanism. It’s designed to be both efficient and accurate enough for the game’s scope, using simple geometric shapes to approximate the player, coins, and enemies’ positions. This simplicity ensures the game runs smoothly without compromising the gameplay experience. Another highlight is the sound integration, which enhances the immersive experience of the game. The careful selection and timing of sound effects for jumping, collecting coins, and colliding with enemies add a layer of polish that elevates the overall game.

Areas for Improvement and Challenges: One area for improvement involves enhancing the game’s replay value. Currently, the game offers a straightforward challenge with a single level that repeats. Introducing varied levels with increasing difficulty with speed, diverse environments, and additional enemy types could significantly enhance the player’s experience and engagement. Implementing a power-up system or special abilities for the character could also add depth to the gameplay.

During development, one challenge encountered was ensuring that the game remained engaging over time. Initially, if the player missed a coin, it wouldn’t reappear, which could’ve led to a monotonous gameplay loop. This issue was addressed by adjusting the coin’s reinitialization logic to ensure it reappears regardless of whether it’s collected or missed, maintaining the game’s pace and challenge. Another technical hurdle was balancing performance with the visual richness of the game, particularly with sprite animation and background scrolling. Also to integrate the sound loops perfectly was hard at first but after fixing the code logic in different ways the desired results were received.

Full code for the game:

//GOLD RUSH BY RAYA TABASSUM

//CHARACTERS: SUPER ONION BOY, GOLD COIN, GOMBA THE ENEMY

//5 POINTS FOR AVOIDING THE ENEMY, 10 POINTS FOR COLLECTING THE COIN

// Preload function for loading assets before the game starts
let img, game_over_bg, sf, coin_sound, jump_sound, enemy_sound, pixel_font;
let xpos = 0, ypos = 0, x1 = 0, x2 = 1000, y = 0, x3 = 0, y2 = 0, score = 0, win = true;
let player, enemy, coin;

function preload() {
  img = loadImage("plt.png"); // Background image
  game_over_bg = loadImage("Gameover.png"); // Game over background image
  soundFormats('mp3', 'ogg'); // Specify the sound formats to use
  sf = loadSound("backgroundmusic.mp3"); // Background music
  coin_sound = loadSound("coin.mp3"); // Sound for collecting coins
  jump_sound = loadSound("jumping.mp3"); // Sound for jumping
  enemy_sound = loadSound("enemy_sound.mp3"); // Sound when colliding with an enemy
  pixel_font = loadFont("PixelFont.ttf"); // Custom font for text display
}

// Player class with properties and methods for the player character
class Player {
  constructor() {
    this.playerYOnGround = 550; // Y position of the player on the ground
    this.playerSize = 60; // Size of the player character
    this.bgGroundHeight = 45; // Height of the ground
    this.animationSlowDown = 8; // Slows down the animation frame rate
    this.width = 1000; // Width of the canvas
    this.jumpHeight = 0; // Current jump height
    this.jumpStrength = 0; // Current strength of the jump
    this.jumpStrengthMax = 5; // Maximum strength of the jump
    this.gravity = 0.1; // Gravity affecting the jump
    this.jumping = false; // Is the player jumping?
    this.playerImg = []; // Array to hold player images for animation
    this.numberPlayerImg = 6; // Number of player images
    this.playerImgIndex = 0; // Current index of the player image
    for (let i = 1; i <= 3; i++) {
      this.playerImg.push(loadImage(`guy-${i}.png`)); // Load player images
    }
  }

  initPlayer() {
    xpos = (this.width * 0.5) - (this.playerSize * 0.5); // Initialize player's horizontal position
    ypos = this.playerYOnGround; // Initialize player's vertical position
  }

  animatePlayer() {
    // Handle jumping logic
    if (this.jumping) {
      this.jumpStrength = (this.jumpStrength * 0.99) - this.gravity; // Apply gravity
      this.jumpHeight += this.jumpStrength; // Update jump height
      if (this.jumpHeight <= 0) {
        // Reset jump parameters if player is back on ground
        this.jumping = false;
        this.jumpHeight = 0;
        this.jumpStrength = 0;
      }
    }

    ypos = this.playerYOnGround - this.jumpHeight; // Update player's vertical position based on jump

    // Display the player image, use jumping image if jumping or animate otherwise
    if (this.jumping) {
      image(this.playerImg[0], xpos, ypos);
    } else {
      image(this.playerImg[this.playerImgIndex], xpos, ypos);
      // Animate player images
      if (frameCount % this.animationSlowDown === 0) {
        this.playerImgIndex = (this.playerImgIndex + 1) % 3;
      }
    }
  }
}

// Enemy class, inherits from Player and represents the enemy character
class Enemy extends Player {
  constructor() {
    super(); // Call the parent class constructor
    this.enemyImg = []; // Array to hold enemy images for animation
    for (let i = 1; i <= 3; i++) {
      this.enemyImg.push(loadImage(`enemy-${i}.png`)); // Load enemy images
    }
    this.enemyX = 800; // Initial horizontal position of the enemy
    this.enemyY = 460; // Initial vertical position of the enemy
    this.enemySize = 100; // Size of the enemy character
    this.enemyOnSky = random(250, 510); // Randomize enemy's vertical position
    this.enemyImgIndex = 0; // Current index of the enemy image
  }

  initEnemy() {
    this.enemyX -= 2; // Move the enemy horizontally
    this.enemyY = this.enemyOnSky; // Update the enemy's vertical position
  }

  animateEnemy() {
    // Display and animate the enemy character
    image(this.enemyImg[this.enemyImgIndex], this.enemyX, this.enemyY, this.enemySize, this.enemySize);
    this.enemyX -= 1; // Move the enemy horizontally
    this.initEnemy(); // Re-initialize the enemy position
    if (frameCount % this.animationSlowDown === 0) {
      this.enemyImgIndex = (this.enemyImgIndex + 1) % 3; // Animate enemy images
    }

    // Reset enemy position and increase score when it moves off-screen
    if (this.enemyX <= 0) {
      this.enemyX = 1000;
      this.enemyOnSky = random(250, 510);
      this.initEnemy();
      score += 5; // Increase score
    }

    // Check for collision with the player
    if (dist(this.enemyX, this.enemyY, xpos, ypos) <= (this.playerSize / 2 + this.enemySize / 2)) {
      win = false; // End the game if collision detected
      if (!enemy_sound.isPlaying()) {
        if (sf.isPlaying()) {
            sf.stop(); // Stop the background music
        }
        enemy_sound.loop(); // Play the enemy sound on loop
      }
    }
  }
}

// Coin class, inherits from Player and represents collectible coins
class Coin extends Player {
  constructor() {
    super(); // Call the parent class constructor
    this.coinImg = []; // Array to hold coin images for animation
    for (let i = 1; i <= 5; i++) {
      this.coinImg.push(loadImage(`coin-${i}.png`)); // Load coin images
    }
    this.coinX = 800; // Initial horizontal position of the coin
    this.coinY = 460; // Initial vertical position of the coin
    this.coinSize = 48; // Size of the coin
    this.coinImgIndex = 0; // Current index of the coin image
  }

  initCoin() {
    this.coinX = width; // Place the coin at the edge of the screen
    this.coinY = random(250, 510); // Randomize the coin's vertical position
  }

  animateCoin() {
    // Display and animate the coin
    image(this.coinImg[this.coinImgIndex], this.coinX, this.coinY, this.coinSize, this.coinSize);
    this.coinX -= 1; // Move the coin horizontally
    if (frameCount % this.animationSlowDown === 0) {
      this.coinImgIndex = (this.coinImgIndex + 1) % 5; // Animate coin images
    }

    // Check if the coin has been collected
    if (dist(this.coinX, this.coinY, xpos, ypos) <= (this.playerSize / 2 + this.coinSize / 2)) {
      this.initCoin(); // Re-initialize the coin position for it to reappear again
      score += 10; // Increase score
      if (!coin_sound.isPlaying()) {
        coin_sound.play(); // Play the coin collection sound
      }
    }
    // Check if the coin has moved off the left edge of the screen without being collected
    else if (this.coinX < 0) {
      this.initCoin(); // Re-initialize the coin position for it to reappear again
    }
  }
}

function setup() {
  createCanvas(1000, 750); // Set up the canvas
  if (!sf.isPlaying()) {
    sf.loop(); // Loop the background music if not already playing
  }
  player = new Player(); // Instantiate the player
  enemy = new Enemy(); // Instantiate the enemy
  coin = new Coin(); // Instantiate the coin
  player.initPlayer(); // Initialize the player
  coin.initCoin(); // Initialize the coin
  enemy.initEnemy(); // Initialize the enemy
}

function draw() {
  background(220); // Set the background color
  image(img, x1, y); // Draw the background image twice for a scrolling effect
  image(img, x2, y);
  x1 -= 1; // Move the background images to create a scrolling effect
  x2 -= 1;
  if (x1 <= -1000) { // Reset the background images positions for continuous scrolling
    x1 = 1000;
  }
  if (x2 <= -1000) {
    x2 = 1000;
  }

  // Animate player, coin, and enemy
  player.animatePlayer();
  coin.animateCoin();
  enemy.animateEnemy();
  
  // Display the score and instructions
  textSize(25);
  textFont(pixel_font);
  fill(255, 215, 0);
  text(`Score: ${score}`, 450, 100);
  text("Use UP Key to Jump", 375, 25);
  textSize(20);
  text("Collect the coins and avoid hitting the enemy!", 250, 45);

  if (!win) {
    image(game_over_bg, x3, y2); // Display the game over background
    textSize(30);
    text("Press SHIFT Key to Play Again", 285, 25);
    //noLoop(); // Stop the draw loop
  }
}

function keyPressed() {
  // Jump when UP key is pressed
  if (keyCode === UP_ARROW && win) {
    player.jumping = true; // Enable jumping
    if (!jump_sound.isPlaying()) {
      jump_sound.play(); // Play jump sound
    }
    player.jumpStrength = player.jumpStrengthMax; // Set jump strength to maximum
  }

  // Reset game when SHIFT key is pressed after losing
  if (keyCode === SHIFT && !win) {
    win = true; // Reset game status
    score = 0; // Reset score
    if (enemy_sound.isPlaying()) {
        enemy_sound.stop(); // Stop the enemy sound if playing
    }
    loop(); // Resume the draw loop
    setup(); // Reinitialize game setup
  }
}

 

Raya Tabassum: Reading Response 4

The article provides a comprehensive examination of how computer vision technologies have evolved from highly specialized tools to accessible instruments for artistic expression and design. The inclusion of historical and contemporary examples of interactive art, such as Myron Krueger’s Videoplace and Golan Levin’s own Messa di Voce, serves not only to illustrate the potential applications of computer vision in art but also to inspire readers to think creatively about how they might employ these tools in their own work. The article does not shy away from addressing the challenges and ethical considerations inherent in surveillance and data collection, using projects like the Suicide Box by the Bureau of Inverse Technology to provoke critical thought about the implications of computer vision technology. The workshop example, LimboTime, serves as a tangible outcome of Levin’s pedagogic approach, demonstrating how novices can rapidly prototype and implement an interactive game using basic computer vision techniques. This example encapsulates the article’s core message: that with the right guidance and tools, computer vision can become a powerful medium for artistic exploration and expression.
By demystifying computer vision and providing practical tools and techniques for novices, Levin opens up new avenues for creative expression and interaction, reinforcing the idea that art and technology are not disparate fields but complementary facets of human creativity.

Raya Tabassum: Midterm Project Progress

 

Concept:
I’m trying to make sort of a version of “Super Mario” game using one player who walks along the path collecting gold coins and the game ends when it collides with the enemy. The player have to jump (using UP key) to collect coin, and there’ll be sound incorporated with each jump and coin collection. When the game is over there’ll be a screen saying “Game Over” and if the player wants to play again they can press SHIFT key and the game will start again. There’ll be a scoring system displayed on the screen too.

Difficulty/Challenges:
Challenge would be to move the sprite smoothly along the background. I want to design the background myself and make the player and enemy designs too – to make it unique. I guess collaborating all the elements of the game together to respond to the user interaction would be a challenge so that the game runs properly.

Visualization:
I want my game screen to look like this (primarily, this is not a definite design, just drawn into Procreate as I’m currently using dummy sprites only to run the game code):

 

Coding:
There’ll be a Player class, an Enemy class, and a Coin class. I’ve designed the basic code for collision etc. Here are some highlighted code snippets:

The Player class:

class Player {
  constructor() {
    this.playerYOnGround = 550;
    this.playerSize = 60;
    this.bgGroundHeight = 45;
    this.animationSlowDown = 8;
    this.width = 1000;
    this.jumpHeight = 0;
    this.jumpStrength = 0;
    this.jumpStrengthMax = 5;
    this.gravity = 0.1;
    this.jumping = false;
    this.playerImg = [];
    this.numberPlayerImg = 6;
    this.playerImgIndex = 0;
    for (let i = 1; i <= 3; i++) {
      this.playerImg.push(loadImage(`guy-${i}.png`));
    }
  }

  initPlayer() {
    xpos = (this.width * 0.5) - (this.playerSize * 0.5);
    ypos = this.playerYOnGround;
  }

  animatePlayer() {
    if (this.jumping) {
      this.jumpStrength = (this.jumpStrength * 0.99) - this.gravity;
      this.jumpHeight += this.jumpStrength;
      if (this.jumpHeight <= 0) {
        this.jumping = false;
        this.jumpHeight = 0;
        this.jumpStrength = 0;
      }
    }

    ypos = this.playerYOnGround - this.jumpHeight;

    if (this.jumping) {
      image(this.playerImg[0], xpos, ypos);
    } else {
      image(this.playerImg[this.playerImgIndex], xpos, ypos);
      if (frameCount % this.animationSlowDown === 0) {
        this.playerImgIndex = (this.playerImgIndex + 1) % 3;
      }
    }
  }
}

When the player collides with enemy:

if (dist(this.enemyX, this.enemyY, xpos, ypos) <= (this.playerSize / 2 + this.enemySize / 2)) {
      win = false;
}

When the player collects coin:

if (dist(this.coinX, this.coinY, xpos, ypos) <= (this.playerSize / 2 + this.coinSize / 2)) {
      this.initCoin();
      score += 10;
}

Raya Tabassum: Reading Response 3

“The Psychopathology of Everyday Things” lays a foundational understanding of how good design should bridge the gap between user experience and functionality.
One intriguing aspect that Norman highlights is the concept of “affordances,” which refers to the perceived and actual properties of an object that determine how it could possibly be used. A door handle, for example, affords pulling, while a push plate suggests pushing. This concept raises questions about how well the design communicates possible actions to users and how intuitive these actions are. It leads one to ponder: How many everyday frustrations are due to poor design rather than user error?
Norman also introduces the idea of “signifiers,” signals that communicate where the action should take place. This is particularly interesting when considering interactive media, where the interface must clearly communicate how to interact with digital environments. These concepts beg the question of how digital interfaces can be designed to be more intuitive and reduce the cognitive load on the user.
“Good design makes a product understandable” – it encapsulates the essence of user-centered design—making the purpose of an object or interface self-evident. Consider the evolution of smartphone interfaces. Early smartphones often required users to navigate through multiple menus to perform simple tasks. Modern smartphones, however, have refined their interfaces to be more intuitive, using design principles like those Norman discusses. Icons are designed with affordances and signifiers in mind, making actions like deleting an app or finding settings more intuitive. This evolution showcases the impact of good design on everyday technology and its role in enhancing user experience.

How can we, as future designers, ensure that our creations are not just functional but also joyous to interact with? How can we minimize frustration and maximize satisfaction? That are the questions it’s high time we ask ourselves.

Raya Tabassum: Generative Text Assignment

Concept:

This kinetic typography transforms static text into an interactive visual display. By treating each point of the font’s letters as a vehicle, the sketch brings the text “Dream” to life, allowing it to respond dynamically to the viewer’s mouse movements. Vehicles “arrive” at their designated spots to form the letters of the word and “flee” when the mouse comes close, creating an engaging effect that feels both chaotic and ordered. The addition of the gradient background adds depth and visual interest, making the typography a part of an aesthetically pleasing composition of a sunset.

Use your mouse to go through the word to interact with it:

Font Points Extraction and Vehicle Initialization:

//Extract points from the font
let points = font.textToPoints(textString, 75, 320, fontSize, {
  sampleFactor: 0.1
});

//Initialize vehicles for each point
for (let i = 0; i < points.length; i++) {
  let pt = points[i];
  let vehicle = new Vehicle(pt.x, pt.y);
  vehicles.push(vehicle);
}

Extracting points from text and converting them into “vehicles” was a bit complex due to the need to handle font rendering and point manipulation. The textToPoints() function is used to get the vector points for each letter, which are then used to create vehicle objects that simulate motion.

Also for the Vehicle class, implementing behaviors such as “arrive” and “flee” required understanding of steering behaviors and force accumulation in a physics-based simulation. Balancing these forces to achieve smooth and natural movement was challenging, especially when trying to simulate both attraction to a target point and repulsion from the mouse cursor.

Full code:

//Preload the font
let font;
let vehicles = []; //Array to hold the 'vehicle' objects

function preload() {
  //Load the font from the assets
  font = loadFont('Hogfish DEMO.otf'); 
}

function setup() {
  createCanvas(700, 500); //Set up the canvas
  //Create a background gradient
  setGradient(0, 0, width, height, color('#EBC249'), color('#A52D56'), Y_AXIS);

  //Define the text properties
  let textString = 'Dream';
  let fontSize = 180;
  //Convert the text to a series of points
  let points = font.textToPoints(textString, 75, 330, fontSize, {
    sampleFactor: 0.1 //Determines the density of the points
  });

  //Create a vehicle object for each point
  for (let i = 0; i < points.length; i++) {
    let pt = points[i];
    let vehicle = new Vehicle(pt.x, pt.y);
    vehicles.push(vehicle);
  }
}

function draw() {
  //Refresh the gradient background each frame
  setGradient(0, 0, width, height, color('#EBC249'), color('#A52D56'), Y_AXIS);

  //Update and display each vehicle
  for (let i = 0; i < vehicles.length; i++) {
    let v = vehicles[i];
    v.behaviors();
    v.update();
    v.show();
  }
}

//Constants for gradient direction
const Y_AXIS = 1;
const X_AXIS = 2;

//Function to create a gradient background
function setGradient(x, y, w, h, c1, c2, axis) {
  noFill();

  //Create a vertical gradient
  if (axis === Y_AXIS) {
    for (let i = y; i <= y + h; i++) {
      let inter = map(i, y, y + h, 0, 1);
      let c = lerpColor(c1, c2, inter);
      stroke(c);
      line(x, i, x + w, i);
    }
  } 
  //Create a horizontal gradient
  else if (axis === X_AXIS) {
    for (let i = x; i <= x + w; i++) {
      let inter = map(i, x, x + w, 0, 1);
      let c = lerpColor(c1, c2, inter);
      stroke(c);
      line(i, y, i, y + h);
    }
  }
}

//The Vehicle class
class Vehicle {
  constructor(x, y) {
    this.pos = createVector(random(width), random(height)); // Start position
    this.target = createVector(x, y); //Target position
    this.vel = p5.Vector.random2D(); //Initial velocity
    this.acc = createVector(); //Acceleration
    this.r = 8; //Radius
    this.maxspeed = 10; //Maximum speed
    this.maxforce = 1; //Maximum steering force
  }

  //Combine behaviors
  behaviors() {
    let arrive = this.arrive(this.target);
    let mouse = createVector(mouseX, mouseY);
    let flee = this.flee(mouse);

    arrive.mult(1);
    flee.mult(5);

    this.applyForce(arrive);
    this.applyForce(flee);
  }

  //Apply a force to the vehicle
  applyForce(f) {
    this.acc.add(f);
  }

  //Update the vehicle's position
  update() {
    this.pos.add(this.vel);
    this.vel.add(this.acc);
    this.acc.mult(0); //Reset acceleration each frame
  }

  //Display the vehicle
  show() {
    stroke(255);
    strokeWeight(8);
    point(this.pos.x, this.pos.y);
  }

  //Steer the vehicle towards a target
  arrive(target) {
    let desired = p5.Vector.sub(target, this.pos); //A vector pointing from the position to the target
    let d = desired.mag();
    let speed = this.maxspeed;
    if (d < 100) {
      //Adjust speed based on distance to the target
      speed = map(d, 0, 100, 0, this.maxspeed);
    }
    desired.setMag(speed);
    let steer = p5.Vector.sub(desired, this.vel);
    steer.limit(this.maxforce);
    return steer;
  }

  //Make the vehicle flee from the mouse
  flee(target) {
    let desired = p5.Vector.sub(target, this.pos);
    let d = desired.mag();
    if (d < 50) {
      desired.setMag(this.maxspeed);
      desired.mult(-1); //Go in the opposite direction
      let steer = p5.Vector.sub(desired, this.vel);
      steer.limit(this.maxforce);
      return steer;
    } else {
      return createVector(0, 0); //No force if the mouse is far away
    }
  }
}

 

Raya Tabassum: OOP Generative Art “The Flower Garden”

Click on the art to interact and create your own flower garden!

//Define the Flower class to represent each flower in the garden
class Flower {
  constructor(x, y) {
    this.x = x; //X position of the flower on the canvas
    this.y = y; //Y position of the flower on the canvas
    this.size = 5; //Initial size of the flower, to be grown over time
    this.growthRate = random(0.05, 0.2); //Random growth rate for dynamic visuals
    this.fullSize = random(30, 70); //Target size of the flower when fully grown
    this.petals = floor(random(4, 9)); //Number of petals, randomly chosen for variety
    this.petalSize = this.fullSize / 2; //Determines the size of each petal
    this.color = [random(100, 255), random(100, 255), random(100, 255)]; //RGB color of the petals, chosen randomly for diversity
  }

  //Method to simulate the growth of the flower
  grow() {
    //Increase the size of the flower until it reaches its full size
    if (this.size < this.fullSize) {
      this.size += this.growthRate; //Grow based on the predefined rate
    }
  }

  //Method to display the flower on the canvas
  show() {
    push(); //Save the current drawing state
    translate(this.x, this.y); //Move the drawing origin to the flower's location
    noStroke(); //Petals and center will not have an outline
    fill(this.color[0], this.color[1], this.color[2]); //Set the color for the petals
    
    //Draw each petal around the center
    for (let i = 0; i < this.petals; i++) {
      rotate(TWO_PI / this.petals); //Rotate the drawing context to evenly space petals
      ellipse(0, this.size / 4, this.petalSize, this.size); //Draw an ellipse for each petal
    }
    
    //Draw the flower's center
    fill(255, 204, 0); //Color for the center of the flower
    ellipse(0, 0, this.size / 4, this.size / 4); //Draw the center as a smaller ellipse
    
    pop(); //Restore the original drawing state
  }
}

let flowers = []; //Array to hold all the flower objects

function setup() {
  createCanvas(800, 600); //Set up the canvas
  background(0); //Initial background color
}

function draw() {
  background(0); //Clear the canvas at each frame to redraw updated flowers
  //Iterate through each flower in the array to update and display it
  for (let flower of flowers) {
    flower.grow(); //Simulate growth
    flower.show(); //Draw the flower on the canvas
  }
}

function mousePressed() {
  //Create a new Flower object at the mouse position when the canvas is clicked
  let flower = new Flower(mouseX, mouseY);
  flowers.push(flower); //Add the new flower to the array
}

The title of this artwork is “The Flower Garden”. The overall concept of this generative art piece is to simulate a digital garden where flowers can spontaneously grow at locations chosen by the user. Each flower starts small and grows over time, with a unique number of petals and colors, creating a diverse and evolving garden scene. This interactive piece allows viewers to contribute to the creation of the artwork, making each experience unique.

Use of Arrays and Objects in OOP
Arrays: The flowers array is used to store multiple instances of the Flower class, showcasing how arrays can manage collections of objects in an OOP context.
Objects: Each flower is an instance of the Flower class, with its properties and behaviors encapsulated within the class. This demonstrates the use of objects to model real-world concepts (like flowers) with data (properties) and actions (methods).

I tried to create an interactive and visually appealing art, allowing both the creator and the viewer to explore the intersection of nature, art, and technology. The inspiration behind this artwork was the concept of similar virtual garden apps/games that allows users to have their garden, creating and nurturing the flowers in it. I tried to make a similar version of it with vivid colors and shapes. The part I most loved is how the flowers actually look – I think they’re very pretty and when they’re blooming it gives a calm and soothing feel to the viewer.

Here’s how it looks when the garden is full of flowers:

I made another one with some revisions(added stem and two leaves to each flower):

Full garden:

Here are some other designs I kinda played with:

Raya Tabassum: Reading Response 2

The first chapter of “The Art of Interactive Design” by Chris Crawford lays out the foundation for understanding what interaction is in the first place. On the other hand, Crawford distinguished between interaction and mere reaction by insisting on the two-way process of communication and stated that a cyclic process is necessary where two actors listen, think, and speak alternately. Crawford’s definition makes one start to question the extent to which the present technologies achieve real interaction versus offering sophisticated forms of reaction. For instance, if we look at voice-activated assistants or chatbots, how much do these systems actually engage in a listen-think-speak cycle, and how much is it just a pre-programmed set of responses to user input? The key question comes up here: can artificial intelligence, as it exists and will in all future products, actually ‘interact’ as Crawford has described interaction, or is it by necessity delegated to the simulation of interaction through a series of complex algorithms?
There are key lines of inquiry related to the ethics of designing for interaction. What, therefore, when the essence of interaction is meaningful exchange? How is it that designers ensure technologies really foster such positive interactions without the manipulation or exploitation of the user? This issue becomes very pertinent in the context of social media platforms in which interaction design can radically impact user behavior and mental health.

Moreover, Crawford’s focus on interaction as something cyclic challenges us to reason about user feedback loops in design. And his differentiation between interaction and reaction raises serious questions of how we categorize and value forms of digital engagement. This prompts us to critically reflect on whether, indeed, our daily engagements with technology are two-way interactions, that is, if as much as we respond to them, devices and platforms themselves also engage and respond to us—or whether, indeed, we are only responding to slick cues, designed by others.
I believe these questions are crucial for both designers and users as we navigate the increasingly complex landscape of interactive systems.

Raya Tabassum: Reading Response 1

Reas navigates through the historical and contemporary landscapes where chance operations have been utilized, underscoring the balance between unpredictability and control, chaos and order.
The concept of employing randomness in art is not new; it traces back to various movements and disciplines, including Dadaism’s use of arbitrary methods to challenge artistic norms and John Cage’s explorations in music that embraced indeterminacy. Reas’ talk prompts one to question: How do these historical instances of chance operations inform and enrich our current understanding of randomness in digital art?
Reas’ emphasis on the symbiosis between order and chaos, particularly in the realm of digital arts, brings to light the nuanced dynamics of control. The artist, through the use of algorithms and computational methods, sets the stage for randomness, yet within predefined constraints. This paradoxical relationship invites reflection on the nature of creativity itself. Is true creativity found in the meticulous planning and execution of an idea, or does it emerge from the serendipitous encounters with the unexpected? The talk challenges one to consider the role of the artist in the digital age: Are they the orchestrators of chaos, the curators of randomness, or simply collaborators with the computational processes they employ?
In conclusion, Casey Reas’ talk on chance operations serves as a profound catalyst for reflection on the intersections between art, technology, and randomness. It compels one to reconsider not just the methodologies of artistic creation but the very essence of creativity and its manifestations in the digital age.