欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

Java 实现飞机大战小游戏

程序员文章站 2024-03-18 14:58:40
...

游戏简介:通过键盘来控制飞机移动,躲避炮弹,碰到炮弹则游戏结束!
游戏项目共有七个类,包含了一些java面向对象基础知识。

首先是MygameFrame游戏窗口类:

import java.awt.*;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.util.Date;


public class MygameFrame extends Frame {//游戏窗口类继承JFrame类
    boolean flag=true;//在这里设置了一个标志,来控制窗口的刷新
    Image planeImg=GameUtil.getImage("images/plane.png");
    Image bg=GameUtil.getImage("images/bg.jpg");
    Image over=GameUtil.getImage("images/over.jpg");//调用GameUtil内重写的函数得到图片
    Plane plane=new Plane(planeImg,250,250);//飞机类对象
    Shell[] shells=new Shell[10];//炮弹数组,用来存放多个炮弹
    Explode ep;//声明爆炸类对象,不需要new,在发生接触再new 
    Date startTime=new Date();//程序开始时new
    Date endTime;//等游戏结束再new
    int period;//计算游戏持续时间
    @Override
    public void paint(Graphics g) {//piant会自动被系统调用一次
        super.paint(g);
        g.drawImage(bg,1,1, this.getWidth(),this.getHeight(),null);//设置背景图片
        plane.drawSelf(g);
     for (Shell shell : shells) {//循环遍历炮弹类数组
           shell.draw(g);
       boolean p = shell.getRect().intersects(plane.getRect());//飞机与炮弹接触检测,用矩形类的intersects方法,测试对象是否接触
            if (p) {
                System.out.println("碰了");
                plane.gameover = true;
           if(ep==null){ep=new Explode(plane.x,plane.y); }
                ep.newimgs();
                ep.draw(g);
                flag=false;//线程执行的标志
                g.clearRect(0,0,500,500);//清空画布
                endTime=new Date();
              g.drawImage(over,0,25,this.getWidth(),this.getHeight(),null);//结束的背景图
                period=(int)((endTime.getTime()-startTime.getTime())/1000);
                g.setColor(Color.blue);
                g.drawString("记录"+period+"秒",10,100);
            }
        }
    }
    class PaintThread extends Thread{
        //内部类,可以调用外部类方法,多线程用于反复重画窗口
        @Override
        public void run() {
            while(flag){
                //System.out.println("窗口刷新");
                repaint();
                try {
                    Thread.sleep(40);//40ms
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    public void launchFrame(){//初始化窗口
        this.setTitle("肖杰航作品");//设置标题
        this.setVisible(true);//窗口可视化
        this.setSize(Constant.GAME_WIDTH,Constant.GAME_HEIGHT); //设置窗口大小与坐标
        this.setLocation(300,300);

        this.addWindowListener(new WindowAdapter() {
            @Override
            public void windowClosing(WindowEvent e) {
                System.exit(0);//重写该方法,使关闭窗口后程序结束运行!
            }
        });

    new PaintThread().start();//启动重画窗口线程,因为paint()方法只会自动调用一次
        addKeyListener(new KeyMonitor());//给窗口增加键盘监听

        for (int i = 0; i <shells.length ; i++) {//初始化炮弹数组内每个炮弹对象
            shells[i]=new Shell();
        }

    }

   class KeyMonitor extends KeyAdapter{//键盘监听内部类,继承 KeyAdapter适配器,重写其中两个方法,按下与释放键


       @Override
       public void keyPressed(KeyEvent e) {
           plane.addDirection(e);
       }

       @Override
       public void keyReleased(KeyEvent e) {
           plane.minusDirection(e);
       }
   }






    public static void main(String[] args) {//主函数调用游戏窗口类
        MygameFrame f=new MygameFrame();
        f.launchFrame();

    }


    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);
    }
   }/*如果窗口类继承自:java.swing.JFrame,则本身已经不完美的解决了闪烁问题,双缓冲是用于Frame,能更好的解决闪烁问题*/

先定义一个常量类,用于存放项目常量

public class Constant{
    public static final int GAME_WIDTH=500;
    public static final int GAME_HEIGHT=500;
}

ImageIO类来实现图片加载,并且为了代码的复用性,将图片加载的方法封装到GameUtil工具类中

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

public class GameUtil {//游戏工具类
    private GameUtil(){}
    public static Image getImage(String path){//获得图片类,输入值是路径,返回值是图片
        BufferedImage bi =null;
        try{
            URL u=GameUtil.class.getClassLoader().getResource(path);
            bi= ImageIO.read(u);
        }catch(IOException e){
            e.printStackTrace(); //在命令行打印异常信息在程序中出错的位置及原因
        }
         return bi;
    }
}

我们知道,在游戏里的物体例如飞机,炮弹有相同的共性,初始位置,长度宽度,速度等。所以我们给这些类先创建一个父类叫做游戏物品类,以便于飞机类继承。

import java.awt.*;

/**游戏内所有物体父类,因为游戏里的物体属性类似
 *
 */
public class GameObject {
     Image img;//图片
     double x,y;//坐标
     int speed;//移动速度
     int width,height;

    public GameObject() {//无参构造
    }

    public GameObject(Image img, double x, double y) {//构造器
        this.img = img;
        this.x = x;
        this.y = y;
    }

    public void drawSelf(Graphics g){//定义一个画图函数
          g.drawImage(img,(int)x,(int)y,null);
    }

    public Rectangle getRect(){//返回图片所在矩形,用于检测碰撞
        return new Rectangle((int)x,(int)y,width,height);//java的矩形类

    }
}

在父类里特地写了getRect()方法,得到物体的位置矩形框,以便后面判断飞机与炮弹的接触
然后写完父类就可以创建子类飞机类

import java.awt.*;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;

ublic class Plane extends GameObject {

    boolean left,right,up,down;//设置标志,用于键盘监听
     boolean gameover=false;//设置标志,用于判断何时结束绘图
    public void drawSelf(Graphics g){//重写父类中的方法
      if(gameover==false){
        g.drawImage(img,(int)x,(int)y,null);
        if(left){//当键盘左键,横坐标左移一个单位
            x=x-speed;
        }
        if(right){
            x=x+speed;
        }
        if(up){
            y=y-speed;
        }
        if(down){
            y=y+speed;
        }
    }}

    public Plane(Image img,double x,double y){
        this.img=img;
        this.x=x;
        this.y=y;
        this.speed=10;
        this.width=img.getWidth(null);//宽度与你导入的飞机图片一致
        this.height=img.getHeight(null);
      }

      public void addDirection(KeyEvent e){//方法实现按下某个键,加方向
        switch(e.getKeyCode()){
            case KeyEvent.VK_LEFT:left=true;break;
            case KeyEvent.VK_UP:up=true;break;
            case KeyEvent.VK_RIGHT:right=true;break;
            case KeyEvent.VK_DOWN:down=true;break;
        }

      }
      public void minusDirection(KeyEvent e){//方法实现松开某个键,不再加方向
          switch(e.getKeyCode()){
              case KeyEvent.VK_LEFT:left=false;break;
              case KeyEvent.VK_UP:up=false;break;
              case KeyEvent.VK_RIGHT:right=false;break;
              case KeyEvent.VK_DOWN:down=false;break;
        }

    }
}

接下来是炮弹类,一样继承了物品类

import java.awt.*;

/*炮弹类
 */
public class Shell  extends GameObject{
    double degree;//角度,炮弹多了一个属性,可以各个方向移动
    public Shell(){
        x=200;//炮弹初速左边,可以设置为随机数
        y=200;
        width=10;
        height=10;
        speed=3;
        degree=Math.random()*Math.PI*2;//炮弹发射角度随机产生

    }

    public void draw(Graphics g){//自己新增的方法,因为画炮弹不用图片,与飞机类不太一样。

        Color c=g.getColor();//记录当前颜色以便还原
        g.setColor(Color.orange);//修改炮弹颜色
        g.fillOval((int)x,(int)y,width,height);//填充椭圆
        x=x+speed*Math.cos(degree);//炮弹移动轨迹
        y=y+speed*Math.sin(degree);
        if(x<=0||x>=Constant.GAME_WIDTH-width){//碰左右边界,角度对称变化
            degree=Math.PI-degree;
        }
        if(y<=30||y>=Constant.GAME_HEIGHT-height){//碰上下边界,角度反向变化
            degree=-degree;
        }
            g.setColor(c);}
    }

最后为了实现飞机与炮弹接触产生动画效果,写了一个爆炸类
类里使用图片数组轮播实现动态效果,使用数组保存图片信息

import java.awt.Graphics;
import java.awt.Image;

/*
 * 爆炸类
 */
public class Explode {
    double x,y;//设置效果显示位置
    Image[] imgs = new Image[16];
    public void newimgs() {
   for(int i=0;i<16;i++){
      imgs[i]=GameUtil.getImage("images/exp/e"+(i+1)+".gif");
}//图片命名规范,以e1~e16
    }
     int count;
    //计数器count来控制到底画哪张图片
    public void draw(Graphics g){
        if(count<=15){
            g.drawImage(imgs[count], (int)x, (int)y, null);
            count++;
        }
    }

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

效果图:
Java 实现飞机大战小游戏
Java 实现飞机大战小游戏

相关标签: java