Processing Game : STRESS FREE NYUAD?

Overview

Finally, after all the ranting and hours of crying, the midterm game project is complete and it looks and works great, as intended, who am I kidding even. To summarize the game, the theme is around stress struggles as a student. To make it more personalized, the student is an NYUAD falcon. The game design includes free-falling stressful and stress-relieving activities that the player has to avoid and collect respectively while moving across the screen horizontally. It is a race between sanity and stress. The first total to reach 320 points wins. There are four types of free-falling activities that are worth a different number of points and allows the player certain boosted or dulled abilities. The game starts with the main page that allows the player to either start the game directly or navigate to the instructions screen. The game has three different difficulty levels that the player has to choose from. As the game concludes, a game over screen is displayed with results and the option to restart the game with a mouse press.

 

Production

This production process has been by far the most stressful, ironic right. With the code breaking down so many times, I started the initial game design from scratch with circles as the objects and incorporated the movement. See the initial sketch below.

Once the intended movement was achieved, building upon previous progress, I selected my images to use and incorporated them into the previous sketch. Finally, as shown below, the basic design of the game was complete.

The following steps included working more on the game outlook. Putting my artsy skills to use was real fun while coloring the free-falling objects png files. To have a better outlook, I used two images for the player, flipped left and right, which were chosen based on the movement of the player on the screen.

After completing this, the main landing screen, instructions screen, main gameplay screen, and game over screen were redesigned. For this, I used different background images, fonts, and text placements. Like most sketch screens, I wanted to have a faded image background during the main gameplay screen. However, with png moving down the screen, the background would distort, and also the increased loading time of the screen made the movement of objects weird and much less smooth. Therefore, after trying several different patterns and backgrounds, I just stick to a solid background. This came out looking pretty good design and allowing the moving objects’ color to pop on screen. Below are screenshots of the final designs.

Once all of the design was finalized, the last step was to include sound. There were challenges with different sounds playing at a time, ending up in weird noise. So, I finalized a single background sound looped until the game over screen and whenever a selection is made using mouse press or keypress, a notification sound is played. With this, I finalized my game design, and below is a demo

Code for the game is below (+500 lines) and the entire sketch can be downloaded from here

import processing.sound.*;

//Global variables responsible for various states in game
//That includes: difficulty select, playing game, game over
Game start;
Player player;
String state = "MAIN";
String difficulty = "EASY";

//array to store the different points
Activity[] activityarray;

//all the images and fonts for design 
PImage food;
PImage leisure;
PImage deadlines;
PImage grades;
PImage user;
PImage userr;
PImage bdrop;
PImage miss;
PImage bg;
PImage diff;
PImage inst;
PImage keys;
PImage back;
PFont f;
PFont g;

//global variables for location check and size
float speed = 1;
float previouspos = 0;

//soundfile
SoundFile audio;
SoundFile sel;

//setup the game

void setup(){
  
  fullScreen();
  
  //initializing game and player
  start = new Game(state);
  player = new Player();
  
  //loading images
  food =loadImage("data/food.png");
  leisure = loadImage("data/leisure.png");
  deadlines = loadImage("data/deadline.png");
  grades = loadImage("data/test.png");
  user = loadImage("data/user.png");
  userr = loadImage("data/userr.png");
  bg = loadImage("data/bg.jpg");
  diff = loadImage("data/diff.jpg");
  bdrop = loadImage("data/backdrop.jpg");
  inst = loadImage("data/inst.jpg");
  keys = loadImage("data/key.png");
  miss = loadImage("data/stress.png");
  back = loadImage("data/backdrop.jpg");
  back.resize(width,height);
  
  //loading sound
  audio = new SoundFile(this, "data/game.mp3");
  audio.loop();
  sel = new SoundFile(this, "data/select.mp3");
  
  //font
  f = loadFont("FootlightMTLight-55.vlw");
  g = loadFont("JavaneseText-55.vlw");
  
  //diffculty level
  if(difficulty == "EASY"){
    speed = 2;
  }
  if(difficulty == "MEDIUM"){
    speed = 4;
  }
  if(difficulty == "HARD"){
    speed = 8;
  }

  activityarray = new Activity[250];
  
  //initializing the array of activity object
  fillarray();
  
  
}

void draw(){
  //image(back,0,0,width,height);
  start.display();
}

//fill activity array
void fillarray(){
  //choose random x values and drop activities
  for(int i=0; i<activityarray.length; i++){
    float x_pos = random(0,width-30);
    while(x_pos == previouspos){
      x_pos = random(0,width-30);
    }
    previouspos = x_pos;
    float type = random(1,50);
    String activity_ability = "FOOD";
    
    //randomly choosing  ability based on random number
    if(type < 5){
      activity_ability = "LEISURE";
    }
    else if(type > 45){
      activity_ability = "GOODGRADES";
    }
    if(type > 10 && type <=25){
      activity_ability = "DEADLINE";
    }
    
    //create new activity object
    activityarray[i] = new Activity(x_pos,random(-10000,0),speed,activity_ability);
  }
}


//game class
class Game{
  String mode;
  int score = 0;
  int lostpoints = 0;
  float speed = 0;
  
  Game(String state){
    mode = state;
  }
  
  void display(){
    textAlign(CENTER,CENTER);

    //check for game over
    if(lostpoints >= 320 || score >= 320){
      mode = "OVER";
      audio.stop();
    }
    
    //load the main landing page
    if(mode=="MAIN"){
      
      //background gradient
      background(255);
      loadPixels();
      for(int y=0;y<height;y++){
        for(int x=0;x<width; x++){
          int index = x+y*width;
          pixels[index] = color(map(y,0,height,155,0),0,map(y,0,height,255,0),50);
        }
      }
      updatePixels();
      
      //displaying text
      textFont(f,random(90,97));
      fill(150,120);
      text("STRESS FREE NYUAD?",width/2,height/3);
      fill(255);
      textFont(f,90);
      text("STRESS FREE NYUAD?",width/2,height/3);
      textFont(g,30);
      fill(255);
      text("START GAME - G",width/2,2*height/3 - height/14);
      text("INSTRUCTIONS - I",width/2,2*height/3);
      textFont(f,20);
      text("Press corresponding keys to initiate the game",width/2,height-height/14);
    }
    
    //loading the instructions page
    if(mode=="INSTRUCTIONS"){
      fill(0);
      image(inst,0,0,width,height);
      textFont(f,60);
      text("INSTRUCTIONS",width/2,height/10);
      
      //display images and text
      image(keys,width/4-width/7,height/2.5 - height/8,130,60);
      image(food,width/2-130/2,height/2.5 - height/8,130,60);
      image(grades,3*width/4+width/16,height/2.5 - height/7,130,80);
      image(leisure,width/4-width/7,1.75*height/2.5 - height/8,130,60);
      image(deadlines,width/2-130/2,1.75*height/2.5 - height/8,130,60);
      image(miss,3*width/4+width/16,1.75*height/2.5 - height/8,130,60);
      textFont(g,22);
      text("Use arrow L-R keys to\nmove across the screen",width/4-width/10,height/2.5);
      text("Eat healthy to gain +05 pts",width/2,height/2.5);
      text("Perform well on assignment\n to get +10 pts ",3*width/4+width/10,height/2.5);
      text("Do refresing leisure activities\n to get boosted speed",width/4-width/10,1.75*height/2.5);
      text("Avoid deadline pressure\nto skip decreased speed",width/2,1.75*height/2.5);
      text("Missed pts added to stress level\nFirst to reach 320 pts win",3*width/4+width/10,1.75*height/2.5);
      textFont(g,random(32,34));
      fill(random(255),0,0);
      text("START GAME - G",width/2,9*height/10);
    }
    
    
    //displaying the difficulty selection screen
    if(mode=="DIFFICULTY"){
      image(diff,0,0,width,height);
      //turn the text red and create shadow effect when mouse is hovered
      //over the level selection part
      if(mouseX>0 && mouseX<width/3){
        fill(255,0,0);
        textFont(g,54);
        text("EASY - E",width/4-width/10,height/2);
      }
      else if(mouseX>width/3 && mouseX<2*width/3){
        fill(255,0,0);
        textFont(g,54);
        text("MEDIUM - M",width/2,height/2);
      }
      else if(mouseX>2*width/3 && mouseX<width){
        fill(255,0,0);
        textFont(g,54);
        text("HARD - H",3*width/4+width/10,height/2);
      }
      fill(255);
      textFont(g,50);
      text("EASY - E",width/4-width/10,height/2);
      text("MEDIUM - M",width/2,height/2);
      text("HARD - H",3*width/4+width/10,height/2);
      textFont(f,20);
      text("Press corresponding keys to initiate the game",width/2,height-height/14);
      
    }
    
    
   //game over screen
    if(mode=="OVER"){
      //display the background image
      fill(255);
      image(bg,0,0,width,height);
      
      //display the text
      textFont(f,60);
      text("GAME OVER",width/2, height/3);
      textFont(f,35);
      text("Your Score:",width/2 - width/6, height/3 +height/6);
      text("Stress Level:",width/2 - width/6, height/3 + height/4);
      textFont(g,45);
      text(score,width/2, height/3 +height/6);
      text(lostpoints,width/2, height/3 + height/4);
      textFont(f,35);
      text("points",width/2 + width/6, height/3 +height/6);
      text("points",width/2 +width/6, height/3 + height/4);
      
      //display result string based on scores
      textFont(g,45);
      if(score>=lostpoints){
        if(score==lostpoints){
          text("IT'S A TIE", width/2, 2.25*height/3);
        }
        else{
          text("YOU WON", width/2, 2.25*height/3);
        }
      }
      else{
        text("YOU LOST", width/2, 2.25*height/3);
      }
      textFont(f,20);
      text("Please click on screen to restart game",width/2,height-height/14);     
    }
    
    
    //main game screen
    if(mode=="PLAY"){
      
      //background color
      background(back);
      fill(0);
      
      //score board
      rect(width-width/6,height/14.5,width/8,height/13.5);
      fill(255);
      textFont(g,18);
      text("Your:", width-width/7,height/12);
      text("Stress:", width-width/7,height/8);
      textFont(f,random(24,26));
      fill(random(200,255));
      text(score,width-width/10,height/12);
      text(lostpoints,width-width/10,height/8);
      fill(255);
      textFont(g,18);
      text("points", width-width/16.5,height/12);
      text("points", width-width/16.5,height/8);
      
      //main display player
      player.display();
      
      //display activities
      for(int i =0; i< activityarray.length;i++)
      {
        activityarray[i].display();
        if(activityarray[i].yloc > height){
          lostpoints += activityarray[i].point;
          activityarray[i].point = 0;
        }
        
        //resize the image upon collision to have effect
        //of collecting the activity 
        if(activityarray[i].collisions() == true){
          score += activityarray[i].point;
          activityarray[i].awidth = 0;
          activityarray[i].aheight = 0;
          activityarray[i].point =0;
        }
      }
    }
  } 
}


//player class
class Player{
  float pwidth;
  float pheight;
  float xPos;
  float yPos;
  boolean left;
  boolean right;
  float speed;
  float fast_time;
  float slow_time;
  
  Player(){
    pwidth= 100;
    pheight = 100;
    xPos = width/2 - pwidth;
    yPos = height - pheight;
    left = false;
    right = false;
    speed = 7;
    fast_time = 0;
    slow_time = 0;
  }
  
  void display(){
    
    //tracking the time when boosted speed
    if(speed == 12){
      fast_time += 1;
      //last 100 frames
      if(fast_time == 100){
        fast_time = 0;
        speed = 7;
      }
    }
    
    //tracking the time when slowed speed
    if(speed == 1){
      slow_time += 1;
      //last 100 frames
      if(slow_time == 100){
        slow_time = 0;
        speed = 7;
      }
    }
    
    //update the position on screen
    update();
    
    //draw the player
    if(left==true){
      image(user,xPos,yPos,pwidth,pheight);
    }
    else if(right==true){
      image(userr,xPos,yPos,pwidth,pheight);
    }
    else{
      image(userr,xPos,yPos,pwidth,pheight);
    }
  }
  
  //update the position of the player
  void update(){
    if(left==true && xPos >=0){
      xPos -= speed;
    }
    if(right==true && xPos <= width-pwidth){
      xPos += speed;
    }
  } 
}


//Class of falling activities/ points
class Activity{
  float awidth = 60;
  float aheight = 60;
  //coordinates
  float yloc;
  float xloc;
  float speed;
  String ability;
  //standard point
  int point = 5;
  //image
  PImage activityimg;
  
  Activity(float xpos, float y,float s, String a){
    xloc = xpos;
    speed= s;
    yloc = y;
    ability = a;
    
    //updating point values and image based on type
    if(ability == "GOODGRADES"){
      activityimg = grades;
      point = 10;
    }
    else if(ability == "LEISURE"){
      activityimg = leisure;
    }
    else if(ability == "DEADLINE"){
      point = 0;
      activityimg = deadlines;
    }
    else{
      point =5;
      activityimg = food;
    }
  }
  
  //display the activity object
  void display(){
    update();
    image(activityimg,xloc,yloc,awidth,aheight);
  }
    
  //update the locations
  void update(){
    //move down
    yloc += speed;
  }
    
  //check for collisions
  boolean collisions(){
    if((player.xPos + player.pwidth >= xloc) && (player.xPos <= xloc + awidth)){
      if((yloc + aheight >= player.yPos) && (yloc <= player.pheight + player.yPos)){
        
        //check if it collides with special activity and update speed accordingly
        if(ability == "LEISURE"){
          player.speed = 12;
        }
        if(ability == "DEADLINE"){
          player.speed = 1;
        }
        return true;
      }
    }
    return false;
  }
}


//keep track of key presses on screen
void keyPressed(){
  if(start.mode == "MAIN"){
    if(keyCode == 73){      //73 = 'i'
      sel.play();
      start.mode = "INSTRUCTIONS";
    }
    if(keyCode == 71){        //71 = 'g'
      sel.play();
      start.mode = "DIFFICULTY";
    }
  }
  
  if(start.mode == "INSTRUCTIONS"){
    if(keyCode == 71){        //71 = 'g'
      sel.play();
      start.mode = "DIFFICULTY";
    }
  }
  
  if(start.mode == "DIFFICULTY"){
    if(keyCode == 69){        //71 = 'e'
      sel.play();
      difficulty = "EASY";
      start.mode = "PLAY";
    }
    if(keyCode == 77){        //71 = 'm'
      sel.play();
      difficulty = "MEDIUM";
      start.mode = "PLAY";
    }
    if(keyCode == 72){        //71 = 'h'
      sel.play();
      difficulty = "HARD";
      start.mode = "PLAY";
    }
  }
  
  //move until key pressed
  if(start.mode=="PLAY"){
    if(keyCode == RIGHT){
      player.right = true;
    }
    if(keyCode == LEFT){
      player.left = true;
    }
  }

}


//stop motion when key is released
void keyReleased(){
  if(start.mode == "PLAY"){
    if(keyCode == RIGHT){
      player.right = false;
    }
    if(keyCode == LEFT){
      player.left = false;
    }
  }
}


//replay the game
void mouseClicked(){
  if(start.mode=="OVER"){
    sel.play();
    player.left = false;
    player.right = false;
    fillarray();
    background(0);
    start = new Game("MAIN");
    audio.play();
  }
}

 

Leave a Reply