Object Oriented Programming Game – Survival Pong

For this project, I wanted to create a simple two-player game. Even though I don’t really have anyone to play it with. 🙁

The game gives each player a ball, player 1 with a red ball and player 2 with a blue ball. On the sides of the map, there are four purple lines that move in a random fashion along their axis. Player 1 controls the red ball with WASD and player 2 controls the blue ball with the direction keys. The goal of each player is to collide with the purple lines as much as possible. Each collision gives the player 1 point and resets them at the center of the screen. Each purple line gets shorter every time it is collided with, making it harder to collide with next time.

To win, collide with more lines than the opponent before all the lines disappear. Going out of bounds also automatically gives the win to the other player, so be careful.

As I was coding this project, I bumped into a few problems, some that still exists.

    • I originally wanted the balls to move by themselves in a smooth fashion around the map, and the players would have to react with their movement keys in order to stop themselves from dying. Ultimately I wasn’t able to make it look smooth, I was using frameCount as my method of timing the balls’ speed and it wasn’t working.
    • The balls would move upon pressing the direction keys nicely. However, if I do something this, there is a bug:
        1. Press left
        2. Press down while not releasing left
        3. Release down while not releasing left
        4. The ball would still be moving down, even though I’m holding left.

Overall, this was a useful project in helping me get a basic understanding of how to do Object-Oriented Programming with Java. I used three tabs for this assignment, one for the main game, one for the Ball class, and one for the Wall class. I actually feel like it’s easier than doing it with Python, and I look forward to doing more of this with Java. The logic just seems more clear.

Below is the video of my gameplay with myself, showing both the death-win scenario and the point-win scenario.

Here is my main game code:

Ball b1;
Ball b2;

Wall w1;
Wall w2;
Wall w3;
Wall w4;

void setup() {
  size(640, 640);
  b1 = new Ball(width/3, height/2, 1);          // player 1 ball
  b2 = new Ball(width/1.5, height/2, 2);        //player 2 ball
  w1 = new Wall(0, height/2, 10, 200, 1);
  w2 = new Wall(width/2, height, 200, 10, 0);
  w3 = new Wall(width, height/2, 10, 200, 1);
  w4 = new Wall(width/2, 0, 200, 10, 0);        //four walls
}

void draw() {
  background(255);
  textSize(24);
  text(b1.score, width/3, height/2 - b1.diameter);
  text(b2.score, width/1.5, height/2 - b2.diameter);

  b1.display();
  b1.move();
  b2.display();
  b2.move();

  
  w1.display();
  w1.move();
  w2.display();
  w2.move();
  w3.display();
  w3.move();
  w4.display();
  w4.move();
  b1.collision();
  b2.collision();
  checkwin();
}

void checkwin(){
  if (b1.score + b2.score >= 16){                  //it is only possible to bump the walls 16 times in total
    stop();
    if (b1.score > b2.score){
      fill(255, 0, 0);
      rect(width/2, height/2, 640, 640);
      fill(255, 255, 255);
      textSize(32);
      text("Player 1 Wins!", width/2, height/2); 
    }
    else if (b2.score > b1.score){
      fill(0, 0, 255);
      rect(width/2, height/2, 640, 640);
      fill(255, 255, 255);
      textSize(32);
      text("Player 2 Wins!", width/2, height/2);
    }
  }
}

Ball class code:

class Ball {

  float x;
  float y;
  float diameter;
  int score;
  int player;

  Ball(float tempX, float tempY, int tempPlayer) {
    x = tempX;
    y = tempY;
    diameter = 40;
    score = 0;
    player = tempPlayer;
  }

  void display() {
    if (player == 1){
      stroke(0);
      fill(255, 0, 0);
      ellipse(x, y, diameter, diameter);
    }
    if (player == 2){
      stroke(0);
      fill(0, 0, 255);
      ellipse(x, y, diameter, diameter);
    }
  }
  
  void move() {  
    if (player == 1){
      if (keyPressed) {
        if (key == 'w' || key == 'W') {
          y = y - 5;
        }
        if (key == 'a' || key == 'A') {
          x = x - 5;
        }
        if (key == 's' || key == 'S') {
          y = y + 5;
        }
        if (key == 'd' || key == 'D') {
          x = x + 5;
        }
      }
    }
    
    if (player == 2){
      if (keyPressed) {
        if (keyCode == UP) {
          y = y - 5;
        }
        if (keyCode == LEFT) {
          x = x - 5;
        }
        if (keyCode == DOWN) {
          y = y + 5;
        }
        if (keyCode == RIGHT) {
          x = x + 5;
        }
      }
    }
  }
  
  void collision() {
    //actions after bumping into each of the four walls
    if (x < 0 || x > width || y < 0 || y > height) {
      if ((x <= (w1.x + (w1.w))) & ((w1.y - (w1.h)/2) <= y && y <= (w1.y + (w1.h)/2))) { //hitting the left wall
        x = width/2;
        y = height/2;
        score = score + 1;
        w1.h = w1.h - 50;
      }
      else if ((y >= (w2.y - (w2.h))) & ((w2.x - (w2.w)/2) <= x && x <= (w2.x + (w2.w)/2))) { //hitting the bot wall
        x = width/2;
        y = height/2;
        score = score + 1;
        w2.w = w2.w - 50;
      }
      else if ((x >= (w3.x - (w3.w))) & ((w3.y - (w3.h)/2) <= y && y <= (w3.y + (w3.h)/2))) { //hitting the right wall
        x = width/2;
        y = height/2;
        score = score + 1;
        w3.h = w3.h - 50;
      }
      else if ((y <= (w4.y + (w4.h))) & ((w4.x - (w4.w)/2) <= x && x <= (w4.x + (w4.w)/2))) { //hitting the top wall
        x = width/2;
        y = height/2;
        score = score + 1;
        w4.w = w4.w - 50;
      }
      
      //going out of bounds
      
      else {
        if (player == 1){
          stop();
          fill(0, 0, 255);
          rect(width/2, height/2, 640, 640);
          fill(255, 255, 255);
          textSize(32);
          text("Player 2 Wins!", width/2, height/2); 

        }
        else if (player == 2){
          stop();
          fill(255, 0, 0);
          rect(width/2, height/2, 640, 640);
          fill(255, 255, 255);
          textSize(32);
          text("Player 1 Wins!", width/2, height/2); 

        }
      }
    }
    
  }

}

Wall class code:

class Wall {

  float x;
  float y;
  float w;
  float h;
  int dir;

  Wall(float tempX, float tempY, float tempW, float tempH, int tempDir) {
    x = tempX;
    y = tempY;
    w = tempW;
    h = tempH;
    dir = tempDir;
  }

  void display() {
    rectMode(CENTER);
    stroke(0);
    fill(165,0,255);
    rect(x, y, w, h);
  }
  
  void move() {
    if (dir == 1){ //vertical walls
      int center = height/2;
      float amplitude = 400;
      float speed = .004;
      float granular = .001;
      float freq = frameCount*speed + x * granular;
      float adjustedHeight = noise(freq);
      adjustedHeight -= .5;
      adjustedHeight *= amplitude;
      y = center + adjustedHeight;
    }
    if (dir == 0){ //horizontal walls
      int center = width/2;
      float amplitude = 600;
      float speed = .002;
      float granular = .001;
      float freq = frameCount*speed + x * granular;
      float adjustedWidth = noise(freq);
      adjustedWidth -= .5;
      adjustedWidth *= amplitude;
      x = center + adjustedWidth;
    }
  }
}

 

He’s back

For this week’s assignment, we were asked to do an art piece with the use of loops. Personally I feel like my previous week’s assignment, the self-portrait, was a fabulous piece of art. However, I needed to implement the use of loops in my piece, so I used for-loops and nested for-loops to create an introduction for Sir. Got Milk Nathan.

One thing that I hope my code can have in the future is implementing more complicated uses of loops and other functions. This week, some of the harder codings were just figuring out nested loops and implementing a timer mechanic based on frameCount. I also like how people implemented external photos and code snippets into an art piece, I think that produces better effects and I’ll try to do that too.

int timer = 0;
int rectDim = 50;


void setup(){
  size(800,800);
  rectMode(CENTER);
}

void draw(){
  background(0);
  if (frameCount % 30 == 0){
    timer++;
    flash();
    if (timer == 21){
      background(255);
      hair();
      face();
      eyes();
      body();
      Nathan();
      Gotmilk();
      stop();
    }
  }
}
  
void flash(){
    pushMatrix();
      translate(width/2, height/2);
      stroke(255);
      rect(0,0, rectDim , rectDim);
    popMatrix();
    println(timer);
  
  if (timer > 4){
      for (int x = 0; x < width; x += rectDim){
        if (frameCount % 30 == 0){
          stroke(255);
          rect(x + rectDim/2, height/2, rectDim, rectDim);
        }
      }
  }
  if (timer > 8){
      for (int x = 0; x < height; x += rectDim){
        if (frameCount % 30 == 0){
          stroke(255);
          rect(width/2, x + rectDim/2, rectDim, rectDim);
        }
      }
  }
   if (timer > 12){
      for (int x = 0; x < height; x += rectDim){
        if (frameCount % 30 == 0){
          stroke(255);
          rect(x + rectDim/2, x + rectDim/2, rectDim, rectDim);
          rect(x + rectDim/2, height - (x + rectDim/2), rectDim, rectDim);
        }
      }
  }
  if (timer > 16){
      for (int x = 0; x < width; x += rectDim){
        for (int y = 0; y < height; y += rectDim){
          if (frameCount % 30 == 0){
          fill(255);
          stroke(255);
          rect(x + rectDim/2, y + rectDim/2, rectDim, rectDim);
          }
        }
      }
      }
      
      
  }
  
void Nathan() {
  textSize(32);
  fill(255, 102, 178);
  text("Heyyyyy", 10, 30); 

}

void Gotmilk() {
  textSize(30);
  fill(255, 255, 255);
  text(" Got \nMilk?\n  :)", 310, 370);
}

void face() {
  //skin
  fill(255, 255, 51);
  ellipse(350, 200, 100, 140);
  noStroke();
  
  //mouth
  fill(0, 0, 0);
  noStroke();
  arc(350, 230, 50, 40, 0, PI, PIE);
  
}

void hair() {
  fill(255, 0, 0);
  noStroke();
  arc(350, 140, 130, 180, 0, PI, PIE);
}

void eyes() {
//sclera
  fill(255, 255, 255);  
  stroke(0, 0, 0);
  strokeWeight(0.5);
  ellipse(350, 180, 40, 50);
  
//pupil
  fill(255, 0, 0);  
  noStroke();
  ellipse(350, 190, 20, 20);
  
}

void body() {
  
  //arms
  stroke(255, 255, 51);
  strokeWeight(30);
  line(280, 320, 220, 400);
  stroke(255, 255, 51);
  strokeWeight(30);
  line(220, 400, 200, 530);
  
  stroke(255, 255, 51);
  strokeWeight(30);
  line(420, 330, 470, 400);
  stroke(255, 255, 51);
  strokeWeight(30);
  line(470, 400, 490, 530);
  
  //neck
  stroke(255, 255, 51);
  strokeWeight(9);
  line(350, 270, 350, 290);
  
  //T-shirt
  fill(0,0,0);
  noStroke();
  rect(350, 410, 150, 250, 15);
  
  //pants
  
  fill(0,76,153);
  quad(275, 515, 270, 820, 340, 820, 350, 515);
  fill(0,76,153);
  quad(350, 515, 355, 820, 425, 820, 425, 515);
  
  fill(102,51,0);
  rect(350, 515, 160, 20);
  
  stroke(255, 255, 51);
  strokeWeight(30);
  line(290, 835, 320, 835);
  line(375, 835, 405, 835);


  

  //sleeves
  noStroke();
  fill(0,0,0);
  triangle(285, 290, 240, 330, 275, 360);
  fill(0,0,0);
  triangle(415, 290, 410, 370, 460, 330);
}

YOUTUBE VID NEEDS TO BE WATCHED IN 1080 RESOLUTION OR IT WONT WORK

http://vimeo.com/user123608994/review/460111802/0c51e48127

Nathan Li

For my first assignment using java, my main goal was to get used to the language. I just finished studying python in the previous semester, so I found that there are some useful similarities while I was coding this project. In general, doing this small exercise proved to be a good introduction to java, helping me develop important coding habits that relate to java.

Project wise, we were asked to draw a not-so-accurate self-portrait of ourselves, so I took that requirement to somewhat of an extreme. I never really excelled at detailed intricate art anyways, so I decided to go a bit crazy and draw a demon version of myself. I have one red eye, red hair, and I knew demons can be scary for some people so I threw in some dad styles to cheer the picture up.

A big drawback to this week’s project is that I didn’t try to avoid hard coding that much, I felt like I wanted to start off just getting to know the language. In next week’s project, I want to design my code better and make it much more aesthetically pleasing.

void setup() {
  size(700, 900);
  background(128,128,128);
}

void draw() {

  ground();
  hair();
  face();
  eyes();
  body();
  Nathan();
  Gotmilk();
}

void Nathan() {
  textSize(32);
  fill(255, 102, 178);
  text("Friendly Demon Nathan", 10, 30); 

}

void Gotmilk() {
  textSize(30);
  fill(255, 255, 255);
  text(" Got \nMilk?\n  :)", 310, 370);
}

void face() {
  //skin
  fill(255, 255, 51);
  ellipse(350, 200, 100, 140);
  noStroke();
  
  //mouth
  fill(0, 0, 0);
  noStroke();
  arc(350, 230, 50, 40, 0, PI, PIE);
  
}

void hair() {
  fill(255, 0, 0);
  noStroke();
  arc(350, 140, 130, 180, 0, PI, PIE);
}

void eyes() {
//sclera
  fill(255, 255, 255);  
  stroke(0, 0, 0);
  strokeWeight(0.5);
  ellipse(350, 180, 40, 50);
  
//pupil
  fill(255, 0, 0);  
  noStroke();
  ellipse(350, 190, 20, 20);
  
}

void body() {
  
  //arms
  stroke(255, 255, 51);
  strokeWeight(30);
  line(280, 320, 220, 400);
  stroke(255, 255, 51);
  strokeWeight(30);
  line(220, 400, 200, 530);
  
  stroke(255, 255, 51);
  strokeWeight(30);
  line(420, 330, 470, 400);
  stroke(255, 255, 51);
  strokeWeight(30);
  line(470, 400, 490, 530);
  
  //neck
  stroke(255, 255, 51);
  strokeWeight(9);
  line(350, 270, 350, 290);
  
  //T-shirt
  fill(0,0,0);
  noStroke();
  rect(275, 290, 150, 250, 15);
  
  //pants
  
  fill(0,76,153);
  quad(275, 515, 270, 820, 340, 820, 350, 515);
  fill(0,76,153);
  quad(350, 515, 355, 820, 425, 820, 425, 515);
  
  fill(102,51,0);
  rect(270, 515, 160, 20);
  
  stroke(255, 255, 51);
  strokeWeight(30);
  line(290, 835, 320, 835);
  line(375, 835, 405, 835);


  

  //sleeves
  noStroke();
  fill(0,0,0);
  triangle(285, 290, 240, 330, 275, 360);
  fill(0,0,0);
  triangle(415, 290, 410, 370, 460, 330);
}

void ground() {
  noStroke();
  fill(0, 0, 0);
  rect(0, 700, 700, 900);
}