弹球游戏分步解析(二)——让小球飞

弹球游戏分步解析(二)——让小球飞

之前跟大家说要把事件监听器和多线程分开来讲,不过之后发现事件监听器要涉及到很多小球运动的操作,所以,决定将两个知识点合起来说,这样会更便于大家理解:

实现小球在我们所绘制的窗体上运动就必须要用到多线程;让小球类继承Thread类,再重写void run(){}方法即可;

先上代码:

(注:浅蓝色字体不是本节要讲的内容,可以忽略) 

package jumpingBall;

 

import java.awt.Color;

import java.awt.Graphics;

import java.util.List;

import java.util.Random;

 

import javax.swing.JPanel;

//小球类是此游戏的关键,我们首先要分析他应该具备什么样的属性,实现什么样的方法

public class BallThread extends Thread {

private static final int North = 1;//用四个整形的数据代表四个方向

private static final int West = 2;

private static final int South = 3;

private static final int East = 4;

private int Xdirection = West;//记录小球在X轴上的方向

private int Ydirection = North;//记录小球在y轴上的方向

private int radios;//半径

private Color color;//颜色

private int Xspeed;//x方向速度

private int Yspeed;//y方向速度

private int X;//当前位置x

private int Y;//当前位置y

private int LastX;//最后位置x

private int LastY;//最后位置y

private int xband;

private int yband;

private JPanel jp;//面板

private Graphics g;//画布

private boolean pauseFlag = false;//暂停标志(默认值否)

private boolean stopFlag = false;//停止标志(false——表示存在)

private boolean beread = false;//是否被储存在文件里过(默认值否)

       public BallThread(JPanel jp){

              this.jp = jp;

              this.g = jp.getGraphics();

       }

 

       public void run(){

              banLlistener band =new banLlistener(jp);//定义滑块

              jp.addMouseMotionListener(band);//给滑块加入鼠标监听器

              if(beread==false){//如果没有被储存在文件里过

              this.setprivate();//方法作用:随机生成它的部分属性

              }

//实现小球运动的思路为:才窗体上沿小球运动路线不断绘制小球,并将之前的小球擦掉

              while(true){//永真表示球会一直运动

                  

                       try{

                                 sleep(30);

                       }catch(InterruptedException e){

                                 e.printStackTrace();

                       }

                       if(stopFlag==true){//如果停止标示为true,停止该线程

                                 clearBall();

                                 return;

                       }

                       if(pauseFlag==true){//如果暂停标示为真,跳过之后的步骤进入下次循环

                                 continue;

                       }

                       

                       this.clearBall();//清除原来位置的小球

                       this.move();//小球运动

                       this.drawBall();//在新的位置画出小球

 

                       

              }

                               

}

       public void clearBall(){//清除小球

              Color color = jp.getBackground();//

              g.setColor(color);//

              g.fillOval(X, Y, radios*2, radios*2);//用背景色,填充之前小球的印记

       }

       public void drawBall(){

              g.setColor(color);//

              g.fillOval(X, Y, radios*2, radios*2);

       }

       public void setprivate(){//设置小球属性

              Random random = new Random();//随机

               radios = 10+random.nextInt(10);//半径

               color=newColor(random.nextInt(255),random.nextInt(255),random.nextInt(255));//颜色

               Xspeed = 2 + random.nextInt(10);//x方向速度

               Yspeed = 2+random.nextInt(10);//y方向速度

       }

       public void exit(boolean flag){//设置停止标示

              stopFlag = flag;

       }

       public void setpause(boolean flag){//设置暂停标示

              pauseFlag = flag;

       }

       public void move(){//让我们的小球在面板中飞起来,同时碰到边界被弹回

 

              switch(Xdirection){//对于x方向

              case 2:X = X - Xspeed;break;//如果小球的运动方向向西,X值减小

              case 4:X = X + Xspeed;break;//如果小球的运动方向向东,X值增大

              }

              switch(Ydirection){//对于y方向

              case 1:Y = Y - Yspeed;break;//如果小球的运动方向向北,Y值减小

              case 3:Y = Y + Yspeed;break;//如果小球的运动方向向难,Y值增大

              }

              //如果碰到边界,方向改变

              if(X<0+radios*2){

                       Xdirection = 4;

              }

              if(X>jp.getWidth()-radios*2){

                       Xdirection = 2;

              }

              if(Y<0+radios*2){

                       Ydirection = 3;

              }

              //如果掉到下面,该小球线程结束

              if(Y>jp.getHeight()-radios*2){

                       //Ydirection = 1;

                       BallThread ball = new BallThread(jp);

                       this.exit(true);

                       for(int i = 0;i<Date.allBall.size();i++){

                                ball=Date.allBall.get(i);

                                if(X == ball.X&&Y == ball.Y){

                                         Date.allBall.remove(i);

                                }

                       }

              }

              //如果碰到滑块,弹回

              if(Y<500+radios/2&&Y>490-radios*2&&X>=Date.xband&&X<=(Date.xband+100)){

                       Ydirection = 1;

              }

       }

          //下面全是getset方法(定义以下方法主要在文件操作时用到):

       public int getXdirection() {

                return Xdirection;

       }

 

       public void setXdirection(int xdirection) {

                Xdirection = xdirection;

       }

 

       public int getYdirection() {

                return Ydirection;

       }

 

       public void setYdirection(int ydirection) {

                Ydirection = ydirection;

       }

 

       public int getRadios() {

                return radios;

       }

 

       public void setRadios(int radios) {

                this.radios = radios;

       }

 

       public Color getColor() {

                return color;

       }

 

       public void setColor(Color color) {

                this.color = color;

       }

 

       public int getXspeed() {

                return Xspeed;

       }

 

       public void setXspeed(int xspeed) {

                Xspeed = xspeed;

       }

 

       public int getYspeed() {

                return Yspeed;

       }

 

       public void setYspeed(int yspeed) {

                Yspeed = yspeed;

       }

 

       public int getX() {

                return X;

       }

 

       public void setX(int x) {

                X = x;

       }

 

       public int getY() {

                return Y;

       }

 

       public void setY(int y) {

                Y = y;

       }

 

       public int getLastX() {

                return LastX;

       }

 

       public void setLastX(int lastX) {

                LastX = lastX;

       }

 

       public int getLastY() {

                return LastY;

       }

 

       public void setLastY(int lastY) {

                LastY = lastY;

       }

 

       public int getXband() {

                return xband;

       }

 

       public void setXband(int xband) {

                this.xband = xband;

       }

 

       public int getYband() {

                return yband;

       }

 

       public void setYband(int yband) {

                this.yband = yband;

       }

 

       public boolean isPauseFlag() {

                return pauseFlag;

       }

       public boolean savePauseFlag() {

                return false;

       }

 

       public void setPauseFlag(boolean pauseFlag) {

                this.pauseFlag = pauseFlag;

       }

 

       public boolean isStopFlag() {

                return stopFlag;

       }

 

       public void setStopFlag(boolean stopFlag) {

                this.stopFlag = stopFlag;

       }

 

       public boolean isBeread() {

                return beread;

       }

 

       public void setBeread(boolean beread) {

                this.beread = beread;

       }

      

       public boolean saveBeread() {

                return true;

       }

 

       public JPanel getJp() {

                return jp;

       }

 

       public void setJp(JPanel jp) {

                this.jp = jp;

       }

      

}

 

定义了小球类之后,我们要考虑的另一个问题就是,我们什么时候要让小球在界面上飞,作为一个游戏,至少需要有开始按钮,当按钮被触发,游戏开始,所以我们需要用到的另一个工具就是事件监听器:

除了开始按钮,我们还为这个游戏做了其他功能:暂停,加一球,减一球;

接下来是代码:

文件一:Date,将小球使用一个链表存起来:

package jumpingBall;

 

import java.util.ArrayList;

import java.util.List;

 

public class Date {//此类专门存放全局变量

 public static int xband;

 public static int yband;

 public static List<BallThread> allBall = new ArrayList<BallThread>();//将链表声明为全局变量

}

 

 

package jumpingBall;

import java.awt.event.ActionEvent;

import java.awt.event.MouseMotionListener;

import java.util.ArrayList;

import java.util.List;

 

import javax.swing.JPanel;

 

import sun.net.www.content.audio.x_aiff;

 

 

 

public class ActionListener  implements java.awt.event.ActionListener{

     

       //private List<BallThread> allBall = new ArrayList<BallThread>();

       private JPanel jpanel;

       private int xband;

       private int yband;

      

       public ActionListener(JPanel jpanel){//构造方法

           //this.allBall = allBall;

           this.jpanel = jpanel;

       }

       public void actionPerformed(ActionEvent e) {

                // TODO Auto-generated method stub

                String cmd = e.getActionCommand(); //

                //选择开始选择 

                if(cmd.equals("Play")){

                            //如果场上没球,添加一个

                            if(Date.allBall.size()==0){

                                     BallThread ball = new BallThread(jpanel);

                                     Date.allBall.add(ball);

                                     ball.start();

                                    System.out.println("增加一个小球,场上小球个数变为:"+Date.allBall.size());

                            }

                            //如果场上有球,让所有静止的球动起来

                            for(int i = 0;i<Date.allBall.size();i++){

                                     BallThread ball= Date.allBall.get(i);

                                     ball.setpause(false);

                            }

                           // banLlistener band = new banLlistener(jpanel);

                            //jpanel.addMouseMotionListener(band);

                  }

                  //选择暂停选项

                  if(cmd.equals("Pause")){

                            //遍历场上所有小球,修改ballpause属性

                            for(int i = 0;i<Date.allBall.size();i++){

                                     BallThread ball= Date.allBall.get(i);

                                     ball.setpause(true);

                            }

                  }

                  //选择增球

                  if(cmd.equals("Add")){

                            BallThread ball = new BallThread(jpanel);

                            Date.allBall.add(ball);

                            ball.start();//运行线程

                           System.out.println("增加一个小球,场上小球个数变为:"+Date.allBall.size());

                  }

                  //选择减一球选项

                  if(cmd.equals("Delet one ball")&&Date.allBall.size()!=0){

                           BallThread ball = Date.allBall.get(Date.allBall.size()-1);

                           ball.exit(true);//修改存在选项(设置其消失)

                           Date.allBall.remove(Date.allBall.size()-1);//减一球

                           System.out.println("减少一个小球,场上小球个数变为:"+Date.allBall.size());

                  }

                 

       }

 

}

此外还要在界面类中敲上以下代码(黑色加粗部分)

//javax.swing.JFileChooser使用此来选择文件

package jumpingBall;

 

import java.awt.Toolkit;

import java.awt.BorderLayout;

import java.awt.Menu;

import java.io.IOException;

import java.util.ArrayList;

import java.util.List;

import javax.swing.JButton;

import javax.swing.JFileChooser;

import javax.swing.JFrame;

import javax.swing.JMenu;

import javax.swing.JMenuBar;

import javax.swing.JMenuItem;

import javax.swing.JPanel;

import javax.swing.JSeparator;

 

 

public class JFjumpingBall extends JFrame{

 

       /**

        * @param args

        * @throws IOException

        */

       public static void main(String[] args) throws IOException {

                // TODO Auto-generated method stub

 

                JFjumpingBall ballgame = new JFjumpingBall();

                ballgame.JFshow();

       }

      

       public void JFshow(){

                //建立一个窗体:

          double width = Toolkit.getDefaultToolkit().getScreenSize().width;//定义width获取显示器在该分辨率下的宽

          double height = Toolkit.getDefaultToolkit().getScreenSize().height;//定义height获取显示器在该分辨率下的高

          this.setSize((int)width,(int)height);//设置窗体大小

          this.setTitle("小鱼躲气泡");//设置标题

          this.setLocationRelativeTo(null);//设置窗口居中

          this.setDefaultCloseOperation(3);//设置关闭窗口程序停止运行

          this.setLayout(new BorderLayout());//设置窗体布局(边框式布局)

                JPanel northPanel = new JPanel();//北部面板

                JPanel jpanel = new JPanel();//面板

                JPanel southjpanel = new JPanel();//南部面板

                northPanel.setLayout(new BorderLayout());//设置北部面板布局方式

                JPanel northLeftPanel = new JPanel();//北部面板左边

                JPanel northRightPanel = new JPanel();//……右边

                JPanel northCenterPanel = new JPanel();//……中间

                northLeftPanel.setSize(100,100); //

                northRightPanel.setSize(100, 100);//

                JButton jbplay = new JButton("Play");//放置游戏按钮(开始游戏)

                JButton jbPause = new JButton("Pause");//放置游戏按钮(游戏暂停)

                JButton jbAdd  = new JButton("Add");//放置游戏按钮(增加)

                JButton deletone = new JButton("Delet one ball");//放置游戏按钮(减少一个小球)

                northCenterPanel.add(jbplay);//将按钮放置在北部面板的中间面板

                northCenterPanel.add(jbPause);//同上

                northCenterPanel.add(jbAdd);//同上

                northCenterPanel.add(deletone);//同上

                northPanel.add(northCenterPanel,BorderLayout.CENTER);//将北部面板的各部分面板加在北部面板里

                northPanel.add(northLeftPanel,BorderLayout.WEST);//

                northPanel.add(northRightPanel,BorderLayout.EAST);//

                this.add(northPanel,BorderLayout.NORTH);//布置窗体

                this.add(jpanel,BorderLayout.CENTER);//

                this.add(southjpanel,BorderLayout.SOUTH);//

                this.setJMenuBar(JMenuline(jpanel));//给窗体添加菜单栏(菜单栏方法:JMenuline;方法声明在下部)

                this.setVisible(true);//设置窗体可见

                //List<BallThread> allBall = new ArrayList<BallThread>();//

                ActionListener l = new ActionListener(jpanel);//动作监听器

                jbplay.addActionListener(l);//jbplay添加动作监听器

                jbPause.addActionListener(l);//jbPause添加动作监听器

                jbAdd.addActionListener(l);//jbAdd添加动作监听器

                deletone.addActionListener(l);//delete添加动作监听器

       }

       public JMenuBar JMenuline(JPanel jpanel){

          JMenuBar jme =new JMenuBar();//定义菜单栏

          JMenu menuF = new JMenu("文件(F");//菜单栏按钮

          JMenuItem jmiFO = new JMenuItem("保存(save)");//定义菜单栏按钮的选项(保存)

          JMenuItem jmiIO = new JMenuItem("读取(login)");//定义菜单栏按钮的选项(读取)

          foListener listener = new foListener();//定义保存监听器

          ioListener listener2 = new ioListener(jpanel);//定义读取监听器

          jmiFO.addActionListener(listener);//将保存监听器加在jmiFO

          jmiIO.addActionListener(listener2);//将读取监听器加在jmiIO

          menuF.add(jmiFO);//将(保存)菜单栏按钮加在menuF

          JSeparator jSeparator = new JSeparator();//定义水平分割线

          menuF.add(jSeparator);//将水平分割线加在menuF

          menuF.add(jmiIO);//将(读取)菜单栏按钮加在menuF

          jme.add(menuF);//讲此菜单栏按钮加在jme

          return jme;

       }

 

}

  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值