Introduction:
Bouncing ball game is one of the old era game which is much popular and is easy to play. The main logic behind this game is to remove all the marbles or tiles from the top of the screen by bouncing the ball towards it through a simple stick laid at the bottom of screen. The ball moves randomly in any direction based on the collision of ball with the stick and touches the marbles at the top with different speed.
Inspiration for the Project:
Children are always found of ball games and the bouncing of ball not only release stress but also gives opportunity for a healthy activity. The visualization of ball bouncing in computer graphics gives smooth and realistic touch to eyes and fun to visualize such graphics. The old game gadgets and devices always incorporate such small games i.e. ball bouncing game. The game rules are easy to understand and anyone can play this game without any professional training. These are facts which inspired me a lot to implement ball bouncing game for my mid project.
Challenges and Problems:
It was challenging for me to give different direction to ball and to simulate the direction based on the collision of ball on stick residing at the bottom of the screen. It was challenging for me to move the ball with random speed and velocity. I faced little problem when detecting collision between ball and marble. It was challenging for me to display marbles on top of the screen at random positions. The addition of more speed and velocity if the ball is hitting the stick at same position was challenging for me.
Procedure:
I started by implementing a ball class as ball object is the main object of the game. In this class I implemented function for the movement of the ball. The class contains attributes for the speed and velocity of the ball movement which sets based on the marble position and collision of ball with the stick. For sound effect I initialized audio sample object which further loads an external sound and plays when ball hits the bottom stick.
I implemented the displayball() inside ball class which draws a ball shape object based on the given screen position and specified size. I filled the ball shape with black color and using nostroke() function to give ball a realistic look.
Then I implemented the marble class which is responsible for displaying marbles at the top of the screen. The marble class object further used in marble aims class which is responsible for handling the collisions of ball with marbles.
In marble constructor I am setting the default size of marble and default position of marble.
I then implemented the display marble function which displays the marble in rectangular shape on top of the screen with specified width and height assigned through the constructor of the marble class.
I game class I implemented function to calculate the ball speed and velocity. If the ball position is far from the targeted marbles then increasing the speed and velocity of the ball.
I implemented the isBallTouchMarble() function which uses distance function to check if the ball touches any marble or not. If the distance between the ball and marble is 0 then the function is returning true otherwise false.
Finally in main program I am initializing the game class object and calling the relevant functions in setup function to display marbles, ball and stick on screen. In draw function which is iterating infinite times I am calling calculate function which updates the ball speed and velocity based on the marble collisions.
Below I attached my final code including data class along with setup and draw function.
import ddf.minim.*; Minim minim = new Minim(this); boolean start= false; class Ball { PVector MarblePosition; PVector velocity; PVector acceleration; AudioSample groove; float MarbleSize = 0; Ball(float MarbleSize) { this.MarbleSize = MarbleSize; groove = minim.loadSample("collision.wav"); MarblePosition = new PVector(200,500); velocity = new PVector(2,2); acceleration = new PVector(0.008,0.008); } void MoveBall() { if(MarblePosition.x>(width-(MarbleSize/2))|| MarblePosition.x<(MarbleSize/2) ) { velocity.x = velocity.x*(-1); acceleration.x = acceleration.x*(-1); this.groove.trigger(); } if(MarblePosition.y>(height-(MarbleSize/2)) || MarblePosition.y<(MarbleSize/2) ) { velocity.y = velocity.y*(-1); acceleration.y = acceleration.y*(-1); this.groove.trigger(); } MarblePosition = MarblePosition.add(velocity); velocity = velocity.add(acceleration); } void DefaultVelocity() { velocity.x=2; velocity.y=2; } void SimulateDirection(float x,float y) { acceleration = new PVector(x,y); } void DisplayBall() { noStroke(); fill(random(255)); ellipse(MarblePosition.x,MarblePosition.y,MarbleSize,MarbleSize); } } class Game { Ball ball; Marble Marble; Aims marbleaims; int score = 0; int level = 1; Game() { ball = new Ball(50); Marble = new Marble(120 , 30); marbleaims= new Aims(); marbleaims.LoadMarbles(); } void calculate() { marbleaims.AimCollision(ball); if(ball.MarblePosition.y> height-(Marble.MarbleHeight*2)) { if((Marble.MarblePosition.x - (Marble.MarbleWidth/2)-(ball.MarbleSize/2)) < ball.MarblePosition.x && ball.MarblePosition.x < ((Marble.MarblePosition.x + (Marble.MarbleWidth/2) + ball.MarbleSize/2))) { ball.velocity.y = ball.velocity.y*(-1); ball.acceleration.y = ball.acceleration.y*(-1); ball.groove.trigger(); } } ball.MoveBall(); Marble.MoveMarble(int(mouseX)); } void display() { marbleaims.DisplayMarbleAim(); ball.DisplayBall(); Marble.DisplayMarble(); if(ball.MarblePosition.y>height-(Marble.MarbleHeight)) { background(255); textSize(40); fill(random(255),random(255),random(255)); text("You lost the ball! Game Over!",width/2-200,height/2); start=true; noLoop(); } textSize(30); score=marbleaims.marblescount-marbleaims.currentmarblecounts; text("score : "+score,width-200,50); if(score==marbleaims.marblescount) { background(255); textSize(40); fill(random(255),random(255),random(255)); text("LEVEL "+level+" COMPLETED",width/2-100,height/2); ++level; marbleaims.LoadMarbles(); } } } class MarbleAim { PVector MarblePosition; float MarbleSize = 40; MarbleAim(int x,int y) { MarblePosition = new PVector(x,y); } boolean isBallTouchMarble(Ball ball) { if(dist(MarblePosition.x,MarblePosition.y,ball.MarblePosition.x,ball.MarblePosition.y)<(this.MarbleSize/2+ball.MarbleSize/2)) { return true; } return false; } void DisplayMarbleAim() { stroke(0); strokeWeight(2); fill(255,0,0); rectMode(CENTER); rect(MarblePosition.x,MarblePosition.y,MarbleSize,MarbleSize); } } class Aims { int marblescount; int currentmarblecounts; ArrayList<MarbleAim> marbleaims; Aims() { marbleaims=new ArrayList<MarbleAim>(); } void LoadMarbles() { for(int i=40; i<height/2; i += 60) { for(int j=40; j<width-20; j += 50) { int flag=int(random(0,2)); if(flag == 1) { marbleaims.add(new MarbleAim(j,i)); } } } marblescount=marbleaims.size(); currentmarblecounts=marblescount; } void AimCollision(Ball ball) { for(int i = marbleaims.size()-1; i>=0; i--) { MarbleAim MarbleAim= marbleaims.get(i); if(MarbleAim.isBallTouchMarble(ball)) { ball.velocity = ball.velocity.mult(-1); ball.acceleration = ball.acceleration.mult(-1); marbleaims.remove(i); currentmarblecounts -= 1; } } } void DisplayMarbleAim() { for(MarbleAim t: marbleaims){ t.DisplayMarbleAim(); } } } // Marble class for displaying marbles at the top of the game screen class Marble { PVector MarblePosition; float MarbleWidth; float MarbleHeight; Marble(float MarbleWidth,float MarbleHeight) { this.MarbleWidth = MarbleWidth; this.MarbleHeight = MarbleHeight; MarblePosition = new PVector(width/2,(height-MarbleHeight/2)); } void MoveMarble(int x) { MarblePosition.x=x; } void DisplayMarble() { noStroke(); fill(0); rectMode(CENTER); rect(MarblePosition.x,MarblePosition.y,MarbleWidth,MarbleHeight); } } Game game; void startgame() { game.calculate(); game.display(); } void setup() { size(1000,800, P2D); game = new Game(); background(255); } void draw() { background(255); if(!start) { startgame(); } else { textSize(18); text("The game is starting......", 40, 120); } }
Conclusion:
In this mid project I learned how to move objects with different speeds and directions. I learned how to create a list of objects and renders on the screen at random positions. I learned how to check intersection of two objects. I learned how call one class function into another class and how to encapsulate the functionalities of each class. I learned how to build and map the game logics in an object oriented way.