Realize a simple brick-breaking game with JAVA

Overview

Use java to implement a brick-and-mortar game, the game interface includes the following elements

  • Bricks of various colors on the top
  • Bottom baffle
  • small ball
  • Game information display panel
  • Gameplay includes

Use mouse or keyboard to move the bezel

  • Break down the bricks and score points
  • There are 3 chances in each round, if the baffle does not receive a small ball, the chance is reduced by 1
  • If the black ball is knocked out, the props will be dropped, and the baffle will become longer when the prop is received
  • Can choose the game difficulty level

Function realization

First, the entire Class inherits from GraphicsProgram. After the program is started, the init() method is executed first, and then the run() method is executed

public class Arkanoid extends GraphicsProgram
{
    
    
    public void init()
    {
    
    
        // 进行初始化
    }

    public void run()
    {
    
    
        // 具体执行
    }
}

Then, in init(), create the game interface.

Create bricks

Before creating a brick, prepare a container to store the color and the corresponding score. Here it is realized by Map. The key saves the Color object, and the value saves the score.

Map<Color,Integer> brickColors;

colors=new Color[]{
    
    
        Color.BLACK,Color.BLUE,Color.CYAN,Color.DARK_GRAY,Color.GRAY,Color.GREEN,
        Color.LIGHT_GRAY,Color.MAGENTA,Color.ORANGE,Color.PINK,Color.RED,Color.YELLOW
};
brickColors=new HashMap<>();
for(int i=0;i<colors.length;i++)
{
    
    
    Color color=colors[i];
    // 黑色砖块是特殊砖块,打掉不得分,但是可以掉落胶囊
    if(color.getRGB() == Color.BLACK.getRGB())
    {
    
    
        brickColors.put(color,0);
    }
    else
    {
    
    
        brickColors.put(color,colors.length%(i+1)+1);
    }
}

With the brick color, the next step is to create the bricks of the specified row and column. Here we use GRect to represent the bricks.

One thing to note is that GRect has a 1 pixel border by default. If you don't remove it, you should take this 1 pixel into consideration when calculating the width of the brick.

final int ROWS=6;
final int COLUMNS=12;

// 砖块实心部分的宽,高
brickW=GAME_PANE_WIDTH/COLUMNS;
brickH=brickW/2;

for(int i=0;i<ROWS;i++)
{
    
    
    for(int j=0;j<COLUMNS;j++)
    {
    
    
        GRect brick=new GRect(brickW,brickH);
        brick.setFilled(true);
        brick.setColor(colors[randomGenerator.nextInt(0,brickColors.size()-1)]);

        brick.setLineWidth(0);
        double x=j*brickW;
        double y=i*brickH;
        add(brick,x,y);
    }
}

Create baffle and ball

Create the baffle and the ball, use GRect and GOval respectively, and then add them to the appropriate position.

Create game information display panel

In the game information display panel, you can add some panels to display information according to the functions to be implemented by the game.

Here create panels including [Game Chance] [Score] [Game Difficulty] [One more game] and so on.

The outermost is created using JPanel, the layout method is GirdLayout, and then each item can be added to it.

Use the mouse or keyboard to control the movement of the bezel

To realize the function of allowing the baffle to move with the mouse, you need to add a mouse listener directly to the outermost component of the game interface.

Call the method addMouseListeners() and then override the mouseMoved(MouseEvent) method, in which the position of the baffle can be set according to the mouse position. Pay attention to limit the moving range of the baffle and keep it from exceeding the game interface.

addMouseListeners();

public void mouseMoved(MouseEvent e)
{
    
    
    if(gameover) // 游戏结束,恢复挡板在底部正中央
    {
    
    
        paddle.setLocation(GAME_PANE_WIDTH/2.-paddle.getWidth()/2,GAME_PANE_HEIGHT-paddle.getHeight()-30);
    }
    else // 游戏运行中,动态改变挡板水平方向的位置
    {
    
    
        //paddle.setLocation(e.getX()-PADDLE_W/2,e.getY()-PADDLE_H/2);
        // 限制挡板左侧和右侧不能超出游戏界面的范围
        double x=e.getX()-paddle.getWidth()/2;
        if(x<0)
        {
    
    
            x=0;
        }
        if(x>GAME_PANE_WIDTH-paddle.getWidth())
        {
    
    
            x=GAME_PANE_WIDTH-paddle.getWidth();
        }
        paddle.setLocation(x,paddle.getY());
    }
}

Similar to using a mouse, using the keyboard to operate the movement of the baffle also requires a key event listener.

addKeyListeners();

@Override
public void keyTyped(KeyEvent e)
{
    
    
    double x=paddle.getX();

    char keyChar=e.getKeyChar();
    if(keyChar == '1') // 左移
    {
    
    
        x-=paddle.getWidth()*1.5;
        if(x<=0)
        {
    
    
            x=0;
        }
    }
    else if(keyChar == '2') // 右移
    {
    
    
        x+=paddle.getWidth()*1.5;
        if(x>GAME_PANE_WIDTH-paddle.getWidth())
        {
    
    
            x=GAME_PANE_WIDTH-paddle.getWidth();
        }
    }
    paddle.setLocation(x,paddle.getY());
}

Moving ball

To move the ball, you only need to be in a loop, as long as the game is not over, just call move() all the time.

You need to give the ball an initial moving speed before the game starts, and the speed is different each time.

VELOCITY_X=3;
VELOCITY_Y=5;
boolean gameover=false;

public void init()
{
    
    
    int offset=randomGenerator.nextInt(0,3);
    vx=VELOCITY_X+offset;        // 水平速度
    vy=-(VELOCITY_Y+offset);        // 竖直速度
}

public void run()
{
    
    
    while(!gameover)
    {
    
    
        ball.move(vx,vy);
        pause(DELAY);
    }
}

Detect whether the ball hits the wall

According to the width and height of the game interface and the current coordinates of the ball, determine whether the ball touches the border of the game interface, so as to determine whether the ball hits the wall.

If the ball hits the upper or lower wall, the speed in the y direction is reversed, and if it hits the left or right wall, the speed in the x direction is reversed.

The code is similar to the following

if(hitBottomWall() || hitTopWall())
{
    
    
    vy=-vy;
}
if(hitLeftWall() || hitRightWall())
{
    
    
    vx=-vx;
}

The ball hits the brick and bounces, the brick disappears

First, get the bricks hit by the ball.

Need to detect 4 vertices, only sample code is given here

GObject getCollidingObject()
{
    
    
    GObject element=getElementAt(x,y);
    if(element!=null)
        return element;
    return null;
}

Then, change the trajectory of the ball according to where it hits the brick

A brick can be divided into 8 areas around it according to the lines extending from the 4 sides:

  • Straight up, straight down
  • Positive left, positive right
  • Top left, bottom left, top right, bottom right

If the center of the ball is in the upper or lower region, just take the speed in the y direction;

If the center of the ball is in the positive left or right area, just take its x-direction speed;

If the center of the ball is in another area, it means that it hits exactly the 4 vertices of the brick, and the speed in the x and y directions are reversed at the same time.

boolean changeX=false;
boolean changeY=false;

private void changeXY(GObject element,double center_x,double center_y)
{
    
    
    double left_brick=element.getX();
    double top_brick=element.getY();
    double right_brick=left_brick+brickW;
    double bottom_brick=top_brick+brickH;

    if(center_y>top_brick && center_y<bottom_brick) // 小球在砖块的左侧,或右侧
    {
    
    
        changeX=true;
    }
    else if(center_x>left_brick && center_x<right_brick) // 小球在砖块的上侧,或xia侧
    {
    
    
        changeY=true;
    }
    else // 小球在砖块的4个顶点范围
    {
    
    
        changeX=true;
        changeY=true;
    }
}

Finally, in the run method, change vx and vy according to the variables changeX and changeY

GObject element=getCollidingObject();
if(element != null)
{
    
    
    if(element == paddle) // 如果打到挡板,反弹
    {
    
    
        vy=-vy;
        // 加一下速
        if(vx>0)
            vx+=va;
        else
            vx-=va;
        if(vy>0)
            vy+=va;
        else
            vy-=va;
        continue;
    }
    else
    {
    
    
        if(changeX)
            vx=-vx;
        if(changeY)
            vy=-vy;
        remove(element);
    }
}

Score

When hitting a brick, you only need to get the score corresponding to the color according to the color of the brick, and add it to the score.

GObject element=getCollidingObject();
if(element != null)
{
    
    
    Color color=element.getColor();
    int point=brickColors.get(color);
    score+=point;
    scoreLabel_num.setText(""+score);
}

Drop props, receive props, the baffle becomes longer

Hit a black brick, and a prop will appear under the brick, and it will fall vertically; if you use a baffle to connect to the prop before the prop drops to the lower wall, the baffle will become longer.

First define an array list to store the dropped items;

After hitting the black bricks, create a prop and add it to the container;

Finally, let the props in the container "fall";

If the baffle receives a prop, reset its size.

ArrayList<GImage> falls;

if(color.getRGB() == Color.BLACK.getRGB())// 如果是黑砖块,落下道具
{
    
    
    Toolkit toolkit=Toolkit.getDefaultToolkit();
    Image image=toolkit.createImage("fall.png");
    GImage fall=new GImage(image);
    fall.setSize(PADDLE_W,PADDLE_W);
    add(fall,element.getX(),element.getY());
    falls.add(fall);
}

for(GImage fall:falls)
{
    
    
    if(fall != null)
    {
    
    
        fall.move(0,5);

        // 接到了道具
        if(Math.abs(paddle.getY()-fall.getY()-fall.getHeight())<=0.1 && (Math.abs(fall.getX()-paddle.getX())<=paddle.getWidth()-0.1))
        {
    
    
            remove(fall);
            double newWidth=paddle.getWidth()*1.5;
            if(newWidth>=GAME_PANE_WIDTH)
            {
    
    
                newWidth=GAME_PANE_WIDTH;
            }
            paddle.setSize(newWidth,paddle.getHeight());
        }
    }
}

Set the game difficulty level

The difficulty here is simply to increase the speed of the ball when it bounces off the baffle. According to the magnitude of the acceleration, it is divided into
3 difficulty levels : [Easy] [General] [Difficult].

Create 3 radio buttons, set their monitors, and change the acceleration range when they are selected

double va=0;

JRadioButton simpleBtn=new JRadioButton("简单",true);
JRadioButton middleBtn=new JRadioButton("一般");
JRadioButton diffcultyBtn=new JRadioButton("困难");

simpleBtn.addActionListener(e ->
{
    
    
    va=0;
});
middleBtn.addActionListener(e ->
{
    
    
    va=1;
});
diffcultyBtn.addActionListener(e ->
{
    
    
    va=2;
});

Then, in the run method, add the acceleration to vx, vy

if(element == paddle) // 如果打到挡板,反弹
{
    
    
    vy=-vy;
    // 加一下速
    if(vx>0)
        vx+=va;
    else
        vx-=va;
    if(vy>0)
        vy+=va;
    else
        vy-=va;
}

Guess you like

Origin blog.csdn.net/weixin_52308504/article/details/113615281