Joanne Chui – Final Project

TILES

sketch

// Joanne Chui
// Section C
// Final Project

var gridLength = 400;

var myLBlue = 0
var myBlue = 0
var myOrange = 0

var tileCount = 0; //amount of columns and rows
var crtPattern = 0; //amount of tiles highlighted
var counter = 0;
var roundNum = 1;

let ready = false;
let wrongAnswer = false;

myGrid = [];
userGrid = [];

function setup(){
  createCanvas(550, 405);
  background(80, 20, 10);
  textSize(32);
  fill('white');
  text("T I L E S", 415, 40);
  textSize(10);
  text("MEMORIZE THE PATTERN", 415, 70);
  text("PRESS R WHEN READY", 420, 90);
  text("CLICK TO CHANGE TILE", 418, 110);
  textSize(20);
  text("ROUND", 440, 180);

  tileCount = int(random(3, 6));
  crtPattern = int(.4 * (tileCount * tileCount));

  myLBlue = color(25, 120, 145);
  myBlue = color(15, 60, 100);
  myOrange = color(200, 80, 50);

  stroke(90, 100, 90);
  for(i = 0; i < tileCount; i++){
    myGrid.push([]);
    userGrid.push([]);
    for(j = 0; j < tileCount; j++){
      myGrid[i].push(myBlue);
      userGrid[i].push(myBlue);
    }
  }
}

function draw(){
  strokeWeight(5);
  rect(440, 185, 70, 70);
  fill('white');
  noStroke();
  textSize(50);
  if(roundNum < 10){
    text(roundNum, 462, 237);
  }else{
    text(roundNum, 447, 237);
  }

  if(ready){
    drawGrid();
  }else{
    drawPatternGrid();
  }

  //GAME OVER
  if(wrongAnswer){
    //have solution pop up
    drawPatternGrid();
    //game over text
    noStroke();
    fill(80, 20, 10)
    rect(0, 170, 410, 60);
    fill("white");
    textSize(34);
    text("GAME OVER", 115, 210);
  }

  //border
  fill(myBlue);
  strokeWeight(10);
  line(4, 4, gridLength, 4);
  line(gridLength, 4, gridLength, gridLength);
  line(gridLength, gridLength, 4, gridLength);
  line(4, gridLength, 4, 4);

}


function drawPatternGrid(){
  stroke(10, 35, 60);
  strokeWeight(7);
  for(i = 0; i < tileCount; i++){
    for(j = 0; j < tileCount; j++){
      patternGenerator();
      fill(myGrid[i][j])
      rect(i * (gridLength/tileCount), j * (gridLength/tileCount), gridLength/tileCount, gridLength/tileCount);
    }
  }

}

//creates the solution pattern of tiles
var keyI = 0;
var keyJ = 0;
var x = 0;
function patternGenerator(){
  while(x < crtPattern){
    keyI = int(random(tileCount));
    keyJ = int(random(tileCount));
    if(myGrid[keyI][keyJ] != myOrange){
      myGrid[keyI][keyJ] = myOrange;
      x += 1;
    }
  }
}

//base grid for guessing
function drawGrid(){
  stroke(10, 35, 60);
  strokeWeight(7);
  for(i = 0; i < tileCount; i++){
    for(j = 0; j < tileCount; j++){
      mouseHover();
      fill(userGrid[i][j]);
      rect(i * (gridLength/tileCount), j * (gridLength/tileCount), gridLength/tileCount, gridLength/tileCount);
    }
  }
}

//highlights tiles if mouse hovers over them
function mouseHover(){
  if(mouseX < (i+1) * gridLength/tileCount & 
     mouseX > i * gridLength/tileCount && 
     mouseY < (j+1) * gridLength/tileCount &&
     mouseY > j * gridLength/tileCount){
    if(userGrid[i][j] != myOrange){
      userGrid[i][j] = myLBlue;
    }
 
  }else{
    if(userGrid[i][j] != myOrange){
      userGrid[i][j] = myBlue;
    }
  }
}


//selecting tiles
function mousePressed(){
 for(i = 0; i < tileCount; i++){
    for(j = 0; j < tileCount; j++){
      if(mouseX < (i+1) * gridLength/tileCount & 
       mouseX > i * gridLength/tileCount && 
       mouseY < (j+1) * gridLength/tileCount &&
       mouseY > j * gridLength/tileCount){
        if(counter < crtPattern - 1){
          if(userGrid[i][j] != myOrange){
            if(myGrid[i][j] == myOrange){
              userGrid[i][j] = myOrange;
              counter += 1;
              print(counter);
              print(crtPattern);
              }else{
              wrongAnswer = true;
              }
            }
          }else{
            ready = false;
            myGrid = [];
            userGrid = [];
            roundNum += 1;
            for(i = 0; i < tileCount; i++){
              myGrid.push([]);
              userGrid.push([]);
              for(j = 0; j < tileCount; j++){
                myGrid[i].push(myBlue);
                userGrid[i].push(myBlue);
              }
            }
            counter = 0;
            x = 0;
        }
      }
    }
  }
}

//switch grid
function keyTyped(){
  if(key === "r" || key === "R"){
    ready = true;
    }else{
      ready = false;
  }
}











This is a memorization game to test a user’s spatial recall ability. A pattern of tiles is first shown, and once the user has committed the pattern to memory, pressing the “r” key will render the grid blank, and the user must recreate the pattern by clicking on the tiles. If the pattern matches the original pattern, a new pattern is generated. Once the user clicks an incorrect tile, the game is over. The division of the grid is randomized.

Looking Outwards 12 – Joanne Chui

matching memorization game

The first game my project was inspired by was a memorization game in which you continuously flip through tiles to find matching ones. This is more of a general game idea that I was inspired by. What I don’t like about this game is how restricted it is, in which you have to match two tiles, and how it has a slower game speed. However, I do like the idea of the flipped tiled interface and memorization aspect.

Tiles^2

Tiles2 is an Iphone game developed by Andrew Abosh in 2018. The premise of the game is that you have three seconds to memorize a sequence of tiles, and you have to select those tiles in chronological order. I like the fast paced atmosphere of the game, but don’t like the restrictive nature of the numbered tiles, and how the game is immediately over once you select an incorrect tile.

Project 12 – Proposal – Joanne Chui

For my final project, I am interested in creating a memorization game that involves the user remembering a pattern of tiles and then recreating that pattern. The game will start with a 3×3 grid, in which a set amount of tiles will randomly be highlighted for a couple of seconds, and then rendered blank again. The user will have to remember which tiles were highlighted, and then reselect them to move on to the next level. Every five levels the grid will increase by one, e.g. level five is a 4×4 grid, and the number of tiles highlighted will also be increased, to make the levels more difficult. I definitely want to figure out how to render the interface of the game in a creative way.

Looking Outwards – 11 – Joanne Chui

Mushtari, Jupiter’s Wanderer

Neri Oxman is an architect, designer, inventor, and a professor at the MIT Media Lab. Her research is focused on how computation design, digital fabrication, material science, and biology intersect, thus coining the term Material Ecology.

I was interested in this project, Mushtari, which is a 3D printed wearable sculpture that supports the flow of cyanobacteria that converts sunlight into sucrose. It’s both indexical and symbolic of the digestive tract, in which it looks and functions as an organ system for absorbing nutrients, digesting biomass, and expelling waste.

https://neri.media.mit.edu/projects/details/mushtari.html#prettyPhoto

Project 11 – Landscape – Joanne Chui

sketch

/*
Joanne Chui
Section C 
Project 11
*/

var terrainSpeed = 0.0001;
var terrainDetail = 0.005;
var riverDetail = 0.0005
var birds = [];
var c1, c2;

function setup() {
    createCanvas(480, 240);
    frameRate(10);
    for(i = 0; i < 10; i++){
      var rx = random(width);
      var ry = random(height);
      birds[i] = makeBird(rx, ry);
    }
}

function draw() {
  // background(220, 220, 230);
  c1 = color(170, 170, 190);
  c2 = color(240, 190, 120);
  setGradient(c1, c2);

  //sun
  noStroke();
  fill(210, 100, 40);
  ellipse(width/2, 160, 170, 170);

  //call landscape and birds
  drawMountain();
  updateBird();
  addBird();
  removeBird();
}

//background gradient
function setGradient(c1, c2){
  noFill();
  for(i = 0; i < height; i++){
    var inter = map(i, 0, height, 0, 1);
    var c = lerpColor(c1, c2, inter);
    stroke(c);
    line(0, i, width, i);
  }
}


function drawMountain(){
  //furthest mountain 
  fill(55, 63, 82);
    noStroke(); 
    beginShape(); 
    for (var x = 0; x < width; x++) {
        var t = (x * terrainDetail) + (millis() * terrainSpeed);
        var y = map(noise(t), 0,1, 0, height);
        vertex(x, y); 
    }
    vertex(width, height);
    vertex(0, height);
    endShape();

    //middle river
    fill(220, 180, 150);
    noStroke(); 
    beginShape(); 
    for (var x = 0; x < width; x++) {
        var t = (x * riverDetail) + (millis() * terrainSpeed);
        var y = map(noise(t), 0,1, height/2, height);
        vertex(x, y); 
    }
    vertex(width, height);
    vertex(0, height);
    endShape();

    //closest mountain
    fill(170, 120, 40);
    noStroke(); 
    beginShape(); 
    for (var x = 0; x < width; x++) {
        var t = (x * terrainDetail) + (millis() * terrainSpeed*4);
        var y = map(noise(t), 0,2, 0, height);
        vertex(x, y*3); 
    }
    vertex(width, height);
    vertex(0, height);
    endShape();
}

function makeBird(birdX, birdY){
  var bird = {
      x: birdX, 
      y: birdY, 
      speed: random(5, 20),
      size: random(5, 20),
      color: random(0, 100),
      move: birdMove,
      display: displayBird
  }
  return bird;
}

function birdMove(){
  this.x += this.speed;
  this.y -= this.speed / 5;
}

function displayBird(){
  strokeWeight(2);
  stroke(this.color);
  noFill();
  push();
  translate(this.x, this.y);
  arc(0, 0, this.size, this.size, PI + QUARTER_PI, 0);
  arc(this.size, 0, this.size, this.size, PI, 0 - QUARTER_PI);
  pop();
}

function updateBird(){
  for(i = 0; i < birds.length; i++){
    birds[i].move();
    birds[i].display();
  }
}

//adding birds with a random probability
function addBird(){
  var newBird = random(1);
  if(newBird < 0.2){
    var birdX = 0;
    var birdY = random(height);
    birds.push(makeBird(birdX, birdY));
  }
}

//removing birds from the array once they fall off the canvas
function removeBird(){
  var keepBird = [];
  for(i = 0; i < birds.length; i++){
    if(birds[i].x + birds[i].size > 0){
      keepBird.push(birds[i]);
    }
  }
  birds = keepBird;
}








I was interested in creating a landscape with many layers to show depth. I was interested in creating birds because i felt that they would add a dynamic movement in the landscape.

sketch

Joanne Chui – Project 10 – Sonic Sketch

sketch

/*
Joanne Chui
Section C 
Project 10
*/

let osc;

function preload() {
    // call loadImage() and loadSound() for all media files here
    mySnd = loadSound("https://courses.ideate.cmu.edu/15-104/f2019/wp-content/uploads/2019/11/xylophone.wav");
    mySnd.setVolume(0.5);
}


function setup() {
    createCanvas(400, 300);
    background(255, 226, 145);
    osc = new p5.TriOsc();
    osc.start();
}


function draw() {
    //glasses
    fill(255, 240, 200);
    stroke("white");
    strokeWeight(2);
    rect(25, 100, 50, 100);
    rect(125, 100, 50, 100);
    rect(225, 100, 50, 100);
    rect(325, 100, 50, 100);
    //drink
    fill(192, 225, 237);
    noStroke();
    rect(27, 120, 46, 78);
    rect(127, 140, 46, 58);
    rect(227, 160, 46, 38);
    rect(327, 180, 46, 18);


}

function mousePressed(){
  //glass clink
  if(mouseX > 25 & mouseX < 75 && mouseY > 100 && mouseY < 200){
    mySnd.play();
  }
  if(mouseX > 125 & mouseX < 175 && mouseY > 100 && mouseY < 200){
    mySnd.play();
  }
  if(mouseX > 225 & mouseX < 275 && mouseY > 100 && mouseY < 200){
    mySnd.play();
  }
  if(mouseX > 325 & mouseX < 375 && mouseY > 100 && mouseY < 200){
    mySnd.play();
  }
  //pitch dependent on height of water
  let f = map(mouseX, 0, 375, 100, 800);
  osc.freq(f);
  
}


I was interested in how a combination of sounds could produce an interesting effect. I combined the sound of the glass clinking with the sound effect of the pitches created when blowing on glasses. I like how simple the project is.

Looking Outwards 10 – Joanne Chui

Performed by the Stanford Laptop Orchestra, Composed by GE Wang
https://ccrma.stanford.edu/~ge/

GE Wang is a professor for Computer Research in Music and Acoustics at Stanford. His research focuses on interactive design in music in collaboration with programming languages. He created Smule and Magic Piano, both for the Iphone. I was interested in this piece, Twilight, because it is both a musical performance and an art performance, and integrates what GE Wang is focused on, which is interactive design in music. Using their laptops, the orchestra is able to translate thir body movements into sound/pitch, and because of that creates a visual performance as well. Something interesting with which they used the laptop seemed to mostly be biased towards gradual changes in sound, and slow build up of music, which is interesting. The algorithm used to create the music and select the pitch is definitely reliant on the length of the string attached to their wrists that the performers use.

Joanne Chui – Looking Outwards 09

Flight Patterns by Aaron Koblin

For this Looking Outwards, I decided to focus on my friend Ammar Hassonjee’s Looking Outwards which is about Aaron Koblin’s project Flight Patterns. It is interesting in how it uses lines to visualize three dimensional flight patterns through America. I thought it was interesting how these scientists took data and input that into an algorithm that creating such a captivating visualization.

I agree with Ammar in how it is interesting that Aaron was able to show movement and directionality just using data. I also liked how Adobe after effects was also used to further edit the visualization.

Portrait – Joanne Chui – Project 09

sketch

/*
Joanne Chui
Section C 
Project 8
*/

var underlyingImage;

function preload() {
    var myImageURL = "https://i.imgur.com/cYVj323.png";
    underlyingImage = loadImage(myImageURL);
}

function setup() {
    createCanvas(500, 500);
    background(0);
    underlyingImage.loadPixels();
    frameRate(100000);
}

function draw() {
    var px = random(width);
    var py = random(height);
    var ix = constrain(floor(px), 0, width-1);
    var iy = constrain(floor(py), 0, height-1);
    var theColorAtLocationXY = underlyingImage.get(ix, iy);
    var value = brightness(theColorAtLocationXY);
    var scaleBrush = map(value, 0, 225, 0, 50);

    noStroke();
    fill(theColorAtLocationXY);
    ellipse(px, py, scaleBrush, scaleBrush);

}

function mouseDragged(){
  var theColorAtTheMouse = underlyingImage.get(mouseX, mouseY);
  noStroke();
  fill(theColorAtTheMouse);
  var brushSize = random(10, 50);
  ellipse(mouseX, mouseY, brushSize, brushSize);
}

I varied the circles that populated the picture based on the brightness. Where the image is brighter, the size of the circle would be bigger. I also included an interactive portion where the user would be able to brush in the photo if they dragged the mouse, creating a more dynamic and abstract image.

using the mouse as a brush tool
size of the circle based on brightness of image
original photo

Looking Outwards – 08 – Joanne Chui

Eyeo 2015 – Jesse Louis Rosenburg and Jessica Rosenkrantz

Jesse Louis-Rosenberg and Jessica Rosenkrantz use their background in architecture, biology, and computer science to fuel their work in computational design for digital fabrication. Together, they started the Nervous System Lab, in which they applied their expertise in digital fabrication and knowledge of generative forms to create products such as jewelry, lighting fixtures, and customizable dresses.

I’m really interested in how they were able to take 3-d printing, which is seen as for producing volumes, and were able to create essentially the fabric of a dress that moves and drapes much like more conventional fabric. It would be interesting to see more of the parametric logic behind the dress.

https://n-e-r-v-o-u-s.com/about_us.php