analog and digital LED – week 9

OBJECTIVE(S):

For this assignment, I have to admit, I did the bare minimum which is fulfilling the criteria for this week. I wanted to control the brightness of one LED to fulfill the analog criteria. Then, to cross the digital sensor requirement, I used a button to control when the LED turns on.

 

DIFFICULTIES:

The moment I read the assignment prompt, I knew I had to learn the structure of an Arduino UNO board since I forgot everything we took in class lol. However, that was fruitful since I learned some things about Arduino boards we did not cover in class 🙂 I also faced difficulties with matching the name of the parts like the potentiometer to the pieces we have in our kits since there are different designs of the same pieces.

 

IMPLEMENTATION:

implementing the pieces and writing the code was fairly easy after learning the structure of the Arduino UNO board. I used a blue LED to be controlled by the potentiometer since it’s blue as well, additionally, I used a red LED to be used with the red button to make it more easy/satisfying to use.

 

CODE:

const int analogIn = A0;  
const int analogOut = 5; 
const int buttonPin = 4;     
const int ledPin =  7; 
int sensorValue = 0;        
int output = 0;  
int buttonState = 0;       

void setup() {
  // initialize serial communications
  Serial.begin(9600);
  pinMode(ledPin, OUTPUT);
  pinMode(buttonPin, INPUT);
  
}

void loop() {
  // read the analong input value
  sensorValue = analogRead(analogIn);
  // map it to the range of 0 to 255
  output = map(sensorValue, 0, 1023, 0, 255);
  // change the analog out value
  analogWrite(analogOut, output);

// delay 2 milliseconds 
  delay(2);

  // read the state of the pushbutton 
  buttonState = digitalRead(buttonPin);

  // check if the pushbutton is pressed
  if (buttonState == HIGH) {
    // turn LED on:
    digitalWrite(ledPin, HIGH);
  } else {
    // turn LED off:
    digitalWrite(ledPin, LOW);
  }
}

 

🙂

 

LED Bell Curve

// higher number is slower
int speed = 20;

// change spread to make the bell curve wiser or narrower
float spread = 0.12;

// set the postion to start outside of 0 to 1 so the first LED is dark
float bellCurveCenter = -spread;

float ledPos[3] = {.25, .5, .75};
int ledIndex[3] = {5, 10, 11};

void setup()
{
  for (int i=0; i<3; i++){
    pinMode(ledIndex[i], OUTPUT);
  }
}

void loop()
{
  // this is the juicy part
  for (int i=0; i< 3; i++) {
    // finding the distance of each LED from the center of our bell curve
    float distance = abs(ledPos[i]-bellCurveCenter);
    // this is the formula for the bell curve, multiply by 255 to put in the proper range for brightness
    float brightness = exp(-0.5*pow(distance/spread, 2.))*255;
    analogWrite(ledIndex[i],brightness);

  }
  
  // move the center
  // you could adjust the speed with a potentiometer
  if (millis()%speed==0)
    bellCurveCenter += .01;

  // start it over when it reaches the end
  // reset based on the spread so that it fades all the way out before resetting
  if (bellCurveCenter>1+spread) {
    bellCurveCenter = -spread;
  }
}

 

Midterm: Dots and Boxes

I really wanted to use the Network library in Processing as this was something new to me. Thus, I hoped to create some sort of two player game.

As a kid, my siblings and I would make a grid of dots on napkins and play the dots and boxes game where you’d have to form as many boxes as possible by drawing lines between the dots.

I hoped to implement a version of this game with a limitation of what dots you could draw on.

I began by creating the Dot class. I thought about user feedback a lot for this object. When the user hovered over a dot, I wanted it to become lighter. I wanted there to be a beep tone. Upon selection, the dot’s color would change. I originally just kept the posX and posY of each dot object, but later realized it would be useful to be able to have the row and column number as attributes to avoid multiple for loops.

Working with the server and client was easier than I expected because it was quite simple to send data over the socket. Originally, I sent a longer string, also including variables like whether a box was created, etc. I realized this was redundant and I would just need to send the selected row and column dot numbers and have a function to handle the data on each side and see whether a box was created, etc.

Some of the edge cases I identified for error validation:

  • Does the user select exactly two dots?
  • Does the user select “opponent dots?”
  • Does the user select dots that are next to each other (not including diagonals)?

To keep track of the dots selected before they were sent to the other player, I used an ArrayList to hold the dots. When the user clicked the user button, the error validation process would occur. If it was okay, then the data was actually sent.

The most difficult aspect for me was designing how to track boxes. I first created another ArrayList to hold all the pairs of a dot, but that was quite inefficient. I also tried manually checking each potential box position, but that was also unsuccessful. I ended up creating a Box class that matched row and column numbers with the dots. This worked because I could simply refer to the x and y position attributes in the dot class when drawing elements like lines between dots and rectangles for the boxes.

Another challenge was making sure to avoid having an array out of bounds error when checking dots/boxes on the edge of the grid. I solved this by only checking a dot if it was within the boundaries of the grid.

Finally, I did not redraw the background each time. Redrawing the background would remove the lines and boxes. Perhaps, I could have redesigned my architecture to draw lines and boxes each frame depending on certain attributes of the objects. However, my choice to not redraw made things difficult when updating the error message and scores. I ended up cheating a bit and redrawing a rectangle on top of the old messages with the same color as the background.

I relied on the Processing function mouseMoved() to help detect hover state of the dots and make the color slightly lighter. I used mouseReleased to help click the dots and do error validation.

I created a start screen to fulfill the image requirement of the project. I designed the screen image in Figma. When the user clicks, the game state changes.

The end screen comes up when every box has been completed.

Overall, this project was fun to complete and I became a lot more familiar with the Network library.

As always, there is room for improvement. I would make the project better by:

  • having a grid size option so the user could make more or less squares depending on their preference
  • having background music in the beginning
  • having an option to mute sound
  • having an instructions/pause game state
  • having a more beautiful method of filling in the rectangles
  • changing the “end turn” button if it is not the user’s turn.
  • use ngrok to make it more playable

But, I suppose there is always more one can do so here is my game for now. The game takes around 12-20 minutes to play through, so here is my game in about a minute. The audio is quite messed up in the demo video since I am playing it at 20x speed.

Here’s the code:

https://github.com/simranparwani/introtoIM_midtermproject

//be sure to read the README.md to start the server and client correctly!

Midterm – 2d Basketball Game

Its finally here…

For my midterm project, I decided to do something related to sports because I was really amused by the kinetic physics models that Professor Aaron had showed us in class. And so building on top of that, I made a simple 2d basketball game wherein the player can control the force applied on the ball and the direction of its trajectory, with the goal being to score at least 15 points in a given time frame. The time frame can be decided by the user and offers them three levels: beginner wherein the ticker is quite slow, intermediate, ticker is pacy but still doable and advanced, it would be a genuine achievement if you can win this level.

 

Here is the video for my game:

 

Here is my Git for this project:

https://github.com/Armaan-Agrawal/IntrotoIM.git

 

For this project, I really wanted to focus on a 90s video cassette type feel to it and so I curated the animations keeping that in mind. I purposely made th audio and timer controls slow so as to accentuate the feel of that old era gaming.

For the audio slider, I basically implemented it using maps

For the animation, I did it through assigning variables to manioulate location and direction.

For the bounce in the ball, I achieved it by dampening the velocity of the ball upon collision.

The physics of the ball is based on the Newtonian laws of motion.

I found most of the game art online but had to curate certain pieces like the baskeball and the player through photoshop to get the desired effect.

Small Brain, sadly not Big brain

So, after the weird phase of having two separate codes that did two separate things (for those weird ones reading this post of mine for some unknown reason, that post is private because I am so ashamed of my level that you shall never see it or else I am going to die from embarrassment) I moved on more risky stuff (at least in my opinion) (and if this is Professor Aaron reading this code and seeing that it’s private, it means that halfway though I got very self-conscious about my code and decided to privatize it).

So, what I did was “merging” them in a way. I needed to substitute ellipses for the images of the books and Instagram. On the way there I changed the pictures because I didn’t like the way the designs of the ones I had looked next to each other, especially now that the background changes from black to white.

In order to change the images, I went to the Drop class and changed the ellipse shape to (image) and there I added all the required global variables and yay, it worked 😀

class Drop {
  float x;
  float y;
  float r;
  float speedY;
  float c;
  PImage dropbrain;
  boolean isCaught;

  Drop() {
    r = 8;
    x = random(width);
    y = -r*4;
    speedY = random(1, 50);
    isCaught = false;
  }

  void update() {
    //position

    y += speedY;

    //check bounds

    if (y>height + r) {
      y = -r;
    }
  }

  void display() {
    if (isCaught != true) {
      imageMode(CENTER);
      dropbrain = loadImage("dropbrain.png");
      image(dropbrain, x, y, r*4, r*4);
    }
  }

  void caught() {
    isCaught = true;
  }

  void reset() {
  }
}

//If (drops[I].alive==true){drops[I].show; drops[I].move}

Then, a few interesting things happened, because I needed to add another drop class for the “bad” things that were going to serve as a distraction (aka instagram). I figured that I needed to create another class, and it would be exactly similar to the drop class I already have. So, I create badDrop class and copied the information from the class above with few alterations of changing the image and adding changes in names of for() loops in the main CatcherGame tab.

The tricky part gets when the images did not disappear when intersecting with the little brain image of a catcher. I asked Mister Jack about this, and he showed a pretty handy solution.

My main issue is that despite having drops[i].caught in the main sketch, I didn’t put the code in there, so it wasn’t running any functions. I needed a boolean that would indicate whether the drop is caught or not. So, after adding it, it worked, yay!

So, now that I had a game that was running with everything except without a score that went down when you caught badDrops. I needed to solve that. So, I just added the score-- in the for() loop for badDrop in the main sketch.

      if (intersect(catcher, badDrops[i]) == true) {
        badDrops[i].caught(); 
        score--;
      }

That worked, however, now the score went to a negative number and I needed the player to lose when the score was less than a zero. Finally… Time for an if function has come. You may not believe it, but I actually never used it because for some unknown reason I was very scared of the power it had. It is partially the reason why I choose switch screen function instead of multiple if functions. I have been avoiding it for as long as I could. So, when I used it today it was a pretty big deal. And of course, I failed :,)

The function worked, however, the reset part of the score did not work, so the game did not switch back to screen 0 (or instructions page) since the score did not reset back to zero. So it basically prevented me from changing the screen by pressing the key. I sat there watching the screen and changing the placement for a good 3 hours and after almost giving up and thinking about dropping Interactive media I decided to ask help from, you guessed it, Mister Jack. Mister Jack enlightened me in the simple truth that my screen was reset, but my small brain should’ve focused on void keyPressed() instead of changing the placement of the if function. So, after changing the placement of score = o to void keyPressed(), my game worked, and now I am here  :3

My final game*:

CatcherGame – PRESS ON ME IT WOULD BE FUNNY!!!

  • – I love seeing the suggestions of videos everyone has since mine are always Minecraft related, and it’s accurate, so we actually get a sneak peek of what every one of us watches haha

Conclusions:

  • Mister Jack is great! If Mister Jack ever reads this, the biggest, huge, enormous thanks to you. You literally saved many (and I don’t have many of them) nerves of mine 😀

P.s. Mister Aaron is great as a given 😀 😀

  • Private button her is just as great in helping me not die from embarrassment in front of many people. Instead, I just need to feel ashamed in from of Mister Aaron, and I am getting quite used to it. Triple 😀 😀 😀

References:

  • The YouTube tutorial for the catcher explanation: https://www.youtube.com/watch?v=dti_mVscdxY and https://www.youtube.com/watch?v=gXPf_R_hDP0
  • The YouTube tutorial for changing the game states that never actually became useful: https://www.youtube.com/watch?v=vgKQHocitd4

Week 7: Midterm Project Sorting Game

Description:

This project consisted of creating a game for our midterm assignment. The game had to include several elements such as shapes, images, sound, text, an initial screen with instructions, and a way to restart the game when the game is lost or won.

Process:

Idea:

I had several ideas when I first started thinking about this assignment. One of my initial ideas was to work on the game I had been working on before in Week 3. The game consisted of a car trying to avoid obstacles by using the left and right arrow keys. However, I wanted to challenge myself and create a game from scratch. First, I thought about recreating an old retro game. Then I changed my mind to create a “Whack a Mole” game. Finally, I remembered a game I used to play when I was a child. This game was a mini-game from Mario Bros on the Nintendo called “Sort or Splode”. The game consisted of sorting different colored bombs into their own color platforms. If a bomb was not sorted on time it would explode and the game would be over. If a bomb was placed on the wrong platform, the game woul

 

d also be over. Since I was recreating a game, I decided to include the creativity part in the visual part of the game. I decided to create my own background and characters and base them on an NYU theme. The idea was to sort falcons and bobcats into different platforms that represent NYU and NYUAD. 

Initial Process:

Initially, I worked on creating a bomb class with its appropriate methods and attributes. Next, I focused on creating a game class with its methods and attributes. I also created a platform class but later realized that I did not need it. 

I first worked with simple shapes (circles) to see the movement of the bombs for my game. I had to create the release of the bombs first and create movement in them while making sure they do not pass the limits of the screen. After accomplishing the change of velocity direction whenever the circle touches a wall on the screen. Then I focused on adding platforms and making sure circles were also colliding and changing direction with the walls of the platform. Later, I focused on creating an array of bombs and creating instances of the class using the frameCount. 

 

After accomplishing the basic structure of the game, I focused on making different types of bombs and confirming they were placed on the correct platform. Later, I focused on identifying a game loss and finally speeding up the release of the bombs. 

 

The final process was making the initial screen and creating a way to start the game or see the instructions of the game. 

 

Using vectors:

When I first started working on the project, I started using individual variables for the velocity and position in the x and y-axis. However, after researching how to make objects collide, I became aware of the existence of a data type called PVector. After looking through the reference guide in Processing, I decided that using PVectors was much simpler than using different variables. Later, I got a better understanding in class when we worked on physics and coding. 

 

Designing part:

I decided to create my own designs for the background, initial screen, and characters. I first worked on creating the background. I decided to make the background look similar to the original game but with a different theme. The platform design was also inspired by the original platform design in the original game. For the characters, I first started by drawing a circle because I needed the characters to be based on a circle as I initially coded the game to recognize characters as circles. The characters, in this case, had a radius, and therefore designing them as circles were crucial to making the game work. The process of design was difficult because I had to create each element from scratch. For the characters, I only used real images for reference and the rest was completely designed by me.

Challenges:

There were several challenges I encountered while creating this game. Some of the major ones were:

 

Detecting the walls of the platform:

When I first started coding the collisions of the bombs and the platform, a part of the bomb was passing through the platform. I had difficulties in fixing this because every time I tried a different solution something wrong came up. For example, sometimes the bomb range was not covering all the space available, sometimes the bombs entered the platform and the game was ended, sometimes the change in direction of the bombs was not working. After several trials, I managed to fix this problem by looking through the code and figuring out what was wrong with the dimensions.

 

Detecting collisions between bombs:

When I first designed this game, I wanted to make collisions between the bombs so that when the player grabs a bomb, the mouse does not accidentally grab two objects at the same time. After some research in physics and collisions, I gave up on understanding this concept to implement so I decided to revert the velocity direction if a collision was detected. This was working fine at the beginning of the game but I realized problems when there were several instances of the bomb within the screen. Later, I changed the code of the game so that objects could overlap but the mouse could only grab one object at a time. This was the best solution I had approached. 

Design

The design process was more difficult than I first thought it would be. Creating the characters and calculating the spaces for the background was a challenge. I had to spend more time than I anticipated because sometimes the location of certain objects in backgrounds would not match with the code. There were also certain objects I created but did not use because I did not end up liking the background with such objects.

 

Conclusion:

I personally really enjoyed the creation of this game and I want to continue making it a better game. I spent a good amount of time making the code work and designing the visual part. At first, I thought it was a simple game to make but it actually ended up being more complicated than I thought it would be. The interaction of the game came out exactly as I wanted and I was satisfied with the visual part of the game. Still, there are certain parts that I would like to change in the future. First, the ending screens for the win and lose of the game are not visually appealing as I did not have the time to create a background for each. I also want to create a level system for the game in the future to make it more challenging. The game indicates a win after 90 bombs are sorted. Finally, one thing I would definitely implement is the part where a function calculates the time the bomb has not been sorted. Although there is a function that identifies if a bomb has not been sorted for a long time and ends the game, I would like to add something to have the player identify unsorted bombs such as making bombs blink or change color or size. Still, I think I am proud of the outcome of this project and I look forward to creating more game projects in the future. 

import processing.sound.*;
SoundFile sound;
int mode = 0; //Determines the mode of the background;
Game game;
Platform platform1, platform2;
boolean locked = false;
int score;
Screen screen;

void setup(){
  sound = new SoundFile(this, "soundfile.mp3");
  
  size(900, 600);
  frameRate(60);
  game = new Game();
  sound.loop(); //SOUND REQUIREMENT
}

void draw(){
  background(130);
  game.drawGame();
  
}
  
  
void mouseReleased(){
  game.checkrelease();
}
Bomb(){
    img[0] = loadImage("img1.PNG");
    img[1] = loadImage("img0.PNG");
    img[1].resize(60,60);
    img[0].resize(70,60);
    platformnum = 0;
    condition = 1;
    x = width/2;
    y = 40;
    velox = 0;
    veloy = random(1, 3);
    typecolor = (int)random(1, 3);
    typeplatform = typecolor;
    correctplat = typecolor;
    position = new PVector(x, y);
    velocity = new PVector(velox, veloy);
    radius = 40;
    plat1x = 0;
    plat2x = 600;
    platy = 150;
    platwidth = 300;
    platheight = 300;
    limitx1 = 300;
    limitx2 = width - 300;
    limity1 = 150;
    limity2 = height - 150;
    upperlimit = 0;
    if(typecolor ==1){
      colorbomb = color(98, 0, 246);
    }
    else if(typecolor == 2){
      colorbomb = color(255);
    }
  }
  
  
  //=========================================================
  void move(){
    
    position.add(velocity);
    
    if( position.x > width - radius/2 ) 
    {
     position.x = width - radius/2;
     velocity.x *= -1;
    }
    else if (position.x < radius/2)
    {
     position.x = radius/2;
     velocity.x *= -1;
    }
    else if (position.y > height - radius/2)
    {
     position.y = height - radius/2;
     velocity.y *= -1; 
    }
    else if (position.y < upperlimit + radius/2 )
    {
     position.y = upperlimit + radius/2;
     velocity.y *= -1;
    }
     
     
  }
  //=========================================================
  //Function used to keep track of time each bomb is on screen
  void updatetimeonscreen(){
    if(inplat == false){
      if(frameCount % 100 == 0){
        timeonscreen++;
      }
    }  
  }
  
  //=========================================================
  //Function to determine whether bomb should explode and game over should be called
  void explode(){
    //TO fill
    if(actualplat != 0){ // Determines whether a bomb is in the wrong platform
      if(actualplat != correctplat){
        gameover = true;
      }
    }
    else if(timeonscreen == 20){ //Determines whether a bomb has been for too long on screen
      gameover = true;
    }
  }
   
  void updatetint(){
    
    
  }
  //=========================================================
  //Function to detect collisions and change direction if collision is made
  void collision(Bomb b){
    //TO fill
    
    if(dist(position.x, position.y, b.position.x, b.position.y) < radius){
      velocity.x *= -1;
      velocity.y *= -1;
      b.velocity.y *= -1;
      b.velocity.x *= -1;
    }
  }
  
  //=========================================================
  //Function to determine whether bomb collides with a platform
  void collisionwithplatform()
  {
    
   if( ((position.x + radius + velocity.x > plat1x &&
   position.x - radius/2 + velocity.x < plat1x + platwidth) ||
   (position.x + radius/2 + velocity.x > plat2x &&
   position.x + velocity.x < plat2x + platwidth)) &&
   position.y + radius/2 > platy &&
   position.y - radius/2 < platy + platheight)
   {
     velocity.x *= -1;
   }
   
   if( ((position.x + radius/2 > plat1x &&
   position.x - radius/2 < plat1x + platwidth) ||
   (position.x + radius/2 > plat2x &&
   position.x < plat2x + platwidth)) &&
   position.y + radius/2 + velocity.y > platy &&
   position.y - radius/2 + velocity.y < platy + platheight){
   
     velocity.y *= -1;
   }
  }
  
  //=========================================================
  //Function indicating mouse released after mouse grabs bomb
  void release(){
    velocity.x = (random(0, 4)-2);
    tempvelox = velocity.x;
    tempveloy = velocity.y;
  }
  
  //=========================================================
  //Function setting the upperlimit after bomb is initially released
  void upperlimsetter(){
    upperlimit = 60;
  }
  
  //=========================================================
  //Function ton 
  void checkinplat(){
   if(position.x > radius &&
   position.x < limitx1 &&
   position.y > limity1 &&
   position.y < limity2){
     platformnum = 1;
     condition = 2;
     inplat = true;
     draggedbomb = 0;
     actualplat = 2;
     
   }
   else if(position.x > limitx2 &&
   position.x < width &&
   position.y > limity1 &&
   position.y < limity2){
     platformnum = 2;
     condition = 2;
     inplat = true;
     draggedbomb = 0;
     actualplat = 1;
   }   
  }
  
  //=========================================================
  void movementaftermouse(){
    if(releasedbymouse == true){ 
    velocity.x = tempvelox;
    velocity.y = tempveloy;
    releasedbymouse = false;
    draggedbomb = 0;
    controlledbymouse = false;
    }
  }
  
  //=========================================================
  void movementinplatform(){
    switch(platformnum){
      
      case 1:
        if( position.x > 300 - radius/2 ) 
        {
         position.x = 300 - radius/2;
         velocity.x *= -1;
        }
        else if (position.x < radius/2)
        {
         position.x = radius/2;
         velocity.x *= -1;
        }
        else if (position.y > limity2 - radius/2)
        {
         position.y = limity2 - radius/2;
         velocity.y *= -1; 
        }
        else if (position.y < limity1 + radius/2 )
        {
         position.y = limity1 + radius/2;
         velocity.y *= -1;
        }
        break;
        
      case 2:if( position.x > width - radius/2 ) 
        {
         position.x = width - radius/2;
         velocity.x *= -1;
        }
        else if (position.x < 600 + radius/2)
        {
         position.x = 600 + radius/2;
         velocity.x *= -1;
        }
        else if (position.y > limity2 - radius/2)
        {
         position.y = limity2 - radius/2;
         velocity.y *= -1; 
        }
        else if (position.y < limity1 + radius/2 )
        {
         position.y = limity1 + radius/2;
         velocity.y *= -1;
        }
        break;
    }
      
  }
  //=========================================================
  void updatescore(){
   if(inplat == true && scoreyes == 1){
     game.score++;
     scoreyes = 0;
     
   } 
  }
  
  //=========================================================
  void drawbomb(){
    if(controlledbymouse == true){
      position.x = mouseX;
      position.y = mouseY;
    }
    updatetimeonscreen();
    // Drawing the circles
    imageMode(CENTER);
    image(img[typecolor-1], position.x, position.y);
    move();
    explode();
    checkinplat();
    updatescore();
    if(position.y > 50 && position.y< 54){
       release();
    }
    if(position.y > 65){
      upperlimsetter();
    }
    switch(condition){
      case 1:
        collisionwithplatform();
        break;
      case 2:
        movementinplatform();
        break;
    }
    if(gameover == true){
      game.gameover = true;
    }
  }
 
      
    
}
class Game{
  Bomb bombarray[]; // Array storing the number of bombs
  int i; // Variable that counts the number of bombs created
  int velobombs; //Variable determining the velocity of creation of bombs
  int score = 0; //Variable containing the score of the game
  PImage[] background = new PImage[3]; // Array storing the images for backgrounds
  PImage buttons[];// Array storing images for buttons
  int condition; //Variable containing the 
  int backgroundimg;
  int casenum; //Case number for screen function.
  String scoretext;
  boolean gameover; // Variable to determine game over
  boolean gamewin; //Variable to determine game win
  int backgroundnum; // Background image index from array
  boolean restart = false; // variable to verify if restart of the game is allowed or not
  
  Game(){
    bombarray = new Bomb[100];
    i = 0;
    velobombs = 200;
    condition = 0;
    background[2] = loadImage("background2.png");
    background[1] = loadImage("background1.png");
    background[0] = loadImage("background0.png");
    casenum = 0;
  }

  //=========================================================
  //Function to create new bombs
  void createbomb(){
    bombarray[i] = new Bomb();
    i++;
  }
  
  //=========================================================
  //Function to check release of bombs if mouse is released
  void checkrelease(){
    for(int j=0; j < i; j++){
       if(bombarray[j].controlledbymouse == true){
         bombarray[j].controlledbymouse = false;
         bombarray[j].release();
         break;
       }
    }
  }
  
  //=========================================================
  //Function checking for bomb collision
  void checkcollisions(){
   for(int j=0; j < i; j++){
     for(int k=j+1; k < i; k++){
       bombarray[j].collision(bombarray[k]);
     }
   }
  }
  
  //=========================================================
  //Function to control the bomb if grabbed
  void controlbomb(){
    for(int j=0; j<i; j++){
      if(bombarray[j].controlledbymouse == true){
        break;
      }
      else if(bombarray[j].inplat == false){
        if(dist(mouseX, mouseY, bombarray[j].position.x, bombarray[j].position.y) < bombarray[j].radius/2){
           bombarray[j].controlledbymouse = true;
           break;
            }
         }
      }
  }  
    

  
  //=========================================================
  //Function to draw the Game
  void drawGame(){
    if(backgroundnum < 3){
      background(background[backgroundnum]);
    }
    
    if( i >= 89){
      gamewin = true;
    }
    
    //Controlling bombs
    if(mousePressed ){
      controlbomb();
    }
    
    //Screen with actual gameplay
    //Having bomb releases
    if(backgroundnum == 1){
      if(frameCount%(velobombs) == 0 && i <= 89 && gameover == false){
        createbomb();
      }
      
      //Make the release of bombs faster
      if(frameCount%1000 == 0){
       velobombs -= 10; 
      }
      
      for(int j=0; j < i; j++){
        bombarray[j].drawbomb(); 
      }
      //printing the score
      textSize(32);
      fill(0);
      text("Score: ", 50, 585);
      text(score, 150, 585);
      
      if(score >= 89){
        backgroundnum = 4;
      }
      
      if(gameover == true){
        backgroundnum = 3;
      }
    }
    
    // First Screen
    if( backgroundnum == 0 ){
      if(mouseX > 350 && mouseX < 550 && mouseY > 380 && mouseY < 430){
        noFill();
        stroke(255, 255, 0);
        rect(350, 380, 200, 50); //SHAPE REQUIREMENT
        if(mousePressed){
          backgroundnum = 1;
        }
      }
      else if(mouseX >350 && mouseX < 550 && mouseY >460 && mouseY < 510){
        noFill();
        stroke(255, 255, 0);
        rect(350, 460, 200, 50);
        if(mousePressed){
          backgroundnum = 2;
        }
      }
    }
      
    //Screen with Instructions
    if( backgroundnum == 2 ){
      if(mouseX > 700 && mouseX < 840 && mouseY > 480 && mouseY < 530 ){
        noFill();
        stroke(255, 255, 0);
        rect(700, 480, 140, 50);
        if(mousePressed){
          backgroundnum = 1;
        }
      }
    }
      
    //Screen with winning message
    if( backgroundnum == 3 ){
      background(51);
      textSize(48);
      fill(255);
      text("Game Over!", 340, 150);
      text("Press any key to restart the game", 70, 250); 
      restart = true;
    }
    
    //Screen with loosing message
    if( backgroundnum == 4 ){
      background(255, 204, 0);
      textSize(48);
      text("You won the game", 280, 200);
      text("Press any key to restart the game", 180, 250);
      restart = true;
    }
    
    if(restart == true){
      if(keyPressed){
        setup();
        sound.stop();
      }
    }
  }
  
}

The original game has music background from:

Summer Days by Roa https://soundcloud.com/roa_music1031 Creative Commons — Attribution 3.0 Unported — CC BY 3.0 Free Download / Stream: http://bit.ly/-summer-days Music promoted by Audio Library https://youtu.be/3wiksi3J_KI

 

ZIP FILE FOR CODE:

Midterm_RockHyungKang

 

Midterm game

For the midterm project, I did a platform game named. The complete code and all resources can be found here.
This game is for 2 players. The goal is to go through “trials”, collect crystals, and get to the airplane to fly away as soon as possible. There is a small problem – you only have 60 seconds.
I wanted to try to create a game myself, similar to the one I played as a child. I always liked the opportunity to play with a friend at the same time, so I decided to add this opportunity to my game.
For this game, I created several classes: 2 character classes, a platform class, a platform class that cannot be stepped on aka platform enemies, a timer class, an airplane class, and a crystal class. Use the A, W, D keys to move Player 2 and the arrow keys to move Player 1.

Problems:
1. It was not easy to create interaction between the character and the rest of the classes – for the game to be interactive, the player must see everything that his actions in the game lead to. I spent a lot of time trying to figure out what kind of response should follow from the game to various interactions, whether this is a “game over” window or, on the contrary, congratulations on winning.
2. It took time to figure out what the distance will be between the objects at the moment of collision and from which side. It was even harder to understand when the picture of the character was in relation to the center, not the edge.
3. For the crystal to disappear when the character touches it, I had to try several options and go through dozens of “null pointer exception” errors. I am pleased with the result, where the crystals are neatly collected in the corner of the screen.
4. Having two players in parallel is not easy: it was necessary to understand the key pressed and released functions, and also not to get confused with them later. Because I named some variables the same for different classes, the character of the second player did not want to appear for a long time.

Final thoughts:
There is no limit to perfection, and you can modify the game indefinitely. I already have dozens of ideas on how I will improve this game in the future, from a progress bar to numerous levels. However, I am happy with how this game has turned out for me at the moment.
While writing the code for this assignment, I have used all the knowledge gained from the last 6 weeks and I have a certain sense of satisfaction with the result. Also, coding is very time-consuming, and it’s best to start as early as possible.

Result:

Midterm: Harry Potter and the Wizarding Maze

Description:

This game, inspired by the successful Harry Potter book series and the retro game  PacMan, consists of discovering the exit of a labyrinth.  During their journey, the player will have to overcome the dim light that illuminates their way, which becomes small each time the villainous dementors approach. The player will have to dodge this evil creatures if wants to reach the end of the maze and win the game

The development of the project of this video game was a process that went through a long path of challenges, difficulties and many hours( and entire days of work). Solving some of those setbacks led me to spend hours and hours watching tutorials, consulting with my teacher, others students and some tours of the buildings in search of answers and solutions that in the end were compensated by the satisfaction of seeing the finished product

Sneak Pic

(My laptop can’t record audio, but all the screens are accompanied by music from the Harry Potter series in the actual game.)

Thought Process:

Testing things:

I had a lot of issues testing things in my code, primarily because I have a lot of files, and eventually Processing ran out of memory so I had to delete some stuff in order for the program to run. Testing some functions could take up to 2 minutes to load. I am happy with how the project looks but not that much with its efficiency.

Testing copies of PGraphics

Testing Mask function

Testing the Flicker of the player’s field of view

Testing of the dementors (enemies)

First version of the Instructions

Final Version of the Instructions

Note: I drew all the UI, titles and Sprites for this project

Things I would Improve

  • I really want to add levels (hard mode, normal mode, easy mode, etc).
  • I also want to have different sets of enemies and maybe a final boss (Voldermort?).

I hope you guys enjoy this game. I put a lot of effort in it and am really happy to share it with you.

Here is the link to my GitHub repository.

Midterm Assignment: Flying Campus Cat

Motivation

I want to replicate the game Flappy Bird but with some modifications in choosing the image and adding some sounds to it such as the background music and the cat’s sound when it is alive/dead.

Process

The game requires player to click mouse to move the cat upwards. If the mouse is not pressed, the cat will be falling down. By controlling the direction and the velocity of the cat, player needs to avoid hitting the palm trees which approach the cat from the right hand side. The final score is the number of times the cat flies through 2 palm tress.

I encountered first problems when trying to upload the sound file to Processing library. It seems Processing on my laptop cannot read the tail .mp3 so I had to have all the mp3 files converted to wav files. The example from processing.org uses mp3 and it works but not for my laptop. I think it can be related to the version of the software. Regarding the class Palm Tree, I used a not so technical method to draw the foliage. I drew a lot of triangles and put one on top of the other to (hopefully) give it a look like the palm tree. Firstly, I drew a palm tree using only triangles on a coordinate plane to check the coordinates of all the points I needed. Then I used Excel to organize all the numbers a bit and gradually form triangles by grouping 3 points together.

Code

Palm tree class

// Draw the palm tree
public class palmTree {
void draw(float x, float y, boolean flip){
  smooth();
  noStroke();  
  
  // Turn the palm trees upside down to create 2 lines of obstacles on both sides
  int flipper = 1;
  if (flip) flipper = -1;
  
  //Draw the tree trunk
  fill(94,62,28);
  //rect (0 + x,0 + y,50 + x,-200+y);
  rect(x, y, 50, -1000*flipper);
  
  
  //Draw the foliage by putting a lot of triangles on top of each other. 
  //The numbers were collected from a mobile app allowing users to know the coordinates of each point when a random shape is drawn
  fill(62, 145, 32);
  triangle(50 + x,  y, 0 + x, (57.5)*flipper + y, -39.25 + x,  (19.25)*flipper + y);
  triangle(50 + x, y,-39.25 + x, (88.75)*flipper + y, 49.5 + x,  (62.5)*flipper + y);
  triangle(50 + x, y, 49.5 + x, (62.5)*flipper + y, 86.25 + x, (11.75)*flipper + y);
  triangle(0 + x, y, 49.5 + x, (62.5)*flipper + y, 75 + x, (-40)*flipper + y);
  triangle(50 + x, y, 0 + x, (57.5)*flipper + y, 57.5 + x, (107.5)*flipper + y);
  triangle(0 + x, y, 0 + x, (57.5)*flipper + y, 90.75 + x, (76)*flipper + y);
  triangle(50 + x, y, 49.5 + x, (62.5)*flipper + y, -2 + x, (110)*flipper + y);
  triangle(50 + x, y, 0 + x, (57.5)*flipper + y, -30.5 + x, (-37.5)*flipper + y);
  fill(0);
}
    
}

 

Main class

import processing.sound.*;


// Image files
PImage background;
PImage cat;

// Sound files
SoundFile backgroundMusic;
SoundFile catAlive;
SoundFile catDead;

palmTree pt;
PFont f;


int interfaceState = 1;
int point = 0;
int max = 0; 
int x = -200, y;
int catFallingSpeed = 0;
int treeX[] = new int[2];
int treeY[] = new int[2];



void setup() {
  size(800,600);
  fill(0);
  textSize(40); 
  
  background =loadImage("background.jpg");
  cat =loadImage("cat.png");
  cat.resize(0,70);
  
  backgroundMusic = new SoundFile(this,"jazz.wav");
  backgroundMusic.play();
  catAlive = new SoundFile(this, "catAlive.wav");
  catDead = new SoundFile(this, "catDead.wav");
  
  pt = new palmTree();
}

boolean catDeadSoundPlayed = false;
int closestPillar = 0;

void draw() { 
  
  if(interfaceState == 0) {
    imageMode(CORNER);
    image(background, x, 0);
    image(background, x+background.width, 0);
    
    //Make the background move to create the illusion that the cat is flying forwards
    x -= 5;
    catFallingSpeed += 1;
    y += catFallingSpeed;
    
    if(x <= -background.width) x = 0;
    for(int i = 0 ; i < 2; i++) {
      imageMode(CENTER);
      
      //Create the gap between two trees
      pt.draw(treeX[i], treeY[i] - 150, false);
      pt.draw(treeX[i], treeY[i] + 150, true);
      
      if(treeX[i] < 0) {
        treeY[i] = (int)random(200, height-200);
        treeX[i] = width;
        //point++;
      }
      if (treeX[i] < width/2 && i == closestPillar) {
        max = max(++point, max);
        closestPillar = 1 - closestPillar;}
        
      //Conditions when the game ends including reaching the boundaries or colliding with the palm tree blocks
      if (y > height || y < 0 || (abs(width/2-treeX[i])<25 && abs(y-treeY[i])>100)) interfaceState=1;
      treeX[i] -= 5;
    }
    image(cat, width/2, y);
    text(""+point, 20, 50);
  }
  else if (interfaceState==1) {
    if (!catDeadSoundPlayed){
      catDead.play();
      catDeadSoundPlayed = true;
    }
    imageMode(CENTER);
    // change to menu image
    image(background, width/2, height/2);
    text("High Score: "+max, 50, width/2);
    f = createFont("Courier New", 30);
    textFont(f);
  }
}


void mousePressed() {
  catAlive.play();
  catFallingSpeed = -17;
  if(interfaceState==1) {
    treeX[0] = width;
    treeY[0] = y = height/2;
    treeX[1] = width*3/2;
    treeY[1] = 300;
    x = interfaceState = point = 0;
    catDeadSoundPlayed = false;
  }
}

 

Final game (I cannot record the sound of it)

Rooms for improvement

In the game, as long as the cat does now hit the tree trunk which is in a rectangular shape, the cat is still alive and the player can keep playing. I do not know how to check if the cat hits the spiky shape of the foliage to end the game at that point so I use collision with the tree trunk only as a determiner if the game is still ok or should be ended.

Also, I did not loop the background music so if a player is playing so well and exceed the time duration of around 2 minutes (the length of the track), the background music disappears.

The file containing all related assets can be accessed here: flying_campus_cat

After making the game and listening to the cat sound several times when testing it, I walked out seeing a cat and it hit differently :<