Jump to content
  • Advertisement
Sign in to follow this  
trblair82

Breakout clone

This topic is 2574 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

Hey everybody! I'm new to programming, about two weeks in. I started out by reading Head First Java. After working through that, I started working on a simple version of the Breakout game. I've got everything working to my satisfaction. However I'm sure the code could be cleaner and more efficient. Any criticism, tips, info, etc...would be greatly appreciated.

My next project is going to be a 2d platform using the Jbox2d physics library. Tips or advice on this are also greatly appreciated.

Anyway, thanks again and heres the code for my version of Breakout.

Start Class (main)


public class Start {
public static Game g;


public static void main(String[] args) {
g = new Game();

g.GameSetup(1, 1);
g.GameLoop();

}
}


Game Class (game setup and loop)




import java.awt.*;
import javax.swing.*;
import java.awt.image.BufferStrategy;
import java.util.*;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.lang.Thread;
import java.lang.Integer;






public class Game extends Canvas {
private BufferStrategy buffer;
private boolean gameRunning = true;
private boolean pause = true;
private boolean gameOver = false;
public static ArrayList bricks; //list to keep bricks in
private int ball_x, ball_y, x_speed, y_speed; //ball variables
public static Ball ball;//makes ball class variable
public static Paddle paddle;
public Integer lives, score;
private Thread myThread;
private Font f = new Font("SansSerif", Font.BOLD, 20);


public class BreakoutKeyListener implements KeyListener{ //handles user keyboard input

@Override
public void keyPressed(KeyEvent e){
int key = e.getKeyCode();
if(key == KeyEvent.VK_LEFT){ //moves paddle

Game.paddle.paddle_speed = -10;
}
if(key == KeyEvent.VK_RIGHT){

Game.paddle.paddle_speed = 10;
}
if(key == KeyEvent.VK_SPACE){ //pauses game
pause = true;

}

}
@Override
public void keyReleased(KeyEvent e){
int key = e.getKeyCode();
if(key == KeyEvent.VK_LEFT){ //moves paddle
Game.paddle.paddle_speed = 0;

}
if(key == KeyEvent.VK_RIGHT){

Game.paddle.paddle_speed = 0;
}
if(key == KeyEvent.VK_SPACE){ //upauses game
pause = false;


}

}
@Override
public void keyTyped(KeyEvent e){ //unused

}
}
public Game(){ //construts main game object


//create window
JFrame container = new JFrame("Breakout");
container.setSize(800,600);
container.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
//get content of frame set resolution
JPanel panel = (JPanel) container.getContentPane();
panel.setPreferredSize(new Dimension(800,600));
panel.setLayout(null);
container.addKeyListener(new BreakoutKeyListener());
//set canvass size and add to window
setBounds(0,0,800,600);
panel.add(this);
setIgnoreRepaint(true); //use my double buffer
container.pack();
container.setResizable(false); //window is not resizeable
container.setVisible(true); //make window visible
bricks = new ArrayList();
x_speed = 4; //set initial ball speed and position
y_speed = 3;
ball_x = 400;
ball_y = 555;
lives = 3; //set initial lives and score
score = 0;



//creates double buffer
createBufferStrategy(2);
buffer = getBufferStrategy(); //sets to variable



}

public void GameSetup(int x, int y){ //initializes ball, bricks, and paddle


int w = 78;
int h = 30;
Brick n = new Brick(x*(w+2),y*(h+2), w, h);
Game.bricks.add(n);

if(y<6){
y++;
GameSetup(x, y);
}
else if(x<8){
x++;
y = 1;
GameSetup(x, y);
}

ball = new Ball(ball_x, ball_y, x_speed, y_speed);
paddle = new Paddle(400-(w/2),600-(h+5), w, h);


}
public void Pause(){ //tells thread to sleep untill key pressed

while(pause){
try {myThread.sleep(10); } catch (Exception e) {};
}
}
public void GameLoop(){ //loop the game runs in
myThread = Thread.currentThread(); //sets variable to current thread
while(gameRunning){
long startTime = System.currentTimeMillis(); //current time in milliseconds
long fps = 32; //my fps
Graphics2D g = (Graphics2D) buffer.getDrawGraphics(); //sets up canvas for paint
g.setColor(Color.black); //sets color to black
g.fillRect(0, 0, 800, 600); //paints canvas black
g.setFont(f); //sets font to my font f


for(int i = 0; i < bricks.size(); i++){ //checks bricks for collision with ball
Brick brick = (Brick) bricks.get(i);
if (brick.collisionDetect() == true){
score += 10;
brick.collisionReaction(); //calls to determine balls reaction to collision
bricks.remove(i); //removes brick if collision occurs
}

brick.paint(g); //paints bricks that did not detect collision


}
if(paddle.collisionDetect()){ //detect collision with paddle
paddle.collisionReaction(); //ball reaction
}
if(ball.y>paddle.y){ //checks if ball is below paddle and adjust lives accordingly
lives += -1;
if(lives>0){
paddle.paddleSet();
ball.ballSet();
pause = true;
}
else{
g.drawString("Game Over", 325, 375);// if no lives game over
gameOver = true;

}

}
if(bricks.size() == 0){ //if no bricks game over
g.drawString("Game Over", 325, 375);
gameOver = true;
}
if(pause){g.drawString("Press Spacebar", 325, 375);} //if paused display press space
String scoreString = "SCORE"+" "+score.toString();
g.drawString(scoreString, 675, 20); //display score
String livesString = "LIVES"+" "+lives.toString();
g.drawString(livesString, 10, 20); //display lives
ball.paint(g); //paints ball
ball.moveBall();
paddle.movePaddle(); //checks for collision with wall and moves ball
paddle.paint(g);

g.dispose(); //flip buffer
buffer.show();
if(gameOver){try {myThread.sleep(3000); } catch (Exception e) {};
System.exit(0);} //if game over wait 30 seconds and exit
Pause();


long fps_lim = (long)(1000/fps); //how many milliseconds per frame at 32 fps
long cur_t;//current time milliseconds
long delta_t;//current time - start time
//sets fps to 32
do{
cur_t = System.currentTimeMillis();
delta_t = (cur_t - startTime);
}while(delta_t < fps_lim);//if current time - start time is less than time of one frame wait

}
}
}


Brick Class (defines brick objects)



import java.awt.*;

public class Brick extends Rectangle implements Paintable { //allow Brick to have properties of Rectangle

public Color color;
public int temp_bx, temp_by;


public Brick(int x,int y, int width, int height){ //creates Brick object with given parameters

super(x, y, width, height); //sets parameters of Rectangle object to parameters of Brick object


color = Color.yellow; //sets Brick color to yellow


}
public boolean collisionDetect(){ //checks to see if Rectangle ball intersects Rectangle brick

if(this.intersects(Game.ball) == true){
return true;
}
else{
return false;
}


}
public void collisionReaction(){ //changes ball direction depending on location of collision

if(Game.ball.intersects(this)){

Rectangle inRect = Game.ball.intersection(this); //sets intersection rectangle


if((Game.ball.x+Ball.radius)<(inRect.x+(inRect.width/2))){

Game.ball.x_speed = -Game.ball.x_speed;


}
if((Game.ball.x+Ball.radius)>(inRect.x+(inRect.width/2))){

Game.ball.x_speed = -Game.ball.x_speed;

}
if((Game.ball.y+Ball.radius)<(inRect.y+(inRect.height/2))){

Game.ball.y_speed = -Game.ball.y_speed;

}
if((Game.ball.y+Ball.radius)>(inRect.y+(inRect.height/2))){

Game.ball.y_speed = -Game.ball.y_speed;
}

}
}

@Override
public void paint(Graphics2D g){
g.setColor(color); //sets color of brick
g.fillRect(x, y, width, height); //paints brick
}
}


Ball Class (defines ball object)



import java.awt.*;

public class Ball extends Rectangle implements Paintable { //allow ball to have properties of Rectangle
public static int radius = 5; //set ball radius to 5

public int x_speed, y_speed;
public Color color;


public Ball(int x, int y, int xs, int ys){ //creats ball with given parameters
super(x, y, radius*2, radius*2); //sets parameters of Rectangle object to parameters of Ball object

x_speed = xs;
y_speed = ys;
color = Color.yellow; //sets Ball color to yellow
}
public void ballSet(){ //resets ball to start position
x = 400;
y = 555;
x_speed = 4;
y_speed = 3;
}

public void moveBall(){
x += x_speed; //moves ball given number of pixles on x axis
y += y_speed; //moves ball given number of pixles on y axis
if (x < 5 ){ //check if ball hits any walls and change direction accordingly
x_speed = -x_speed; //if ball hits left wall
x = 5;
}
else if (x > 795){
x_speed = -x_speed; //if ball hits right wall
}
if (y < 5){
y_speed = -y_speed; //if ball hits top wall
y = 5;
}
else if (y > 595){
y_speed = -y_speed; //if ball hits bottom wall
y = 595;
}


}
@Override
public void paint(Graphics2D g){
g.setColor(color); //sets Ball color
g.fillOval((int) (x), (int) (y), (int) (radius*2), (int) (radius*2) ); //paints Ball

}
}


Paddle Class (defines paddle object)


import java.awt.*;

public class Paddle extends Brick implements Paintable { //paddle has properties of brick object
public Color color;
public int paddle_speed;
public Paddle(int x, int y, int width, int height){
super(x, y, width, height); //send parameters to brick
color = Color.yellow;


}

public void movePaddle(){ //moves paddle
x += paddle_speed;

if(x <= 2){
x = 2;
}
if(x+width >= 798){
x = 798-width;
}
}
public void paddleSet(){ //resets paddle to start location
x = 400-(width/2);
y = 600-(height+5);
}


@Override
public void paint(Graphics2D g){
g.setColor(color); //sets color of paddle
g.fillRect(x, y, width, height); //paints paddle
}
}


Paintable Interface (makes my objects paintable)



import java.awt.*;
public interface Paintable { //makes my bricks, ball, and paddle paintable
public void paint(Graphics2D g);
}

Share this post


Link to post
Share on other sites
Advertisement
GameSetup shouldn't be recursive. I'm guessing you are doing it to make all the bricks, but you're actually making all the bricks and reinitializing the paddle and ball for every brick you make. You should have a make bricks function that is just a loop (NOT RECURSIVE) that makes all the bricks and just call that function in your gamesetup function.


for (int y=1; ++y; y<6)
{
for(int x=1; ++x; x<8)
{
int w = 78;
int h = 30;
Brick n = new Brick(x*(w+2),y*(h+2), w, h);
Game.bricks.add(n);
}
}

Share this post


Link to post
Share on other sites

GameSetup shouldn't be recursive. I'm guessing you are doing it to make all the bricks, but you're actually making all the bricks and reinitializing the paddle and ball for every brick you make. You should have a make bricks function that is just a loop (NOT RECURSIVE) that makes all the bricks and just call that function in your gamesetup function.


for (int y=1; ++y; y<6)
{
for(int x=1; ++x; x<8)
{
int w = 78;
int h = 30;
Brick n = new Brick(x*(w+2),y*(h+2), w, h);
Game.bricks.add(n);
}
}



Thanks, was just trying to play around with recursion a bit. Didn't think about the fact that it was reinitializing of the paddle and ball every brick.

Share this post


Link to post
Share on other sites

[quote name='way2lazy2care' timestamp='1322670330' post='4889113']
GameSetup shouldn't be recursive. I'm guessing you are doing it to make all the bricks, but you're actually making all the bricks and reinitializing the paddle and ball for every brick you make. You should have a make bricks function that is just a loop (NOT RECURSIVE) that makes all the bricks and just call that function in your gamesetup function.


for (int y=1; ++y; y<6)
{
for(int x=1; ++x; x<8)
{
int w = 78;
int h = 30;
Brick n = new Brick(x*(w+2),y*(h+2), w, h);
Game.bricks.add(n);
}
}



Thanks, was just trying to play around with recursion a bit. Didn't think about the fact that it was reinitializing of the paddle and ball every brick.
[/quote]
If you want to do recursion you can make the bricks recursively without the paddle/ball, but this is one case where I wouldn't recommend it.

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

GameDev.net is your game development community. Create an account for your GameDev Portfolio and participate in the largest developer community in the games industry.

Sign me up!