Small ball game - start our first game ----- java. In-depth understanding of multithreading

Whenever we play various games, such as LOL, Genshin Impact, Hollow Knight, will you suddenly have an idea in your mind, if you can make such a game yourself, it would be great. Although this is very far away for us, maybe we can become such a part when embarking on this road of game production.

So, let's start making our first game, which I'll call Collision Balls.

Multi-threaded games 2022-07-26 16-35-38

Create the Ballgame class:

1. Establish the visualization part, it's a cliché

this.setTitle("多线程游戏");
        this.setSize(1000,1000);
        this.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
        FlowLayout flow=new FlowLayout();
        this.setLayout(flow);
        JButton btn=new JButton("停止");
        JButton btn1=new JButton("继续");
        Dimension dim=new Dimension(100,50);
        btn.setPreferredSize(dim);
        btn.addActionListener(ll);
        this.add(btn);
        btn1.setPreferredSize(dim);
        btn1.addActionListener(ll);
        this.add(btn1);
        this.setVisible(true);//建立好所需的界面,给按钮绑好监听器

2. Add a mouse listener internally:

addMouseListener(new MouseAdapter() { //内部监听器加法,节省空间

            @Override
            public void mousePressed(MouseEvent e) {
                super.mousePressed(e);
                Random rnd=new Random();
                double speedx=rnd.nextInt(8)-1.6;
                double speedy=rnd.nextInt(6)-2.1;
                Color cl=new Color(rnd.nextInt(Integer.MAX_VALUE));
                int size=rnd.nextInt(40)+10;
                Ball ball=new Ball(e.getX(),e.getY(),speedx,speedy,size,cl);
                bl[index++]=ball;
            }//每点击鼠标一次,即给储存小球信息的数组,Ball[],赋予最开始的信息。

        });

3. Create a thread and let it be responsible for the movement of the ball, so that other operations on the interface will not be stuck (the most important thing is to study carefully)

 Graphics g=getGraphics();
        Threadball run=new Threadball(this,g);//值得注意的是,我们这次传的是一个对象,方便线程取值
        Thread t=new Thread(run);
        t.start();//开辟一个新线程,同时将所需信息传过去

 4. In order to make the game have a sense of hierarchy, use paint to draw a black rectangle:

public void paint(Graphics g){
        g.setColor(Color.black);
        g.fillRect(0,100,1000,50);
    }//绘制黑矩形,使区域划分开,让按钮可以不被遮盖。

Maybe you will feel strange about passing objects, which is an important point in multithreading and will be explained later.

Create the button listener Ac class: used to control the thread

 public void actionPerformed(ActionEvent e){
            btnname=e.getActionCommand();
            if(btnname.equals("停止")){
                flag=false;
            }
            if(btnname.equals("继续")){
                flag=true;
               }
    }//写好按钮反应,控制线程进行。

Create the Ball class:

Use the method of analysis to obtain the required information.

Draw the ball:

public void drawball(Graphics g){
        g.setColor(cl);
        g.fillOval((int)(x),(int)(y),size,size);
    } //绘制小球

How to move the ball:

 public void move(){

       if(x<0+0.5*size){
           x=0+0.5*size;
           speedx=-speedx;
       }
       if(x>1000-0.5*size){
           x=1000-0.5*size;
           speedx=-speedx;
       }
        if(y<150+0.5*size){
            y=150+0.5*size;
            speedy=-speedy;
        }
        if(y>1000-0.5*size){
            y=1000-0.5*size;
            speedy=-speedy;
        }//小球碰到边界后,及时位置回复,同时改变速度方向

        x+=speedx;
        y+=speedy;//通过使小球的x,y值发生变化,当下次绘制时达到移动的效果。
    }//小球移动

Create the ThreadBall class and implement the Runable interface:

Use the structuring method to obtain the required information, and it is worth noting that the object of Ballgame is obtained.

Operations of threads:

public void run() {//线程所具操作
        while (true) {

            g.setColor(Color.black);
            g.fillRect(0,100,1000,50);//多次绘制黑矩形,防止被小球遮盖

            try {
                Thread.sleep(10);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }//用延时来控制小球速度,否则计算机计算过快,会使得小球移速过快而效果不好

            for (int i = 0; i < gui.index; i++) {/*之所以一开始要将对象传来,是因为在线程中,无法完成值传递
                故想要获取信息,只能动态得到,用对象来完成*/
                /*如果只是将index传入的话,哪怕进行点击后,index++,而线程中的index始终为0*/

                for (int j = i + 1; j < gui.index; j++) {
                    double distance = Math.abs(bl[i].x - bl[j].x) * Math.abs(bl[i].x - bl[j].x) +
                            Math.abs(bl[i].y - bl[j].y) * Math.abs(bl[i].y - bl[j].y);
                    double rad = ((bl[i].size + bl[j].size) * (bl[i].size + bl[j].size)) / 4;
                    if (distance < rad) {
                        if (bl[i].speedx * bl[j].speedx > 0) {
                            bl[i].speedx = -bl[i].speedx;
                        }
                        if (bl[i].speedy * bl[j].speedy > 0) {
                            bl[i].speedy = -bl[i].speedy;
                        }//检测碰撞与否,利用高中数学原理

                        bl[i].speedx = -bl[i].speedx + rnd.nextInt(1) - 0.7;
                        bl[i].speedy = -bl[i].speedy + rnd.nextInt(1) - 0.4;
                        bl[j].speedx = -bl[j].speedx + rnd.nextInt(1) - 0.5;
                        bl[j].speedy = -bl[j].speedy + rnd.nextInt(1) - 0.3;//如果碰撞了,不仅要反向,还要有变化,防止卡死

                    }
                }

                Ball ball = gui.bl[i];//值得注意的是,数组是地址传递,所以才可以使信息迭代
                ball.move();
                ball.drawball(g);

            }

            try {
                Thread.sleep(20);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }//让小球留在屏幕上的时间

            while (!gui.ll.flag/*取到监听器的flag来控制线程的进行*/) {
                try {
                    Thread.sleep(10);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }//利用while循环卡死

            g.setColor(Color.white);
            g.fillRect(0,150,1000,850);//通过白屏的手段消除之前图像,方便小球独立出来

        }
    }

It is worth recalling that when we get the number of balls, that is, the index, we do not use any structuring method or pass value to get it, but get it dynamically through the gui object of the Ballgame class, so that we can get it.

In addition, we should keep in mind that the array is passed by address, so although every time we loop, we will create a temporary ball object of the Ball class to perform the move method, so that the coordinate value changes, and the next temporary object remains the same. The ability to get the changed information lies in the particularity of the array.

Guess you like

Origin blog.csdn.net/AkinanCZ/article/details/125997854