# 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.

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.

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++) {

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;
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));

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

if (dist(m.x, m.y, circle.x, circle.y) < radius) {
m.sub(circle);
m.normalize();
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);
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);

}
}```