Week 11 – Exercises

  1. I used a photoresistor as input to control the position of the sphere.

p5js:

let xcord = 0;
let left=0;
let right=0;

function setup() {
  createCanvas(640, 480);
}

function draw() {
  background("white");
  
  if (!serialActive) {
    text("Press Space Bar to select Serial Port", 20, 30);
  } else {
    text("Connected", 20, 30);

    ellipse(xcord,height/2,100,100);
    console.log(xcord);

  }

}

function keyPressed() {
  if (key == " ") {
    // important to have in order to start the serial connection!!
    setUpSerial();
  }
}

function readSerial(data) {


  if (data != null) {

    let fromArduino = trim(data);

    xcord = int(fromArduino);
    
  }
}

Arduino:

int inPin = A0;

void setup() {
  // Start serial communication so we can send data
  // over the USB connection to our p5js sketch
  Serial.begin(9600);

  pinMode(LED_BUILTIN, OUTPUT);
  pinMode(inPin, INPUT);
}

void loop() {

  digitalWrite(LED_BUILTIN, HIGH);  // led on while receiving data


  int sensor = analogRead(A0);
  delay(5);
  Serial.println(sensor - 300);

  digitalWrite(LED_BUILTIN, LOW);
}

2.

p5js:

let ycord;

function setup() {
  createCanvas(640, 480);
  textSize(18);
}

function draw() {

  if (!serialActive) {
    text("Press Space Bar to select Serial Port", 20, 30);
  } else {
    text("Connected", 20, 30);

  }

  if (mouseIsPressed) {
    ycord=mouseY;
    console.log(ycord);
  }
}

function keyPressed() {
  if (key == " ") {
    // important to have in order to start the serial connection!!
    setUpSerial();
  }
}

function readSerial(data) {

  if (data != null) {
    let fromArduino = trim(data);
                     
    let sendToArduino = ycord + "\n";
    writeSerial(sendToArduino);
    console.log("sent");
  }

}

Arduino:

int inPin = A0;
int outpin = 8;

void setup() {
  // Start serial communication so we can send data
  // over the USB connection to our p5js sketch
  Serial.begin(9600);

  pinMode(LED_BUILTIN, OUTPUT);
  pinMode(inPin, INPUT);
  pinMode(outpin, INPUT);
}

void loop() {

  digitalWrite(LED_BUILTIN, HIGH);  // led on while receiving data

  int brightness = Serial.parseInt();
  if (Serial.read() == '\n') {
    digitalWrite(outpin, HIGH);
    delay(brightness/100);

    digitalWrite(outpin, LOW);
    delay(4.80-brightness/100);
  }
  Serial.println(brightness);
}

3. It works but the lag is insane.

Arduino:

int inPin = A0;
int outpin = 8;

void setup() {
  // Start serial communication so we can send data
  // over the USB connection to our p5js sketch
  Serial.begin(9600);

  pinMode(LED_BUILTIN, OUTPUT);
  pinMode(inPin, INPUT);
  pinMode(outpin, INPUT);
}

void loop() {
  digitalWrite(LED_BUILTIN, LOW);

  while (Serial.available()) {
    // led on while receiving data
    digitalWrite(LED_BUILTIN, HIGH);
    int left = Serial.parseInt();
    if (Serial.read() == '\n') {

      int sensor = analogRead(A0);
      Serial.println(sensor);
    }
    if (left >= 350 && left <= 360) {
      digitalWrite(outpin, HIGH);
    } else {
      digitalWrite(outpin, LOW);
    }
  }
  int sensor = analogRead(A0);
  Serial.println(sensor);
}

P5:

let velocity;
let gravity;
let position;
let acceleration;
let wind;
let drag = 0.99;
let mass = 50;

function setup() {
  createCanvas(640, 360);
  noFill();
  position = createVector(width/2, 0);
  velocity = createVector(0,0);
  acceleration = createVector(0,0);
  gravity = createVector(0, 0.1*mass);
  wind = createVector(0,0);
}

function draw() {

  background(255);
  applyForce(wind);
  applyForce(gravity);
  velocity.add(acceleration);
  velocity.mult(drag);
  position.add(velocity);
  acceleration.mult(0);
  ellipse(position.x,position.y,mass,mass);
  if (position.y > height-mass/2) {
      velocity.y *= -0.9;  // A little dampening when hitting the bottom
      position.y = height-mass/2;
    }
}

function readSerial(data) {
    ////////////////////////////////////
    //READ FROM ARDUINO HERE
    ////////////////////////////////////
  
    if (data != null) {
    // make sure there is actually a message
    
    let fromArduino = trim(data);
   
    //console.log(fromArduino);
    let sensorVal = int(fromArduino);
      
    if (sensorVal < 600){
      wind.x=1;
    }
    else if(sensorVal >= 600 && sensorVal < 800){
      wind.x = 0;
    }

    else {
      wind.x = -1;
    }
//           //////////////////////////////////
//           //SEND TO ARDUINO HERE (handshake)
//           //////////////////////////////////
  }
  else{
    console.log("empty input");
  }
//height of ball sent to arduino to check if ball on floor or not
  let sendToArduino = position.y + 0.5 * mass + "\n";
  writeSerial(sendToArduino);

}

function applyForce(force){
  // Newton's 2nd law: F = M * A
  // or A = F / M
  let f = p5.Vector.div(force, mass);
  acceleration.add(f);
}

function keyPressed(){
  if (keyCode==LEFT_ARROW){
    wind.x=-1;
  }
  if (keyCode==RIGHT_ARROW){
    wind.x=1;
  }
  // if (key==' '){
  //   mass=random(15,80);
  //   position.y=-mass;
  //   velocity.mult(0);
  // }
  if (key == " ") {
    if (!serialActive) {
      setUpSerial();
      console.log("serial")
    }
    mass=random(15,80);
    position.y=-mass;
    velocity.mult(0);
  }
}

 

Week 10 Instrument

Video: https://youtu.be/d6cVEQlEJnk

For our group assignment, we weren’t sure in what way a sensor could be implemented to generate musical notes, so we first brainstormed on an instrument on which we could base this assignment: the accordion. To replicate the keys, we decided to use switches (buttons) and for “bellows” we decided on the flex sensor. We first planned out our schematic, first mapping out the switches, resistors then the analog (connecting) wires. However when actually delving into the construction of the breadboard and subsequently the coding aspect, we ran into a few problems that required us to improvise. We first realized through using the serial monitor that the output generated by the flex sensor was incredibly jittery and inconsistent. It was hard to make out a constant value range. Hence we decided to use an alternative sensor: the photoresistor. Ultimately our approach was predominantly to improvise. Once we had resolved our main code, we decided to utilize the LCD, on a whim, to show “:)” or “:(” pertaining to specific conditions. This required us to do some research on how the LCD is connected to the breadboard, and the code used to display characters: https://docs.arduino.cc/learn/electronics/lcd-displays

HOW IT WORKS:
3 buttons play different notes. The range in tone of the note varies according to the photoresistor – the more the light is conceived, the higher the note is played. Subsequently, the LCD shows “:)” when the tone frequency, determined by the analog reading from the flex sensor, is higher than the previous frequency; otherwise, it displays “:(“. This comparison is specific to each color (red, green, blue), and the frequency values are mapped accordingly.

Schematic:

Arduino Code:

// include the library code:
#include <LiquidCrystal.h>

// initialize the library by associating any needed LCD interface pin
// with the arduino pin number it is connected to
const int rs = 12, en = 11, d4 = 5, d5 = 4, d6 = 3, d7 = 2;
LiquidCrystal lcd(rs, en, d4, d5, d6, d7);

int buzzerPin = 8;
int redpin = A0;
int greenpin = A1;
int bluepin = A2;
int phopin = A3;
float prev = 0;

void setup() {
  // put your setup code here, to run once:
  pinMode(buzzerPin, OUTPUT);
  pinMode(redpin, INPUT);
  pinMode(greenpin, INPUT);
  pinMode(bluepin, INPUT);
  pinMode(phopin, INPUT);  //
  lcd.begin(16, 2);
  Serial.begin(9600);
}

void loop() {
  // put your main code here, to run repeatedly:
  int redState = digitalRead(redpin);
  int greenState = digitalRead(greenpin);
  int blueState = digitalRead(bluepin);
  int flexState = analogRead(phopin);  // 350 to 1000
  float redvariance = 130.8 + map(flexState, 350, 1050, 0, 130.8);
  float greenvariance = 261.6 + map(flexState, 350, 1050, 0, 261.6);
  float bluevariance = 523.2 + map(flexState, 350, 1050, 0, 523.2);
  if (redState == HIGH) {
    tone(buzzerPin, redvariance);
    if (higherThanPrev(prev, redvariance)) {
      lcd.print(":)");
    } else {
      lcd.print(":(");
    }
    prev = redvariance;
    delay(100);
  } else if (greenState == HIGH) {
    tone(buzzerPin, greenvariance);
    if (higherThanPrev(prev, greenvariance)) {
      lcd.print(":)");
    } else {
      lcd.print(":(");
    }
    prev = greenvariance;
    delay(100);
  } else if (blueState == HIGH) {
    tone(buzzerPin, bluevariance);
    if (higherThanPrev(prev, bluevariance)) {
      lcd.print(":)");
    } else {
      lcd.print(":(");
    }
    prev = bluevariance;
    delay(100);
  } else {
    noTone(buzzerPin);
  }
  lcd.clear();
}

bool higherThanPrev(float prev, float now) {
  return prev < now;
}

Overall we were quite pleased with the end result, even more so with our LCD addition. However, we felt as though it was difficult to classify our project as a musical instrument since, despite the complex interplay between analog/ digital sensors, the sounds produced were less “musical” in a sense. Furthermore, we realized that whilst the tone of the sound produced by the blue switch was very clearly affected by the amount of light perceived by the photoresistor, this was not the case for the red switch. It was much harder to distinguish a change in the tone of the sound. We believe it is because the red button signals the C note in the 3rd octave, and the blue one signals the C note in the 5th octave. Since the frequency of octaves is calculated with the formula “Freq = note x 2N/12”, the changes in frequencies mapped to the notes will be more significant as octaves increase. For future improvements, especially with regards to its musicality, perhaps we could have each button play a series of notes, hence the 3 switches would produce a complete tune. Rather than mapping ranges for the photoresistor, we could choose a (more than/ less than) specific value. For example, in a dark room, the complete tune would be played in a lower key whilst in a bright room, the tune would play in a higher key.

Week 10 Reading

After reading this article (or rant),  I am amazed by the author’s vision. It was not until now I realized the explicit difference between current production tools and tools we used in the past. It is not that the tools we used in the past are better than the tools we use now, but personally, I always thought something was missing in the tools we use nowadays. Now I know the thing that was missing was feedback.

I am not saying that the current tools we use now do not have feedback. On the contrary, these tools have plenty of ways to provide feedback. Ringtones, vibrations, different kinds of displays, etc. However, those feedbacks all have one problem: it does not represent an aspect of the action performed. our brains have to process what the response or the feedback means, and that is what I feel is missing in current tools. If I use a hammer, when I hit the nail it gives me a force so that I know I hit something. The meaning of this feedback is completely intuitive. Therefore in this way, traditional tools are easier to learn and more intuitive.

However, I remain doubtful of the claim that the more we use our hands the better. Yes, it is true that our fingers have an incredibly rich and expressive repertoire, and we improvise from it constantly without the slightest thought. However, we have it does not mean we need to use it. I think whether it’s better or not should not be determined by how much repertoire of our hand we use, but by how intuitive it is for us to use. Therefore even though I agree with the author that the iPad or phones are not perfect tools, I remain doubtful that the tools in the future will use that many hand functions.

Week 9 Arduino

Concept

For this assignment, I used the ultrasonic sensor to make something like a parking sensor. If the distance is above a certain threshold, the LED displays green. If the distance is below the threshold, it gradually turns red along the distance of 20 centimeters. After that, the LED turns completely red. There are two switches used as input for digital data. One is this system’s overall switch, which shuts the entire system when open. Once it’s closed, a blue LED lights up indicating the system is functioning. The other button when pressed, records the current distance the sensor gets and stores this data as the new threshold.

Video Example:

Week 9 Reading

Physical Computing’s Greatest Hits

In this article what I really like is the floor pads. I think it’s one of the interactive art that’s most used in real-life scenarios and I really enjoy it. It’s set up in most of the arcades in China and I find it fun. I also like the concept of video mirrors. I once read that people tend to think of humanoid shapes as human figures even if they might be very different. Video mirrors are like the reverse of this concept, changing images of people into humanoid shapes. Therefore when people see these humanoid shapes as themselves, more value is added through the composition or the material of these humanoid shapes.

Making Interactive Art: Set the Stage, Then Shut Up and Listen

I can really relate to this. In my high school, we have literature classes where we are supposed to learn to appreciate, analyze, and interpret literature pieces. At first, when we interpreted it by ourselves we had many different ideas and conclusions. However, when the teacher told us how she analyzed and interpreted it, our own thoughts about the work disappeared and only one interpretation remained. But the thing with art I believe is that it should not have only one “correct answer”. It should be allowed to be openly interpreted by the public, and interpreting your own work kills that possibility. Even if there really is something you want to show to the viewers, it should not be shown through killing the other possibilities of interpretation. I think it is okay to lead viewers to think in a certain way, but it’s completely different than telling the viewers what they should think.

Week 8 – Reading Reflections

Norman,“Emotion & Design: Attractive things work better”

I agree with the author’s ideas on balancing design and practicability when designing objects. From my personal experience, I know how frustrating it is when I am in a hurry and something doesn’t work. I was doing a group assignment and the final step was to finalize everything and put our final elements together and format them. However, the formatting software was extremely difficult to use. It wasn’t until I almost finished everything that it told me I needed to use paid methods to finish the export. I was so stressed that I did what they wanted and paid a subscription because the deadline was getting near. In the end, the task was finished. But it was after that I realized I didn’t use the paid method at all. It was only advising me to pay the subscription because it thought I might need the method. That is how I realized that in stressful situations, certain designs can serve different purposes and lead the user to do certain stuff they might not have done without the pressure. If there had been no pressure when I was exporting the project, I would have read what it said more carefully and thought about whether I needed the subscription. Therefore from my perspective, I agree with the author’s idea that emotions affect design, and for a design to be easy to use in stressful situations, all functions should have clear implications on how they should be used.

Her Code Got Humans on the Moon

After reading the article, I have great respect for Margaret Hamilton. At a time when men dominated the tech industry, Mrs Hamilton, as a working mother, achieved much that other men could have never thought of. Also, at the crime, coding was much harder than it is today. These days coding can be done with languages that have syntax pretty close to human language that’s easy for people to understand. However, at that time, coding was “punching holes in punchcards”. The difficulty and the stress of being responsible for developing a manned spacecraft are insane and unthinkable. Her achievements were outstanding enough, and the environments in which she got those achievements added to the greatness of her work. I have nothing but respect and awe for this woman.

Creative Switch

Concept

The main concept is to create a switch that isn’t necessarily a physical switch but a gate that returns true when a requirement is fulfilled. I created a switch that can provide an alert based on the water level of a specific environment. The circuit looks like this:

The two switches at the bottom part of the board indicate the water levels. Whatever the water level is, the rightmost LED always shines. If the water level is above a threshold, the second LED shines too. If another threshold is met, the third LED shines. This serves as an alert system for the water level of a specific environment. The actual functional circuit is shown below:This is what happens when there is no water in the cup.This is what happens when the water in the cup only reaches the first thresholdThis is what happens when the water level reaches the maximum value.This is what happens when I disconnect the second LED, because the power the red LED needs is more than the yellow one needs, so it might not be obvious that the red one is shining. This image is to show that the red one is shining when the water level is high.

Midterm Project

Fullscreen link: https://editor.p5js.org/fhgggtyf/full/_GaqN8_Sa

Overall Concepts

The concepts didn’t change much compared to what I thought of when planning. However, instead of staring with randomly generated maps, I chose to use the original map for the first few levels so that the difficulty won’t get too insane at the beginning. Then, after the user is familiar with the game, they will encounter randomly generated maps which are insanely difficult. The main gameplay is the same with the original Pac-Man version, but the success condition for finishing a level no longer is to eat all pellets but also reaching the portals to get to the next level. Each level has a theme which is rotated in a pool of three: fire, wood, and water. Each theme has its own sets of environment and music. This is because I do not want this game to only feel like a game to the user, but feel like a real adventure in various landscapes. The player also gets a record of their final score after their 3 health is depleted. The four ghosts each have a different logic system of pursuing the player, and the mode changes of the ghosts are coherent with the original game. As levels increase, scatter mode and chase mode ratios will change to make difficulties higher.

Implementation

The game is mostly separated into 3 modules: Game, Player, Ghosts. It could be divided to make the structure clearer but since its not such a big project I decided to keep it simple.

The game module is responsible for controlling how the game progresses. There are 3 game states, which are start, in game, and game over. In the in game state, it is responsible for the game interactions, level states, and sending signals to the ghosts making them go to different modes. There should be a game effect controller to do this but I integrated the elements into the game module instead. Basically, this module controls all in-game state changes and the program state changes.

the player module is responsible for taking in inputs and converting it into actions of the player object. it also contains stats of the player.

The ghosts module is used for calculating the actions of the ghosts. each ghost have its own rules in pursuit of the player. Also the ghosts have different states, which would effect their destination points. Overall, All ghosts have the same rules pursuing a certain destination point. However, different ghosts usually have different destination points due to their unique behaviors. Therefore I have subclasses inheriting the Ghosts class so they can determine their own destinations. These squares refers to their different destination points based on their behaviors. The squares in the following image stands for the destinations of each of the ghosts.

The code is shown below.

class Ghosts{
  constructor(){
    this.position=[1,1];
    this.img=blinkyImage;
    this.vulnerable=false;
    this.addPointFlag=false;
    this.absPos=[round(this.position[0]),round(this.position[1])];
    this.prevAbsPos=this.absPos;
    this.state=0;//prepare state
    this.dir=[1,0];//no direction
    this.speed=ghostSpeed[game.gameLevel];
    this.dest=[0,0];
    this.next=[0,0];
    this.sur=[[this.absPos[0],this.absPos[1]-1],
              [this.absPos[0]+1,this.absPos[1]],
              [this.absPos[0],this.absPos[1]+1],
              [this.absPos[0]-1,this.absPos[1]]];
    this.choices=[];
  }
  
  checkState(){ // Check ghost's state to determin action
    if(this.state==0&&this.absPos[1]>11){
      this.resetMode();
    }
    else if(this.state==9){
      if(this.absPos[0]==13&&this.absPos[1]==15){
        this.state=0;
        this.addPointFlag=false;
      }
    }
    else{
      if(game.frightened && game.frightenedTimer<=7){
        this.frightenedMode();
      }
      else{
        this.vulnerable=false;
        game.frightened=false;
        game.frightenedTimer=0;
        if(game.cycleTimer/(int(chaseTime[game.gameLevel])+int(scatterTime[game.gameLevel]))<=5 && game.cycleTimer%(int(chaseTime[game.gameLevel])+int(scatterTime[game.gameLevel]))<scatterTime[game.gameLevel]){
          this.scatterMode();
        }
        else{
          this.chaseMode();
        }
      }
    }

    
  }
   
  defeatedMode(){
    this.state=9;
    this.img=eyesImage;
    this.dest=[13,15];
  }
  
  resetMode(){
    this.dest=[13,11];
  }
  
  checkMoved(){ // check if the ghost moved a whole block, if moved calculate new destination
    this.absPos=[round(this.position[0]),round(this.position[1])];
    this.sur=[[this.absPos[0],this.absPos[1]-1],
              [this.absPos[0]+1,this.absPos[1]],
              [this.absPos[0],this.absPos[1]+1],
              [this.absPos[0]-1,this.absPos[1]]];
    if(this.absPos[0]!=this.prevAbsPos[0] || this.absPos[1]!=this.prevAbsPos[1]){
      this.calcMovement();
      this.prevAbsPos=this.absPos;
    }
  }
  
  calcMovement(){ // calculate new destination and how to get there
    this.choices=[];
    this.sur.forEach(element => {
      if((element[0]!=this.prevAbsPos[0] || element[1]!=this.prevAbsPos[1]) && mapData[game.mapNum][element[1]][element[0]]!=1){
        if((this.state != 0 && this.state != 9)&& mapData[game.mapNum][element[1]][element[0]]==3){
        }
        else{
          this.choices.push(element);
        }

      } 
    });
    
    if(this.choices.length==0){
      if(this.absPos[0]==1 && this.absPos[1]==14){
        this.position=[26,14];
        this.absPos=[round(this.position[0]),round(this.position[1])];
        this.choices.push([25,14]);
      }
      else if(this.absPos[0]==26 && this.absPos[1]==14){
        this.position=[1,14];
        this.absPos=[round(this.position[0]),round(this.position[1])];
        this.choices.push([2,14]);
      }
    }
    
    let closest = Infinity;
    
    this.choices.forEach(element => {
      
      let difference = sq(element[0]-this.dest[0])+sq(element[1]-this.dest[1]);

      // Check if the current element is closer than the previous closest element
      if (difference < closest) {
        closest = difference;
        this.next = element;
      }
    });
    
    this.dir=[this.next[0]-this.absPos[0],this.next[1]-this.absPos[1]];
  }
  
  moveToNext(){ // move
    if(this.dir[0]!=0){
      this.position[0]+=this.dir[0]*this.speed*deltaTime/1000;
      this.position[1]=this.absPos[1];
    }
    else{
      this.position[1]+=this.dir[1]*this.speed*deltaTime/1000;
      this.position[0]=this.absPos[0];
    }
  }
  
  frightenedMode(){
    this.vulnerable=true;
    this.img=vulImage;
    if(this.choices.length>1){
      this.dest=this.choices[floor(random(this.choices.length))];
    }

  }
  
}

class Blinky extends Ghosts{
  constructor(state,dest,position,img){
    super(state,dest,position,img);
    this.position=[13.5,11]
    this.img=blinkyImage;
  }
  
  scatterMode(){ // Scatter mode determine destination
    if(this.state!=2){
      this.dir[0]=-this.dir[0];
      this.dir[1]=-this.dir[1];
      this.state=2;
    }
    this.dest=[27,0];
  }
  
  chaseMode(){ // Chase mode determine destination
    if(this.state!=1){
      this.dir[0]=-this.dir[0];
      this.dir[1]=-this.dir[1];
      this.state=1;
    }
    this.dest=player.position;
  }
  
  display(){
    if(this.state!=9 && this.vulnerable==false){
      this.img=blinkyImage;
    }
    fill("red");
    // rect(this.dest[0]*40,this.dest[1]*40,40,40);
    image(this.img,this.position[0]*40,this.position[1]*40,40,40);
    fill(0); // Set the text fill color to black  
  }

}

In the code above I only shown one subclass so that it won’t be too long. The basic concept of the subclasses are similar. I am pretty proud of this part because the structure is clear and it made the development progress so much easier.

Areas for Improvement

Some areas of improvements could be the aesthetics of the different scenes. I planned to do a pixelated low-poly tile-map styled map design but it turned out to look very unnatural and dirty. If I have more knowledge in graphic design I might be able to do better. Another thing is that the program has a few minor rule bugs that may allow the user to gain points incredibly fast (with a great risk). Maybe I’ll fix them in the future. Also, the random maps may cause the ghosts to behave abnormally because of the limitations of a 43-year-old algorithm. It could also be refined. Also a user login system could be applied to store people’s personal bests online. Apart of random maps, I could also add one way areas or blockages that would slow the player down, etc. But that would require refines in the ghosts’ AI, which I didn’t have time to do in this project.

Week 5 – Midterm Concept

Concept

For people who know me, I was a gamer my entire life, and I loved the concept of video games as art. I always believed that games themselves can convey meaning like any other artwork, and for some their aesthetic values might even exceed what people traditionally identify as art. Also due to games’ nature of being an interactive medium, it can achieve much more that traditional art forms cannot. For example, the immersion that games bring to people playing them goes far beyond just viewing them, but actually experiencing them yourselves. Therefore, I decided to look for these artistic values in the earliest games, played on the arcades. When I was reading the webpage on The Art of Video Games exhibition in 2012 on the Smithsonian Art Museum website, I came across this game that I had heard of but never played before (because it was too old, obviously), Pac-Man. I knew it was a famous game and almost as old as Tetris, and then soon found out it was one of the first video games that “took this leap beyond the arcade, beyond the screen, into the broader popular culture. That changed the way the world looked at video games and understood that there was something bigger happening here than just a place to waste a quarter.” I took a great interest in this and decided to modify it by combining some other game elements into it and upgrading its interface for my midterm assignment.

I plan to leave the core gameplay of Pac-Man alone and focus on other aspects of the game. In the original version of the game, The map is always the same. I want to combine some roguelike game elements into my project by randomly generating the map every time the player resets the game. therefore the player would always get a new experience when in the game. I also want to make it an endless mode, therefore the player can play to update their personal records. I plan to achieve that by using the tunnels on the left and right sides of the map. Once the player finishes eating all the dots in one map, the tunnels turn into portals that teleport them to other maps with different backgrounds and different theme songs.

Functions and Classes

In this game, I think the main classes are Ghosts, Map, Player, Dots, and Game.

For ghosts, the four types of ghosts (Blinky (red), Pinky (pink), Inky (cyan), and Clyde (orange)) inherit the Ghost class. The Ghost class has certain attributes: intposition for identifying its absolute position, also responsible for calculating destination position; realposition for identifying the true position of the ghost and for determining collisions; targetposition for identifying the target the ghost tries to reach; speed for the speed of the ghosts, and state for determining the current state the ghost is in for it to have different actions. The functions the Ghost class includes are checkCollision, updateTarget, stateChange, directionUpdate, etc. In these functions, updateTarget is different for different types of ghosts.

For the map, it will only have a few attributes. One is a 2D array used to represent the map, and one is its state. it will only have one function, that is mapGen, called every time it is initialized.

For Player, it will have attributes: intposition, realposition, direction, and speed. The only functions it will have are movement and checkDot.

For Dots, the only attribute is its position and type, and the only function is to destroy itself after being touched.

Lastly, for the game class, will have attributes such as points, lives, gamestate(pause, ongoing, in between, etc). It will take care of loading each state of the game and contain data necessary to keep the game going.

This is just a brief outlook of what the system would be like. In practice, some parts may be modified.

Uncertain Part of Project

I find the most uncertain part to be the random map generator. I need to come up with a set of rules so that the map is playable and won’t include too many long corridors the player can be cornered, long dead ends, or areas the player cannot access. However, I have made a preliminary generator that follows one set of rules. This set of rules makes sure that the map is different every time and will not have corridors with width 2 in it. However, this set of rules could result in inaccessible areas. Right now I have an idea about another set of rules to be applied after this so that the inaccessible areas and dead ends can be connected to the other corridors so that the map could be more reasonable. I plan to make any tile that should be accessible with only one or fewer connections with other accessible tiles have at least two connections with other accessible tiles. There will be tiles that cannot find two connection points. Then this tile will be discarded into a wall tile. This process will repeat until no action can be done, and a usable map is then created. I haven’t implemented the second rule set yet, but I have a prototype of the first rule set and it yields satisfying results. It generates grids shown below:

Therefore I am confident that this map generator will be achievable, and I only need to tweak some details.

Week 5 – Reading Reflection

After reading the paper, what I find most interesting is the methods used for computer vision and how simple they actually are. I always thought computer vision requires a significant amount of different complex algorithms, but it turns out to be as simple as comparing pixels one by one at different times. However, I still have no idea how arrays of pixels (how algorithms interpret images or videos) can be used to gain advanced information such as “tracking the orientation of a person’s gaze.”

I also find it interesting how these techniques can be applied to interactive media art. The way it makes artwork interactive is not making the viewer touch buttons whatsoever, but only move around and see what happens. This method of interactivity gives the viewer more freedom to explore what lies beyond the artwork, instead of just playing within the set of rules the artist sets. It also gives viewers an urge to explore the artwork more because they feel freedom when participating in the artwork. They would want to try out different ways of interaction and see what happens, and that’s what I find most interesting about computer vision used in interactive art pieces.