Saturday 6 August 2016

Tetris Game program in java

import java.awt.*;
import java.applet.*;
import java.awt.event.*;
import java.util.Random;
import java.net.URL;
import java.net.MalformedURLException;

public class Tetris extends Applet {

//
// STATIC MEMBERS
//

private final static int INITIAL_DELAY = 1000;
private final static byte ROWS = 18;
private final static byte COLUMNS = 10;
private final static int EMPTY = -1;
private final static int DELETED_ROWS_PER_LEVEL = 5;
private final static Color PIECE_COLORS[] = {
new Color(0xFF00FF), // fucia
new Color(0xDC143C), // crimson
new Color(0x00CED1), // dark turquoise
new Color(0xFFD700), // gold
new Color(0x32CD32), // lime green
new Color(0x008080), // teal
new Color(0xFFA500), // orange
};
private final static Color BACKGROUND_COLORS[] = {
new Color(0xFFDAB9), // peachpuff
new Color(0xFFC0CB), // pink
new Color(0xFF99CC), // hot pink
new Color(0x0099CC), // sky blue
new Color(0x9966CC), // lavender
};
private final static Color BACKGROUND_COLOR = new Color(0x99FFCC);

//   *    **   *    *    *    *
//   *    *    *    **   **   **   **
//   *    *    **    *   *    *    **
//   *
//   0    1    2    3    4    5    6  
private final static boolean PIECE_BITS[][][] = {
{
{false, true, false, false},
{false, true, false, false},
{false, true, false, false},
{false, true, false, false},
},
{
{false, false, false, false},
{false, true, true, false},
{false, true, false, false},
{false, true, false, false},
},
{
{false, false, false, false},
{false, true, false, false},
{false, true, false, false},
{false, true, true, false},
},
{
{false, false, false, false},
{false, true, false, false},
{false, true, true, false},
{false, false, true, false},
},
{
{false, false, false, false},
{false, false, true, false},
{false, true, true, false},
{false, true, false, false},
},
{
{false, false, false, false},
{false, true, false, false},
{false, true, true, false},
{false, true, false, false},
},
{
{false, false, false, false},
{false, false, false, false},
{false, true, true, false},
{false, true, true, false},
},
};
private static boolean tmp_grid[][] = new boolean[4][4]; // scratch space
private static Random random = new Random();

private static class TetrisLabel extends Label {
private final static Font LABEL_FONT = new Font("Serif", Font.BOLD, 18);
private TetrisLabel(String text) {
super(text);
setFont(LABEL_FONT);
}
private void addValue(int val) {
setText(Integer.toString((Integer.parseInt(getText())) + val ));
}
}

//
// INSTANCE DATA
//

private int grid[][] = new int[ROWS][COLUMNS];
private int next_piece_grid[][] = new int[4][4];
private int num_rows_deleted = 0;
private GridCanvas game_grid = new GridCanvas(grid, true);
private GridCanvas next_piece_canvas = new GridCanvas(next_piece_grid, false);
private Timer timer;
private TetrisPiece cur_piece;
private TetrisPiece next_piece = randomPiece();
private TetrisSound sounds;// = new TetrisSound(this);
private TetrisLabel rows_deleted_label = new TetrisLabel("0");
private TetrisLabel level_label = new TetrisLabel("1");
private TetrisLabel score_label = new TetrisLabel("0");
private TetrisLabel high_score_label = new TetrisLabel("");
final Button start_newgame_butt = new TetrisButton("Start");
final Button pause_resume_butt = new TetrisButton("Pause");

//
// INNER CLASSES
//

private class TetrisButton extends Button {
public TetrisButton(String label) {
super(label);
}
public Dimension getPreferredSize() {
return new Dimension(120, super.getPreferredSize().height);
}
}

private class TetrisPiece {
private boolean squares[][];
private int type;
private Point position = new Point(3, -4); // -4 to start above top row
public int getX() { return position.x; }
public int getY() { return position.y; }
public void setX(int newx) { position.x = newx; }
public void setY(int newy) { position.y = newy; }
public void setPosition(int newx, int newy) { setX(newx); setY(newy); }

public TetrisPiece(int type) {
this.type = type;
this.squares = new boolean[4][4];
for(int i=0; i<4; i++)
for(int j=0; j<4; j++)
this.squares[i][j] = PIECE_BITS[type][i][j];
}

public boolean canStepDown() {
synchronized(timer) {
cut();
position.y++;
boolean OK = canPaste();
position.y--;
paste();
return OK;
}
}

public boolean canPaste() {
for(int i=0; i<4; i++) {
for(int j=0; j<4; j++) {
int to_x = j + position.x;
int to_y = i + position.y;
if(squares[i][j]) { // piece contains this square?
if(0 > to_x || to_x >= COLUMNS // square too far left or right?
|| to_y >= ROWS) // square off bottom?
{
return false;
// note: it's always considered OK to paste a square
// *above* the grid though attempting to do so does nothing.
// This allows the user to move a piece before it drops
// completely into view.
}
if(to_y >= 0 && grid[to_y][to_x] != EMPTY)
return false;
}
}
}
return true;
}

public void stepDown() {
position.y++;
}

public void cut() {
for(int i=0; i<4; i++)
for(int j=0; j<4; j++)
if(squares[i][j] && position.y+i>=0)
grid[position.y + i][position.x + j] = EMPTY;
}

/**
* Paste the color info of this piece into the given grid
*/
public void paste(int into[][]) {
for(int i=0; i<4; i++)
for(int j=0; j<4; j++)
if(squares[i][j] && position.y+i>=0)
into[position.y + i][position.x + j] = type;
}

/**
* No argument version assumes pasting into main game grid
*/
public void paste() {
paste(grid);
}

public void rotate() {
// copy the piece's data into a temp array
for(int i=0; i<4; i++)
for(int j=0; j<4; j++)
tmp_grid[i][j] = squares[i][j];
// copy back rotated 90 degrees
for(int i=0; i<4; i++)
for(int j=0; j<4; j++)
squares[j][i] = tmp_grid[i][3-j];
}
public void rotateBack() {
// copy originally saved version back
// this of course assumes this call was preceeded by
// a call to rotate() for the same piece
for(int i=0; i<4; i++)
for(int j=0; j<4; j++)
squares[i][j] = tmp_grid[i][j];
}

// this method is a bit of a hack to check for the case
// where a piece may be safely on the grid but have one or more
// rows of empty squares that are above the grid and therefore OK
public boolean isTotallyOnGrid() {
for(int i=0; i<4; i++) {
if(position.y + i >= 0)
return true; //everything from here down is on grid
// this row is above grid so look for non-empty squares
for(int j=0; j<4; j++)
if(squares[i][j])
return false;
}
System.err.println("TetrisPiece.isTotallyOnGrid internal error");
return false;
}
} // end class TetrisPiece


private class Timer extends Thread {
private long m_delay;
private boolean m_paused = true;
private boolean m_fast = false;
private ActionListener m_cb;
public Timer(long delay, ActionListener cb) {
setDelay(delay);
m_cb = cb;
}
public void setPaused(boolean pause) {
m_paused = pause;
if(m_paused) {
sounds.stopSoundtrack();
}
else {
sounds.playSoundtrack();
synchronized(this) {
this.notify();
}
}
}
public boolean isPaused() { return m_paused; }
public void setDelay(long delay) { m_delay = delay; }
public boolean isRunning() { return !m_paused; }
public void setFast(boolean fast) {
m_fast = fast;
if(m_fast) {
try {
this.checkAccess();
this.interrupt(); // no exception, so OK to interrupt
} catch(SecurityException se) {}
}
}
public boolean isFast() { return m_fast; }
public void faster() {
m_delay = (int)(m_delay * .9); //increase the speed exponentially in reverse
}
public void run() {
while(true) {
try {
sleep(m_fast ? 30 : m_delay);
} catch (Exception e) {}
if(m_paused) {
try {
synchronized(this) {
this.wait();
}
} catch(InterruptedException ie) {}
}
synchronized(this) {
m_cb.actionPerformed(null);
}
}
}
} // end class Timer

private class GridCanvas extends DoubleBufferedCanvas {
private int grid[][];
private boolean paint_background;
public GridCanvas(int[][] grid, boolean do_background) {
this.grid = grid;
paint_background = do_background;
clear();
}

private void clear() {
for(int i=0; i<grid.length; i++)
for(int j=0; j<grid[0].length; j++)
grid[i][j] = EMPTY;
}
public Dimension getPreferredSize() {
return new Dimension(grid[0].length * 30, grid.length * 30);
}
public void paint(Graphics g) {
g = this.startPaint(g); // returned g paints into offscreen image
int width = this.getSize().width;
int height = this.getSize().height;
g.clearRect(0, 0, width, height);
int cell_size, xstart, ystart;
double panel_aspect_ratio = (double)width/height;
double grid_aspect_ratio = (double)grid[0].length/grid.length;
if(panel_aspect_ratio > grid_aspect_ratio) {
// extra space on sides
cell_size = (int)((double)height/grid.length + 0.5);
xstart = (int)(width/2 - (grid[0].length/2.0 * cell_size + 0.5));
ystart = 0;
}
else {
// extra vertical space
cell_size = (int)((double)width/grid[0].length + 0.5);
xstart = 0;
ystart = (int)(height/2 - (grid.length/2.0 * cell_size + 0.5));
}
if(paint_background) {
g.setColor(BACKGROUND_COLORS[(num_rows_deleted / DELETED_ROWS_PER_LEVEL) % BACKGROUND_COLORS.length]);
g.fillRect(xstart, ystart, COLUMNS*cell_size, ROWS*cell_size);
}
for(int i=0; i<grid.length; i++) {
for(int j=0; j<grid[0].length; j++) {
if(grid[i][j] != EMPTY) {
g.setColor(PIECE_COLORS[grid[i][j]]);
int x = xstart + j*cell_size;
int y = ystart + i*cell_size;
g.fill3DRect(x, y, cell_size, cell_size, true);
}
}
}
this.endPaint(); // paints accumulated image in one shot
}
} // end class GridCanvas

private class TetrisSound {
private AudioClip soundTrack = null;
private AudioClip destroyRowSounds[] = new AudioClip[4];
private AudioClip gameOverSound = null;
private AudioClip getClip(String name) throws MalformedURLException {
URL soundFileUrl = new URL(getCodeBase(), name);
try {
AudioClip clip = getAudioClip(soundFileUrl);
return clip;
} catch(NullPointerException npe) {
System.err.println("exception " + npe);
return null;
}
}
public TetrisSound() {
//load sound files
try {
soundTrack          = getClip("theme.au");
destroyRowSounds[0] = getClip("quiteImpressive.au");
destroyRowSounds[1] = getClip("smashing.au");
destroyRowSounds[2] = getClip("yeahbaby.au");
destroyRowSounds[3] = getClip("great.au");
gameOverSound       = getClip("groovy.au");
}
catch (Exception e) {
System.err.println(e.getMessage());
}
}
public void playSoundtrack() {
if(soundTrack == null)
return;
soundTrack.loop();
}
public void playDestroyRows(int rows) {
int soundid = rows - 1;
if(0 > soundid || soundid >= destroyRowSounds.length || destroyRowSounds[soundid] == null)
return;
destroyRowSounds[soundid].play();
}
public void playGameOverSound() {
if(gameOverSound == null)
return;
gameOverSound.play();
}
public void stopSoundtrack() {
if(soundTrack == null)
return;
soundTrack.stop();
}
} // end class TetrisSound


//
// INSTANCE METHODS
//

private TetrisPiece randomPiece() {
int rand = Math.abs(random.nextInt());
return new TetrisPiece(rand % (PIECE_COLORS.length));
}

private void installNewPiece() {
next_piece_canvas.clear();
cur_piece = next_piece;
cur_piece.setPosition(3, -4); //-4 to start above top of grid
if(cur_piece.canPaste()) {
next_piece = randomPiece();
next_piece.setPosition(0, 0);
next_piece.paste(next_piece_grid);
next_piece_canvas.repaint();
}
else
gameOver();
}

private void gameOver() {
System.out.println("Game Over!");
timer.setPaused(true);
pause_resume_butt.setEnabled(false);
int score = Integer.parseInt(score_label.getText());
int high_score = high_score_label.getText().length() > 0 ?
Integer.parseInt(high_score_label.getText()) : 0;
if(score > high_score)
high_score_label.setText("" + score);
sounds.playGameOverSound();
}

private boolean rowIsFull(int row) {
for(int i=0; i<COLUMNS; i++)
if(grid[row][i] == EMPTY)
return false;
return true;
}

private int countFullRows() {
int n_full_rows = 0;
for(int i=0; i<ROWS; i++)
if(rowIsFull(i))
n_full_rows++;
return n_full_rows;
}

private void removeRow(int row) {
for(int j=0; j<COLUMNS; j++)
grid[row][j] = EMPTY;
for(int i=row; i>0; i--) {
for(int j=0; j<COLUMNS; j++) {
grid[i][j] = grid[i-1][j];
}
}
}

private void removeFullRows() {
int n_full = countFullRows();
score_label.addValue((int)(10 * Math.pow(2, n_full) - 10)); //give points exponentially
if(n_full == 0)
return;
sounds.playDestroyRows(n_full);
if(num_rows_deleted / DELETED_ROWS_PER_LEVEL != (num_rows_deleted+n_full) / DELETED_ROWS_PER_LEVEL) {
timer.faster();
level_label.addValue(n_full / DELETED_ROWS_PER_LEVEL + 1);
level_label.repaint();
}
rows_deleted_label.addValue(n_full);
num_rows_deleted += n_full;
for(int i=ROWS-1; i>=0; i--)
while(rowIsFull(i))
removeRow(i);
game_grid.repaint();
}

public void start() {
timer = new Timer(INITIAL_DELAY, new ActionListener() {
public void actionPerformed(ActionEvent ae) {
synchronized(timer) {
if(cur_piece.canStepDown()) {
cur_piece.cut();
cur_piece.stepDown();
cur_piece.paste();
if(timer.isFast())
score_label.addValue(1); // a small reward for using fast mode
}
else { // it hit something
timer.setFast(false);
if( ! cur_piece.isTotallyOnGrid())
gameOver();
else {
removeFullRows();
installNewPiece();
}
}
}
game_grid.repaint();
}
});
timer.start(); // pauses immediately
}

public void stop() {
pauseGame();
synchronized(timer){
timer.stop();
}
timer = null;
}

private void startGame() {
timer.setDelay(INITIAL_DELAY);
timer.setPaused(false);
start_newgame_butt.setLabel("Start New Game");
pause_resume_butt.setEnabled(true); // stays enabled from here on
pause_resume_butt.setLabel("Pause");
pause_resume_butt.validate();
sounds.playSoundtrack();
}

private void newGame() {
game_grid.clear();
installNewPiece();
num_rows_deleted = 0;
rows_deleted_label.setText("0");
level_label.setText("1");
score_label.setText("0");
startGame();
}

private void pauseGame() {
timer.setPaused(true);
pause_resume_butt.setLabel("Resume");
sounds.stopSoundtrack();
}

private void resumeGame() {
timer.setPaused(false);
pause_resume_butt.setLabel("Pause");
sounds.playSoundtrack();
}

public void init() {
sounds = new TetrisSound(); // NOTE: Must be initialized after Applet fully constructed!
installNewPiece();

pause_resume_butt.setEnabled(false);
start_newgame_butt.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent ae) {
if(start_newgame_butt.getLabel().equals("Start"))
startGame();
else
newGame();
}
});
pause_resume_butt.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent ae) {
if(pause_resume_butt.getLabel().equals("Pause"))
pauseGame();
else
resumeGame();
}
});

//create key listener for rotating, moving left, moving right
KeyListener key_listener = new KeyAdapter() {
public void keyPressed(KeyEvent e) {
if(timer.isPaused()) //don't do anything if game is paused
return;
if (e.getKeyCode() == 37 || e.getKeyCode() == 39) { //left or right arrow pressed
int dir = e.getKeyCode() == 37 ? -1 : 1;
synchronized(timer) {
cur_piece.cut();
cur_piece.setX(cur_piece.getX() + dir); // try to move
if( ! cur_piece.canPaste())
cur_piece.setX(cur_piece.getX() - dir); // undo move
cur_piece.paste();
}
game_grid.repaint();
}
else if (e.getKeyCode() == 38) { //rotate
synchronized(timer) {
cur_piece.cut();
cur_piece.rotate();
if( ! cur_piece.canPaste())
cur_piece.rotateBack();
cur_piece.paste();
}
game_grid.repaint();
}
if (e.getKeyCode() == 40) { //down arrow pressed; drop piece
timer.setFast(true);
}
}
};

// add the key listener to all components that might get focus
// so that it'll work regardless of which has focus
start_newgame_butt.addKeyListener(key_listener);
pause_resume_butt.addKeyListener(key_listener);

Panel right_panel = new Panel(new GridLayout(3, 1));
right_panel.setBackground(BACKGROUND_COLOR);

Panel control_panel = new Panel();
control_panel.add(start_newgame_butt);
control_panel.add(pause_resume_butt);
control_panel.setBackground(BACKGROUND_COLOR);
right_panel.add(control_panel);

Panel tmp = new Panel(new BorderLayout());
tmp.add("North", new TetrisLabel("    Next Piece:"));
tmp.add("Center", next_piece_canvas);
tmp.setBackground(BACKGROUND_COLOR);
right_panel.add(tmp);

Panel stats_panel = new Panel(new GridLayout(4, 2));
stats_panel.add(new TetrisLabel("    Rows Deleted: "));
stats_panel.add(rows_deleted_label);
stats_panel.add(new TetrisLabel("    Level: "));
stats_panel.add(level_label);
stats_panel.add(new TetrisLabel("    Score: "));
stats_panel.add(score_label);
stats_panel.add(new TetrisLabel("    High Score: "));
stats_panel.add(high_score_label);
tmp = new Panel(new BorderLayout());
tmp.setBackground(BACKGROUND_COLOR);
tmp.add("Center", stats_panel);
right_panel.add(tmp);

// finaly, add all the main panels to the applet panel
this.setLayout(new GridLayout(1, 2));
this.add(game_grid);
this.add(right_panel);
this.setBackground(BACKGROUND_COLOR);
this.validate();
}


public static void main(String[] args) {

Frame frame = new Frame("Tetris");
Tetris tetris = new Tetris();
frame.add(tetris);
tetris.init();
tetris.start();

frame.addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent e) {
System.exit(0);
}
});

frame.setSize(489, 441);
frame.setResizable(false);
frame.setVisible(true);
}
} // end class Tetris


class DoubleBufferedCanvas extends Canvas {
private Image mActiveOffscreenImage = null;
private Dimension mOffscreenSize = new Dimension(-1,-1);
private Graphics mActiveOffscreenGraphics = null;
private Graphics mSystemGraphics = null;

DoubleBufferedCanvas() {
/*
this.addComponentListener(new ComponentAdapter() {
public void componentResized(ComponentEvent e) {
repaint();
}
});*/
}

  /**
  * NOTE: when extending applets:
* this overrides update() to *not* erase the background before painting
*/
public void update(Graphics g) {
paint(g);
}

public Graphics startPaint (Graphics sysgraph) {
mSystemGraphics = sysgraph;
// Initialize if this is the first pass or the size has changed
Dimension d = getSize();
if ((mActiveOffscreenImage == null) ||
(d.width != mOffscreenSize.width) ||
(d.height != mOffscreenSize.height))
{
mActiveOffscreenImage = createImage(d.width, d.height);
mActiveOffscreenGraphics = mActiveOffscreenImage.getGraphics();
mOffscreenSize = d;
mActiveOffscreenGraphics.setFont(getFont());
}
//mActiveOffscreenGraphics.clearRect(0, 0, mOffscreenSize.width, mOffscreenSize.height);
return mActiveOffscreenGraphics;
}

public void endPaint () {
// Start copying the offscreen image to this canvas
// The application will begin drawing into the other one while this happens
mSystemGraphics.drawImage(mActiveOffscreenImage, 0, 0, null);
}
}


Brick and Ball Game in Java

//Commons.java-------------------------------------start
public interface Commons {
   
    public static final int WIDTH = 300;
    public static final int HEIGTH = 400;
    public static final int BOTTOM_EDGE = 390;
    public static final int N_OF_BRICKS = 30;
    public static final int INIT_PADDLE_X = 200;
    public static final int INIT_PADDLE_Y = 360;
    public static final int INIT_BALL_X = 230;
    public static final int INIT_BALL_Y = 355;  
    public static final int DELAY = 1000;
    public static final int PERIOD = 10;
}


//Breakout.java---------------------------------------------1
import java.awt.EventQueue;
import javax.swing.JFrame;

public class Breakout extends JFrame {

    public Breakout() {
       
        initUI();
    }
   
    private void initUI() {
       
        add(new Board());
        setTitle("Breakout");
       
        setDefaultCloseOperation(EXIT_ON_CLOSE);
        setSize(Commons.WIDTH, Commons.HEIGTH);
        setLocationRelativeTo(null);
        setResizable(false);
        setVisible(true);
    }

    public static void main(String[] args) {
       
        EventQueue.invokeLater(new Runnable() {
           
            public void run() {              
                Breakout game = new Breakout();
                game.setVisible(true);              
            }
        });
    }
}

//Ball.java----------------------------------------------------------2
import javax.swing.ImageIcon;

public class Ball extends Sprite implements Commons {

    private int xdir;
    private int ydir;

    public Ball() {

        xdir = 1;
        ydir = -1;

        ImageIcon ii = new ImageIcon("ball.png");
        image = ii.getImage();

        i_width = image.getWidth(null);
        i_heigth = image.getHeight(null);

        resetState();
    }

    public void move() {
       
        x += xdir;
        y += ydir;

        if (x == 0) {
            setXDir(1);
        }

        if (x == WIDTH - i_width) {
            setXDir(-1);
        }

        if (y == 0) {
            setYDir(1);
        }
    }

    private void resetState() {
       
        x = INIT_BALL_X;
        y = INIT_BALL_Y;
    }

    public void setXDir(int x) {
        xdir = x;
    }

    public void setYDir(int y) {
        ydir = y;
    }

    public int getYDir() {
        return ydir;
    }
}

//Board.java--------------------------------------------------------------3
import java.awt.Color;
import java.awt.Font;
import java.awt.FontMetrics;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.RenderingHints;
import java.awt.Toolkit;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.util.Timer;
import java.util.TimerTask;
import javax.swing.JPanel;

public class Board extends JPanel implements Commons {

    private Timer timer;
    private String message = "Game Over";
    private Ball ball;
    private Paddle paddle;
    private Brick bricks[];
    private boolean ingame = true;

    public Board() {

        initBoard();
    }

    private void initBoard() {

        addKeyListener(new TAdapter());
        setFocusable(true);

        bricks = new Brick[N_OF_BRICKS];
        setDoubleBuffered(true);
        timer = new Timer();
        timer.scheduleAtFixedRate(new ScheduleTask(), DELAY, PERIOD);
    }

    @Override
    public void addNotify() {

        super.addNotify();
        gameInit();
    }

    private void gameInit() {

        ball = new Ball();
        paddle = new Paddle();

        int k = 0;
        for (int i = 0; i < 5; i++) {
            for (int j = 0; j < 6; j++) {
                bricks[k] = new Brick(j * 40 + 30, i * 10 + 50);
                k++;
            }
        }
    }

    @Override
    public void paintComponent(Graphics g) {
        super.paintComponent(g);

        Graphics2D g2d = (Graphics2D) g;

        g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
                RenderingHints.VALUE_ANTIALIAS_ON);

        g2d.setRenderingHint(RenderingHints.KEY_RENDERING,
                RenderingHints.VALUE_RENDER_QUALITY);

        if (ingame) {
           
            drawObjects(g2d);
        } else {

            gameFinished(g2d);
        }

        Toolkit.getDefaultToolkit().sync();
    }
   
    private void drawObjects(Graphics2D g2d) {
       
        g2d.drawImage(ball.getImage(), ball.getX(), ball.getY(),
                ball.getWidth(), ball.getHeight(), this);
        g2d.drawImage(paddle.getImage(), paddle.getX(), paddle.getY(),
                paddle.getWidth(), paddle.getHeight(), this);

        for (int i = 0; i < N_OF_BRICKS; i++) {
            if (!bricks[i].isDestroyed()) {
                g2d.drawImage(bricks[i].getImage(), bricks[i].getX(),
                        bricks[i].getY(), bricks[i].getWidth(),
                        bricks[i].getHeight(), this);
            }
        }
    }
   
    private void gameFinished(Graphics2D g2d) {

        Font font = new Font("Verdana", Font.BOLD, 18);
        FontMetrics metr = this.getFontMetrics(font);

        g2d.setColor(Color.BLACK);
        g2d.setFont(font);
        g2d.drawString(message,
                (Commons.WIDTH - metr.stringWidth(message)) / 2,
                Commons.WIDTH / 2);
    }

    private class TAdapter extends KeyAdapter {

        @Override
        public void keyReleased(KeyEvent e) {
            paddle.keyReleased(e);
        }

        @Override
        public void keyPressed(KeyEvent e) {
            paddle.keyPressed(e);
        }
    }

    private class ScheduleTask extends TimerTask {

        @Override
        public void run() {

            ball.move();
            paddle.move();
            checkCollision();
            repaint();
        }
    }

    private void stopGame() {

        ingame = false;
        timer.cancel();
    }

    private void checkCollision() {

        if (ball.getRect().getMaxY() > Commons.BOTTOM_EDGE) {
            stopGame();
        }

        for (int i = 0, j = 0; i < N_OF_BRICKS; i++) {
           
            if (bricks[i].isDestroyed()) {
                j++;
            }
           
            if (j == N_OF_BRICKS) {
                message = "Victory";
                stopGame();
            }
        }

        if ((ball.getRect()).intersects(paddle.getRect())) {

            int paddleLPos = (int) paddle.getRect().getMinX();
            int ballLPos = (int) ball.getRect().getMinX();

            int first = paddleLPos + 8;
            int second = paddleLPos + 16;
            int third = paddleLPos + 24;
            int fourth = paddleLPos + 32;

            if (ballLPos < first) {
                ball.setXDir(-1);
                ball.setYDir(-1);
            }

            if (ballLPos >= first && ballLPos < second) {
                ball.setXDir(-1);
                ball.setYDir(-1 * ball.getYDir());
            }

            if (ballLPos >= second && ballLPos < third) {
                ball.setXDir(0);
                ball.setYDir(-1);
            }

            if (ballLPos >= third && ballLPos < fourth) {
                ball.setXDir(1);
                ball.setYDir(-1 * ball.getYDir());
            }

            if (ballLPos > fourth) {
                ball.setXDir(1);
                ball.setYDir(-1);
            }
        }

        for (int i = 0; i < N_OF_BRICKS; i++) {
           
            if ((ball.getRect()).intersects(bricks[i].getRect())) {

                int ballLeft = (int) ball.getRect().getMinX();
                int ballHeight = (int) ball.getRect().getHeight();
                int ballWidth = (int) ball.getRect().getWidth();
                int ballTop = (int) ball.getRect().getMinY();

                Point pointRight = new Point(ballLeft + ballWidth + 1, ballTop);
                Point pointLeft = new Point(ballLeft - 1, ballTop);
                Point pointTop = new Point(ballLeft, ballTop - 1);
                Point pointBottom = new Point(ballLeft, ballTop + ballHeight + 1);

                if (!bricks[i].isDestroyed()) {
                    if (bricks[i].getRect().contains(pointRight)) {
                        ball.setXDir(-1);
                    } else if (bricks[i].getRect().contains(pointLeft)) {
                        ball.setXDir(1);
                    }

                    if (bricks[i].getRect().contains(pointTop)) {
                        ball.setYDir(1);
                    } else if (bricks[i].getRect().contains(pointBottom)) {
                        ball.setYDir(-1);
                    }

                    bricks[i].setDestroyed(true);
                }
            }
        }
    }
}

//Brick.java-------------------------------------------------------------------4
import javax.swing.ImageIcon;

public class Brick extends Sprite {

    private boolean destroyed;

    public Brick(int x, int y) {
       
        this.x = x;
        this.y = y;

        ImageIcon ii = new ImageIcon("brick.png");
        image = ii.getImage();

        i_width = image.getWidth(null);
        i_heigth = image.getHeight(null);

        destroyed = false;
    }

    public boolean isDestroyed() {
       
        return destroyed;
    }

    public void setDestroyed(boolean val) {
       
        destroyed = val;
    }
}

//Paddle.java--------------------------------------------------------5
import java.awt.event.KeyEvent;
import javax.swing.ImageIcon;

public class Paddle extends Sprite implements Commons {

    private int dx;

    public Paddle() {

        ImageIcon ii = new ImageIcon("paddle.png");
        image = ii.getImage();

        i_width = image.getWidth(null);
        i_heigth = image.getHeight(null);

        resetState();
    }

    public void move() {

        x += dx;

        if (x <= 0) {
            x = 0;
        }

        if (x >= WIDTH - i_width) {
            x = WIDTH - i_width;
        }
    }

    public void keyPressed(KeyEvent e) {

        int key = e.getKeyCode();

        if (key == KeyEvent.VK_LEFT) {
            dx = -1;
        }

        if (key == KeyEvent.VK_RIGHT) {
            dx = 1;
        }
    }

    public void keyReleased(KeyEvent e) {

        int key = e.getKeyCode();

        if (key == KeyEvent.VK_LEFT) {
            dx = 0;
        }

        if (key == KeyEvent.VK_RIGHT) {
            dx = 0;
        }
    }

    private void resetState() {

        x = INIT_PADDLE_X;
        y = INIT_PADDLE_Y;
    }
}

//Sprite.java--------------------------------------------------------------6
import java.awt.Image;
import java.awt.Rectangle;

public class Sprite {

    protected int x;
    protected int y;
    protected int i_width;
    protected int i_heigth;
    protected Image image;

    public void setX(int x) {
        this.x = x;
    }

    public int getX() {
        return x;
    }

    public void setY(int y) {
        this.y = y;
    }

    public int getY() {
        return y;
    }

    public int getWidth() {
        return i_width;
    }

    public int getHeight() {
        return i_heigth;
    }

    Image getImage() {
        return image;
    }

    Rectangle getRect() {
        return new Rectangle(x, y,
                image.getWidth(null), image.getHeight(null));
    }
}