安卓程序设计报告

时间:2024.4.20

弹球游戏

物联一班  谢鑫  20100740123

一、实验目的

1、掌握Swing图形用户界面编程以及事件处理等,掌握java绘图技术。

2、掌握多线程编程的基本原理,能使用Runnable、ExecutorService等接口进行线程的创建、启动等工作。

二、实验任务

设计并编程实现弹球游戏:

用户能通过GUI组件指定生成小球的数量,每个小球将从随机的位置出现,并具有随机颜色,随机速度以及随机的运动方向,小球沿初始方向匀速运动,当碰到窗口边缘时,小球将依据受力原理改变运动方向(可简化考虑,受力只改变小球的运动方向,小球仍按照初始速度匀速运动,且不考虑小球之间的碰撞)。

鼠标在界面中显示为方块状,玩家需按住鼠标来回移动以避开运动的小球及屏幕四周,如果鼠标碰到任一小球或者窗口四周,则游戏结束。

程序需提供计时功能,并最终显示玩家能坚持多少秒。

三、设计思路

1.界面设计

(1)制作一个简单的面板JFrame,文件保存为bollFrame.java

其中为一public的类 bollFrame,其构造方法为:

   

bollFrame(int n){

              super();

        setTitle("我的弹球小游戏");

              setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

              Dimension dimension = Toolkit.getDefaultToolkit().getScreenSize();//得到 电脑屏幕大小

              setSize(450,450);

              setLocation((dimension.width-game.getWidth())/2-250,   (dimension.height-game.getHeight())/2-250);//设置面板显示基中;

              this.n = n;

              myBollPanel = new bollPanel(n);//构造一个画板;

          add(myBollPanel);//将画板放入JFrame

              createMenu();//创建菜单;

              setJMenuBar(bar);

       }

(2)构造画板类,文件保存为bollPanel.java

 其构造函数如下:

bollPanel(int n){

               this.n = n;

              // executorThread = Executors.newCachedThreadPool();//创建线程池;

               mouse = new mouseThread(mxNow,myNow,groupThread,this);//启动鼠标线程;

               this.setIsOver(false);//游戏开始线程条件的判断;

               for(int i =0 ;i<n;++i){

                     myBollThread =new bollThread(this);

                     groupThread.add(myBollThread);

                     //executorThread.execute(myBollThread);//小球线程加入线程池;

               }

                 addMouseListener(this);

                 addMouseMotionListener(this);

       }

Paint()方法如下构造:

  public  void paint(Graphics g){

                if(!this.getIsOver())    //如果游戏还没结束;

                {

                      super.paint(g);//清除原先的图像

                     

                     g.setColor(Color.RED);

                  g.setFont(new Font("宋体",Font.BOLD+Font.ITALIC,15));

                  g.drawString("你已坚持:"+getT()+"S", 15, 15);//计时器的显示;

                 

                      for(int i = 0;i<n;++i){//画出每个线程球

                      

                        int xNow =groupThread.get(i).getxNow();

                        int yNow = groupThread.get(i).getyNow();

                            g.setColor(groupThread.get(i).getColor());

                            g.fillOval(xNow,yNow,30,30);

                            

                           if(xNow>(getWidth()-23)||xNow<0){//碰到左右边界;

                                  groupThread.get(i).dx = -groupThread.get(i).dx;

                            }

                            if(yNow>(getHeight()-23)||yNow<0){//碰到上下边界;

                                   groupThread.get(i).dy = -groupThread.get(i).dy;

                            }          

                             groupThread.get(i).setxNow(xNow+groupThread.get(i).getdx());// 设置下一个位置;

                            groupThread.get(i).setyNow(yNow+groupThread.get(i).getdy());

                 }

               }

                           if(isMouse){

                                  g.drawImage(new ImageIcon("boll.gif").getImage(), mxNow, myNow, 40,40, this);//鼠标的图像;

                           }      

      }//end paint();

总体界面如下:

2.逻辑设计

(1).首先,我们考虑到多个小球的运动,实质上是多线程的使用,n个小球我们就同时启动n个线程去控制每个小球的运动。因此我构造出一个类作为一个小球的线程,保存文件为bollThread.java,顾名思义,小球线程类。相关构造方法如下:

 public bollThread(bollPanel my){

              this.myPanel = my;

              xStart = data.nextInt(200);//随机产生开始位置;

              yStart = data.nextInt(200);

              setxNow(xStart);////设置现在的位置;

              setyNow(yStart);

              setdx();//设置随机方向使用;注意:若不设置为随机,则所有小球将相同一个方向运动;

              setdy();

           }

(2)再次,小球的出现需要有载体,这就是画板,前面界面设置中已提到过,通过让多个小球共享一个画板,以及通过线程控制小球的重绘,最后通过画板显示给用户。

(3)在第(2)点中提到的画板上我们需要实现鼠标的监听,以下给出几个重要的鼠标事件监听:

public void mousePressed(MouseEvent e) {//单击启动鼠标事件;

                if(e.getButton()==MouseEvent.BUTTON1){

                       copy.schedule(new task(), 0,1000);//启动定时器;

                        for(int i =0 ;i<n;++i){

                               Thread my = new Thread(groupThread.get(i));

                                my.start();//启动游戏,启动小球线程;

                        }

                       mxNow = e.getX();

                       myNow = e.getY();

                    isMouse = true;

                    if(!mouse.isAlive()){

                           mouse.start();//启动鼠标线程;

                    }

                }//end if(e.getButton()==MouseEvent.BUTTON1);

         }//注意按下鼠标开始游戏

   public  void mouseDragged(MouseEvent e) {//游戏过程中通过按住鼠标左键控制“眼睛”的移动来躲避小球;

                mxNow = e.getX();// TODO Auto-generated method stub

                  myNow = e.getY();

                 if(mxNow>(this.getWidth()-30)||mxNow<=0||myNow>(this.getHeight()-30)||myNow<=0){//鼠标是否碰到边界;

                             // executorThread.shutdown();

                             this.setIsOver(true);

                              copy.cancel();

                                JOptionPane.showMessageDialog(null, "你撞墙了,下次小心点。。。游戏结束","提示" ,JOptionPane.OK_OPTION);     

                                 this.removeMouseListener(this);

                                 this.removeMouseMotionListener(this);

                          }

                 

                for(int i =0 ;i<n;++i){

                       int xNow =groupThread.get(i).getxNow();

                        int yNow = groupThread.get(i).getyNow();

                       

                       if(isPeng(xNow,yNow,mxNow,myNow)){

                               // executorThread.shutdown();

                                this.setIsOver(true);

                                copy.cancel();

                                JOptionPane.showMessageDialog(null, "if(你撞球了){"+"\n"+"挑战失败,游戏结束.}","提示" ,JOptionPane.OK_OPTION);

                                //System.exit(0);

                                this.removeMouseListener(this);

                                this.removeMouseMotionListener(this);

                        } //鼠标的上下左右边和 球碰撞的情况,

                       }

               

         }

  (4)  如果游戏开始后我们突然松开鼠标,让我们控制的小球(或"眼睛")停留在最后松开的点上,那么小球碰到它还会判断是否相撞吗?答案是可以的,我们可以通过编写一个鼠标线程类来实现,保存文件为mouseThread.java;让此线程在我们按下鼠标开始游戏时同时启动,在我们松开鼠标时启动判断相撞事件。

相关的构造方法如下:

mouseThread(int mxNow,int myNow,List<bollThread>group,bollPanel bollpane){

              this.mxNow = mxNow;//传入鼠标现在位置;

              this.myNow = myNow;

              this.groupThread = group;//传入小球线程组;

              this.bollpane = bollpane;//传入画板对象;

       }

3.程序测试

在程序测试中,先后测试出了,以下几个注意点:

A.在判断小球与鼠标控制的小球(“眼睛”)相撞时,条件中用到两点之间的距离问题,发现条件不能是两点距离刚好等于两相撞物体半径和,此条件太苛刻,可能引起判断的失误(概率蛮高的呵呵),而应该是小于半径和。

B..在小球碰撞或控制的小球(”眼睛“)碰到边界游戏结束时,已经停止了线程,小球竟然还能动,而且是缓慢移动,但是判断是否碰撞及边界问题都能正常执行,与我所意料的完全相反,到现在也不知道是怎么回事,只能在paint() 里进行条件判断,只让bollPanel留下最后一次的个小球及“眼睛”位置。

C.这是最后才调试出来的,也是这个游戏中较难注意到的。

  就是一些boolean变量的设置:

        privateboolean isTime;//定时器是否启动;

        privateboolean isGroupThread;//所有小球线程组是否启动;

        privateboolean isMouseThread;//鼠标线程是否启动;

        privateboolean isMouse;//鼠标事件是否启动;

        privateboolean isOver;//游戏是否结束;

    刚开始时并没有注意到这些,如果我点击鼠标左键开始游戏时,启动了小球线程,这时要设置变量isGroupThread = true标志小球线程组已启动,释放鼠标启动鼠标线程时,isMouseThread = true让鼠标线程来控制与小球相撞的判断,定时器也在这时响应启动 isTime =true开始计时,若不设置这些的话,将发生以下本质上的共同错误:

    :等我释放鼠标后想再次控制小球,就必须在一次启动鼠标事件,这时将重新启动一次计时器,重新启动一次小球线程组,重新启动鼠标线程;这样的结果是导致游戏的结果不确定性,没碰到小球(实际上已碰撞)它就检测碰撞结束游戏。以及计时器的计时紊乱等。

具体调试后的相关代码实现见附录.。

五、实验总结

     通过这次的程序设计,我更加明白了学以致用的道理,对线程的应用使得我更好更快的掌握了线程的本质,同时,在此次的程序设计中,经过不断地调试,是我明白了一个程序或项目要做到“精致”,是是需要花多大的精力和耐心,总之,学以致用,会将学到的知识应用到实际中才是学之根本。

   此次实验也更了解到了线程的知识,比如:一个线程stop后,不能再用start启动,而应当重新实例化,在start()。也就是说线程的状态转换过程(新建-就绪-运行-阻塞-死忙)是不可逆的,这是个人理解,至少从本实验中可以得到验证。

      最后,感谢老师的指导和同学们对我的帮助。

六、附录

  以下是调试后的相关算法实现:

A:

          public boolean isPeng(int xNow,int yNow,int mxNow,int myNow){//利用两点之间的距离算法,判断是否撞球

              int x1 = xNow+15,y1 = yNow+15;

              int x2 = mxNow+20,y2 = myNow+20;

              int mulx = x1-x2,muly = y2 -y1;

              double sum = Math.pow(muly, 2)+Math.pow(mulx, 2);

              if(sum<Math.pow(35, 2))

                    return true;

              else return false;

}

B:

     public  void paint(Graphics g){

                if(!this.getIsOver())    //在此判断游戏是否结束;

                {

                      super.paint(g);//清除原先的图像

                     

                     g.setColor(Color.RED);

                  g.setFont(new Font("宋体",Font.BOLD+Font.ITALIC,15));

                  g.drawString("你已坚持:"+getT()+"S", 15, 15);

                 

                      for(int i = 0;i<n;++i){//画出每个线程球

                      

                        int xNow =groupThread.get(i).getxNow();

                        int yNow = groupThread.get(i).getyNow();

                            g.setColor(groupThread.get(i).getColor());

                            g.fillOval(xNow,yNow,30,30);

                           if(xNow>(getWidth()-23)||xNow<0){//碰到左右边界;

                                  groupThread.get(i).dx = -groupThread.get(i).dx;

                            }

                            if(yNow>(getHeight()-23)||yNow<0){//碰到上下边界;

                                   groupThread.get(i).dy = -groupThread.get(i).dy;

                            }          

                             groupThread.get(i).setxNow(xNow+groupThread.get(i).getdx());

                            groupThread.get(i).setyNow(yNow+groupThread.get(i).getdy());

                 }

               }

                           if(isMouse){

                                  g.drawImage(new ImageIcon("boll.gif").getImage(), mxNow, myNow, 40,40, this);

                           }      

                          

      }//end paint();

C :

(1)public void mousePressed(MouseEvent e) {//单击启动鼠标事件;

                if(e.getButton()==MouseEvent.BUTTON1){

                       if(isMouseThread){//鼠标线程是否活着;

                              mouse.stop();

                              isMouseThread = false;

                       }

                       if(!isTime){

                          copy.schedule(new task(), 0,1000);//启动定时器;

                          isTime = true;

                       }

                       if(!isGroupThread){

                               for(int i =0 ;i<n;++i){

                                      Thread my = new Thread(groupThread.get(i));

                                       my.start();//启动游戏,启动小球线程;

                               }

                               isGroupThread = true;

                       }

                       mxNow = e.getX();

                       myNow = e.getY();

                    isMouse = true;

                }//end if(e.getButton()==MouseEvent.BUTTON1);

         }

     (2)     public void mouseReleased(MouseEvent e) {

               //mouse.setmxNow(e.getX());

              // mouse.setmyNow(e.getY());//设置松开点的鼠标位置;

                mxNow = e.getX();

                myNow = e.getY();   

             if(!isMouseThread){

                    mouse = new mouseThread(mxNow,myNow,groupThread,this);// 新建鼠标线程;/启动鼠标线程;............................................................................

                     mouse.start();

                     isMouseThread = true;

             }

         }

(3)public  void mouseDragged(MouseEvent e) {

         

            mxNow = e.getX();// TODO Auto-generated method stub

            myNow = e.getY();

            if(mxNow>(this.getWidth()-30)||mxNow<=0||myNow>(this.getHeight()-30)||myNow<=0){//鼠标是否碰到边界;

                   // executorThread.shutdown();

                    this.setIsOver(true);

                    copy.cancel();

                    JOptionPane.showMessageDialog(null, "你撞墙了,下次小心点。。。游戏结束","提示" ,JOptionPane.OK_OPTION); 

                    this.removeMouseListener(this);

                    this.removeMouseMotionListener(this);

                }

           for(int i =0 ;i<n;++i){

               int xNow =groupThread.get(i).getxNow();

               int yNow = groupThread.get(i).getyNow();

              

               if(isPeng(xNow,yNow,mxNow,myNow)){

                   // executorThread.shutdown();

                    this.setIsOver(true);

                    copy.cancel();

                    JOptionPane.showMessageDialog(null, "if(你撞球了){"+"\n"+"挑战失败,游戏结束.}","提示" ,JOptionPane.OK_OPTION);

                    //System.exit(0);

                    this.removeMouseListener(this);

                    this.removeMouseMotionListener(this);

                } //鼠标的上下左右边和 球碰撞的情况,

               }

          

       }

更多相关推荐:
安卓android课程设计报告

湘潭大学课程设计报告课程课题指导名称手机安卓开发名称天气预报APP老师周唯姓名黄柳学号20xx600719班级12计2班小组棒棒糖时间20xx年1月26日一需求分析一引言1编写目的11为用户提供一个显示天气预报...

安卓日志程序开发设计报告

沈阳理工大学专用纸摘要随着无线移动设备的发展手机也日益普及Android系统的推出使手机的发展进入到了一个新的领域世界上一些知名的移动设备生产厂商对于Android智能机的开发热情也日益提高Android系统的...

安卓txt阅读器课程设计报告

Android期末考核作业作品名称酷阅txt阅读器100班级专业软件工程姓名学号一软件功能1查找书功能点击菜单键在弹出的SD卡列表中查找2字体点击菜单键在弹出的菜单中选择设置可以更换字体大小和字体颜色3翻页特效...

安卓课程设计报告

安卓课程设计班级09级计算机二班学号20xx7923姓名郭丹1目录第1章安卓应用程序开发背景311开发背景312开发环境4第2章第3章313233第4章安卓应用程序开发理论与方法4计算器应用程序的设计与实现6拟...

安卓课程设计报告

安卓学生姓名学号专业班级设计题目学年学期指导教师课程设计简易计算器20xx20xx学年第一学期日期1签名目录第1章安卓应用程序开发背景错误未定义书签11开发背景错误未定义书签12开发环境错误未定义书签第2章安卓...

20xx20xx32周璋 安卓程序开发报告

Android程序设计课程作业报告题任课教师李游哈尔滨工程大学20xx年10月14日哈尔滨工程大学本科生Android程序设计课程作业报告摘要随着移动设备技术的蓬勃发展人们从传统的的办公室一人一桌一电脑的普遍方...

安卓课程设计报告

安卓课程设计报告设计题目五子棋目录一需求分析2二功能模块2三界面设计3四分工说明5五所遇到的问题5六代码注释6一需求分析网络技术的日新月异让世界惊叹高速发展的网络技术和日渐成熟的3G网络让越来越多的用户沉浸在手...

安卓贪吃蛇课程设计报告

滨江学院智能手机程序设计题目安卓智能手机贪吃蛇游戏设计院系专业信息工程学生姓名周盈伟学号指导教师高超二0一四年六月一日目录第一章绪论311开发背景3111安卓系统简介3112游戏简介312开发目的及意义413开...

安卓记事本开发设计报告

滨江学院移动通信程序设计课程设计题目Android记事本院系计算机系专业计科3学生姓名窦同庆学号20xx2308904二一四年五月二十九日1目录一引言311Android背景312可行性分析3二开发环境的安装和...

安卓计算器设计报告

科信学院通信终端创新课程设计项目说明书20xx20xx学年第二学期课程名称通信终端创新课程设计题目android计算器专业班级通信工程092学生姓名戴维松学号090312245指导教师马小进陈湘国赵欣崔冬设计周...

Android程序设计报告-标准体重

Android应用程序设计报告学院信息工程与自动化学院专业通信工程班级姓名学号日期20xx年7月8日一背景介绍随着移动通信与Internet向移动终端的普及网络和用户对移动终端的要求越来越高而SymbianWi...

3G程序设计报告

3GAndroid应用程序设计报告学院信自学院专业通信工程班级通信123姓名巨博学号20xx10404317指导老师谢涛一背景介绍随着移动通信与Internet向移动终端的普及网络和用户对移动终端的要求越来越高...

安卓程序设计报告(13篇)