Midterm – Progress – My Spin on Snakes and Ladders

For the midterm, I wanted to work on a game that was in the board games genre of games, and thus, I decided to take a spin on Snakes and Ladders. Snakes and Ladders is a board game with a grid of numbers. It is a multi-player game and the target is to reach the 100th block from the 1st block. The movement of the tokens is decided by a die and if you happened to land on a square with a snake or a ladder – you’ll either move down a lot of squares or move up respectively. 

Setting the elements of the game

On brainstorming how I could rethink this game, I ended up deciding on having the elements of cards in the game. In addition, I started off with a lot of variations for the pathway: from spirals to a boat path to circles – but I finalized on a grid-style format so that, the familiarity of the grid-style game plays into easing the player into learning how to play the game. 

Instead of the elements of snakes and ladders, I put in cards on random squares on the grid – these squares are randomly picked at the beginning of every game – on landing on the square – the player would have to look at the corresponding card and do what the instructions say (related to moving on the squares). These cards are related to my home in Kerala and things that a person from Kerala, India would be familiar with. I wanted to make the cards accessible for anyone, without context to understand – so, there will be text included that will dictate the movement of the user token. Types of cards would include:

      • Move-ahead cards: Examples – Dosa, Grandma’s Food, Filter Coffee, etc.
      • Move-behind cards: Examples – Powercuts, Humungous mosquitoes, Coconut falling on your head, etc.

I tried making these cards using images I could find online but since the styles of art depicting all of these ideas were different, it looked out of place. So, I decided to draw the card art on my own for the game – to keep the aesthetics consistent.

Finally, since it is a multiplayer game – I decided to limit the number to two people to play the game. But if I have the time, I might consider improving the game by having the players input the number of players. For now, the user tokens are images from celebrated artforms in Kerala – Kathakali & Theyyam. Depending on whose turn it is, the corresponding token lights up and the other token is grayed out.

Implementation

I started off working on the grid. The grid is made by putting together a number of squares – so I made a class called Rect and a function called grid() which was responsible for making the objects of class Rect and numbering and displaying them. Having classes here helped a lot in adding additional functionality like putting in the number of the rectangle when displaying. For the later part of implementation too, this would greatly help in terms of randomly assigning squares in the grid and have them light a different color to represent the snake or ladder element.

//grid print
void grid(){
  int xlen = (width)/size ;
  int ylen = (height)/size;
  rect = new Rect[(xlen-7)*(ylen)]; 
  int i=0;
  
  for (int y=0; y < ylen; y++) {
      for (int x = 3; x <xlen-4; x++) {
        PVector p = new PVector(x*size,y*size);
        rect[i] = new Rect(p, size,i);
        i++;    
      }
    }
}


class Rect{
   float size;
   PVector position;
   int num;
   
   Rect(PVector p, float s, int n){
     position = p;
     size = s;
     num=n;
   }
   void display(){
     stroke(255);
     fill(0);
      
     rect(position.x,position.y,size,size); 
     fill(255);
     text(num,position.x,position.y+size-5);
   }
}
Grid with the Theyyam user token

Then, I worked on implementing a die program on a separate processing sketch.  I used this link as a reference to work on this. When you press within the die, it stops otherwise it keeps rolling.

void dice(){
  fill(255);
  text("Click on the dice to roll it, Player 1", diceX-diceSize,diceY-diceSize+20);

  fill(#FFF3D6);
  rectMode(CENTER);
  rect(diceX, diceY, diceSize, diceSize, diceSize/5);

  //dots
  fill(50);
  int side = int(random(1, 7));
  if (side == 1 || side == 3 || side == 5)
    ellipse(diceX, diceY, diceSize/5, diceSize/5); 
  if (side == 2 || side == 3 || side == 4 || side == 5 || side == 6) { 
    ellipse(diceX - diceSize/4, diceY - diceSize/4, diceSize/5, diceSize/5);
    ellipse(diceX+ diceSize/4, diceY + diceSize/4, diceSize/5, diceSize/5);
  }
  if (side == 4 || side == 5 || side == 6) {
    ellipse(diceX - diceSize/4,diceY + diceSize/4, diceSize/5, diceSize/5);
    ellipse(diceX + diceSize/4, diceY- diceSize/4, diceSize/5, diceSize/5);
  }
  if (side == 6) {
    ellipse(diceX, diceY- diceSize/4, diceSize/5, diceSize/5);
    ellipse(diceX, diceY + diceSize/4, diceSize/5, diceSize/5);
  }
  
  rectMode(CORNER);
  
}

void mousePressed(){
  if(mouseX>(diceX)-(diceSize/2) && mouseX<(diceX)+(diceSize/2) && mouseY>(diceY)-(diceSize/2) && mouseY<(diceY)+(diceSize/2 ))
  toggleRun=!toggleRun;
}

 

I combined all of these together and finally, put in the user tokens on the side indicating whose turn it is.

PImage kathakali,kathakaliInactive;
PImage theyyam,theyyamInactive;
Rect rect[];
int size = 80;
int diceX = (100*width/8)+25;
int diceY =(60*height/8)+10;
int diceSize = 90;
boolean toggleRun=false;



void setup() {
  fullScreen();
  background(0);
  theyyam = loadImage("theyyam.png");
  theyyamInactive = loadImage("theyyamInactive.png");
  theyyam.resize(220, 260);
  theyyamInactive.resize(220, 260);
  kathakali = loadImage("kathakali.png");
  kathakaliInactive = loadImage("kathakaliInactive.png");
  kathakali.resize(180,224);
  kathakaliInactive.resize(180,224);  
  
  //how to play
  
  //players choose whether they want theyyam or kathakali

  image(theyyamInactive, 0, height/2-190);
  image(kathakaliInactive, 15, height/2+20);
  dice();
}

void draw() {
  grid();
   for (int j=0; j<rect.length; j++){
    rect[j].display(); 
  }
  scale(0.4);
  image(theyyam, width/2+80, height/2+140);
  if(toggleRun){
    for(int i=0;i<10;i++)
    {
   dice(); 
  }
 }
}

Next Steps:

    • Add in a beginning and final sketch for the game
    • Add an instructions page
    • Random function to assign cards to squares and change their colors
    • Make the movement function, so that the tokens move according to the die input and the cards, if applicable. 
    • Celebration visuals when one of the players wins – My idea is to have the grid light up in all sorts of colors to generate excitement. 

References:

Open Processing – Dice Rolling 

Midterm Prototype

Description:

For my midterm project, I referred to OpenProcessing. This game is  a combination of Tetris and SameGame. In this game, the player’s goal is to eliminate the highlighted cube. Every turn, a cube falls down and the player can move it left or right, just like in the Tetris, but only in the form of a cube. Also, random cubes will generate across the canvas to increase the difficulty and playability. The player should manage to make combos of cubes with the same color in order to eliminate them. It is set that the player can eliminate at most 5 cubes.

 

Challenges:

Considering the mechanisms of the game is the most challenging part so far. Since it is a new game (I’ve never seen it elsewhere), it takes me a lot of time to play it myself and adjust the game rules.

At first, I set the goal to be eliminating every cube, which is almost impossible because if you are left with only a few cubes, you have to be really lucky to get the color you want to make combos.

I also found it logically tricky to write the codes for combos.  👇

void checkSame() {
    int nb = 0;//number of full lines
    int mark_x = 0;
    int mark_y = 0;
    boolean same = false;
    
    // check horizontal
    for (int j = 0; j < h; j ++) {
      for (int i = 0; i < w; i++) {
        color c1 = cells[i][j];
        if ((i+2 < w) && (!isFree(i, j))) {
          if ((cells[i+1][j] == c1) &&
            (cells[i+2][j] == c1)) {
              int mark_num = 2;
              mark_x = i;
              mark_y = j;
              if ((i+3 < w) && (cells[i+3][j] == c1)) {
                mark_num = 3;
              }
              if ((i+4 < w) && (cells[i+4][j] == c1)) {
                mark_num = 4;
              }
              nb = nb + mark_num - 1;
              for (int k = mark_y; k > 0; k--) {
                for (int m = mark_x;  m <= mark_x + mark_num; m++) {
                  if ((j+2 < h) && (cells[m][j+1] == c1) &&
                  (cells[m][j+2] == c1)) { 
                    cells[m][j+1] = 0;
                    cells[m][j+2] = 0;
                  }
                  checkGame();
                  cells[m][k] = cells[m][k-1];
                  cells[m][0] = 0;
              continue;
             }           
            }
           }
      }
      if ((j+2 < h) && (!isFree(i, j))) {
          if ((cells[i][j+1] == c1) &&
          (cells[i][j+2] == c1)) {
            same = true;
            mark_x = i;
            mark_y = j;
           }           
          }
      if (same) {
        nb++;
        for (int k = mark_y; k < mark_y + 3; k++) {
          try{
          cells[mark_x][k] = 0;
          checkGame();
          } catch(Exception e) {           
          }
        }
        for (int k = mark_y; k > 2; k--) {
          cells[mark_x][k] = cells[mark_x][k-2];
        }
      } 
      }
      }
    deleteLines(nb);
    }

 

Codes:

int w = 10;
int h = 10;
int q = 40;
int dt;
int currentTime;
Grid grid;
Piece piece;
Piece nextPiece;
Pieces pieces;
Score score;
int level = 1;
int nbLines = 0;

int txtSize = 20;
int textColor = 0;
int x1;

Boolean gameOver = false;
Boolean gameOn = false;
Boolean gamePause = false;
Boolean gameWin = false;

void setup()
{
  size(600, 480, P2D);
  textSize(30);
}

void initialize() {
  nbLines = 0;
  dt = 1000;
  currentTime = millis();
  score = new Score();
  grid = new Grid();
  pieces = new Pieces();
  piece = new Piece(-1);
  nextPiece = new Piece(-1);
  grid.generate();
  score = new Score();
  level = 1;
  
  x1 = int(random(0, w)); 
  while (grid.isFree(x1,h-1)) {
    x1 = int(random(0, w));
  }
}

void draw()
{
  background(#3D4E81);
  if (grid != null) {
    grid.drawGrid();
    int now = millis();
    if (gameOn) {
      if (now - currentTime > dt) {
        currentTime = now;
        piece.oneStepDown();
      }
    }
    piece.display(false);
    score.display();
    fill(#F2D7D7);
    text("Goal: ", 40, 200);
    stroke(#F8FC08);
    strokeWeight(5);
    fill(grid.cells[x1][h-1]);
    rect(50, 220, q, q);
  }
  
  if (gameOver) {
     noStroke();
     background(0);
     fill(255);
     text("Game Over", width/2 - 80, height/2 - 80);
     text("Press 'ENTER' to restart.", width/2 - 140, height/2 + 60);
     text("Press 'ESC' to exit.", width/2 - 140, height/2 + 100);
  }
  
  if (!gameOn) {
    noStroke();    
    fill(0, 60);
    rect(30, 30, 540, 420, 10);
    fill(255);
    text("Press <-- or --> to move the cubes.", 40, 200);
    text("If a chain of three same colors is formed, ", 40, 100);
    text("they can be eliminated!", 40, 140);
    text("Press 'P' to pause.", 40, 260);
    fill(#F0A5A5);
    text("Press 'ENTER' to start.", width/2-160, 360);
  }
  
  if (gameWin) {
     noStroke();
     background(#C9A4D8);
     fill(255);
     text("Congratulations! You win!", width/2 - 160, height/2 - 80);
     text("Press 'ENTER' to restart.", width/2 - 140, height/2 + 60);
     text("Press 'ESC' to exit.", width/2 - 140, height/2 + 100);
  }
}

void goToNextPiece() {
  piece = new Piece(nextPiece.kind);
  nextPiece = new Piece(-1);
}

void goToNextLevel() {
  score.addLevelPoints();
  level = 1 + int(nbLines / 100);
  dt *= .98;
}

void keyPressed() {
  if (key == CODED && gameOn) {
    switch(keyCode) {
    case LEFT:
    case RIGHT:
    case DOWN:
    case UP:
    case SHIFT:
      piece.inputKey(keyCode);
      break;
    }
  } else if (keyCode == 80) {
    if (gameOn) {
      gamePause = !gamePause;
      
      if (gamePause) {
        fill(0, 60);
        rect(width/2 - 200, height/2 - 50, 400, 100, 10);
        fill(255);
        text("Press 'P' to restart the game.", width/2 - 180, height/2);
        noLoop();
      } else if (!gamePause){
        loop();
      }
    }
    
  } else if (keyCode == ENTER) {
    if (gameOver) {
      gameOn = false;
      gameOver = false;
      loop();
    }
    
    if (!gameOn) {
      initialize();
      gameOver = false;
      gameOn = true;
      loop();
    }
  }  
}

 

class Piece {

  final color[] colors = {
    //color(#047E83), 
    //color(#760483), 
    //color(#830424), 
    color(#DE5410), 
    color(#368E6D), 
    color(#D380C1), 
    color(#E3A7AC)
  };

  final int[][] pos;
  int x = int(w/2);
  int y = 0;
  int kind;
  int c;
  int c0, c1, c2, c3, c4;

  Piece(int k) {
    if (k < 0) {
      kind = int(random(0, 4));
    } else {
      kind = k;
    }
    c = colors[kind];
    pos = pieces.pos[kind];
  }

  void display(Boolean still) {
    stroke(250);
    fill(c);
    pushMatrix();
    if (!still) {
      translate(160, 40);
      translate(x*q, y*q);
    }
    rect(pos[0][0] * q, pos[0][1] * q, 40, 40);

    popMatrix();
  }

  // returns true if the piece can go one step down
  void oneStepDown() {
    y += 1;
    if(!grid.pieceFits()){
      piece.y -= 1;
      grid.addPieceToGrid();
    }
  }

  // try to go one step left
  void oneStepLeft() {
    x --;
  }

  // try to go one step right
  void oneStepRight() {
    x ++;
  }

  void goToBottom() {
    grid.setToBottom();
  }

  void inputKey(int k) {
    switch(k) {
    case LEFT:
      x --;
      if(grid.pieceFits()){
      }else {
         x++; 
      }
      break;
    case RIGHT:
      x ++;
      if(grid.pieceFits()){
      }else{
         x--; 
      }
      break;
    case DOWN:
      oneStepDown();
      break;
    case SHIFT:
      goToBottom();
      break;
    }
  }

}



class Pieces {
  int[][][] pos = new int [4][1][2];
  
  Pieces() {
    pos[0][0][0] = -1;
    pos[0][0][1] = 0;
    pos[1][0][0] = -1;
    pos[1][0][1] = 0;
    pos[2][0][0] = -1;
    pos[2][0][1] = 0;
    pos[3][0][0] = -1;
    pos[3][0][1] = 0;
    //pos[4][0][0] = -1;
    //pos[4][0][1] = 0;
    //pos[5][0][0] = -1;
    //pos[5][0][1] = 0;
    //pos[6][0][0] = -1;  
    //pos[6][0][1] = 0;
  }
}
class Grid {
  int [][] cells = new int[w][h];

  Grid() {
    for (int i = 0; i < w; i ++) {
      for (int j = 0; j < h; j ++) {
        cells[i][j] = 0;
      }
    }
  }

  Boolean isFree(int x, int y) {
    if (x > -1 && x < w && y > -1 && y < h) {
      return cells[x][y] == 0;
    } else if (y < 0) {
      return true;
    }
    return false;
  }

  Boolean pieceFits() {
    int x = piece.x;
    int y = piece.y;
    int[][] pos = piece.pos;
    Boolean pieceOneStepDownOk = true;
    int tmpx = pos[0][0]+x;
    int tmpy = pos[0][1]+y;
    if (tmpy >= h || !isFree(tmpx, tmpy)) {
      pieceOneStepDownOk = false;
     }
    return pieceOneStepDownOk;
  }

  void addPieceToGrid() {
    int x = piece.x;
    int y = piece.y;
    int[][] pos = piece.pos;
      if(pos[0][1]+y >= 0){
        cells[pos[0][0]+x][pos[0][1]+y] = piece.c;
      }else{
        gameOn = false;
        gameOver = true;
        return;
      }
    checkSame();
    
    
    goToNextPiece();
    random_gen(int(random(0, 2)));
    checkSame();
    drawGrid();
    checkGame();
    
  }
  

  void checkSame() {
    int nb = 0;//number of full lines
    int mark_x = 0;
    int mark_y = 0;
    boolean same = false;
    
    // check horizontal
    for (int j = 0; j < h; j ++) {
      for (int i = 0; i < w; i++) {
        color c1 = cells[i][j];
        if ((i+2 < w) && (!isFree(i, j))) {
          if ((cells[i+1][j] == c1) &&
            (cells[i+2][j] == c1)) {
              int mark_num = 2;
              mark_x = i;
              mark_y = j;
              if ((i+3 < w) && (cells[i+3][j] == c1)) {
                mark_num = 3;
              }
              if ((i+4 < w) && (cells[i+4][j] == c1)) {
                mark_num = 4;
              }
              nb = nb + mark_num - 1;
              for (int k = mark_y; k > 0; k--) {
                for (int m = mark_x;  m <= mark_x + mark_num; m++) {
                  if ((j+2 < h) && (cells[m][j+1] == c1) &&
                  (cells[m][j+2] == c1)) { 
                    cells[m][j+1] = 0;
                    cells[m][j+2] = 0;
                  }
                  checkGame();
                  cells[m][k] = cells[m][k-1];
                  cells[m][0] = 0;
              continue;
             }           
            }
           }
      }
      if ((j+2 < h) && (!isFree(i, j))) {
          if ((cells[i][j+1] == c1) &&
          (cells[i][j+2] == c1)) {
            same = true;
            mark_x = i;
            mark_y = j;
           }           
          }
      if (same) {
        nb++;
        for (int k = mark_y; k < mark_y + 3; k++) {
          try{
          cells[mark_x][k] = 0;
          checkGame();
          } catch(Exception e) {           
          }
        }
        for (int k = mark_y; k > 2; k--) {
          cells[mark_x][k] = cells[mark_x][k-2];
        }
      } 
      }
      }
    deleteLines(nb);
    }
    
    
  Boolean checkWin() {
    if (isFree(x1, h-1)) {
      return true;
    }
    return false;
  }

  void deleteLines(int nb) {
    nbLines += nb;
    if (int(nbLines / 100) > level-1) {
      goToNextLevel();
    }
    score.addLinePoints(nb);
  }

  void setToBottom() {
    int j = 0;
    for (j = 0; j < h; j ++) {
      if (!pieceFits()) {
        break;
      } else {
        piece.y++;
      }
    }
    piece.y--;
    delay(1500);
    addPieceToGrid();
  }

  void drawGrid() {
    stroke(150);
    pushMatrix();
    translate(160, 40);
    line(-10, 0, -10, h*q);

    strokeWeight(sin(10/4-200)*6);
    stroke(0,0,10);
    for (int i = 0; i < w; i ++) {
      for (int j = 0; j < h; j ++) {
        if (cells[i][j] != 0) {
          fill(cells[i][j]);
          rect(i*q, j*q, q, q);
        }
      }
    }
    pick(x1, h-1);
    popMatrix();
  }
  
  void generate() {
    color[] colors = {
    //color(#047E83), 
    //color(#760483), 
    //color(#830424), 
    color(#DE5410), 
    color(#368E6D), 
    color(#D380C1), 
    color(#E3A7AC)
  };
     for (int i = 0; i < w; i ++) {
      for (int j = h * 2/3 ; j < h ; j ++) { // h * 3/4
        color c1 = colors[int(random(0, 4))];
        fill(c1);
        cells[i][j] = c1;
      }
    }
    checkSame();
  }
  
  void random_gen(int num) {
    color[] colors = {
    //color(#047E83), 
    //color(#760483), 
    //color(#830424), 
    color(#DE5410), 
    color(#368E6D), 
    color(#D380C1), 
    color(#E3A7AC)
  };
    int i=1, j=1;
    for (int k=0; k<=num; k++) {
      while (isFree(i, j+1) || !isFree(i, j)){
        i = int(random(1, w));
        j = int(random(1, h-1));
      }
      color c1 = colors[int(random(0, 4))];
      fill(c1);
      cells[i][j] = c1;
    }
    checkSame();
    
  }
  
  void checkGame() {
    for (int i=0; i<w; i++) {
      if (!isFree(i, 0)) {
        gameOver = true;
      }
    }    
    if (checkWin()) {
      gameWin = true;
    }
  }
  
  void pick(int x, int y) {
    stroke(#F8FC08);
    strokeWeight(5);
    fill(cells[x][y]);
    rect(x*q, y*q, q, q);
  }

}
  void display() {
    pushMatrix();
    translate(40, 60);

    //score
    fill(#F2D7D7);
    text("score: ", 0, 0);
    fill(230, 230, 12);
    text(""+formatPoint(points), 0, txtSize + 10);
    
    popMatrix();

  }

  String formatPoint(int p) {
    String txt = "";
    int qq = int(p/1000000);
    if (qq > 0) {
      txt += qq + ",";
      p -= qq * 1000000;
    }

    qq = int(p/1000);
    if (txt != "") {
      if (qq == 0) {
        txt += "000";
      } else if (qq < 10) {
        txt += "00";
      } else if (qq < 100) {
        txt += "0";
      }
    }
    if (qq > 0) {
      txt += qq;
      p -= qq * 1000;
    }
    if (txt != "") {
      txt += ",";
    }

    if (txt != "") {
      if (p == 0) {
        txt += "000";
      } else if (p < 10) {
        txt += "00" + p;
      } else if (p < 100) {
        txt += "0" + p;
      } else {
        txt += p;
      }
    } else {
      txt += p;
    }
    return txt;
  }
}

 

Plan:

For the next week, I plan to insert images and music to make the game visually better, and changing the display for the game rules,  game over and game clear.

I will also modify the calculations of the scores to be more reasonable.

 

 

Looking forward to your suggestions  🙂

MIDTERM PROJECT PROGRESS

UNI RUSH 

INSPIRATION:

The inspiration behind the game I want to create comes from how overprotective I tend to be with my GPA. Since I was a kid, I always would work to achieve the highest grades and an even the slightest deduction of grades would make me cry. However, after I came to university, that reality changed, and it’s been like a roller-coaster with all its ups and downs. The games resemble a university student who is running all over to catch the grades they want. Based on that, the gpa gets either incremented or decremented depending on the letter grade they catches.  I have always been keen to understand how gpa calculation works, so I searched it up and decided to base my game on that. Also, gpa calculator still always saves my life. Finally, uni rush is a game logic in which a student character is moving different grades comes along the path. So, when the student catches the appearing grade, then GPA is getting calculated at the back end based on the overall grades taken.

GAME RULES:


To score a higher GPA score, the character must catch the better grades and skip the bad ones. The winner of the game will get a maximum GPA score of four. For the movement, the user must move the character in the right path either up or down, right, or left.

IMPLEMENTATION STRATEGY:


I will be using object-oriented approach to divide the coding patterns based on the game logic. Then, I will use an array data structure to store the grade letters in form of images. Afterwards, I will implement 3 different sound effects for each game screen. Eventually, I will have a win sound effect if GPA score was 4.0.

OBJECTS TO BE USED IN GAME:


Grade letters

The grade letter objects will be images of each grade letter on its own

Student Character

This can be any cartoon character with a bigger size as compared to grade letters and can move either left-right or up and down based on the key pressing

Game Background

This object will be a university campus image which is set as the background of the game

GPA Score Prompt

This object will be a simple text prompt and the value of the GPA score will be calculated at run time depending on the game logic.

STORY BOARD OF THE GAME


The game starts with a menu screen on which a prompt will display that shows which key to press to start the game and other instructions. On the main menu screen there is a button to move to the game rules screen. The game rule screen shows all keys for the movement of character for example up, down, left, and right. The start game button on the main menu screen will move to the game screen which is the main part of the game. Furthermore, on the top there will be a GPA score prompt. The character on the other hand will be either standing on one side, and the grades are coming towards him from the other side, or the character is moving while grades are appearing suddenly on a random basis. Background sound effects will be played on every screen.

PROGRESS :

 

CODE FOR NOW :

// import library for sound 
import processing.sound.*;
// objects for bakcground, charcter,  alphabets, and gpa calculation
PImage background;
PImage character;
PImage A;
PImage B;
PImage C;
PImage D;
PImage F;
int score; 

// Position of the character in x and y coordinates 
int posx=0;
int posy=300;

//  background sound object 
SoundFile backmusic;

// Set up function 
void setup() 
{
  // setting screen size
  size(1080, 720);
  // every 30 milescond, a new screen is rendering 
  frameRate(30);
  // initialzie background image object and setting background image as parameter
  background = loadImage("back.png");
  // initializing charcter image object 
  character = loadImage("character.png");
  // initializing letter grade objects 
  A= loadImage("A.png");
  B= loadImage("B.png");
  C= loadImage("C.png");
  D= loadImage("D.png");
  F= loadImage("F.png");
  // initiliaze sound object 
  backmusic = new SoundFile(this, "BackSound.mp3");
}

void keyPressed() 
{
  // if key is pressend by w , then move charcter up
  if(key == 'w') 
  {
    image(character,0,posy-1);
  }
  // if press a, charcter move to left side 
  if(key == 'a') 
  {
    image(character,posx-1,0);
  }
  // if charcter press s, charcter move down 
  if(key == 's') 
  {
    image(character,posx,posy);
  }
  // if press d, character, move right 
  if(key == 'd') 
  {
    image(character,posx+1,posy);
  }
  
}


void draw() 
{ 
  // playing the sound
  backmusic.play();
  // dispalying  background image 
  image (background,0,0);
  // displaying chacrter image and give its initial positions (x,y)
  image(character,posx,posy);
  // displaying letter grades,  plus I give each letter grade their position (x,y)
  image(A,width-120,300);
  image(B,width-150,500);
  image(C,width-180,200);
  image(D,width-220,600);
  image(F,width-140,150);
  // displaying gpa score at the top 
  text("GPA Score: ",30,30);

 

Midterm Progress

Idea:

I wanted to create something, fun and simple. I remember loving the where’s Waldo books when I was young, and there was this super Mario game where you have to find Mario. I decided to incorporate nyuad as a theme. The players have to find the thief on our campus before it’s too late!

These are the main points of the game:

  1. The campus will be pitch black other than a flashlight the the player has.
  2. use the flashlight to find the thief before the 45 second timer goes off, if you don’t it is game over and nyuad will be robbed !
  3. the thief will change places every time a new game is started.

Progress until now:

First of all in order to create a unique background I loaded a nyuad backdrop image.

Then after a lot of research and a lot of help from the coding train(https://www.youtube.com/watch?v=j-ZLDEnhT3Q)  I was able to create the flashlight effect and make the rest pitch black. By using image processing with pixels.

void draw() {
  

     
  loadPixels();
  nyu.loadPixels();

 
  for (int x = 0; x < nyu.width; x++ ) {
    for (int y = 0; y < nyu.height; y++ ) {

      
      int loc = x + y*width;

      float r = red  (nyu.pixels[loc]);
      float g = green(nyu.pixels[loc]);
      float b = blue (nyu.pixels[loc]);

      
      float distance = dist(mouseX,mouseY,x,y);

      
      float adjustBrightness = map(distance, 0, 200, 2, 0);
      pixels[loc]=color(r*adjustBrightness,g*adjustBrightness,b*adjustBrightness);
    
    }
   

  
  }
  updatePixels();
 image(sprites[direction][step], x, y);
  
  }
  

 

This created this effect which I think is very cool:

 

Now I had to incorporate a sprite in order to add the thief. This is what I decided to go with

Challenges:

there are definitely a lot of questions that I need to ask in order to be able to move forward. The main one being, that when I added the sprite (thief) to the game he was visible above the darkness as is shown here:

I am not sure how to fix this.

Next steps:

  1. add instructions to the beginning and a game over or congratulations indication at the end.
  2. make the sprite appear in random locations every time a new game begins.
  3. make the game stop (and congrats appears) when the mouse is clicked on the sprite.
  4. add alarm sounds to when the thief is found.

Hopefully it goes well!

PImage nyu;
PImage spritesheet;
PImage[][] sprites;
int direction = 1; 
int step = 0;
int x;
int y;
int speed = 3;
void setup() {
  size(1200, 800);
 
  spritesheet = loadImage("thief.png");


  sprites = new PImage[4][3]; 

  int w = spritesheet.width/3;
  int h = spritesheet.height/4;

  for (int y=0; y < 4; y++) {
    for (int x=0; x< 3; x++) {
      sprites[y][x] = spritesheet.get(x*w, y*h, w, h);
    }
}

  x = width/2;
  y = height/2;
  
  imageMode(CENTER);
   nyu = loadImage( "nyu.png" );
}

void draw() {
  

     
  loadPixels();
  nyu.loadPixels();

 
  for (int x = 0; x < nyu.width; x++ ) {
    for (int y = 0; y < nyu.height; y++ ) {

      
      int loc = x + y*width;

      float r = red  (nyu.pixels[loc]);
      float g = green(nyu.pixels[loc]);
      float b = blue (nyu.pixels[loc]);

      
      float distance = dist(mouseX,mouseY,x,y);

      
      float adjustBrightness = map(distance, 0, 200, 2, 0);
      pixels[loc]=color(r*adjustBrightness,g*adjustBrightness,b*adjustBrightness);
    
    }
   

  
  }
  updatePixels();
 image(sprites[direction][step], x, y);
  
  }
  

 

Midterm In Progress

Catching fallen stars(Taiwanese Version)

INSPIRATION:

There is a Taiwanese myth about catching fallen stars to make a wish come true. I intend to create a game that consists of a traditional Taiwanese bamboo woven basket and white stars falling from the night sky.

RULES:

The way to win is to collect a set number of stars. The player would be faced with fallen meteoroids, plastic trash, and satellite remains. They have three lives in total and loses the game when all three lives are wasted. However, players can catch Taiwanese street food to restore lost lives.

OBJECTS:
Array to store these objects
  • Background: import an image of Taiwanese famous night sky
  • Sound:
    1. Background music: summer night time in Taiwanese mountains
    2. Fallen objects: all have their respective sounds
  • Object behavior:
    1. Meteoroids: will look like a fallen star at first, but will enlarge and transform into a disastrous meteoroid
    2. Plastic trash: if it hits the basket, the player would be paralyzed for 1-2 second
    3. Satellite: falling with extremely fast speed
    4. Food: will be moving from side to side
STORYBOARD:
  1. MENU (START/RESTART)
  2. RULES
  3. STORYTIME
  4. GAME
CODES (FOR NOW):
PImage sky;
  
void setup(){
  size (512,1024);
  //drag image into processing and it creates a file in the folder
  sky = loadImage("pinxi sky lantern.jpeg");
  noStroke();
}

void draw (){
image (sky,0,0);
}
VISUALS: 

Should extend the photo to cover the vertical interface!

P.S:

Will attempt to add a lot of Taiwanese related elements (images, sounds, stories…)

Week 5 Data Visualization – Leo Shirky

Inspiration:

I find that Google Trends is great for telling time when you search for seasonal or repetitive events. For example, searches for Mariah Carey’s “All I Want for Christmas” always increases around the start of the holiday season in the United States. I eventually chose to use Ramadan, as it occurs once per calendar year, but changes when in the calendar year it occurs.

Process:

I started by downloading the Google Trends spreadsheet and adding it to Processing. I first made a simple version of what I wanted the final graph to look like, simply by telling Processing to pull the dates and searches from the .csv file. This made a simple bar chart, at which point I started to mess with the scale I wanted. I had to map the values from the .csv chart into x and y coordinates. I did this simply by messing around with different values until I found a scale I liked.

Next I added a title and a date/searches counter to display the values from the .csv file. I thought that labelling each date and having a scale on the y-axis would be too difficult for the user to read. This calculator allowed the user to easily tell exactly when and how much “Ramadan” was being searched.

The final aspect that I wanted in my graph was to highlight the bar that was being selected. I wanted the color and thickness of the bar to change to make it very clear which was being selected. Rather than have the user click each bar, I wanted it to happen automatically based on where the users mouse was.

Final Work:

Below is a video displaying how the graph works.

 

Challenges:

I had a lot of trouble figuring out the highlighting. I made an integer mx for the x position of the mouse. I initially tried “if (mx == x)” with x being the x value of the bar, but that would only highlight a few bars when the mouse hovered over them, rather than each bar. In the end I used if(abs(mx>3)), which worked much better.

Code:

Table table;
PFont titleFont;
int mx = 30; // mouseX position
void setup() {
  size(1280, 400);
 titleFont =  createFont("Courier New", 15);
 table = loadTable("RamadanTimeline.csv", "header");
 smooth(0);
 
}
void draw() {
  background(235,236,237);
  textFont(titleFont);
  stroke(0);
  fill(227,70,126);
  textAlign(CENTER);
  text("Interest in Ramadan by Week over past 5 years", width/2, 50);
  fill(253,93,96);
  text("Data via Google Trends", width/2, 70);
  
//take data from the .csv file
  for (int row = 0; row < table.getRowCount(); row++) {
    String dates = table.getString(row, 0);
    float searches = table.getFloat(row, 1);
    float x = map(row, 0, 216, 0, width);
    float y = map(searches, 0, 100, 375, 60);
    
//draw the lines on the graph, and change the color of the selected line
    line(x, y, x, 375);
    if(abs(mx - x)<3){
      strokeWeight(6);
      stroke(252,192,109);
    }else{
      strokeWeight(2);
      stroke(60,73,129);
    }

//display the date and data for each selected line
    if(abs(mx - x) < 3) {
      fill(66,190,171);
      text(dates, width-50, 50);
      text(nfp(searches, 1, 3), width-50, 80);
      }
    }
  }
 
void mouseMoved() {
  mx = mouseX;
}