Production Assignment – Week #3

For this assignment, we were tasked with creating a generative artwork using Object-Oriented Programming. I wanted to use something we use everyday in our culture to create my artwork, and took inspiration from the Emarati Ghutra (Ghitra):

I tried to use its some of its colors (white, and the different shades of red) and shapes (zigzags, diamonds, checkered squares, etc) to create my artwork.

I created a class for the Ghutra elements, consisting of a constructor, display function, and changeColor function to change the color on mouse click.

class GhutraPatternElement {
  
  // Setup the constructor with the required attributes to draw the shapes
  constructor(x, y, size, color, shapeType) {
    this.x = x;
    this.y = y;
    this.size = size;
    this.color = color;
    this.shapeType = shapeType;
  }

  // Display function to draw the shapes based on the attributes passed to the constructor
  display() {
    fill(this.color);
    noStroke();
    
    // Diamond Shape
    if (this.shapeType === 'diamond') {
      beginShape();
      vertex(this.x, this.y - this.size);
      vertex(this.x + this.size * 0.8, this.y);
      vertex(this.x, this.y + this.size);
      vertex(this.x - this.size * 0.8, this.y);
      endShape();
    }
    
    // Checkered Squares
    else if (this.shapeType === 'checkered') {
      rectMode(CENTER);
      rect(this.x, this.y, this.size, this.size);
    } 
    
    // Zigzags
    else if (this.shapeType === 'zigzag') {
      let numZigs = 10;
      let zigzagWidth = this.size / numZigs;

      beginShape();
      for (let i = 0; i < numZigs; i++) {
        let x1 = this.x + i * zigzagWidth;
        let y1 = this.y + (i % 2 === 0 ? -this.size : this.size) * 0.5;
        vertex(x1, y1);
  
        let x2 = this.x + (i + 1) * zigzagWidth;
        let y2 = this.y + (i % 2 === 0 ? this.size : -this.size) * 0.5;
        vertex(x2, y2);
      }
      endShape();
    }
  }

  // Function to change color on mouse press
  changeColor() {
    // Change the color only when the mouse is pressed
    if (mouseIsPressed) {
      this.color = random(colorPalette);
    }
  }
}

I used ChatGPT to generate the color codes for the different shades of red I used to avoid having to manually sample each color and waste time:

let colorPalette = [
  '#FFFFFF',    // White
  '#FF0000',    // Red
  '#990000',    // Dark Red
  '#FF6666',    // Light Red
  '#CC0000',    // Medium Red
];

Overall, this was the result:

Looking to the future, there are definitely many things I can change to improve this artwork and make it more aesthetic. Additionally, there seems to be a bug in my code that changes the shape color multiple times per each mouse click instead of just once.

Assignment 3

For this assignment, I used OOP and arrays to create an interactive Popcorn experience. On mouse Click, the user can see the popcorn bouncing from the popcorn machine straight to their popcorn box. The user can keep adding popcorn whenever they like.

<

The code that I am most proud of is allowing the user to add more popcorn at any time. I used the mousePressed function for that:

function mousePressed(){
  for(let i = 0; i < 10; i++){
    let x = i;
    let y = i*10;
    let xspeed = i*2;
    popcorns[i] = new Popcorn(x,y,xspeed,-1);

}

For improvements, I want to learn how to make the popcorn objects land on each other so that it shows that they are stacking. I also want to allow the user to enter a number which represents how much popcorn they would want to have.

Week 3 Reading Response – Saeed Lootah

When first going through the article I enjoyed the authors’ style of writing. Even though his style may not have to do with interactivity I found it interesting how he it seemed he was at times angry or fed-up with the current state of things surrounding the word interactivity. This may show that he is biased in that he starts off by feeling annoyed rather than objectively considering how the word interactivity is being used already as he only starts by mentioning advertisements, then throughout the text mentions more real-world scenarios (like reading, or dancing) but I wish I could have seen more mention of how interactivity is used in academia as words are often loosely used/defined in normal conversation.

In any case he makes a compelling alternative to how the word interactivity should be used. For example interactivity should be more than just being true or false but should consider how interactive something is. Then also mentioning what qualities are needed for something to be highly interactive. Listening, thinking, and speaking. The only problem I see is that I believe how interactive something is, is subjective, but whether or not something is interactive is objective. The author believes that if one of the qualities are missing then it cannot be considered highly interactive but people can play games against someone else who is reacting to their moves (which makes it interactive) but not speak at all for example and still find it highly interactive since it is based on emotions rather than logic alone. One of the interesting things I found towards the end is that a good interactive designer should have a good understanding of both the backend and the frontend of a product. Backend in this case meaning the algorithms, and frontend the general appearance.

Week 3 Reading Response – Khalifa Alshamsi

Reading “The Art of Interactive Design” by Chris Crawford has got me thinking about the many aspects of digital interaction, from the narrow scope of game design and conventional software development to the larger social and technical context. Among the many interesting, thought-provoking points brought up by Crawford, the essence of interaction was something I never really got to think about in the way Crawford brought it up. Crawford’s exploration of interaction as a conversation between the user and the system prompts a reconsideration of what effective communication means in a digital context. It makes me think about how devices, apps, and platforms are not just tools but participants in a dialogue with users. This perspective challenges designers to create more empathetic and responsive systems that genuinely understand and adapt to user needs, or else it becomes useless as if a person is speaking to you in a different language than the one you know.

 

Reflecting on “The Art of Interactive Design” inspires a personal commitment to lifelong learning in the field of technology. The pace of change is rapid, and staying informed about new theories, tools, and methodologies is essential for anyone interested in creating meaningful interactive experiences. It reinforces the importance of curiosity, creativity, and critical thinking in navigating the complexities of interactive design.

Assignment 3 – Saeed Lootah

When starting this assignment I set the goal of creating classes which behaved differently to each other. In my previous assignment I had a similar goal but wasn’t able to achieve it so I thought I would try again. When it came to the code I took inspiration from the car sketch, where the location of each car was stored as posX and posY. I also wanted to make something similar to what some of my other classmates were making without looking at their code and spending as much time figuring it out myself. I tried to replicate Snehil’s design with the use of what looked like snakes but I wanted a different color scheme. I found Darko’s color scheme more appealing. Then lastly, I wanted to make a class which I could easily repurpose or re-use if I wanted to make shapes which could move around almost randomly.

class snake {
  
  constructor(posX, posY, radius, magnitude, coefficient) {
    
    this.posX = posX;               // x-position of the shape
    this.posY = posY;               // y-position of the shape
    this.radius = radius;           // radius of the circle, could be changed if the shape is different
    this.magnitude = magnitude;     // magnitude refers to the amount the shape moves every frame
    this.coefficient = coefficient; // coefficient is the number that multiplies the frameCount in the noise function, I prefer it when it is the same for all snakes but it is a variable that can be changed regardless
    
  }
  
  // This class sets a new posX and posY based on a randomly generated heading
  update() {
    // update random heading
    
    let noiseRandom = noise(this.coefficient * frameCount);
    
    angleMode(RADIANS);
    
    let randomHeading = map(noiseRandom, 0, 1, -2*PI, 2*PI); //random heading
    
    // setting new posX, and posY based on the magnitude
    
    this.posX = this.posX + cos(randomHeading) * this.magnitude;
    this.posY = this.posY + sin(randomHeading) * this.magnitude;
    
    // The reason I used sin and cos is because setting the new values is similar to a right angle triangle: The magnitude can be represented as the hypotenuse, and the random heading an angle, then the adjacent value is the change in x, the opposite value is the change in y, then add said changes to the posX and posY respectively. Of course to calculate the new aformentioned values the formula sin(randomHeading) = x / magnitude has to be rearranged, and the same for cosine. 

  }
  
  // this class just draws the shape, it could really be anything, it could even be modified to be a rectangle or an ellipse or anything else you can think of.
  drawShape() {
    
    circle(this.posX,this.posY,this.radius);
    
  }
  
}

Above is the entire class which I named snake. I only used 2 functions not including the constructor which was update and drawShape. the update function’s purpose was to create a new heading, and update the posX and posY variables based on the heading and the magnitude inputed when creating the class. I tried to explain how it’s done but I feel the long comment does not do it justice. Before I explain, originally I tried to use vectors and the translate method. What I realized was that the translate function could also move other shapes on the screen, and instead of trial and error-ing my way around, I decided to use posX and posY like what I remembered from the car-sketch.

To do this I thought of a right angled triangle and using the trigonometric equations to find what the new coordinates for the shape would be.

While the math isn’t very complicated I felt it was worth explaining and documenting regardless. The hypotenuse is in this case the magnitude, the adjacent side (see left triangle) is the change in x, and the opposite side (left triangle) is the change in y, and theta is the randomHeading variable I generated in the update function. I knew the equations sin and cosine could be used as they had all the variables I needed and so by rearranging for x and y respectively, then adding the new values I got to the pre-existing posX and posY variables I could get the new posX and posY variables. This was the main problem I had, and it was what took me the most time to figure out since at the beginning I chose not to look directly into the code of others and to use what I knew already or what I remembered from class.

Below is the finished product:

Click to reset the circles.

Week 3 Assignment: The Ant Life

For this assignment, I had initially planned to create Agar Plate V2, but quickly found out that there would be very few ways to add more features and convert it to follow the guidelines of OOP without overhauling some major parts, so I decided to start from scratch. The bouncing balls example we did in class inspired me to do a project on generative art using ants.

Four Tips to Keep Ants out This Spring · ExtermPRO

Fig.: A column of ants, hard at work carrying food back to their colony

The patterns formed by scout ants searching for food and then leading worker ants to the food using pheromones always fascinated me. I wanted to replicate something along those lines in a generative art project. Because this was generative art, most of it had to involve randomness in initial positions, direction, and motions. I first got to work to converting the bouncing balls to ants. For this, I also converted my simple speedX and speedY parameters to be calculated from polar coordinates instead. The hope was that using angles instead of plain coordinate directions would allow better control over the behavior when reflecting off surfaces. I also finally figured out how to set up the collision between two objects in p5.js, which I implemented as below:

collide(other) {
  var d = dist(this.x, this.y, other.x, other.y);
  if (d < this.rad + other.rad) {
  return true; 
  } else {
  return false;
  }
}
for (var j = 0; j < ants.length; j++) {
  if (i != j && ants[i].collide(ants[j]) && !(ants[i].collide(colony))) {
    ants[i].speedDir += PI/2;
    ants[j].speedDir += PI/2;
  }
}

I was initially having the ants go in opposite directions when they met, but decided that having them bounce off 90 degrees instead better matched the behavior of real ants, who often exchange information about the presence or lack of food along their already searched path and move off in different directions instead.

This is the final result:

Finally, I decided to add a bit of randomness to the motion to avoid having them go in exact straight lines and be a closer match to ant-like motion.

Overall, there are many more things that I wanted to include in this project, but figuring out direction and the p5.js rotate() function took the bulk of my time. I had initially planned to have user interactivity in the form of sugar cubes they could drop, which would cause all the ants nearby to rush towards it. But, I had already tired of the math required just to figure out which direction the ants would be oriented in when they bounced off the walls, and I wasn’t too eager for further math. If I have more time in the future, I would love to revisit this project and improve upon it.

Assignment 3 – Pixel Dragon, Redha Al Hammad

My third assignment started with experimentation rather than ideation. As I initially struggled to grasp the concept of OOP and how to implement it into my own work, I went through the examples provided and began to change different variables just to see how they affected the output.

After some time, I decided that I wanted to continue my theme of recreating natural experiences. I initially wanted to pursue this by expanding on the concept of my last assignment (sitting under trees) to “sitting under clouds”. The idea for this was to have clouds move smoothly with a Sine function and incorporate some interactivity using “if (mouseIsPressed == true)” such as lighting or rainfall. However, after implementing Sine movement to my object, I noticed that it felt more “alive” than something as passive as clouds. As I had already conceptually situated my idea in the sky, I decided to branch off from my original concept and create a scene which depicts the body of a dragon.

While I decided to only create the body as a result of my inexperience, I personally like the unique perspective of only viewing a small part of something that is intended to be big. I believe that films often use this technique of showing a small part of a large creature in order to produce a sense of scale without having to animate its whole body.

In terms of interactivity, I still incorporated “if (mouseIsPressed == true)” in order to simulate the (off-screen) effect of the dragon breathing fire. I did this by generating a random color palette within the range of a faded red – a greenish grey on the background when the user clicks on the mouse.

I a simple yet effective piece of code from this assignment which I am proud of would be the “shading” which I managed to produce on the dragon’s body by increasing the number of rectangles in the for loop and selecting two analogous colors for the fill and stroke. I have included the two examples together below.

 // spacing and for loop
 let spacing = width / 163;
  for (let i = 0; i < width; i += spacing) {
    manyRectangles.push( new SineRect(i, 10 + i * 2)  );
  }

/////////////////

// dragon's body color
  fill(140, 70, 70);
  stroke(80, 50, 50);

Some points of improvement going forward (beyond learning how to make a full dragon) could be to create a more realistic sky as the flat/cartoonish style of the clouds contradicts the smooth aesthetic of the dragon. I feel that I could have also made the sketch more interactive by allowing the user to interact with the dragons body in some way (e.g it moves when the mouse is pressed or it follows the mouse).


 

Assignment 3 & Reading Response – Shereena AlNuaimi

For this assignment, I drew inspiration from abstract paintings in general. That’s mostly because abstract paintings are essentially shapes layered on top of shapes, or at least that’s what we initially believed. The audience can learn that there’s more to an abstract artwork than meets the eye. which I attempted to include into my work.

Making this project more realistic in some manner and pushing myself to replicate at least one of Picasso’s paintings would be my best improvements, if there are any. But that will have to wait. The ellipses and circles that emerge when the mouse is clicked, which are larger than the squares themselves, is something I’m proud of.Overall, I’m somewhat proud of the outcome.

// Global variables to store the canvas and arrays of shapes and colors
let canvas;
let shapes = [];
let colors = [];
let numColors = 7; // Number of colors to generate

function setup() {
  createCanvas(600, 600);
  canvas = createGraphics(800, 600); // Create off-screen graphics buffer
  canvas.background(255); // Set background color of off-screen canvas

  // Draw background and shapes, generate colors, and apply colors to the off-screen canvas
  drawBackground();
  drawShapes();
  generateColors();
  tintColors();
}

// Function to draw the background of the off-screen canvas
function drawBackground() {
  canvas.noStroke(); 
  canvas.fill(255); 
  canvas.rect(0, 0, 600, 600); // Draw white rectangle covering the canvas
}

// Function to randomly generate and draw shapes onto the off-screen canvas
function drawShapes() {
  let numShapes = 50; // Number of shapes to draw
  let maxSize = 400; // Maximum size of shapes

  // Loop to create and draw random shapes
  for (let i = 0; i < numShapes; i++) {
    let x = random(canvas.width); 
    let y = random(canvas.height); 
    
    let size = random(50, maxSize); // Random size for the shape

    // Generate random fill and stroke colors for the shape
    let fillColor = color(random(255), random(255), random(255));
    let strokeColor = color(random(255), random(255), random(255));

    // Creates an object to represent the shape and adds it to the shapes array
    let shape = {
      x: x,
      y: y,
      size: size,
      fillColor: fillColor,
      strokeColor: strokeColor,
      shapeType: int(random(3)) // Randomly choose shape type (0: ellipse, 1: rectangle, 2: polygon)
    };

    shapes.push(shape); // Add the shape object to the shapes array
  }

  // Loop through shapes array and draw each shape onto the off-screen canvas
  for (let shape of shapes) {
    canvas.fill(shape.fillColor); 
    canvas.stroke(shape.strokeColor);
    canvas.strokeWeight(2); 

    // Draw different types of shapes based on their shapeType property
    if (shape.shapeType === 0) {
      canvas.ellipse(shape.x, shape.y, shape.size, shape.size); // Draw ellipse
    } else if (shape.shapeType === 1) {
      canvas.rect(shape.x - shape.size / 2, shape.y - shape.size / 2, shape.size, shape.size); // Draws rectangle
    } else {
      // Draws polygon with random number of vertices
      let numVertices = int(random(3, 8)); // Random number of vertices between 3 and 7
      let angle = TWO_PI / numVertices; // Angle between vertices
      let halfSize = shape.size / 2; // Half the size of the shape
      canvas.beginShape(); // Begin drawing a custom shape
      for (let a = 0; a < TWO_PI; a += angle) {
        let sx = shape.x + cos(a) * halfSize; // Calculate x-coordinate of vertex
        let sy = shape.y + sin(a) * halfSize; // Calculate y-coordinate of vertex
        canvas.vertex(sx, sy); // Add vertex to the shape
      }
      canvas.endShape(CLOSE); // End drawing the custom shape
    }
  }
}

// Function to generate random colors and store them in the colors array
function generateColors() {
  colors = []; // Clear the colors array
  for (let i = 0; i < numColors; i++) {
    colors.push(color(random(255), random(255), random(255))); // Generate random color and add it to the colors array
  }
}

// Function to apply tinted colors to the off-screen canvas
function tintColors() {
  let colorIndex = 0; // Initialize color index
  // Loop through the canvas in a grid pattern
  for (let y = 0; y < canvas.height; y += 50) {
    for (let x = 0; x < canvas.width; x += 50) {
      let c = colors[colorIndex % colors.length]; // Get the color from the colors array
      canvas.tint(c); // Apply tint with the color
      canvas.image(canvas, x, y); // Draw the off-screen canvas onto itself with the applied tint
      colorIndex++; // Increment color index
    }
  }
}

// Function called when mouse is clicked
function mouseClicked() {
  generateColors(); // Regenerate colors
  canvas.clear(); // Clear off-screen canvas
  drawShapes(); // Redraw shapes on off-screen canvas
  tintColors(); // Apply tinted colors
}

// Function called when mouse is moved
function mouseMoved() {
  generateColors(); // Regenerate colors
  canvas.clear(); // Clear off-screen canvas
  drawShapes(); // Redraw shapes on off-screen canvas
  tintColors(); // Apply tinted colors
}

// Main draw function to display the off-screen canvas onto the main canvas
function draw() {
  image(canvas, 0, 0); // Display off-screen canvas on the main canvas
}

Reading Response:

In the book “The Art Of Interactive Design”, Crawford delves into the concept of interactivity by addressing the misinterpretations of the term “interactivity” itself. He emphasizes the importance of the quality of each subtask for successful interaction, distinguishing between the genuine interactivity and instances where the terms is diluted. Moreover, Crawford introduces the concept of and “interactivity designer,” highlighting the specialized skills and consideration required for designing interactive experiences. The chapter concludes by addressing the resistance faces by interactivity designers.

In essence, this chapter provides a thought-provoking and insightful exploration of interactivity, challenging conventional understandings and advocating for a more comprehensive approach to designing interactive experiences. Crawfords perspective redefines interactivity but also emphasizes the need for a paradigm shift and integration of diverse expertise in the evolving field of interactivity design.

Week 3 Assignment – Khalifa Alshamsi

 

For this assignment, I drew inspiration from the rainfall in the UAE this past weekend, a truly cherished occurrence. Given my lack of color perception, I aimed to infuse this natural phenomenon with a vibrant spectrum of colors.

The Sketch:

Description:

The sketch simulates colorful raindrops falling against a light lavender background, which Is meant to be a blue-tinted window on a foggy morning; at least, that’s the color I see when I look at it. Each ‘raindrop’ object tracks its position, speed, and color. The raindrops reset once they fall off the bottom of the canvas, simulating a continuous rainfall.

Script:

// Defing the Raindrop's class 
class Raindrop {
  constructor() {
    this.x = random(width);
    this.y = 0; // Start from the top
    this.length = random(10, 20);
    this.speed = random(1, 5);
    this.color = color(random(255), random(255), random(255), 200); 
    // Semi-transparent
  }

  // Method to update raindrop properties for each frame
  fall() {
    this.y += this.speed;
    // Reset the drop when it goes off screen
    if (this.y > height) {
      this.y = 0;
      this.x = random(width);
      this.color = color(random(255), random(255), random(255), 200);
    }
  }

  // Method to draw the raindrop
  show() {
    stroke(this.color);
    line(this.x, this.y, this.x, this.y + this.length);
  }
}

let raindrops = []; // Array to hold Raindrop objects
const numDrops = 400; // Total number of raindrops

function setup() {
  createCanvas(640, 684);
  // Initialize raindrops
  for (let i = 0; i < numDrops; i++) {
    raindrops.push(new Raindrop());
  }
}

function draw() {
  background(230, 230, 250); // Light lavender background
  // Update and draw each raindrop
  raindrops.forEach(drop => {
    drop.fall();
    drop.show();
  });
}

Problems Encountered:

The challenge was ensuring the raindrops’ continuous flow and dynamic color changes without creating visual clutter. To address this, I implemented a reset mechanism for each raindrop once it fell off the screen and used semi-transparent colors to soften the visual impact.

Reading Response – Interactivity and Others

How can we define interactivity? I realize that the word “interactive” has been overused by many things that involve some kind of human’s action in it. However, I believe that similar to the reading, the human’s interaction with any object must also result in a response from the object. Hence, the object is interaction. To some sense, this is similar to having a conversation where the speaker expects a response from the listener. Furthermore, as in the reading mentioned, the interaction is just not simply the meaningless communication between communicators but it must involve the process of thinking in related to the given subject. It is worth noting that the level between the subjects in the interactive conversation should be similar.

Another aspect that interests me is the notion of whether interactivity is subjective. While the reading is trying define the term interactivity universally, I would like the think that interactivity is subjective. It does not limit to the functionality of the interaction, but I would rather argue that some interactivity are designed to target a certain group of people. For example, any interaction that requires a response from the text/quote questions without audio support could not consider as interactive to the young children who have not studied how to read yet. Each design for interaction seems to target a certain subject group, or all, but it is certain that interaction is not universal in my opinion.