• 线程之小球的运动


    ---恢复内容开始---

    线程之小球的运动

         线程这个知识点我写了将近三天,而且现在还在完善阶段,写线程也暴露了我写程序时的很多缺点,下面就来看看写线程时烦的那些傻吧!

    一:当我是用一个线程控制一个球的时候:(即点击一下按钮就启动一个线程)

    基本思路是:

    1.第一步:设置好窗体,给按钮加上监听器;

    2.创建一个类实现按钮的监听;

    3.创建一个线程类,实现Run()方法。

         第一个越不过的坎:画小球时小球会闪动:

    原因:我画小球的步骤是:改变小球颜色,改变坐标,画小球,暂停,擦除;但是线程一启动它的速度是很快的,所以先要暂停,然后擦除,改颜色和坐标,最后画小球。

        //暂停
                try {
                    Thread.sleep(60);// 休眠0.01秒
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }//方法一:暂停时的循环休眠
            //    System.out.println();//空循环方法二
                if (stateFlag) {// 若stateFlag为true,执行continue,进行空循环或者是循环休眠的状态,不执行下面的语句;否则,执行下面的语句
                    continue;
                }
                //擦除
                g.drawImage(img, 0, 70, 700, 700, null);
                //改变坐标
                x += movex;
                y += movey;
                //改颜色
                g.setColor(new Color(a, b, c));
                //画小球
                g.fillOval(x, y, size, size);

    第二个越不过的坎:小球的创建,暂停,启动,删除;

    /*
         * 先前把小球的创建,启动和暂停想的太复杂了,其实可以把问题简单化:
         * 创建的时候就启动线程,暂停的话就是持续休眠,启动就是让已经创建的小球继续移动,删除就是清空画图板
         * 
         */
        @Override
        public void actionPerformed(ActionEvent e) {
            String str = e.getActionCommand();
             System.out.println("al" +"   "+ al);
            if (str.equals("创建")) {
                System.out.println("=======================" + str);
                //实例化一个线程类
                BallThread ball = new BallThread(rand.nextInt(700),
                        rand.nextInt(600)+100, 40, 10, 10, bf, al);
                ball.start();//启动线程
                al.add(ball);
            } else if (str.equals("启动")) {
                for (int i = 0; i < al.size(); i++) {
                    BallThread ball = al.get(i);//获得已经创建的小球
                    ball.stateFlag = false;//让已经创建的小球继续移动
                }
    
            } else if (str.equals("暂停")) {
                for (int i = 0; i < al.size(); i++) {
                    BallThread ball = al.get(i);
                    ball.stateFlag = true;//让已经创建的小球进入无限休眠的循环状态
                }
            }
            else if (str.equals("删除")) {
                for (int i = 0; i < al.size(); i++) {
            ball = al.get(i);
            ball.flag = true;
            ball.stateFlag=false;
            ball.drawwhiterecrt();
                }
            }    
        }

    第三个越不过的坎:小球运动的处理方法;

    难点是:当两个小球碰撞时是要互相弹开时,其实是两个小球移动的方向是往回退的,机两个小球的移动方向互换

    // 碰撞处理,比较圆心之间距离,遍历数组队列,找出当前球与其他球的圆心距离
                for (int i = 0; i < al.size(); i++) {
                    ball = al.get(i);//获得其他的球
                    if (this == ball) {//如果找出的球是和自己一样的,就继续找球,否则就继续下面的程序
                        continue;
                    }
                    int xx = Math.abs(this.x - ball.x);
                    int yy = Math.abs(this.y - ball.y);
                    int xy = (int) Math.sqrt(xx * xx + yy * yy);//求两个球的圆心距
                    int tempx = 0;
                    int tempy = 0;
                   //如果两个球碰撞了,两个球交换坐标(移动的方向);
                    if (xy <= (this.size / 2 + ball.size / 2 )) {
                        tempx = this.movex;
                        tempy = this.movey;
                        this.movex = ball.movex;
                        this.movey = ball.movey;
                        ball.movex = tempx;
                        ball.movey = tempy;
    
                    }
                }

    第四个越不过去的坎:不要让小球把按钮擦掉了;

    用随机数控制小球移动的坐标就好了:

    BallThread ball = new BallThread(rand.nextInt(700),
    rand.nextInt(600)+100, 40, 10, 10, bf, al);

    运行的结果:

    二:用一个线程控制多个小球的运动:(方法更优)

    思路:

    1.首先画窗体;

    2.创建一个小球类,把小球的属性和方法都写上去;

    属性:坐标,颜色,速度,直径

    方法:画小球,移动,碰撞

    3.创建一个类实现监听和Runable()和actionListener();

     要注意的问题是:小球队列的存储问题,要在点击一下“创建”的时候存小球

    运行的结果:

    用一个线程控制多个小球的好处:

    1.解决加入背景图片时小球的闪动的问题(因为背景图片带替了擦除的功能,它不停地画就会出现不断地闪动);

    2.节省内存,提高程序运行的速度(时间复杂度&&空间复杂度);

    因为线程没有自己独立的内存空间(运行空间),所以每次启动一个线程都需要向进程申请运行空间,多个线程就需要更多的运行空间,从而在积累到一定数量的时候,会影响到CPU的运行速度。如图所示:

    三 背景图片的移动

     思路:把背景图片也当作一个小球,在画小球的方法中加入背景图片的移动方法。

    // 画小球的方法:暂停,擦除,换坐标,画小球
        public void drawOval() {
            background(img);
            //小球的移动
            move();    
            // 改变坐标
            x += movex;
            y += movey;
            // 改颜色
            g.setColor(new Color(a, b, c));        
            // 画小球
            g.fillOval(x, y, size, size);
            
        }
        //背景移动的方法
        public void background(Image img){    
            y1+=1;
            if(y1==0){
                y1=-100;
            }
            g.drawImage(img,0,y1,700,700,null);
        }

    线程进一步的设想:

    1.在小球上再添加一个线程,发射子弹;

    2.小猪冒险的游戏;

    ---恢复内容结束---

  • 相关阅读:
    200行代码实现Mini ASP.NET Core
    使用Elastic APM监控你的.NET Core应用
    .NET西安社区「拥抱开源,又见 .NET:壹周年Party」活动简报
    西安7月21日「拥抱开源,又见.NET:壹周年Party」线下交流活动
    领域驱动设计(DDD)编码实践
    再谈领域驱动设计
    「拥抱开源, 又见 .NET」系列第三次线下活动简报
    西安活动 | 4月20日「拥抱开源,又见.NET :云时代 • 新契机」
    在Xunit中使用FsCheck
    rocketMq特性(features)
  • 原文地址:https://www.cnblogs.com/java-7/p/5807720.html
Copyright © 2020-2023  润新知