“This is the 24th day of my participation in the First Challenge 2022. For details: First Challenge 2022”
❤️ Author’s home page: Xiao Xu Zhu
❤️ About the author: Hello everyone, I am Xiao Xu Zhu. Java field quality creator 🏆, CSDN blog expert 🏆, Huawei cloud enjoy expert 🏆, Nuggets of the year popular author 🏆, Ali Cloud expert blogger 🏆
❤️ technology live, the appreciation
❤️ like 👍 collect ⭐ look again, form a habit
preface
JAVA Brick Breaking is a homemade game. The e player operates an on-screen horizontal “stick” so that a constantly bouncing “ball” does not fall to the bottom of the screen on its way to hitting the “brick” removed as a clearance target.
The main design
- Design the game interface, with Swing implementation
- Design brick, brick class,
- Design balls, small balls that run around the screen and break bricks
- Design rods, wood panels that move left and right
- The ball hits the brick, the stick and the bottom of the three sides will bounce, fall to the bottom will lose a ball, all the bricks can be broken.
- Design of callback algorithm for ball hitting brick
- Design of callback algorithm for ball touching rod
- Design collision effects, a class responsible for displaying explosion effects
- Design sound class, sound when collision.
Screenshot function
The game begins:
Collision effect:
Code implementation
Game Core
public class BricksGame extends BaseGame {
private ArrayList<GameObject> list = new ArrayList<>();
private RenderTask render;
private Random random = new Random();
private boolean over;
private Image memImage;
private Graphics memG;// Double buffered canvas
public BricksGame(int width, int height, String title) throws HeadlessException {
super(width, height, title);
super.setBgColor(new Color(0x23.0x30.0x41));
initGame(width, height);
}
private void initGame(int width, int height) {
setFps(60);
over=false;
// Get the inside and outside size of the window
Container contentPane = this.getContentPane();
Dimension size = contentPane.getSize();
int contentWidth = size.width;
int contentHeight = size.height;
this.setContentWidth(contentWidth);
this.setContentHeight(contentHeight);
//System.out.println(contentPane instanceof JPanel); // true
//System.out.println(size.width); / / 582
//System.out.println(size.height); / / 403
// The boundary values of the four directions of the window
Insets insets = getInsets();
//System.out.println(insets.top);
//System.out.println(insets.bottom);
//System.out.println(insets.left);
//System.out.println(insets.right);
Scene env = new Scene(width, height, new Margin(insets.left, insets.right, insets.top, insets.bottom));
ImageIcon woodIcon = new ImageIcon("image/wood.png");
int w = woodIcon.getIconWidth();
int h = woodIcon.getIconHeight();
Wood wood = new Wood(w, h, new Color(0x97.0x5B.0x12));
wood.setScene(env);
wood.setX(getWidth()/2 - w/2);
wood.setY(getHeight()-50);
wood.setImage(woodIcon.getImage());
list.add(wood);
Ball ball = new Ball(10, Color.WHITE);
ImageIcon iconBall = new ImageIcon("image/ball2.png");
ball.setImage(iconBall.getImage());
ball.setScene(env);
ball.setCoordinator(width / 2 - ball.getRadius(), wood.getY()-ball.getRadius()*2);
ball.setWoodBar(wood);
list.add(ball);
Color[] colors = new Color[]{
new Color(0xAA.0xCF.0x51),
new Color(0xFC.0xA9.0x4B),
new Color(0x73.0xC7.0xFF),
Color.PINK,
Color.GRAY
};
//ImageIcon brickIcon = new ImageIcon("image/brick_1.png");
int brW = 60;
int brH = 30;
int start = 25;
int brickX = start;
int brickY = 100;
int brickAreaWidth = getWidth() - start *2;
int count = brickAreaWidth / brW - 1;
int remainWidth = brickAreaWidth - count * brW;
int intervalHort = brW + 3;
start = brickX = (getWidth() - intervalHort * (count)) / 2;
int intervalVert = brH + 3;
HitBrick hitBrick = new HitBrick();
for (int j = 0; j < 3; j++) {// brick line
for(int i = 0; i< count; i++){// brick columns
Brick brick = new Brick();
brick.setColor(colors[i % colors.length]);
//brick.setImage(brickIcon.getImage());
brick.setWidth(brW);
brick.setHeight(brH);
brick.setX(brickX);
brick.setY(brickY);
brick.setBall(ball);
brick.setHitListener(hitBrick);
brickX += intervalHort;
list.add(brick);
}
brickX = start;
brickY += intervalVert;
}
// Double buffering, create an Image in memory the same size as the window JFrame
memImage = createImage(getWidth(), getHeight());
memG = memImage.getGraphics();
GameOver gameOver = new GameOver(memG);
ball.setGameOverListener(gameOver);
// Listen for keyboard events
Input input = new Input();
input.init();
addKeyListener(input);
// Re-render the screen task
render = new RenderTask(this);
render.start();
addMouseListener(new MouseAdapter() {
@Override
public void mousePressed(MouseEvent e) {
//super.mousePressed(e);
System.out.println(String.format("x:%d, y:%d", e.getX(), e.getY()));
//x:218,y:305,w:164,h:45
if ((e.getX() >= 218 && e.getX() <=(218+164))
&& (e.getY() >= 305 && e.getY() <= (305+45))
){
render.setExitd(true);
render = null;
memImage = null;
memG = null;
removeKeyListener(input);
removeMouseListener(this); list.clear(); initGame(width, height); }}}); }@Override
public void paint(Graphics g) {
clear(memG);// Clear the canvas to a background color
for (int i = 0; i < list.size(); i++) {
list.get(i).onTick();
list.get(i).draw(memG);
}
if (list.size() == 2) {// Only the ball and the baffle are left, then the level is successful!
Wood wood = (Wood) list.get(0);
wood.setX(getWidth()/2 - wood.getWidth()/2);
wood.setY(getHeight()-50);
Ball ball = (Ball) list.get(1);
ball.setCoordinator(getWidth() / 2 - ball.getRadius(), /*bottom*/wood.getY()-ball.getRadius()*2);
ball.setMoving(false);
String gameOver = "Congratulations on getting through!;
memG.setFont(new Font("Serif", Font.BOLD, 35));
int stringWidth = memG.getFontMetrics().stringWidth(gameOver);
memG.setColor(Color.RED);
memG.drawString(gameOver, getWidth()/2 - stringWidth/2, getHeight()/2);
stopRenderTask();
}
if (over) {
String gameOver = "Game Over";
memG.setFont(new Font("Serif", Font.BOLD, 35));
int stringWidth = memG.getFontMetrics().stringWidth(gameOver);
memG.setColor(Color.WHITE);
memG.drawString(gameOver, getWidth()/2 - stringWidth/2, getHeight()/2);
String playAgain = "Start over";
stringWidth = memG.getFontMetrics().stringWidth(playAgain);
int increase = 16;
int fontSize = memG.getFont().getSize();
int rectH = (int) (fontSize * 1.3);
int rx=getWidth()/2 - stringWidth/2 - increase /2;
int ry=getHeight() - fontSize * 4-(rectH-fontSize)/2;
int rw = stringWidth + increase;
int rh = rectH;
//System.out.println(String.format("x:%d,y:%d,w:%d,h:%d", rx, ry, rw, rh));
memG.drawRect(rx, ry, rw, rh);
memG.setColor(new Color(33.165.230));
memG.drawString(playAgain, getWidth()/2 - stringWidth/2, getHeight() - fontSize * 3 - 5);
}
// Copy the contents of the memory Image to the window
g.drawImage(memImage, 0.0.null);
// A performance-intensive polling to determine whether an object is going to disappear
for (int i = 2; i < list.size(); i++) {// the 0,1 position is the baffle and the ball, cannot disappear
GameObject gameObject = list.get(i);
if(gameObject.isGone()) { list.remove(i); --i; }}}private void stopRenderTask(a) {
new Thread(new Runnable() {
@Override
public void run(a) {
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
render.setExitd(true);
}
}).start();
}
public void exit(a){
//System.exit(1);
}
public void clear(Graphics g){
if(g! =null) {
g.setColor(getBgColor());
g.fillRect(0.0, getWidth(), getHeight()); }}// The ball hits the brick's callback
class HitBrick implements Brick.HitListener{
private ExecutorService executorService = Executors.newFixedThreadPool(3);
private File file = new File("audio/brick2.wav");
private AudioClip audio;
public HitBrick(a) {
try {
audio = Applet.newAudioClip(file.toURI().toURL());
} catch(MalformedURLException e) { e.printStackTrace(); }}@Override
public void hit(Brick brick) {
executorService.execute(new PlayHitAudioTask(audio));
ExplodeObject eo = newExplodeObject(); eo.x = brick.x; eo.y = brick.y; eo.width = brick.width; eo.height = brick.height; eo.color = brick.color; list.add(eo); }}// Draw the end of the game
class GameOver implements Ball.GameOverListener{
private Graphics memG;
public GameOver(Graphics g) {
this.memG = g;
}
@Override
public void over(a) {
over = true; }}}Copy the code
A small ball
public class Ball extends RectGameObject{
private int radius;
private int speed = 4;// How fast the ball moves
private boolean moving;// Is it moving
private boolean gameOver;/ / is over
private boolean postv;// Initial horizontal movement left and right
private int horiMove;// Horizontal movement distance (positive and negative signs represent movement direction)
private int vertMove;// Vertical moving distance (positive and negative signs represent moving direction)
private Wood woodBar;/ / wood board
private Image image;
private Point center = new Point();
private GameOverListener l;
public Ball(int radius, Color color){
this.radius = radius;
this.color = color;
}
@Override
public void draw(Graphics g) {
g.setColor(color);
//g.drawImage(image, x, y, null);
g.fillOval(x, y, radius * 2, radius * 2);
}
@Override
public void onTick(a) {
if(! moving){if(Input.getKeyDown(KeyEvent.VK_UP)){
postv = (Math.random() * 10) < =4 ? true : false;
moving = true;
gameOver = false;
horiMove = postv ? speed : -speed;
vertMove = -speed;
} /*else if(Input.getKeyDown(KeyEvent.VK_LEFT)){ Wood wb = woodBar; if (! wb.isReachEdge()) { transferBy(-wb.getSpeed(), 0); } } else if(Input.getKeyDown(KeyEvent.VK_RIGHT)){ Wood wb = woodBar; if (! wb.isReachEdge()) { transferBy(wb.getSpeed(), 0); }} * /
}
if (moving){
// arrive at left and right edge
Scene scene = getScene();
Margin margin = scene.in;
if (x <= margin.left || x >= scene.width - margin.right - radius * 2){
horiMove = -horiMove;
}
// arrive at top edge
if (y <= margin.top && vertMove < 0){
vertMove = -vertMove;
}
// The ball landed on the baffle
if(getCenter().x >= woodBar.getX()
&& getCenter().x <= woodBar.getX() + woodBar.getWidth()
&& Math.abs(getCenter().y - woodBar.y) <= radius
&& vertMove > 0
){
vertMove = -vertMove;
}
// arrive at bottom edge
// The ball falls to the bottom of the window and stops the ball to GAME OVER
if (y >= scene.height - margin.bottom - radius * 2){
moving = false;
gameOver = true;
if(l ! =null)
l.over();
return;
}
this.transferBy(horiMove, vertMove); }}public int getRadius(a) {
return radius;
}
public void setRadius(int radius) {
this.radius = radius;
}
public Wood getWoodBar(a) {
return woodBar;
}
public void setWoodBar(Wood woodBar) {
this.woodBar = woodBar;
}
public Image getImage(a) {
return image;
}
public void setImage(Image image) {
this.image = image;
}
public boolean isMoving(a) {
return moving;
}
public void setMoving(boolean moving) {
this.moving = moving;
}
public int getHoriMove(a) {
return horiMove;
}
public void setHoriMove(int horiMove) {
this.horiMove = horiMove;
}
public int getVertMove(a) {
return vertMove;
}
public void setVertMove(int vertMove) {
this.vertMove = vertMove;
}
@Override
public int getWidth(a) {
return 2 * radius;
}
@Override
public int getHeight(a) {
return getWidth();
}
public Point getCenter(a){
center.x = x + radius;
center.y = y + radius;
return center;
}
public boolean isGameOver(a) {
return gameOver;
}
public void setGameOver(boolean gameOver) {
this.gameOver = gameOver;
}
public GameOverListener getGameOverListener(a) {
return l;
}
public void setGameOverListener(GameOverListener l) {
this.l = l;
}
public interface GameOverListener{
void over(a); }}Copy the code
The brick class
package game;
import java.awt.*;
public class Brick extends RectGameObject {
private Ball ball;
private Point leftTop = new Point();
private Point leftBottom = new Point();
private Point rightTop = new Point();
private Point rightBottom = new Point();
public Brick(a){}
@Override
public void draw(Graphics g) {
g.setColor(getColor());
g.fillRect(x, y, getWidth(), getHeight());
}
@Override
public void onTick(a) {
if (ball.isMoving()) {
/ / start collision detection / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / /
boolean is = isSameQuadrant(ball.getCenter(), getLeftTop(), getRightBottom());
if (is) {
int r = ball.getRadius();
Point lt = getLeftTop();
Point lb = getLeftBottom();
Point rt = getRightTop();
Point rb = getRightBottom();
Point c = ball.getCenter();
int dx1 = Math.abs(c.x - lt.x), dy1 = Math.abs(c.y - lt.y);
int dx2 = Math.abs(c.x - lb.x), dy2 = Math.abs(c.y - lb.y);
int dx3 = Math.abs(c.x - rt.x), dy3 = Math.abs(c.y - rt.y);
int dx4 = Math.abs(c.x - rb.x), dy4 = Math.abs(c.y - rb.y);
if(((dx1*dx1) + (dy1*dy1) <= r*r)
||((dx2*dx2) + (dy2*dy2) <= r*r)
||((dx3*dx3) + (dy3*dy3) <= r*r)
||((dx4*dx4) + (dy4*dy4) <= r*r)){
System.out.println("There was a collision.");
if(hitListener ! =null) {
hitListener.hit(this);
}
setGone(true); }}else {
Point c = ball.getCenter();
int squareW = ball.getRadius() * 2;
int squareH = squareW;
int brcx = x + getWidth() / 2;
int brcy = y + getHeight() / 2;
if((Math.abs(c.x - brcx) <= (squareW + getWidth())*0.5)
&&(Math.abs(c.y - brcy) <= (squareH + getHeight())*0.5)
){
System.out.println("... Collide");
if(hitListener ! =null) {
hitListener.hit(this);
}
setGone(true);
/* Hit the brick and change the direction of the ball */
// It is very important to determine whether the ball first hits the left and right or the up and down side of the brick, otherwise it will move in an unreasonable direction.
double horizontal = (squareW + getWidth())*0.5 - Math.abs(c.x - brcx);
double vertical = (squareH + getHeight())*0.5 - Math.abs(c.y - brcy);
if (horizontal < vertical)
ball.setHoriMove(-ball.getHoriMove());
elseball.setVertMove(-ball.getVertMove()); }}/ / end collision detection / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / /}}public Ball getBall(a) {
return ball;
}
public void setBall(Ball ball) {
this.ball = ball;
}
public Point getLeftTop(a){
leftTop.x = x;
leftTop.y = y;
return leftTop;
}
public Point getRightTop(a){
rightTop.x = x+getWidth();
rightTop.y = y;
return rightTop;
}
public Point getLeftBottom(a){
leftBottom.x = x;
leftBottom.y = y + getHeight();
return leftBottom;
}
public Point getRightBottom(a){
rightBottom.x = x + getWidth();
rightBottom.y = y + getHeight();
return rightBottom;
}
private HitListener hitListener;
public void setHitListener(HitListener hitListener){
this.hitListener = hitListener;
}
public interface HitListener {
void hit(Brick brick); }}Copy the code
conclusion
Through the implementation of the “JAVA bricks”, let me have a further understanding of the relevant knowledge of JAVA, the Language of JAVA also have a deeper understanding than before.
Basic Java syntax, such as data types, operators, program flow control, and arrays, is better understood. Java is the core of the core object oriented thought, for this concept, finally realized some.
The source code for
After clicking “like” and following the blogger, the private blogger will get it for free