One More Time: Rolly Vortex (the Addictive Game) – Beethoven

Still hooked up by the mobile app game Rolly Vortex since last week’s assignment, I decided to take a shot at creating the game.

The mobile app game

I started out by trying to create the grey hoops which give the feeling of you being inside a vortex. I struggled with making them because I wanted to create white spaces between each of them, and because I wanted each hoop to restart from the middle after it expands more than the height of the screen. I wanted to do 3D where the z-dimension increases but I wasn’t comfortable enough at the start.

This was how they looked before fixing the distances between each of them, their thickness, and how they restart.

picture of the improved hoops

This is the better version where the hoops actually look like a vortex and are quite similar to the game.

I then started to create the ball and I wanted it to be 3D so a sphere instead of an ellipse. But I struggled at first with making sure the ball doesn’t enter the center of the vortex and did it manually, which was still unsuccessful.

I then did the blocks, where I started out by creating them using rectangles and moving their z-coordinate towards the screen to give the feeling of a vortex. However, after so many trial and error, I realized that the pushMatrix() and popMatrix() are quite dangerous if not used properly and that I had so many issues because of them. or example, I couldn’t move the blocks properly while moving the ball as in the video.

After many attempts I was finally able to create 3D boxes which get closer to the screen and to successfully move the ball without touching the center and to properly make a collide function that checks if the ball touches any block. I was able to end and restart the game without errors and to keep score while playing and at the end of the game.

The code for the overall game:

Hoop[] hoops;    //list of grey vortex circles
float x, y, z;
Ball ball;       // ball of the player
ArrayList<Block> blocks;    //array list of obstacle blocks
boolean gameOn;      //condition under which the game operates
PFont f;         //text for ending game
int score;        //score of user, increases with each block block they


void setup () {
  
  size(1280, 720, P3D);
  
  hoops = new Hoop[200];    //instances of the three main classes
  ball = new Ball();
  blocks = new ArrayList<Block>();
  
  blocks.add(new Block(60));    //initial theta in argument
  
  gameOn = true;
  score = 0;
  
  f = createFont("Arial",72,true);
  
  for (int i =0; i < hoops.length; i++) {      //creates the continuous hoops
    hoops[i] = new Hoop();
  }
  
  
}

void draw () {
  
  background(255);
  
  if (gameOn == true) {
    
    for (int i = 0; i < hoops.length; i+= 20) {      //draws the hoops and calls the related functions
      hoops[i].drawHoop(i*10);
      hoops[i].update();
      hoops[i].checkEdge();
    }
    
    ball.drawBall();          // draws the ball
    
    for (int i = blocks.size()-1; i >= 0; i--) {       //draws block for each element in the array list
      Block block = blocks.get(i);
      block.drawBlock();
      
    }
    
    if (frameCount % 60 == 0){                      //creates instances of the blocks of number between 1 and 6 randomly
      for(int i = 0; i < int(random(1,6)); i++) {
        blocks.add(new Block(int(random(1,12)*30)));
        
        if (gameOn == false) 
          {break;}
        
      }
    }
    score = blocks.size();          //updates the value of score to be number of elements in array list
    
    for (int i = blocks.size()-1; i >= 0; i--) {            //checks if the ball collided with any block, if true the game stops
      if (ball.checkCollide(blocks.get(i).posX, blocks.get(i).posY) == true) {
          gameOn = false;
       };
    }
    
    textAlign(CORNER);
    textFont(f,24);
    fill(0);
    text("Score: "+ score,width -120,height -30);        //score text bottom right
    
    
  }
  
  else {
    textFont(f,72);               
    fill(#000080);
    textAlign(CENTER);
    text("GAME OVER!",width/2,height/2 - 30);
    textFont(f,24);
    fill(0);
    text("CLICK ANYWHERE TO RESTART",width/2,height/2 +30);      //game over text
    
    textAlign(CORNER);
    textFont(f,24);
    fill(0);
    text("Score: "+ score,width -120,height -30);      //final score text
    
    
    
  }
}

void mouseClicked() {
  if (gameOn == false) {
    score = 0;
    gameOn = true;
    for (int i = blocks.size()-1; i >= 0; i--) { 
      Block block = blocks.remove(i);
      block.drawBlock(); 
    }
  }
}

Code for the Ball() class:

class Ball {
  float ballWidth, ballHeight;
  float locX, locY;
  color ballColor;
  float speed;
  int radius;
  PVector m;
  PVector circle;
  float z;
  float easing = 0.95;

  
  Ball() {
  
    locX = width/2;
    locY = height/2;

    ballWidth = 100;
    ballHeight = ballWidth;
    
    speed = 15;
  
    ballColor = color(random(255), random(255), random(255)); 
    
    radius = 150;
    
    z= 0;
  
  }
  
  void drawBall() {
     //idea inspired from ellipse constraint code from https://forum.processing.org/one/topic/ellipse-constrain-shape.html
   
    fill(#F5F5F5);
    noStroke();
    m = new PVector(mouseX, mouseY, z);      //vector of movement of ball
    circle = new PVector(width/2, height/2, z); //vector circle around which ball is constrained
    ellipse(circle.x, circle.y, radius, radius);     //circle of cosnstrain
    

    if (dist(m.x, m.y, circle.x, circle.y) < radius) {
      m.sub(circle);
      m.normalize();
      m.mult(radius);
      m.add(circle);      //constrains movement of ball to be everywhere except at a distance from teh center of the vortex
    }
    locX = locX + (m.x - locX) * easing;
    locY = locY + (m.y - locY) * easing;     //sets the x and y coordinates such that the ball is updated properly and doesn't disappear or enter middle 
    
    noStroke();
    lights();
    pushMatrix();
      translate(locX, locY - 30, z);
      fill(ballColor);
      sphereDetail(36, 36);
      sphere(30);
    popMatrix();      //draws the 3D sphere at the updated location
    //z+= 0.5;
  }
  
  boolean checkCollide(float posX, float posY) {

    if (dist(locX, locY - 30, posX - 30, posY + 25) < 55) {    //if ball touches the x,y coordinates of the block it collides and returns true to end game
      gameOn = false;
      return true;
    }
    
    else {
      return false;
    }
  }
}

Code for the Block() class:

class Block {
  float blockWidth, blockHeight, blockDepth;
  float locXB, locYB, locZ;
  color a, g, b;
  float posX, posY;
  float theta;
  float speed;

  Block(int _theta ) {
    
    locXB = width/2;
    locYB = height/2;
    locZ = 0;
  
    blockWidth = 60;
    blockHeight = 50;
    blockDepth = 30;
    
    a = int(random(255));
    g = int(random(255));
    b = int(random(255));    //randomized color
    
     posX = width/2;
     posY = height/2;
     theta = _theta;
    
    speed = 6;    //speed of shift
  
  }
  
  void drawBlock() {
   fill(a, g, b);
   noStroke();
   pushMatrix();
     
     translate(posX, posY, locZ);
     rotate(radians(theta));      //rotates blocks before moving
     posX += speed*sin(theta);    // horizontal shift
     posY += speed*cos(theta);    //vertical shift
     box(blockWidth, blockHeight, blockDepth);
     
     locZ+= 8;      //z-dimension shift towards the screen

   popMatrix();
   
  }
}

Code for the Hoop() class:

class Hoop {
  float outerHoopWidth, outerHoopHeight;
  float innerHoopWidth, innerHoopHeight;
  float locXH, locYH;
  float speed, acceleration;

  Hoop () {

    locXH = width/2;
    locYH = height/2;

    outerHoopWidth = 100;      //width of circle
    outerHoopHeight = outerHoopWidth;

    speed = 5;

  }

  void update() {
    
    if (outerHoopHeight + 400 == height) {
      speed = 10;
    }
    
    outerHoopWidth += speed;
    outerHoopHeight += speed;
    
  }

  void checkEdge() {
    if (outerHoopHeight + 300 == height) {    //if hoop is out of screen then restart it at the middle of the screen
      outerHoopWidth = 200;
      outerHoopHeight = 200;
    }

  }

  void drawHoop(int xFactor) {

    float circle1w = outerHoopWidth + xFactor;    //xFactor is to space out the different hoops

    float circle1h = outerHoopHeight + xFactor;

    noFill(); 
    stroke(#F5F5F5);
    strokeWeight(55);
    ellipse(locXH, locYH, circle1w, circle1h);
    
    
    
  }
}

 

 

One thought on “One More Time: Rolly Vortex (the Addictive Game) – Beethoven”

Leave a Reply