Java修炼——飞机生存小游戏

Wesley13
• 阅读 523

在学习了java入门的课程之后,自己动手跟着老师写的一个小游戏,用的是Frame。总共有七个类。
1.飞机游戏的主窗口(MyGameFrame)继承Frame。

package com.bjsxt.plane;

import java.awt.Color;
import java.awt.Font;
import java.awt.Frame;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.io.Writer;
import java.util.Date;

import javax.swing.JFrame;

/**
 * 飞机游戏的主窗口
 * @author 机械师
 *
 */
public class MyGameFrame extends Frame{

    //导入图片
    Image planeImage=GameUtil.getImage("images/plane.png");
    Image bg=GameUtil.getImage("images/bg.jpg");

    Plane plane=new Plane(planeImage,250,250);
    Shell[] shells=new Shell[50];
    Explode bao;
    Date startTime=new Date();
    Date endTime;
    int period;
    //帮助绘制窗口
    @Override
    public void paint(Graphics g) {//自动调用
        g.drawImage(bg, 0, 0, null);    
        plane.drawSelf(g);//画飞机
        //        画出所有的炮弹
        for(int i=0;i<shells.length;i++){
            shells[i].draw(g);
            boolean peng=shells[i].getRect().intersects(plane.getRect());
            
            if (peng) {
                plane.live=false;
                if (bao==null) {     
                    bao=new Explode(plane.x, plane.y);
                    endTime=new Date();
                    period=(int)((endTime.getTime()-startTime.getTime())/1000);
                }
                
            }
            if (!plane.live) {
                Color c=g.getColor();
                Font f=new Font("楷体", Font.BOLD, 25);
                g.setFont(f);
                g.setColor(Color.red);
                g.drawString("游戏结束!!  您已存活:"+period+"秒", 110, 250);
                bao.draw(g);
                g.setColor(c);
            }
        }
    }

    class PaintThread extends Thread{
        //帮助我们反复的重画窗口
        @Override
        public void run() {
            while (true) {
                repaint();

                try {
                    Thread.sleep(40);//一秒画25次窗口
                } catch (InterruptedException e) {    
                    e.printStackTrace();
                }
            }
        }
    }

    //定义键盘监听
    class KeyMonitor extends KeyAdapter{

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

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

    }

    /**
     * 初始化窗口
     */
    public void launchFrame(){
        setTitle("bjsxt_yxf--飞机躲避子弹小游戏游戏");
        setVisible(true);//true表示窗口可见
        setSize(Constant.GAME_WIDTH,Constant.GAME_HEIGHT);
        setLocation(300,300);
        //增加监听事件,关闭动作,点击窗口的关闭按钮,程序便已经结束。
        this.addWindowListener(new WindowAdapter() {
            @Override
            public void windowClosing(WindowEvent e) {
                System.exit(0);
            }

        });
        new PaintThread().start();//启动重画窗口的线程
        addKeyListener(new KeyMonitor());//增加键盘的监听

        //初始化50个炮弹
        for (int i = 0; i < shells.length; i++) {
            shells[i]=new Shell();
        }
    }
    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);
    }
}

2.游戏的图片导入工具类(GameUtil)

package com.bjsxt.plane;

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

import javax.imageio.ImageIO;

public class GameUtil {
    //将工具类私有化
    private GameUtil(){
        
    }
    /**
     * 返回指定文件的路径对象
     * @param path
     * @return
     */
    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;
        
    }
}

3.游戏物体的父类,游戏里的炮弹,飞机的属性都是继承这个类(GameObject)

package com.bjsxt.plane;

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

/**
 * 游戏物体的父类
 * @author 机械师
 *
 */
public class GameObject {
     Image image;
     double x,y;
     int speed;
     int width,height;
     
    public void drawSelf(Graphics g){
        g.drawImage(image, (int)x, (int)y, null);
    }

    public GameObject(Image image, double x, double y, int speed, int width,
            int height) {
        super();
        this.image = image;
        this.x = x;
        this.y = y;
        this.speed = speed;
        this.width = width;
        this.height = height;
    }

    public GameObject(Image image, double x, double y) {
        super();
        this.image = image;
        this.x = x;
        this.y = y;
    }

    public GameObject() {

    }
    /**
     * 返回物体所在的矩形
     * @return
     */
    public Rectangle getRect(){
        return new Rectangle((int)x, (int)y, width, height);
        
    }
    
}

4.爆炸类,飞机死亡的一系列动画操作(Explode)

package com.bjsxt.plane;

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

/**
 * 爆炸类
 * @author 机械师
 *
 */
public class Explode {
    double x,y;
    
    static Image[] imgs=new Image[16];
    static{
        for (int i = 0; i < imgs.length; i++) {
            imgs[i]=GameUtil.getImage("explode/e"+(i+1)+".gif");
            imgs[i].getWidth(null);
        }
    }
    
    int 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;
    }
}

5.飞机类,里面有飞机的速度,键盘按键设置等属性(Plane)

package com.bjsxt.plane;

import java.awt.Graphics;
import java.awt.Image;
import java.awt.event.KeyEvent;
/**
 * 飞机类
 * @author 机械师
 *
 */
public class Plane extends GameObject {
    boolean left,right,down,up;
    int speed=4;
    boolean live=true;
    
    public void drawSelf(Graphics g){
        
        if (live) {
            g.drawImage(image, (int)x, (int)y, null);
            if (left) {
                x-=speed;
            }
            if (right) {
                x+=speed;
                
            }
            if (up) {
                y-=speed;
                
            }
            if (down) {
                y+=speed;
                
            }
        }
    }
    
    public Plane(Image image,double x,double y){
         this.image=image;
         this.x=x;
         this.y=y;
         this.speed=speed;
         this.width=image.getWidth(null);
         this.height=image.getHeight(null);
    }
    
    public void addDirection(KeyEvent e){
        switch (e.getKeyCode()) {
        case KeyEvent.VK_LEFT:
            left=true;
            speed++;
            break;
        case KeyEvent.VK_UP:
            up=true;
            speed++;
            break;
        case KeyEvent.VK_RIGHT:
            right=true;
            speed++;
            break;
        case KeyEvent.VK_DOWN:
            down=true;
            speed++;
            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;
        }
    }
}

6.炮弹类,里面包含了炮弹在固定位向任意方向发出数个炮弹,以及碰撞边界弹回。(Shell)

package com.bjsxt.plane;

import java.awt.Color;
import java.awt.Graphics;

/**
 * 炮弹类
 * @author 机械师
 *
 */
public class Shell extends GameObject{
    
    double degree;
    public Shell(){
        x=200;
        y=200;
        speed=3;
        width=10;
        height=10;
        degree=Math.random()*Math.PI*2;//o-2π之间的随机数
    }
    
    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);
        
        if (x<0||x>Constant.GAME_WIDTH-width) {
            degree=Math.PI-degree;
            speed++;
        } else if(y<30||y>Constant.GAME_HEIGHT-height){
            degree=-degree;
            speed++;
        }
        g.setColor(c);
    }
    
}

7.常数类。存储游戏边界的大小(Constant)

package com.bjsxt.plane;

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

此小游戏在一开始,我们是继承Jframe的,但是由于在写到后面,看运行画面的时候还是有很多点闪烁,因此我们就改回到Frame,并且在主窗口类中使用了双缓冲。

    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修炼——飞机生存小游戏

点赞
收藏
评论区
推荐文章
blmius blmius
2年前
MySQL:[Err] 1292 - Incorrect datetime value: ‘0000-00-00 00:00:00‘ for column ‘CREATE_TIME‘ at row 1
文章目录问题用navicat导入数据时,报错:原因这是因为当前的MySQL不支持datetime为0的情况。解决修改sql\mode:sql\mode:SQLMode定义了MySQL应支持的SQL语法、数据校验等,这样可以更容易地在不同的环境中使用MySQL。全局s
Jacquelyn38 Jacquelyn38
2年前
2020年前端实用代码段,为你的工作保驾护航
有空的时候,自己总结了几个代码段,在开发中也经常使用,谢谢。1、使用解构获取json数据let jsonData  id: 1,status: "OK",data: 'a', 'b';let  id, status, data: number   jsonData;console.log(id, status, number )
皕杰报表之UUID
​在我们用皕杰报表工具设计填报报表时,如何在新增行里自动增加id呢?能新增整数排序id吗?目前可以在新增行里自动增加id,但只能用uuid函数增加UUID编码,不能新增整数排序id。uuid函数说明:获取一个UUID,可以在填报表中用来创建数据ID语法:uuid()或uuid(sep)参数说明:sep布尔值,生成的uuid中是否包含分隔符'',缺省为
Wesley13 Wesley13
2年前
Java日期时间API系列31
  时间戳是指格林威治时间1970年01月01日00时00分00秒起至现在的总毫秒数,是所有时间的基础,其他时间可以通过时间戳转换得到。Java中本来已经有相关获取时间戳的方法,Java8后增加新的类Instant等专用于处理时间戳问题。 1获取时间戳的方法和性能对比1.1获取时间戳方法Java8以前
Stella981 Stella981
2年前
SpringBoot整合Redis乱码原因及解决方案
问题描述:springboot使用springdataredis存储数据时乱码rediskey/value出现\\xAC\\xED\\x00\\x05t\\x00\\x05问题分析:查看RedisTemplate类!(https://oscimg.oschina.net/oscnet/0a85565fa
Easter79 Easter79
2年前
SpringBoot整合Redis乱码原因及解决方案
问题描述:springboot使用springdataredis存储数据时乱码rediskey/value出现\\xAC\\xED\\x00\\x05t\\x00\\x05问题分析:查看RedisTemplate类!(https://oscimg.oschina.net/oscnet/0a85565fa
Wesley13 Wesley13
2年前
00:Java简单了解
浅谈Java之概述Java是SUN(StanfordUniversityNetwork),斯坦福大学网络公司)1995年推出的一门高级编程语言。Java是一种面向Internet的编程语言。随着Java技术在web方面的不断成熟,已经成为Web应用程序的首选开发语言。Java是简单易学,完全面向对象,安全可靠,与平台无关的编程语言。
Stella981 Stella981
2年前
JOptionPane修改图标
1.在Linux平台下.JOptionPane会显示Java默认的图标,在window平台不显示图标,如何替换这个图标了?2JOptionPane.setIcon(Icon)修改的是内容区域的icon,而不是左上角的Icon.所以需要通过修改Jdialog/Frame的图标来达到修改默认图标的问题.3.代码:if(JOptio
Wesley13 Wesley13
2年前
MySQL部分从库上面因为大量的临时表tmp_table造成慢查询
背景描述Time:20190124T00:08:14.70572408:00User@Host:@Id:Schema:sentrymetaLast_errno:0Killed:0Query_time:0.315758Lock_
Python进阶者 Python进阶者
3个月前
Excel中这日期老是出来00:00:00,怎么用Pandas把这个去除
大家好,我是皮皮。一、前言前几天在Python白银交流群【上海新年人】问了一个Pandas数据筛选的问题。问题如下:这日期老是出来00:00:00,怎么把这个去除。二、实现过程后来【论草莓如何成为冻干莓】给了一个思路和代码如下:pd.toexcel之前把这