桌面弹球--学习笔记(二)

下面实现主界面类(BallFrame)和业务处理类(BallService)。
主界面类(BallFrame)中定义了:

一个业务处理类(BallService)的对象,通过调用BallService中的方法来处理业务逻辑;
一个初始化方法initialize(),用来初始化游戏的界面;

一个画板类(BallPanel),该内部类继承了JPanel,重写了void paint(Graphics g)画图方法。

     //定义一个JFrame的内部类来完成画图功能
     class BallPanel extends JPanel{
        //私有构造器
        private BallPanel(){           
        }
        //重写void paint(Graphics g)画图方法
        public void paint(Graphics g){
            //调用BallService的画图方法        }
    }

注意:这里不要写成print,是paint,否则就无法重写JPanel的paint()方法了,画板上也绘制不出任何图像,笔者经常犯这种低级错误,图片一直绘制不出来,后来一检查,才发现是函数名写错了!

 

下面来想办法实现动画效果,动画效果的实现奥秘也在这个绘图函数上,就是每隔很短的一段时间,就重新绘制一次弹球、砖块、挡板、道具。

 

之前编写坦克大战时,使用的方法是定义一个线程类,在run函数中使用循环结构来实现周期绘图:

class PaintThread implements Runnable{
		public void run() {
			while(true){
				repaint();
				try {
					Thread.sleep(100);
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
			}
		}	
	}
 

这里使用另外一种方法,使用javax.swing.Timer可以设定每隔一段时间周期就重复执行某个task,类似于Windows系统的计划任务或者Linux系统的crobtab。


在帮助文档里找到:
Timer(int delay, ActionListener listener)
创建一个 Timer 并将初始延迟和事件间延迟初始化为 delay 毫秒。
start()
启动 Timer,使它开始向其侦听器发送动作事件。
restart()
重新启动 Timer,取消所有挂起的触发并使它按初始延迟触发。

 

先定义每0.1秒执行一次的监听器,在定义过程中,改变各游戏对象状态的业务逻辑全部扔给BallService的对象ballService完成,但是在引用ballService时,出现了一个错误:“不能引用另一方法中定义的内部类中非终态变量ballService”。

public class BallFrame extends JFrame{
    //此处略去10行代码
    public void initialize(){
		//此处略去4行代码,若干注释
		BallService ballService = new BallService();
		//定义每0.1秒执行一次的监听器
		ActionListener task = new ActionListener(){
				public void actionPerformed(ActionEvent ae){
					//改变位置
//不能引用另一方法中定义的内部类中非终态变量ballService
					ballService.run();
					//刷新画板
					ballPanel.repaint();
				}
		};
		//此处略去14行代码,若干注释
	}
     //此处略去14行代码,若干注释
}

 

经过分析,将ballService声明为一个类属性,而不是initialize()中的一个局部变量。

 

public class BallFrame extends JFrame{
//此处略去10行代码
BallService ballService = null;
public void initialize(){
        //此处略去4行代码,若干注释
        ballService = new BallService();
        //定义每0.1秒执行一次的监听器
        ActionListener task = new ActionListener(){
                public void actionPerformed(ActionEvent ae){
                    //改变位置
                    ballService.run();
                    //刷新画板
                    ballPanel.repaint();
                }
        };
       //此处略去14行代码,若干注释
    }
    //此处略去14行代码,若干注释
}

 

定义好专用的监听器后,创建一个定时器,如下:

//设定每隔一个时间周期就重复执行的某个task
        if( timer!=null){
            //如果不是第一次游戏,重新启动游戏
            timer.restart();
        }else{
            //如果是第一次游戏,新建一个timer
            timer = new Timer(100,task);
            //启动timer
            timer.start();
        }

 

还有就是在游戏中,玩家是通过键盘的左右键来操纵挡板的左右移动的,还需要创建一个键盘监听器:

//验证该窗口是否添加了其它键盘监听器
        KeyListener [] keylisteners = this.getKeyListeners();
        //如果没有任何其它的键盘监听器,定义键盘监听器
        if(keylisteners.length ==0){
            KeyListener keyAdapter = new KeyAdapter(){
                public void keyPressed(KeyEvent ev){
                    //移动挡板的坐标
                    ballService.setStickPos(ke);
                }
            };
            //注册键盘监听器
            this.addKeyListener(keyAdapter);
        }        
 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值