需购买观看

全屏

13.2.4 多线程和内部类实现动画效果(0.4版)


【专业IT培训机构,真正零首付入学www.bjsxt.com


·增加绘制窗口的线程类

      前三个版本,我们步步为营,每个小版本都有功能的突破。但是,目前为止我们的窗口仍然是静态的,并没有像真正的游戏窗口那样“各种动、各种炫”。本节我们结合多线程实现动画效果。

      我们在MyGameFrame类中定义“重画窗口线程PaintThread类”,为了方便使用MyGameFrame类的属性和方法,我们将PaintThread定义成内部类。

【示例13-6】MyGameFrame类:增加PaintThread内部类

public class MyGameFrame extends Frame {
	//其他代码和上个版本一致,限于篇幅,此处只呈现新增的代码
	/**
	 * 定义一个重画窗口的线程类,是一个内部类
	 * @author 高淇
	 *
	 */
	class PaintThread extends Thread {
		public void run(){
			while(true){
				repaint();
				try {
					Thread.sleep(40); //1s = 1000ms
				} catch (InterruptedException e) {
					e.printStackTrace();
				}   
			}
		}
	}	
}

      定义好PaintThread内部类后,我们还需要在窗口的launchFrame()方法中创建线程对象和启动线程:

【示例13-7】launchFrame方法:增加启动重画线程代码

public void launchFrame(){
	//本方法其他代码和上个版本一致,限于篇幅,只显示新增的代码
	new PaintThread().start();  //启动重画线程
}

【示例13-8】示例13-7完成后的MyGameFrame类

package cn.sxt.game;

import java.awt.Frame;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;

public class MyGameFrame extends Frame {
	Image bgImg = GameUtil.getImage("images/bg.jpg");
	Image planeImg = GameUtil.getImage("images/plane.png");

	static int count = 0;
	
	//paint方法作用是:画出整个窗口及内部内容。被系统自动调用。
	@Override
	public void paint(Graphics g) {  
		g.drawImage(bgImg, 0, 0, null);
		System.out.println("调用paint,重画窗口,次数:"+(count++));
		g.drawImage(planeImg, 200, 200, null);
	}	
    /**
     * 定义一个重画窗口的线程类,是一个内部类
     * @author 高淇
     */
    class PaintThread extends Thread {
	    public void run(){
		    while(true){
			    repaint();
			    try {
				    Thread.sleep(40); //1s = 1000ms
			    } catch (InterruptedException e) {
				    e.printStackTrace();
			    }   
		    }
	    }
    }	
	
	public void launchFrame(){
		//在游戏窗口打印标题
		setTitle("尚学堂学员_程序猿作品");
		//窗口默认不可见,设为可见
		setVisible(true);
		//窗口大小:宽度500,高度500
		setSize(500, 500);
		//窗口左上角顶点的坐标位置
		setLocation(300, 300);
		
		//增加关闭窗口监听,这样用户点击右上角关闭图标,可以关闭游戏程序
		addWindowListener(new WindowAdapter() {
			@Override
			public void windowClosing(WindowEvent e) {
				System.exit(0);
			}
		});
		new PaintThread().start();  //启动重画线程
	}
	public static void main(String[] args) {
		MyGameFrame f = new MyGameFrame();
		f.launchFrame();
	}
}

      执行结果如图13-9所示:

图13-9 示例13-8运行效果图.png

图13-9 示例13-8运行效果图

      根据控制台打印的数据,我们发现paint方法被系统反复调用,一秒N次。按照线程中我们规定的是40ms画一次,1秒大约调用25次(1秒=1000ms)。也就是说,“现在,窗口被1秒重复绘制25次”,如果我们调整飞机的位置变量,每次画飞机位置都不一致,在肉眼看来不就实现动画了吗?

·调整飞机位置,让飞机动起来

      之前,我们绘制飞机的代码为:g.drawImage(planeImg, 200, 200, null); 每次都绘制到(200,200)这个坐标位置。我们将位置定义为变量planeX,planeY,每次绘制变量值都发生变化(planeX += 3; ),这样飞机就动起来了。 代码如下:

【示例13-9】改变飞机的坐标位置

public class MyGameFrame extends Frame {
	Image bgImg = GameUtil.getImage("images/bg.jpg");
	Image planeImg = GameUtil.getImage("images/plane.png");
    //将飞机的坐标设置为变量,初始值为(200,200)
	int planeX=200;
	int planeY=200;
	
	static int count = 0;
	
	//paint方法作用是:画出整个窗口及内部内容。被系统自动调用。
	@Override
	public void paint(Graphics g) {  
		g.drawImage(bgImg, 0, 0, null);
		System.out.println("调用paint,重画窗口,次数:"+(count++));
		//不再是写死的位置
		g.drawImage(planeImg, planeX, planeY, null);
        //每次画完以后改变飞机的x坐标
		planeX +=3;
	}	
    //限于篇幅,其他代码不放此处,和上个版本一致!
}

      运行程序,我们发现,飞机真的飞起来了!

分类导航
点击按住视频可拖动

缩小

关闭

  • 正在学习
  • 北京总部地址:北京市海淀区西三旗街道建材城西路中腾建华商务大厦东侧二层尚学堂
  • 咨询电话:400-009-1906 010-56233821
  • Copyright 2007-2015 北京尚学堂科技有限公司
  • 京ICP备13018289号-1 京公网安备11010802015183