Week 5 – Reading Response | COMPUTER VISION FOR ARTISTS AND DESIGNERS

When I think of Computer Vision, the first thing that comes to my head is this coder called the Poet Engineer on social media who uses computer vision to create the most insane visuals purely from the camera capturing their hand movements. They have the coolest programs ever. I also love it when artists make videos of them creating cool things with their hands purely through code, and one of my favourite examples of using code to create art is Imogen Heap’s MiMu gloves. And, also, the monkey meme face recognizer I keep seeing everywhere (photo attached). It still baffles me that we can use our hands and our expressions to control things on a device that usually interacts with touch! So, this reading was one of my favourite readings so far, because it discussed one of the main concepts that hooked me into interactive media in the first place. 

From what I understood of the text, the primary difference between computer and human vision is that while a human observer can understand symbols, people or environmental context like whether it’s day or night, a computer (unless programmed otherwise) perceives video simply as pixels. Computer vision uses algorithms now to make assertions about raw pixels, and even then, designers need to optimize the physical environment to make it “legible” to the software, such as using backlighting to create silhouettes or using high-contrast and retroreflective materials. Despite these limitations, is it still not insane that we’ve evolved so much that we can make computers identify specific things now, despite it being a computer? The fact that now computers can have hardware that goes beyond our own capabilities, such as infrared illumination, polarizing filters and more is almost scary to think about. I’d also say that computer vision is much more objective than human vision. Is it possible for computers to suffer from inattentional blindness as much as we do? For example, when we enter a room and fail to see something and then we come back and the object is right there and it never moved, is a computer capable of the same thing?

I liked that this reading stated down the different techniques used in computer vision, because when I originally understood CV, I was overwhelmed by the amount of things it could sense. I understood these techniques (and I’m listing them down so I can refer to them later as well):

  1. Frame Differencing / Detecting Motion: Detects motion by comparing each pixel in a video frame to the corresponding pixel in the next frame.
  2. Background Subtraction / Detecting Presence: Detects the presence of objects by comparing the current video frame to a stored image of an empty background.
  3. Brightness Thresholding: Isolates objects based on luminosity, by comparing brightness to a set threshold. (I did an ascii project a few years ago, where it would capture your image, figure out the contrast and brightness and then replicate the live video input as letters, numbers and symbols. I would like to replicate that project with this concept now!)
  4. Simple Object Tracking: Program computer to find the brightest or darkest pixel in a frame to track a single point. 
  5. Feature Recognition: Once an object is located, the computer can compute specific characteristics like area or center of mass (this is CRAZY). 

There are definitely more techniques that are out there, but I’ll start off with the basics, since I’m a complete beginner at this. I did want to try using feature recognition paired with simple object tracking, something I noticed is used in hand tracking (and the monkey video. LOL).

I mentioned the objectivity of CV earlier, but what happens if the datasets that they are trained on are biased? What if the creator behind the program has their own biases that they implement into the program? I like how Sorting Daemon (2003) mentioned looking at the social and racial environment, because I was wondering about situations where CV could be programmed to unintentionally (or intentionally) discriminate against certain traits such as race, gender, or disabilities. Surveillance is a scary concept to me too, because what happens to the question of consent?  While computer vision could be used to reveal hidden data in environments that are often overlooked, create programs that can help people without the need for a human to be present (e.g. Cheese), and so many other cool things, it could also be used in a negative way. I need to make sure to find a way that any programs I create with CV are inclusive and not used for ill intent.

Week 4 – Reading Response | THE PSYCHOPATHOLOGY OF EVERYDAY THINGS

When I was younger, like every other midrange Gen-Z kid, I used to scroll on Buzzfeed as much as I could in class in middle school. The quizzes, the news, and the articles. I remember there would be lists of things in articles (25+ times X did Y! or 45+ gifts to get your X on Y!), and I’d find the ones about bad design choices really funny. Seeing the assignment for this reading response reminded me of these articles, so here are my own personal favourite (well, least favourite) bad design choices:

  • Microsoft Office’s “Save As” option. Schools here love using Office365, so we would use it for EVERYTHING. Class notes, essay drafts and final essays, powerpoints and even calling your friends during COVID. However, one thing that frustrated us throughout, was that in order for you to save your document, rather than letting you save it to your most active parent folders, it always, ALWAYS defaults to some remote directory, usually the OneDrive Cloud directory. Maybe I’m being dramatic, but this was a nightmare for us, because we were all living under a timer. Our schools would delete our OneDrives almost as soon as we would leave the school or graduate.

I get that this may be a marketing tactic to get people to use their products more, but maybe they could also consider getting people to LIKE the usability of their products more too. I’m not sure if they’ve made it easier now because I’ve switched and resorted to using Google sites more (easier sharing, easier saving, etc.). If I was to change this product in a non-marketing mindset, I would just make an option to save it to your folders next to the option to save it to your drive. If you want people to save it to OneDrive, you could just add that button first, but also have the other button there too.

  • Apple’s alarm sounds before iOS 17. I’m an avid user of Apple alarms, and I use Apple’s alarm sound that is literally titled “Alarm.” It sounds a lot like an alarm, in more of a ‘fire alarm, I need to run’ way and not a ‘wow, I could dance myself to be awake right now’, but it was one of Apple’s most used alarms nonetheless. Unfortunately, after updating my phone to iOS 17 (I had no choice), I realized that I couldn’t find that sound unless I scroll alllllll the way to the bottom of the list of alarm sounds, and then afterwards, you’d need to press on a button called “classic”, and THEN ONLY do you see the sound. As someone who is an avid alarm user every day and sleeps through them all (thus, the need for me to set 8-9 alarms every morning at varying times), I prefer having the same sound for all of them. It’s a hassle to individually change the sound each time.

Maybe it’s not as serious as I’m making it, and maybe the newer sounds are actually better. I haven’t listened to them yet. However, I don’t like the alarm sound interface in general. Regarding this problem in specific, however, would it not be easier to start off with two categories (‘new sounds’ and ‘old sounds’) and then users could decide whether they wanted the newer or the classic sounds? Rather than listing all the newer ones and then having to scroll and then click to see the older ones, it would be easier to sort it from the beginning.

The examples in this reading were very relatable, especially the example of the doors. I hate it when I push a door and it doesn’t push, so I need to pull it, but there is no way I could have known that it was a ‘pull’ door and not a ‘push’ door. I’ve bumped into the revolving doors at Galleria so often that now I need to stick my hands in front of me so I don’t hit my head. There were some principles that were mentioned in the text in regards to Human-Centered Design, which were affordances / signifiers / mapping / feedback / constraints. I was surprised that I hadn’t seen these principles before, because they made a lot of sense to me. It’s also one thing to understand a product, but you need to be able to discover the product well enough to understand it. If a product doesn’t follow HCD and we don’t understand it, what is the point? To apply the author’s principles of design to Interactive Media, maybe it’s a good idea to keep the user in mind. Rather than focusing on affordances of a product, I should focus on the signifiers instead, because they tell you how you can use the product the way it is meant to be used, not how to use the product for every possible use you can probably think up of. I want to look a bit more into UI/UX design in regards to mapping, because I think that would be much more useful. If I take all of these principles into account, I can make projects that are not only fun and interactive, but also understandable and used the way they are intended to.

Week 4 – Click to affirm, I guess? (Generative Text and Data Assignment)

Concept:

I really like Frutiger Aero, and I love things that are designed so badly that they just become funny and it actually works. I’ve fallen victim so many times to buying products with designs that were just so ugly and horrendous that it made me laugh. Lately, on my Pinterest, I keep seeing these stupid affirmation memes with really loud and emphatic text and completely random background and this horrendous gradient border. Naturally, I was so drawn to it, that now I have these stuck up on my wall back home. My parents are frustrated. My sister loves it.

I’m not a fan of making the same thing as something I see, but since I’m still a beginner to Javascript, I wanted to make something that I would enjoy making, especially in such a short period of time. So, I decided to make my own version of these. I hope you find this as funny as I do.

Artwork:

(I laughed a lot while making this.)

Process:

I had to make so many sections and so many functions and so many variables and etcetera, etcetera. Firstly, I had to import each image into the program, and I named each image by number so that importing them would be easier. I also made a list of affirmations I found online and through my friends onto a spreadsheet and imported it as a .csv file. Since I wanted the option of inputting your own affirmations, I made another list for user input.

function preload(){
  table = loadTable('Affirmations.csv','csv'); //csv file
  for (let i=0; i < totalImages; i++)
  {
    images.push(loadImage(i+'.jpg'));
  }
}

I loaded each row from the .csv file.

// load from csv file (I'm starting on row 2 because header lol)
 for (let r = 2; r < table.getRowCount(); r++){
   let line = table.getString(r,0);
   if (line) Affirmations.push(line); // prevent empty
)

After adding user input, I made a function to generate a new image every 3 seconds. There were multiple steps I had to take for this, which were:

FIRSTLY! Pick a random nature image:

let nextImgIndex;
  do {
    nextImgIndex = floor(random(images.length));
  } while (nextImgIndex == lastImgIndex);
  currentImg = images[nextImgIndex];
  lastImgIndex = nextImgIndex;

SECONDLY! Pick which list is currently active (the .csv file or the user input list):

let activeList;
if (modeCheckbox.checked() &&
   userAffirmations.length > 0) {
  activeList = userAffirmations;
} else {
  activeList = Affirmations;
}

THIRDLY! Pick a random affirmation from the chosen list:

if (activeList.length > 0){
   let nextTextIndex;
   do {
     nextTextIndex = floor(random(activeList.length));
   } while (nextTextIndex === lastTextIndex && activeList.length > 1);
   
   currentText = activeList[nextTextIndex];
   lastTextIndex = nextTextIndex;
 }

FOURTHLY! Add glow. Yay!

colorMode(HSB, 360, 100, 100);
 glowColor = color(random(360), 85, 100);
 colorMode(RGB);

For drawScene(), I used this code. I realized I could crop the nature images in the code (code is so cool… wow) so I did it in this.

function drawScene() {
  if (!currentImg || currentImg.width <= 1) return;

  // automatic crop image to square size
  let imgAspect = currentImg.width / currentImg.height;
  let canvasAspect = width / height;
  let sx, sy, sw, sh;
  if (imgAspect > canvasAspect) {
    sh = currentImg.height;
    sw = sh * canvasAspect;
    sx = (currentImg.width - sw) / 2;
    sy = 0;
  } else {
    sw = currentImg.width;
    sh = sw / canvasAspect;
    sx = 0;
    sy = (currentImg.height - sh) / 2;
  }
  
  image(currentImg, 0, 0, width, height, sx, sy, sw, sh);
  drawGlowBorders();

  // text style
  let txt = currentText;
  let maxWidth = width * 0.85;
  let fontSize = constrain(map(txt.length, 0, 50, 80, 40), 35, 90);

  push();
  translate(width / 2, height / 2);
  scale(1, 1.7); 
  textAlign(CENTER, CENTER);
  textFont('Arial');
  textStyle(BOLD);
  textSize(fontSize);

  drawingContext.shadowBlur = 30;
  drawingContext.shadowColor = glowColor.toString();
  fill(255);
  noStroke();
  
  text(txt, -maxWidth/2, -height/3.4, maxWidth, height/1.7);
  
  drawingContext.shadowBlur = 0;
  text(txt, -maxWidth/2, -height/3.4, maxWidth, height/1.7);
  pop();
}

I thought the glow borders at the very end were really funny to figure out, but this is what I ended up with.

function drawGlowBorders() {
  let bSize = 45;
  noFill();
  for (let i = 0; i < bSize; i++) {
    let alpha = map(i, 0, bSize, 180, 0);
    stroke(red(glowColor), green(glowColor), blue(glowColor), alpha);
    strokeWeight(1);
    rect(i, i, width - i*2, height - i*2);
  }
}

Reflection:

There’s a lot of things I want to improve. Obviously, with the current skill level and time that I have, I don’t think this would be feasible, but I wanted to make sure you could save your custom affirmations into a file you can download later. I also wanted to let you delete affirmations you didn’t like and add more (database management? I guess?).  I also found out that .csv files cannot store images, so I was limited to using only 21 images for now. I honestly made this so it could double not only as an assignment but also a funny thing for my friends to laugh at, so I think I achieved this, but I would like to play more with the generative aspect and data aspect of this. The text itself on the screen is not interactive (e.g. if I click it, nothing happens) and the data is not really visualized, more being used as a list to remove the need to individually type each affirmation into the code. I’m glad I figured out parts of the code that I know in Python though (like input) so hopefully that should make future projects easier.

Week 3 – Oops… cells!

Concept:

My mom is a Pathologist, and when I was younger, she was fascinated in showing me cells under a microscope from blogposts on Facebook (her feed was a very nice spectrum of plant care and medical studies). I never took biology in school (I’m more of a physics person), but I always found these images really fascinating. So, I thought I would try and recreate cells (very unrealistically) using Javascript. In middle school, when we were taught about cells, we saw cells as this blobby, almost round, jelly-looking circle with things inside of them. While I only remember a few organelles such as the mitochondria and the nucleus, I thought it would be interesting to include these when making the cells. These say skin cells but it’s the closest I can get to explaining what I have in mind:

Artwork:

(Click the screen to generate new cells!)

Process:

I experimented a lot this time, especially with the motion and shapes of the cells. I had two classes, one for the organelles and one for the cells themselves. This is the class code for the organelles:

class Organelle {
  constructor(type, relX, relY, hue) {
    this.type = type;
    this.relX = relX;
    this.relY = relY;
    this.hue = hue;
    this.angle = random(TWO_PI);
    this.spin = random(-0.02, 0.02);
  }

  display(px, py, radius) {
    push();
    translate(px, py);

    let floatX = this.relX + sin(frameCount * 0.02 + this.angle) * 5;
    let floatY = this.relY + cos(frameCount * 0.02 + this.angle) * 5;

    translate(floatX, floatY);
    rotate(frameCount * this.spin);
    noStroke();

    if (this.type === "nucleus") {
      // Hematoxylin stain: Deep purples/blues
      fill(280, 70, 40, 0.9);
      ellipse(0, 0, radius * 0.4);
      fill(280, 80, 20, 0.9);
      ellipse(0, 0, radius * 0.15);
    } else if (this.type === "mito") {
      // Eosin stain: Deeper pink
      fill(340, 60, 70, 0.8);
      ellipse(0, 0, 14, 8);
    } else if (this.type === "crystal") {
      // Hexagon shape in vibrant magenta
      fill(320, 80, 80, 0.7);
      beginShape();
      for (let a = 0; a < TWO_PI; a += PI / 3) {
        vertex(cos(a) * 8, sin(a) * 8);
      }
      endShape(CLOSE);
    } else if (this.type === "ring") {
      // Ring shape in light purple/pink
      noFill();
      stroke(300, 40, 60, 0.7);
      strokeWeight(2);
      circle(0, 0, 16);
    }
    pop();
  }
}

I used H&E staining as a reference for the color scheme to mimic cell scans. For this, there were multiple shapes I used:

  1. Nucleus (filled in circle at the center of the cell)
  2. Mitochondria (filled in ellipses)
  3. Rings and Hexagons for random organelles

These are then randomly generated in each cell.

This is the class code for the cells:

class Cell {
  constructor(x, y) {
    this.pos = createVector(x, y);
    this.baseRadius = random(40, 90);
    this.radius = this.baseRadius;
    
    // Constraint to Eosin spectrum (Pink/Magenta)
    this.hue = random(325, 350); 
    
    this.noiseOffset = random(1000);
    this.organelles = [];
    this.pulseSpeed = random(0.01, 0.03);
    this.rotation = random(TWO_PI);
    this.spin = random(-0.002, 0.002);

    this.organelles.push(new Organelle("nucleus", 0, 0, this.hue));

    let count = floor(random(3, 8));
    let types = ["mito", "crystal", "ring"];
    for (let i = 0; i < count; i++) {
      let angle = random(TWO_PI);
      let dist = random(this.baseRadius * 0.2, this.baseRadius * 0.7);
      let rx = cos(angle) * dist;
      let ry = sin(angle) * dist;
      this.organelles.push(new Organelle(random(types), rx, ry, this.hue));
    }
  }

  move() {
    this.pos.x += map(noise(this.noiseOffset), 0, 1, -0.8, 0.8);
    this.pos.y += map(noise(this.noiseOffset + 100), 0, 1, -0.8, 0.8);
    this.noiseOffset += 0.005;
    this.rotation += this.spin;

    // Breathing pulse
    this.radius = this.baseRadius + sin(frameCount * this.pulseSpeed) * this.baseRadius * 0.1;

    // Screen Wrap
    if (this.pos.x > width + this.radius) this.pos.x = -this.radius;
    if (this.pos.x < -this.radius) this.pos.x = width + this.radius;
    if (this.pos.y > height + this.radius) this.pos.y = -this.radius;
    if (this.pos.y < -this.radius) this.pos.y = height + this.radius;
  }

  display() {
    push();
    translate(this.pos.x, this.pos.y);
    rotate(this.rotation);

    // Soft Eosin cytoplasm layers
    for (let layer = 1.2; layer > 0.8; layer -= 0.1) {
      noStroke();
      fill(this.hue, 30, 95, 0.15); 
      beginShape();
      for (let a = 0; a < TWO_PI; a += 0.1) {
        let xoff = map(cos(a), -1, 1, 0, 1.5);
        let yoff = map(sin(a), -1, 1, 0, 1.5);
        let offset = map(noise(xoff, yoff, frameCount * 0.01), 0, 1, -10, 10);
        let r = (this.radius + offset) * layer;
        vertex(cos(a) * r, sin(a) * r);
      }
      endShape(CLOSE);
    }

    // Main Cell Membrane Outline
    noFill();
    stroke(this.hue, 50, 70, 0.6);
    strokeWeight(2);
    beginShape();
    for (let a = 0; a < TWO_PI; a += 0.1) {
      let xoff = map(cos(a), -1, 1, 0, 1.5);
      let yoff = map(sin(a), -1, 1, 0, 1.5);
      let offset = map(noise(xoff, yoff, frameCount * 0.01), 0, 1, -10, 10);
      let r = this.radius + offset;
      vertex(cos(a) * r, sin(a) * r);
    }
    endShape(CLOSE);
    pop();

    for (let o of this.organelles) {
      o.display(this.pos.x, this.pos.y, this.radius);
    }
  }
}

For the cells to breathe, move and change shape, I used Perlin Noise and sin() functions. I also included screen wrapping to make sure no cell would wander off screen. This part was difficult for me, so I did get some help from my friends. Making the constantly changing shape and boundary of the cell was also especially difficult for me but I’m glad it turned out the way it did.

Reflection:

I liked working with classes! It makes it much more organized (I think… as of now…) and I’m able to separate parts. It was definitely hard though, because I’m primarily a Python user so this threw me off, but it was a good challenge. I want to try and create more projects using OOP now, and try to link more of my interests to making projects like this. I did ask ask my mom for help with the colors and stains, so hopefully she approves of this! I want to experiment more with cell lifespans and cell shapes, maybe set a certain amount of time before a cell “dies” and disappears or set a condition to generate new cells every once in a while too.

Week 3 – Reading Response | THE ART OF INTERACTIVE DESIGN (Chris Crawford)

As a designer, there’s one phrase I find really funny that people ask me: “Can you make it more interactive?” This confuses me immensely. Do you want me to make it “pop” out more? More interactions on your social media posts? Are you expecting something else but you can’t think of the exact word to sum all your thoughts up so instead you tell me to make it more interactive? What do you mean? Thus, I 100% agree with all, if not most, statements that Chris Crawford makes in this reading. Interactivity is “overused and underunderstood.” Just like any other concept (think common internet words and phrases today like “hyperfixation” or “gaslight / gatekeep / girlboss”), interactivity is also one of those words that we didn’t originally know the importance of when it first came out, but now that we live in such a technologically advanced (and advancing) world, we see that word everywhere. And, if you asked someone to define what exactly interactivity is… well. You won’t receive the same definition twice.

I liked how he brought up the example of people using interactivity as a way to make things sound interesting. Interactive screen! Interactive book. Interactive art. Interactive clothes. Shoes. You see them in adverts all the time now. Interactive exhibitions. Interactive events. Washing machines with interactive interfaces. Are we using this term correctly? What is the actual definition of interactivity?  When thinking of defining interactivity, he states, “the joy of thinking comes from all of those fascinating nooks and crannies that lurk in nuance.” Could this not also be applied to defining art? There are so many flexibilities in defining what art exactly is, because we all have such varying definitions of what we determine is art or not. So, anything can be considered interactive, because everyone interacts with things differently… right? 

I also found his definition interesting, interaction as “a cyclic process in which two actors alternately listen, think and speak.” In Understanding Interactive Media, we discussed interactivity as feedback loops. I, the artist, act a certain way. My audience acts a certain way in response. Then, to their response, I change the way I act too. Even when artists study art, they create an artwork, they see how others react to it and act accordingly, some responses being an art teacher calling their work trash, or a person on the internet sending a comment of how much they like their artstyle. The Gomer and Fredegund example is similar to this. I also never really considered interaction existing in degrees, which surprised me. I liked the comparison of degrees of interaction to having two different conversations where you talk in one and the other person barely responds to you, and another conversation where you both flow really well. They both are interactive! They’re just different degrees of interactions.

In a strongly interactive system, I think the degree of interaction should be very high – there should be a very prominent feedback loop. For example, if an artwork starts off as the color green, and I don’t like that and I say I don’t like this color, it changes to orange. And, I can tell it again, and it can change if it can. However, even with this example, the artwork follows my instructions and doesn’t adapt. It is simply following my instructions and not actually responding. The system should be able to respond to the audience’s conversation. Regarding what ideas I have for improving the degree of user interaction in my P5 sketches, I think I’m yet to figure this out. I do feel like when I create a design, I don’t think too much about interaction and visuals separately. I unintentionally put them together and work with them together, because a good design should have both working collaboratively, not side by side. I’ll probably be more intentional when I design now, though.

Week 2 – Reading Response | Casey Reas @ Eyeo2012

There is often a debate about how the universe works. Are we really in control of what decisions we make, or has some otherworldly being already written them for us? Is destiny real? Are the things we deem unpredictable actually predictable, and when people say they’re unpredictable… are they really? 

These same questions can be made about artwork. Older (“traditional”)  artwork was very methodical; we could fit artwork into different “eras,” find commonalities within artworks in certain eras, understand a very specific technique that artists would follow during a certain period of time or in a certain geographical area. However, now with our unlimited access to the internet and the rise of globalization, art has branched out significantly. We have shifted from order to chaos – we have people raising questions about which artwork is better (the usual digital versus traditional artwork battle), who decides what art is, and whether that shovel in the corner can actually even be considered artwork! (For this one, we’ll have to ask Duchamp himself.)

I found this talk interesting and I found that many arguments linked to my conversations in other classes. In Understanding Interactive Media, we discussed procedural art; art that is more focused on the process, and not the end product itself. One example I want to discuss in relation to this video is Sol Lewitt’s “Wall Painting”. In this artwork, the same set of instructions are given to everyone – draw 50 points anywhere on a continuous stretch of wall, and then draw lines connecting these dots. Yet, every artwork that comes from these instructions come out differently – super random! The reason I bring this up is because I feel that in this video, we discuss whether there is true randomness in artwork. Randomness allows you to remove your own egos and “preconceived notions” from creative processes (or at least, that’s what artists like John Cage and Marcel Duchamp believe). Randomness is a jumping-off point to get outside your own ideas of correctness.

The thing with algorithms, however, is that even when you code something to be random, there may eventually be a point that the code reaches where it stops being random, especially in generative art. Depending on the complexity of the code, it may become the same earlier, or may take a very long time, but Reas discovered that it eventually will reach homogeneity. Humans cannot replicate the same drawing the exact same ever, but computers can eventually. Hence, how random really is randomness? You can add some randomness to keep a system homeostatic, to keep it consistent but also remain dynamic, but even then, this is still a confusing concept to me. Even with the example of Mondrian explaining that the grid can still be used to represent pure feeling, through his physical brushstrokes being visible, that made me wonder about the difference in human and computer artwork.

In regards to making my own generative artwork, I made it before watching the video completely. Even when making it, I knew that no two artworks would be the same at the beginning, but eventually, at some point (whether it be in a thousand runs or even millions), there will be a moment where my artwork will be the same as another iteration earlier. Thus, maybe we can also acknowledge randomness depending on scale and complexity. Maybe the art we code doesn’t have to be 100% random, because maybe we will never be able to reach that certain percentage. However, within the percentages we can reach, we can play around with them and have fun.

Week 2 – Generative Artwork

Concept:

I’m very new to the concept of generative art, and so I found myself struggling to come up with an idea for this project. Upon scrolling through some of the resources provided to us, I was inspired by this one artwork in Computer Graphics And Art (May, 1978), “Simulated Color Mosaic” by Hiroshi Kawano, and I liked how randomized the blocks were. Thus, I wanted to try and create an algorithm that would allow for a different randomized result at each run or click. No two patterns would look the same (hopefully). In order to create these blocks to be randomized, however, I needed to find an algorithm that would let me create blocks randomly, or at least have some planned out randomness (reference to the reading… haha).

Artwork:

(Click the screen to create a new pattern!)

Process:

To create this, I had to first come up with how to create a different pattern each time. Thus, I decided to create the variable blocks, so I could perform actions on it. It was an array, so it could hold many blocks that would be generated on each run. The block then had specific elements (blocks.push({ x: 0, y: 0, sz: 600, black: false })); it would start off at a size bigger than the canvas (to create bigger blocks) and then have a condition of black:false to edit the color of each block.

Afterwards, to draw the blocks, it would firstly go through every square, staring with a block and then targeting it to split it in half and so on. For this, I used this condition:

function draw() {
  background(randomColor);

  // go through every square
  for (let i = blocks.length - 1; i >= 0; i--) {
    let b = blocks[i];

    rect(b.x, b.y, b.sz, b.sz);

    if (blocks.length < 400 && b.sz > 30 && random(1) < 0.05) {
      splitBlock(i);
    }
  }
}

function splitBlock(index) {
  let b = blocks[index];
  let newSz = b.sz / 2;

  blocks.splice(index, 1);

  for (let x = 0; x < 2; x++) {
    for (let y = 0; y < 2; y++) {
      blocks.push({
        x: b.x + x * newSz,
        y: b.y + y * newSz,
        sz: newSz,
        black: random(1) < 0.4 ? !b.black : b.black
      });
    }
  }
}

It draws the block, and then to split the block, it checks the array and size to make sure it splits blocks of a certain size (not too big nor small boxes) and under the limit of 400 blocks in the screen (not too high to lag but also at a lower size so you can see more variation in size of bigger blocks). There’s many random possibilities for the blocks splitting to make sure that the pattern is different each time.

Then, to reset the artwork when it is pressed, I used a different function:

function mousePressed() {
  blocks = [{ x: 0, y: 0, sz: 600, black: false }];
}

Originally, I was planning on keeping the artwork black and white (similar to the inspiration). However, after creating the code, I decided to add color to it. However, instead of just having the same color each time, I added code to change color on every reset.

I added two more variables, randomColor and randomColor2. In setup(), before starting to add the blocks, I set the colors to random with this code:

randomColor = color(random(255), random(255), random(255));
randomColor2 = color(random(255), random(255), random(255));

After, I also set this condition:

if (b.black) {
     fill(randomColor2);
   } else {
     fill(randomColor);
   }

I wrote in the code earlier, black: random(1) < 0.4 ? !b.black : b.black. This was to change the colors of some blocks randomly so it wouldn’t all accidentally end up the same color. Finally, I also added the random code again in mousePressed(), so it would reset into different colors again.

This is the final code:

let blocks = [];
let randomColor;
let randomColor2;

function setup() {
  createCanvas(500, 500);
  noStroke();

  randomColor = color(random(255), random(255), random(255));
  randomColor2 = color(random(255), random(255), random(255));

  blocks.push({ x: 0, y: 0, sz: 600, black: false });
}

function draw() {
  background(randomColor);

  // go through every square
  for (let i = blocks.length - 1; i >= 0; i--) {
    let b = blocks[i];

    if (b.black) {
      fill(randomColor2);
    } else {
      fill(randomColor);
    }

    rect(b.x, b.y, b.sz, b.sz);

    if (blocks.length < 400 && b.sz > 30 && random(1) < 0.05) {
      splitBlock(i);
    }
  }
}

function splitBlock(index) {
  let b = blocks[index];
  let newSz = b.sz / 2;

  blocks.splice(index, 1);

  for (let x = 0; x < 2; x++) {
    for (let y = 0; y < 2; y++) {
      blocks.push({
        x: b.x + x * newSz,
        y: b.y + y * newSz,
        sz: newSz,
        black: random(1) < 0.4 ? !b.black : b.black
      });
    }
  }
}

// reset when press screen
function mousePressed() {
  randomColor = color(random(255), random(255), random(255));
  randomColor2 = color(random(255), random(255), random(255));

  blocks = [{ x: 0, y: 0, sz: 600, black: false }];
}
Reflection

The loops were confusing. I spent a a while trying to figure this out (much longer than I would have liked) and I think the outcome is okay, but I definitely want to explore creating more artworks that are more complex. The logic took more time to create than the actual code, but it was fun nonetheless. Next time, I would like to work a bit more with colors and shapes, and create a more interesting animation. It’s okay right now but it could be so much better. I really do like the color combinations I’ve been getting! Maybe I could make a color palette generator for my artworks later… or add more colors to this… we’ll see. I’m still not completely confident about loops and conditionals in Javascript, so I hope to get better with more practice.

Week 1 – Self-Portrait

Concept:

Lately, on my TikTok feed, I keep seeing these square profile pictures which look really cute. I tried to generate my own version of it online, but then the website required me to use Flash… which I do not have. Oops. So, when I was coming up for an idea for my self-portrait during lab on Thursday last week, I thought I could probably just make this by myself, right?

I wanted to make three different versions of the profile picture: one that (somewhat) resembled me normally, one that resembled me when I am tired (me 70% of the time) and one that was fun and colorful. I would use the same base code, so that I wouldn’t need to make completely different faces, but would change some aspects so that the faces would still have some clear changes (e.g. closed vs. open eyes, different color schemes, accessories etc.).

To switch between the three different faces, I would make buttons at the bottom of a screen as a panel. I wanted to make each face more interactive, but I was worried that it would interfere with the faces and the buttons programming, so I’ll work on it once I learn the language better.

Process:

Firstly, before actually deciding on the panels and buttons, I had to figure out how I was even going to code the face. I started with the hair as the background color, making a long ellipse for the face and then adding circles for the bangs. After, I created the eyebrows and eyelids with even more ellipses (I think I may have abused the ellipse() tool…), and the eyes on top (for layering purposes). I used the ellipse with noFill() to create the glasses, and then to make the mouth, I used triangles. Most of the face was just trying and testing out shapes and coordinates, which took me around two hours. However, once I figured out the first face, it didn’t take me that long (only an hour or so) to edit and modify the other faces.

To make it easier, I also coded a line to make sure I could navigate the coordinate system better rather than trial and error-ing again and again.

For the third face, I used this code for the star hair clip. I struggled quite a bit, but I asked one of my friends for help, and we came up with this:

function star(x, y, radius1, radius2, npoints) {
  let angle = TWO_PI / npoints;
  let halfAngle = angle / 2.0;
  beginShape();
  for (let a = 0; a < TWO_PI; a += angle) {
    let sx = x + cos(a) * radius2;
    let sy = y + sin(a) * radius2;
    vertex(sx, sy);
    sx = x + cos(a + halfAngle) * radius1;
    sy = y + sin(a + halfAngle) * radius1;
    vertex(sx, sy);
  }
  endShape(CLOSE);
}
    strokeWeight(3);
    fill(255, 247, 161);
    star(200, 220, 70, 150, 5);

After, I had to create the buttons. I created a new file (so I could just copy and paste the face codes into the file after I programmed the buttons), and I used this as the code:

let currentScene = 1;

let btnSize1 = 200;
let btnSize2 = 150;
let btn1X = 20,btn1Y = 725;
let btn2X = 240,btn2Y = 725;
let btn3X = 460,btn3Y = 725;

 function setup() {
  createCanvas(700,900);
 }
  
 function draw() {
  background(220);
  
//state
  
  if (currentScene === 1){
    drawImage1();
  } else if (currentScene === 2){
    drawImage2();
  } else if (currentScene === 3){
    drawImage3();
  }
   
// panel
   
  fill(251,251,251);
   noStroke();
  //x y w h
  rect(0, 700, 700, 200); 

// buttons
   
   //1
  fill(217, 93, 83); 
  rect(btn1X, btn1Y, btnSize1, btnSize2);
  fill(0);
   
   //2 
  fill(161, 126, 140); 
  rect(btn2X, btn2Y, btnSize1, btnSize2);
  fill(0); 
   
   //3
  fill(66, 164, 255); 
  rect(btn3X, btn3Y, btnSize1, btnSize2);
  fill(255);

 } 
  function mousePressed(){
    
  //button 1
    
  if (mouseX > btn1X && mouseX < btn1X + btnSize1 && mouseY > btn1Y && mouseY < btn1Y + btnSize2) {
    currentScene = 1;
  }
    
  //button 2
    
    if (mouseX > btn2X && mouseX < btn2X + btnSize1 && mouseY > btn2Y && mouseY < btn2Y + btnSize2) {
    currentScene = 2;
  }
    
  //button 3
    
    if (mouseX > btn3X && mouseX < btn3X + btnSize1 && mouseY > btn3Y && mouseY < btn3Y + btnSize2) {
    currentScene = 3;
  }
    
}
   
function drawImage1(){
  // code for first expression;
  
}

function drawImage2(){

// code for second expression;

}
   
function drawImage3(){
 
// code for third expression;

}

   
note: I realized I put the wrong coordinates for the buttons, so now there's more space on the right than the left. I'll fix it soon.
note2: I used the resources from p5.js tutorials, references and examples for most of the code.
Reflection and Possible Improvements:

I had been pushing this off for a while because I was scared it would take too long and I would not be able to create something I would be satisfied with. However, I think this turned out better than I expected! I’m happy with the button interaction and the facial expressions.

I really do want to work with adding more interactivity in the future and maybe also coding an animation (such as spinning the star and flower hair clips in the ‘happy’ expression or waking my picture up for the ‘tired’ expression). I would really like to experiment with adding more features once I become more confident with loops and putting commands within commands, since the many lines of code for each face threw me off and made it hard for me to navigate where one command started and ended. (Oops.)