首页 > 其他 > 详细

用AWT实现简易版飞机大战

时间:2016-03-29 10:46:28      阅读:241      评论:0      收藏:0      [点我收藏+]

主要需要的类:(解释取自API 1.6)
1.Frame -java.awt.Frame 是带有标题和边框 的顶层窗口
2.Graphics-java.awt.Graphics 是所有图形上下文的抽象基类,允许应用程序在组件以及闭屏图像上进行绘制,通俗的说,就是Graphics类提供方法来画图片,线段,矩形,椭圆等等
3.Rectangle-java.awt.Rectangle 指定坐标空间中的一个区域(矩形类),通过坐标空间中 Rectangle 对象左上方的点 (x,y)、宽度和高度可以定义这个区域
4.Image-java.awt.Image 是以特定平台的方式获取图形
5.BufferedImage-java.awt.image.BufferedImage 是Image的子类,描述具有可访问图像数据缓冲区的Image
6.ImageIO-javax.imageio.ImageIO 该类包含一些用来查找 ImageReader 和 ImageWriter 以及执行简单编码和解码的静态便捷方法
7.WindowAdapter-java.awt.event.WindowAdapter 是抽象类,此类中的方法为空,此类存在的目的是方便创建侦听器对象
8.WindowEvent-java.awt.event.WindowEvent 是窗口状态改变的低级别事件,比如打开,关闭,激活,停用等
9.KeyAdapter-java.awt.event.KeyAdapter 抽象类,目的是方便创建侦听键盘对象,KeyAdapter 对象实现 KeyListener 接口
10.KeyEvent-java.awt.event.KeyEvent 表示组件中发生键击的事件,当按下、释放或键入某个键时,组件对象(如文本字段)将生成此低级别事件。该事件被传递给每一个 KeyListener 或 KeyAdapter 对象,这些对象使用组件的 addKeyListener 方法注册,以接收此类事件,发生事件时,所有此类侦听器对象都将获得此 KeyEvent
11.URL-java.net.URL 代表一个统一资源定位符,它是指向互联网“资源”的指针,资源可以是简单的文件或目录,也可以是对更为复杂的对象的引用,比如对数据库或者搜索引擎的查询
12.IOException-java.io.IOException 当发生某种 I/O 异常时,抛出此异常
13.Thread -java.lang.Thread 线程 是程序中的执行线程,Java 虚拟机允许应用程序并发地运行多个执行线程

代码实现分析:
模拟飞机大战,首先我们需要两个类,飞机类和子弹类,封装了各自对象的属性和方法

1.飞机类:作为一个飞机首先得有个形状,这里用一张图片实现,设置它的长宽,起始坐标,飞机要上下左右移动,其实就是操作它的坐标,用布尔值判断飞机飞向哪个方向,然后对坐标值进行增减,以及布尔值判断飞机生死
飞机类所要实现的方法,第一,需要在我们的窗口将它自己展现出来;第二,它移动时对坐标相应的操作;第三,我们需要实现的效果是按下键盘的上下左右键,飞机对应的上下左右移动,松开键盘,飞机就停止移动;第四,为了判断飞机的生死需要返回可容纳飞机的最小矩形,这里就是容纳飞机的最小矩形如果和子弹最小矩形有相交,则飞机死亡

package cn.wwy.plane;

import java.awt.Graphics;
import java.awt.Image;
import java.awt.Rectangle;
import java.awt.event.KeyEvent;
import cn.wwy.util.GameUtil;

public class Plane {
    Image img;
    double x,y;
    double width,height;
    boolean left,up,right,down;//飞机飞行方向
    int speed=10;//飞机飞行的速度
    boolean live=true;

    public Plane(String path,double x,double y,double width,double height){
        super();
        this.img=GameUtil.getImage(path);//GameUtil见下文
        this.x=x;
        this.y=y;
        this.width=width;
        this.height=height;
    }

    public Plane(){

    }

    /**
     * 画飞机
     * @param g
     */
    public void draw(Graphics g){
        if(live){
            g.drawImage(img, (int)x, (int)y, (int)width, (int)height, null);
            move();
        }
    }

    /**
     * 飞机沿八个方向飞行
     */
    public void move(){
        if(left){
            x-=speed;
        }
        if(right){
            x+=speed;
        }
        if(up){
            y-=speed;
        }
        if(down){
            y+=speed;
        }
    }

    /**
     * 按下键盘方向键,e.getKeyCode()会返回一个具体的数字,键盘上每一个按键都代表一个数字
     * @param e
     */
    public void addDirection(KeyEvent e){
        switch (e.getKeyCode()) {
        case 37://左键
            left=true;
            break;
        case 38://上键
            up=true;
            break;
        case 39://右键
            right=true;
            break;
        case 40://下键
            down=true;
            break;
        default:
            break;
        }
    }

    /**
     * 放开键盘方向键
     * @param e
     */
    public void minusDirection(KeyEvent e){
        switch (e.getKeyCode()) {
        case 37://左键
            left=false;
            break;
        case 38://上键
            up=false;
            break;
        case 39://右键
            right=false;
            break;
        case 40://下键
            down=false;
            break;
        default:
            break;
        }
    }

    /**
     * 返回一个刚好容纳飞机的矩形
     * @return
     */
    public Rectangle getRect(){
        Rectangle r=new Rectangle((int)x,(int)y,(int)width,(int)height);
        return r;
    }
}

2.子弹类: 类似于飞机类,子弹类也需要坐标控制它的飞行,子弹大小,由于子弹是无规则的在窗口随意运动,所以需要设置子弹的角度,子弹类要实现的方法比较简单,第一,画无规则从窗口中心散出的子弹;第二,返回最小矩形

package cn.wwy.plane;

import java.awt.Color;
import java.awt.Graphics;
import java.awt.Rectangle;
import cn.wwy.util.Constant;

/**
 * 子弹类
 * @author wwyDEPP
 */
public class Bullet {
    double x,y;
    double degree;
    int speed=10;//子弹速度
    int width=10;
    int height=10;

    public Bullet() {
        super();
        this.degree = Math.random()*Math.PI*2;//随机生成子弹运行角度(0-2PI)
        x=Constant.GAME_WIDTH/2;//关于Constant见下文
        y=Constant.GAME_HEIGHT/2;
    }

    /**
     * 画子弹
     * @param g
     */
    public void draw(Graphics g){
        Color c=g.getColor();
        g.setColor(Color.yellow);
        g.fillOval((int)x, (int)y, width, height);//画圆点

        x+=speed*Math.cos(degree);
        y+=speed*Math.sin(degree);

        //保证子弹不在窗口内移动,关于Constant见下文
        if(x>Constant.GAME_WIDTH-60||x<0){
            degree=Math.PI-degree;
            double tempX=x;
            double tempY=y;
        }
        if(y>Constant.GAME_HEIGHT||y<30){
            degree=-degree;
            double tempY=y;
        }
        //保证使用完画笔以后,画笔颜色不变
        g.setColor(c);
    }

    /**
     * 返回子弹的矩形
     * @return
     */
    public Rectangle getRect(){
        Rectangle r=new Rectangle((int)x,(int)y,(int)width,(int)height);
        return r;
    }
}

3.常量类: 封装了一些常量,便于修改,在飞机类和子弹类中也使用了该类

package cn.wwy.util;

/**
 * 游戏中用到的常量
 * @author wwyDEPP
 *
 */
public class Constant {
    public static final int GAME_WIDTH=400;//窗口宽
    public static final int GAME_HEIGHT=600;//窗口长
}

4.工具类: 该工具类只封装了加载图片这个方法,为便于调用方法设置为静态

package cn.wwy.util;

import java.awt.Image;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.net.URL;
import javax.imageio.ImageIO;

/**
 * 游戏开发中常用的工具类(如:加载图片)
 * @author wwyDEPP
 */
public class GameUtil {
    //传入图片的地址,加载图片,注意处理IO异常
    public static Image getImage(String path){
        URL u=GameUtil.class.getClassLoader().getResource(path);
        BufferedImage img=null;
        try {
            img=ImageIO.read(u);
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        return img;
    }
}

5.飞机死亡爆炸类: 爆炸也需要爆炸地点即坐标,用一系列图片来实现爆炸,所以也需要设置图片的大小长度和宽度,以及存放这些图片的数组,还需要设置一个int变量来计数,确保你一系类图片加载结束以后就不再爆炸,不会炸个没完没了

package cn.wwy.plane;

import java.awt.Graphics;
import java.awt.Image;
import cn.wwy.util.GameUtil;
/**
 * 爆炸类
 * 数组图片的切换
 * @author wwyDEPP
 */
public class Explode {
    double x,y;
    double width,height;
    int count=0;
    static Image[] imgs=new Image[10];

    //使用静态块加载图片组,只加载一次,从属于类
    static{
        for(int i=0;i<imgs.length;i++){
            imgs[i]=GameUtil.getImage("images/explode"+(i+1)+".jpg");
            //通过调用这个方法,真实的把图片加载出来
            imgs[i].getWidth(null);
        }
    }

    public Explode(double x,double y,double width,double height){
        super();
        this.x=x;
        this.y=y;
        this.width=width;
        this.height=height;
    }

    public void draw(Graphics g){
        if(count<10){
            g.drawImage(imgs[count],(int)x,(int)y,(int)width,(int)height, null);
            count++;
        }
    }
}

到这一步,准备工作就做完了,接下来就要把创建窗口类来实现这个游戏,窗口类需要继承Frame类,这里多加了一部,把经常使用的关于窗口的方法包装成一个独立的MyFrame类,它继承Frame类,然后让游戏窗口类直接继承MyFrame类

6.MyFrame类:
第一,窗口的加载,那么就得先聊聊Frame类

技术分享
Window 对象是一个没有边界和菜单栏的顶层窗口,Windows类提供了方法来设置窗口的大小,位置等信息
在我们加载这个窗口的时候就需要设置这些值,设置好以后就可以运行出一个空白的带框窗口了

技术分享

第二,定义一个内部线程类,因为我们的飞机和子弹都是时刻在运动的,所以就需要不断的创建新的线程,使飞机和子弹动起来

class PaintThread extends Thread {
        public void run(){
            while(true){
                repaint();
                try {
                    //线程休眠,控制运动速度
                    Thread.sleep(40);//1s=100
                } catch (InterruptedException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
            }
        }
    }

第三,AWT存在闪烁问题,这里使用双缓冲技术消除闪烁,在spring会自动消除闪烁

private Image offScreenImage=null;
public void update(Graphics g){
    if(offScreenImage==null){
        offScreenImage=this.createImage(Constant.GAME_WIDTH,Constant.GAME_HEIGHT);
    }
    Graphics gOff=offScreenImage.getGraphics();
    paint(gOff);
    g.drawImage(offScreenImage,0,0,null);
}

7.窗口类:
第一,把飞机和子弹画在窗口里面,画飞机的条件就是飞机还是存活着的,然后直接调用飞机对象的draw方法,画子弹的时候,因为子弹数目比较多,所以这里需要用到集合的知识,把子弹放在一个集合中(这里没有使用泛型,一般建议使用),每创建一个子弹,都检测它是否与飞机碰撞,若是,则飞机死亡爆炸

while(plane.live){
    Date newTime=new Date();
    int period2=(int)(newTime.getTime()-startTime.getTime())/1000;
    pringInfo(g, "时间:"+period2+"秒", 30,Color.blue,Constant.GAME_WIDTH-150,60);
    break;
}
for(int i=0;i<bulletList.size();i++){
    Bullet b=(Bullet)bulletList.get(i);
    b.draw(g);

    //检测子弹和飞机的碰撞
    boolean peng=b.getRect().intersects(plane.getRect());
        if(peng){
            //飞机死掉
            plane.live=false;
        }   
}

未完。。。

用AWT实现简易版飞机大战

原文:http://blog.csdn.net/bazingaea/article/details/50997116

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!