Luke Nguyen – Midterm

 

 

Overall concept:

When I was a kid, I was obsessed with the game Chicken Invaders. I remembered spending 2-3 hours playing it every time I was free from school and homework. It was a way of life for my PC back then. And so, I wanted to emulate the engine of that game for this mid-term project and have fun creating it. I call my interactive game “Alien Slayer.”This is my initial sketch/design for the game. I ended up not following up in terms of arranging the aliens. This is because I approached designing the game using arrays and randomness. And creating lines of aliens did not feel realistic at all.

 

How the project works:

Here are the images of the game that use:

I found a sprite sheet for the spaceship and edited it down into just 4 basic movement directions.

The rules of the game are very intuitive: to kill all the aliens. That said, the number of aliens generated and the speeds at which they ascend down the screen are randomized using this:

if (random(1) < 0.008) {
    aliens.push(
      new alien(
        width / 10,
        width / 10,
        random(width - 40),
        random(-10, 0),
        random(1, 3)
      )
    );
  }

So the difficulty of the game is randomized throughout the game.

The spaceship is first created and placed at the starting position using the class:

class spaceship {
  constructor(w, h, x, y, direction, speed) {
    this.w = width/10;
    this.h = height/10;
    this.x = width/2;
    this.y = height - 60;
    this.direction = 0;
    this.speed = 5;
  }

  move() {
    if (keyIsPressed) {
      if (keyCode == UP_ARROW) {
        if (0 < this.y) {
          this.direction = 0;
          this.y -= this.speed;
        }
      }

      if (keyCode == DOWN_ARROW) {
        if (this.y < height - this.h) {
          this.direction = 1;
          this.y += this.speed;
        }
      }

      if (keyCode == LEFT_ARROW) {
        if (0 < this.x) {
          this.direction = 2;
          this.x -= this.speed;
        }
      }

      if (keyCode == RIGHT_ARROW) {
        if (this.x < width - this.w) {
          this.direction = 3;
          this.x += this.speed;
        }
      }
    }
  }

  display() {
    if (this.direction == 0) {
      image(spaceshipUP, this.x, this.y, this.w, this.h);
    }

    if (this.direction == 1) {
      image(spaceshipDOWN, this.x, this.y, this.w, this.h);
    }

    if (this.direction == 2) {
      image(spaceshipLEFT, this.x, this.y, this.w, this.h);
    }

    if (this.direction == 3) {
      image(spaceshipRIGHT, this.x, this.y, this.w, this.h);
    }
  }
  
  setW(w){
    this.w=w;
  }
  
  setH(h){
    this.h=h;
  }
  
  setX(x){
    this.x=x;
  }
  setY(y){
    this.y=y;}
  
  setDir(direction){
    this.direction = direction;
  }
}

The laser beams are also created using class:

class laser {
  constructor(w, h, x, y, direction) {
    this.w = w;
    this.h = h;
    this.x = x;
    this.y = y;
    this.direction = direction;
    this.speed = 5;
  }

  display() {
    if (this.direction == 0) {
      image(laservertical, this.x, this.y, this.w, this.h);
    }

    if (this.direction == 1) {
      image(laservertical, this.x, this.y, this.w, this.h);
    }
  }

  move() {
    if (this.direction == 0) {
      this.y -= this.speed;
    }
    if (this.direction == 1) {
      this.y += this.speed;
    }
  }
}

And the aliens are also PRE-created using class:

class alien {
  constructor(w, h, x, y, speed) {
    this.w = w;
    this.h = h;
    this.x = x;
    this.y = y;
    this.speed = random(1, 3);
  }

  move() {
    this.y += this.speed;
  }

  display() {
    image(alien_image, this.x, this.y, this.w, this.h);
  }

  hits(obj) {
    return (
      obj && 
      obj.x > (this.x - obj.w) + 10 &&
      obj.x < (this.x + this.w) - 10 &&
      obj.y > (this.y - obj.h) + 12 &&
      obj.y < (this.y + this.h) - 15 
    );
  }
}

When the user presses the space bar, a laser beam is released. The user can press the space bar multiple times. The number of laser beams released correspond to the number of times the space bar is hit.

//   Display laser beams
  for (let i = lasers.length - 1; i >= 0; i--) {
    drawingContext.shadowBlur = 10;
    drawingContext.shadowColor = color("rgb(181,0,255))");
    lasers[i].display();
    drawingContext.shadowBlur = 0;
    lasers[i].move();

  }
}

// Add the laser beams to an array to shoot with sound
function keyPressed() {
  if (key == " ") {
    lasers.push(
      new laser(
        width / 12,
        width / 12,
        spaceship1.x + spaceship1.w / 10,
        spaceship1.y - spaceship1.h / 1.4,
        spaceship1.direction
      )
    );
    beam.play();
  }
}

When the laser beam hits the alien:

for (let j = 0; j < lasers.length; j++) {
      if (aliens[i].hits(lasers[j])) {
        aliens.splice(i, 1);
        lasers.splice(j, 1);
        counter_scores++;
        break;
      }
    }

When the alien hits the spaceship:

if (aliens[i].hits(spaceship1)) {
      counter_lives--;
      aliens.splice(i, 1);
      continue;
    }

I am particularly proud of these two code snippets because I had such a hard time figuring out how to slice and make either the laser beam or the obliterated alien disappear on the screen. The hardest part was to figure out the loop using continue() and break so as the game can continue. I spent a lot of time fixing the errors relating to this.

The final rule is when the alien hits the Earth, at which point there is no return and the player will automatically lose:

if (aliens[i].y > height) {
      console.log("Game Over");
      textStyle(BOLD);
      textAlign(CENTER);
      aliens.splice(i, 1);
      gameState = "stop";
      continue;
    }

In terms of statistics, there is a score counter and a lives counter. Lives counter determines how the player progresses through out the game.

Besides checking the hit conditions, other parts that I’m proud of include coding the movement of the spaceship, coding the reset of the game, figuring out the coordinates where the spaceship meets the alien and the coordinates where the laser beam hits the alien, and creating the backgrounds and images that I use:

Creating the game start, instructions, and game restart screens also took me a lot of time. I had to refer the example sketch “Ramsha Bilal” by Save the Ocean from last year given by you to figure it out. It took me a lot of time until I could do it right, ie. creating user input before starting and creating a new session start after the previous session is completed.

Areas for improvement and problems:

In terms of using arrays, I want to make some aliens appear next to one another and move down the screen at the same time. It will vary the difficulty of the game even more. I also wanted to make the buttons for getting user’s input more aesthetic and varied, instead of what I have now.

Problems I ran into:

I couldn’t generate the stars properly so I had to refer to this YouTube tutorial from Back to Code: https://www.youtube.com/watch?v=xbmwfg5U9-s

I couldn’t make the game run in full screen properly without the elements shifting around although it still run:

https://editor.p5js.org/luke.s.ng/full/g7Hnh5lV4

There was a minor break error. If the user shoots many lasers at the same time to kill the alien, sometimes this error will pop up. During testing, the error appeared with a random number of lasers, REGARDLESS of the high score (or number of aliens killed) and the number of aliens on screen. It was a random bug while playing. But I figured out I had to add “break” to the checking condition when the laser beam hits the alien.


The lives counter initially didn’t display the number of lives when it reaches 0 properly.

I also had a lot of problems creating the starting/restarting user input pages mainly because of the buttons’ coordinates. It took me a lot of time to figure out.

Overall, it has been a fun process with lots of trial and error. I learned a lot about Object-Oriented Programming as well as debugging.

Luke Nguyen – Week 5 Reading

I find the Suicide Box project that surveyed the suicide jumpers from the Golden Gate Bridge to be very intriguing. Jeremijenko stated that the project was able to monitor real data and formulate a database for this. What I, as well as other people who thought the project was controversial, would like to know is how it was programmed to capture such data to the point where it could be called “real.” Usually machines/softwares are prone to the black box issue, which makes them very susceptible to making inexplicable mistakes while they are working. Obviously, this project faced the controversy for the right reason regarding the ethics of technology, that is using it to measure something very tragic. Nevertheless, the authors had good intention, but the way the data was recorded needed to be examined carefully.

In regard to computer vision techniques, detection through brightness thresholding mainly deals with illumination or contrast. The computer does some very simple comparison to figure out if objects are darker or lighter than the surroundings. But I would like to learn more about this aspect in terms of color vibrance and saturation. Say for example, can the computer compare the vibrance in at least 8-bit RGB color between a given object and the surrounding? Or between different objects?

As for computer vision in multimedia authoring tools, in addition to Java-based scripting, live video input and fast pixel manipulation these days can also be done with other languages. Art-based softwares are having a prime time given how much these languages are being developed. However, the more advanced processing a software is written in, the more complicated the interaction between users and computers will become, which entails a detailed and almost error-free instruction designs.

Luke Nguyen – Week 5 Mid-term Progress

Concept and design:

When I was a kid, I was obsessed with the game Chicken Invaders. I remembered spending 2-3 hours playing it every time I was free from school and homework. It was a way of life for my PC back then. And so, I wanted to emulate the engine of that game for this mid-term project and have fun creating it. I call my interactive game “Alien Slayer.”

Here’s my design:

Here’s the overall structure of the code design:

let spritesheet;
// example spritesheet: https://png.toolxox.com/vhv?p=imRwRx_top-down-spaceship-sprite-hd-png-download/
// i'll edit the spritesheet so that the spaceship can only move left, right, up, down
let sprites = [];
let direction = 1;
let step = 0;
let x; //the spaceship's x position
let y; //the spaceship's y position
let speed = 4; //the animation speed, image moving on canvas

function setup() {
  createCanvas(400, 400);
}

function preload()
  loadImage()
  spaceship = loadImage ("spaceship.png")
//   or create a pixelated spaceship

function draw() {
  background(220);
  
// create a cosmos background
// 1. gradient color
// 2. use loops (for/while loops) to create stars scattered across the space
  
// create evil aliens
// 1. create a class for show() and move() the evil aliens, with loops (for/while loops). The number of evil aliens is random, from 2 to 10. They will appear at the top of the canvas
// 2. use loops (for/while loops) to make the evil aliens start moving down 5 steps every time the frame is refreshed.
// 3. the evil aliens will randomly drop bombs.

//   use sprite sheet animation for the spaceship
//   1. use (for loops) to create a nested array for the spaceship sprite sheet
//   2. use get() to get different tiles of the sprite sheet
//   3. use function keyPressed() and if conditions to make the spaceship move each step
  
// create a laser beam attack for the spaceship
//   1. create a class to draw the laser beam and use the show() to call out the beam
//   2. use function mousePressed() {} to shoot the laser beam that can only go up
  
// gameplay
// game screen gives instructions and waits for user input
// The spaceship needs to be moved around using the keys on the keyboard, to the location vertically under an evil alien to attack it (sprite sheet animation)
// if (){} the laser beam hits the evil alien, the alien is obliterated
// if (){} the bombs dropped by the evil alien hit the spaceship, it will lose one life.
// keep playing until all evil aliens are obliterated.
// if (){} one evil alien touches the spaceship, the player loses.
  
// displaying score
// user gets one score everytime an evil alien is obliterated.
// user receives 5 lives per game. if the number of lives == 0, the user loses and the game will end.
}

The most frightening or complex part of the project is to match the coordinate of the aliens’ bombs so that when they touch the spaceship, it will lose one life. Similarly, the laser beam’s coordinate has to match that of the alien so that the spaceship can kill it. Also, I still need to figure out how to make the aliens erratically drop bombs for the spaceship to dodge. I also still need to figure out how to display the score and the spaceship’s lives in a translucent board at the top of the canvas.

What I’ve been doing is I’ve been trying to write the algorithm for matching coordinates. It’s mostly about using the if function. I’ve also been testing the algorithm for randomly creating bombs from the aliens. This game is essentially about two objects having the same coordinates and randomness.

I’m also going to implement a sound library into the project (for example, a laser beam sounds, the alien dropping a bomb, the sound of the spaceship’s moving, etc.).

 

Luke Nguyen – Week 4 Reading

I like how the author points out the fact that no matter how much knowledge the machines’ operators accumulate over the years and how well-versed they are in their field, they still have to make the construction and/or programming simple. It’s all about precision and accuracy, or perfection in the process in other words, which humans are not prone to. But it’s fascinating how, given the contradictory nature between machines and humans, humans have managed to churn out some very advanced technology that requires high level of precision and accuracy and to minimize the number of errors as much as possible merely through experimentation and testing! But that said, added complexities equate increased difficulty in use and frustration. High-tech machines/gadgets today require a lot of knowledge from users, and not every form of knowledge is easy to be acquired.

Another point from the author with which I resonate is about the relationship between affordance and signifier. This kind of relationship is not very clear-cut as one would say, as the author points out, “some affordances are perceivable, others are not” and “perceived affordances often act as signifiers, but they can be ambiguous” (19). Despite the fact that signifiers are more important than affordances, I’ve seen some terrible signifiers that do not fulfil their duty at all, which leaves users to figure out affordances all on their own and hence, suffer from frustration. The more high-tech and more complex machines, the more effort operators should put into curating the signifiers for a more effective affordance from the users.

Luke Nguyen – Assignment 4 – Top 20 Movies of 2023

I went to the cinema a lot so I was fascinated about the box office of the movies released in 2023 (mainstream movies only as their box offices are always reported with accurate data from cinemas). I wanted to make a data visualization of the top box office of movies released last year. I searched on Kaggle and came across a CSV files compiling the US Domestic box office of top 200 movies in 2023 (https://www.kaggle.com/datasets/mohammadrizwansajjad/top-200-movies-of-2023). I edited the dataset a little bit, removing unnecessary data columns and reducing the dataset down to 20 to reflect the top 20 movies with the highest box office. The chart displays the movies’ box offices as well as the month they were released while also vertically ranking them according the box offices.

Snippets of code:

//Retrieving data from the table
  let Month = movies.getColumn("Release Date");
  let Name = movies.getColumn("Title");
  let Rank = movies.getColumn("Rank");
  let Boxoffice = movies.getColumn("Total Gross");

  for (let i = 0; i < img.length; i++) {
    // split data into string
    let splitString = split(Month[i], "/");

    //     displaying data
    image(
      img[i],
      12.5 + ((int(splitString[0]) - 1) * (width - 20)) / 12,
      map(Rank[i], 1, 22, 50, height - 20),
      53,
      23
    );
  }

Embedded Sketch (hover mouse diagonally to see all box offices):

The chart essentially displays the movies’ logos according to their box offices using the Map function. We can eyeball and compare one movie’s box office with another’s. The hardest part is to figure out the placements of the movies’ logos. But more importantly, it is also about extracting the data from the dataset and come up with a way to graph them.

For future improvement, I want to come up with a way to display the movies’ logos in a more visible manner. As of now, because of the size of the chart, the logos are pretty small and the accompanying hover number for the box offices are also small. I also want to display the box office number separately as well, i.e. it only shows when the mouse hover on the image. The challenge here is to figure out the coordinate of mouseX and mouseY.

Luke Nguyen – Week 3 Reading

I resonate with the interaction that the author proposes. Interaction is a “cyclic process” in which two actors alternately listen, think, and speak; it’s a back-and-forth listening, thinking, and speaking process indeed. The key is more than one, irrefutably. But I entertain his idea that we should think of interactivity as a “variable with relative measures.” Sometimes, defining whether an object as either interactive or non-interactive seems reductive and regressive. Things are more than what they seem and they certainly belong in the grey area of interactivity definition. Aiming to discuss the degree of interactivity seems to be a legitimate approach.

The author thinks that movies are non-interactive. However, in today’s context, this is not true entirely anymore, given the rise of interactive content on streaming platforms such as Netflix, with shows or movies like Carmen Sandiego: To Steal Of Not To Steal, Black Mirror Bandersnatch, etc.. Sure, the end result is pretty much very pre-determined, these programs are scripted anyway, but the concept and operation of the interactivity is successfully implemented. Pretty soon in the future, there will be interactive movie made for VR glass devices such as the newly released Apple Vision Pro.

I also find the idea about the contention between user interface and interactivity design to be fascinating. User interface from what I understand is all about front-end and the interactivity design back-end. But I’ve never thought about the tense relation between the interactivity designers and the user interface designers who detest the intrusion of interactivity designers into their work. I’ve always thought that each of these two aspects cannot exist without the other!

Luke Nguyen – Assignment 3 – Rainbow Spikes

This generative artwork is essentially me implementing the concepts of arrays and class that we learned. I was thinking of creating something fun and colorful and demonstrate a chaotic pattern that can be generated when a user press the mouse. And while scrolling through Openprocessing.org to look for inspirations, I stumbled upon a generative artwork called “Noise Turbulence Doodles” by Raven Kwok (https://openprocessing.org/sketch/143842).

The idea is that a circle generated from a mouse click is followed by a chain of automatically generated circles decreasing in size that scatter in random directions. I set the color spectrum for the circles to be a rainbow spectrum (referencing this p5js example by aferriss: https://editor.p5js.org/aferriss/sketches/Bys1YDQx7), with the root circle taking a random color every time the mouse is pressed or held. The longer the mouse is pressed at one position on the canvas, the more rainbow “spikes” are generated starting from the root. If the user moves the cursor around, they will scatter the root while creating the spikes as well.

The artwork generated looks like sea urchins or something spiky in 3D. This illusion is created by randomizing the distance between each circle that are generated in the chain from the root.

Using class and array:

let particle = new Particles(
      mouseX,
      mouseY,
      30,
      random(-5, 5),
      random(-5, 5)
    );
    //     add each circle generated after the root circle to the array
    circlelst.push(particle);

Creating a move class:

move() {
    //     the x-coordinate the circles increase according to the x-direction
    this.posX += this.directionX;
    //     the y-coordinate the circles increase according to the y-direction
    this.posY += this.directionY;
    //     the radius of the circles decrease by a random float from 0 to 1
    this.radius -= random(0, 1);
    //     draw the chain of circles
    if (this.radius > 0) {
      circle(this.posX, this.posY, this.radius);
    }
  }

Embedded sketch (Please press the mouse (either short press or long press) and move the cursor around to play with the effects):

This is very fun to make. The hardest part is to figure out how to generate the chain of circles that decrease in size as they are generated and how to trigger the circles to move in random direction consisting of x-direction and y-direction. It essentially required me to figure out how to work with arrays.

As for future work or improvements, I want to make the circles blend with one another smoothly to create a shape instead of separate circles. That way it can look even more hallucinatory.

Luke – Reading Reflection – Week 2

I find the work that he did the Process 18 project to be very interesting. It’s about the nature of noise or jitters. I think that whether in a controlled or uncontrolled environment, noise particles seem to group together, or in other words, homogenize, and create odd/unique patterns. Reas proves in this project that his noise system gradually became homogenous and over time, the system still kept its homogenous characteristic but added more resolution in time and space. What I wish Reas could do is maybe to add some sort of catalyst to the noise experiment, to see how such a catalyst could impact the way the particles behave over time, mimicking the real environment.

I also find his commission work in creating composited photos for the Frank Gary in Miami Beach as a miniature version of the Disney Concert Hall Los Angeles to be intriguing. Reas and his colleague Rosner used randomness as a jumping off point in tailoring the printed compositions. A lot of decision making was also taken into account to determine how they want the compositions to feel like. One of the details Reas shared behind the process is that the team rolled the dice in putting the images of the neighborhood together wherever they want it to be with a condition that they had to be at 90° angles to trigger the final composition. We talked about how randomness can prove to be a useful tool in coding in class. In Reas’ example, it not only helps him and his colleague come up with exciting artworks but also acquire a firmer grasp of the process while observing the pattern to arrive at the outcome. His work support the fac that randomness and decision making, although seeming to contrast one another, can be a helpful combination for observation in interactive media coding.

Luke Nguyen – Assignment 2

Concept:
During last week, I got to listen back to one of my favorite song, “Sativa” by Jhené Aiko from her album “Trip.” I have been obsessed with this song since high school. What really interests me is the cover for the album:

Jhené Aiko, Trip

It has graphically designed rings that circularly loop around the square cover. So, I thought I’d apply the concept learned in class to recreate my interpreted version of this album cover.

A highlight of some code I’m particularly proud of:
I’m particularly proud of creating the circular loops of the rings. I learned how to do the circular loop from Daniel Shiffman’s The Coding Train YouTube video here (https://www.youtube.com/watch?v=rO6M5hj0V-o), at around 6:27 where he teaches using the sin and cos in the for loop.

drawingContext.shadowBlur=10;
drawingContext.shadowColor=color('rgb(250,84,0)');

// first loop of rings
for (let m = 0; m < 1440; m += 30) {
noFill()
let x = 50 * sin(m) + 200;
let y = 50 * cos(m) + 200;
stroke('rgb(250,84,0)')
circle(x,y,50)

Embedded sketch:

Reflection:

Creating a loop in a circular motion is rather fascinating to me. I was trying on my own to create the effect, but to no avail. Coincidentally, I was experimenting with creating custom shapes different from the primitive shapes we’ve learned in class while learning p5js on my own. And my research online into how to do so led me to come across Daniel Shiffman’s video that taught me how to create custom shape and create a circular loop.

I had fun creating all the loops and the circles. I played around with the input for the function within the loop to create the effect. Since I have multiple loops of rings for the assignment, I have to use multiple loops.

To emulate the colors from the album cover, I also looked up how to add the glow effect to an object in p5js and came across a video by Kazuki Umeda at https://www.youtube.com/watch?v=iIWH3IUYHzM. I added two functions for the effect, namely “drawingContext.shadowBlur” and “drawingContext.shadowColor=color”.

And for the girl in the center, it’s just an uploaded transparent png file. But in order to know how to insert an image, I also look up a p5js reference created by claesjohnson https://editor.p5js.org/claesjohnson/sketches/f0huO1Y4h.

Ideas for future work or improvements:

  • The codes for the loops right now are rather repetitive, so I’m trying to figure out how to clean them up, maybe into another “while” or “for” loop.
  • I wanted to add a radial gradient background and use the white color for the looped rings instead but I didn’t know how to do so, so this is another idea for improvement.
  • I also wanted to experiment with a shape that looks like a parabol instead of the primitive circle.

Assignment 1 – Self portrait | Luke

Concept:
It’s still during winter so I thought I’d make something that reflects the weather and personally, I love the cold. Designing the portrait is not too difficult. The character only needs a puffer jacket and a beanie hat. Winter is the season when colors are not vibrant, so I go for something that’s neutral such as orange/brown for the beanie hat and a little bit blue for the puffer jacket to make the outfit stand out. The character I created is a guy who’s feeling the holiday spirit. He enjoys other people’s company during the holiday season. You can see the glow in his eyes; he’s smiling back at you. He’s waiting for you to welcome him inside your house, because “Baby, it’s cold outside!”

A highlight of some code that I’m particularly proud of:

// nose_1
strokeWeight(2);
arc(185, 125, 25, 100, 0, -30);
noFill();
  
// nose_2
strokeWeight(2);
arc(205.5, 159, -30, -45, -30, -10, OPEN);
noFill();

// mouth_lips
noFill();
arc(190, 210, 70, 10, 0, 1/2*(HALF_PI) + 1/2*(HALF_PI));

// left_ear
fill("rgb(251,205,159)")
arc(124, 165, 25, 50, -30, -20.5);
noFill();
  
// right_ear
fill("rgb(251,205,159)")
arc(297, 160, 25, 50, -2, -3.9);
noFill();

Embedded sketch:

Reflection:
Overall, this is a simple enough sketch that incorporates many shapes I learned in class. I particularly practiced creating the arcs a lot, in figuring out the right arcs. Arcs are more difficult to create than other shapes so this part took me a lot of time.

Ideas for future work or improvements:
I want to add the gradient for the background. I also want to add more details in the background such as the leafless trees in the winter and the streetlights. These would require shapes more difficult to create than the ones we learned in class.

I particularly want to add interactivity for the snow; something like the snow spreads out or bounces off wherever the cursor moves. I also want to add randomness to the snow every time I generate the code as well. And I want to add movement to the snow, making it fall vertically in a natural way.