直升飞机java游戏_java飞机游戏

飞机游戏

需求分析

本意是做一个类似雷霆战机的小游戏, 但超出了知识范围, 简化成为了一个没有敌人, 生命, 得分, 菜单栏的小游戏, 游戏内容变成了飞机闪躲从固定位置发出的多个子弹, 计算存活时间的样子

游戏窗口通过Frame实现, 双缓冲技术解决闪烁问题

使用paint方法画出所有游戏内容, 且定义了一个线程不断重画窗口

增加键盘监听实现飞机的移动

使用ArrayList<>储存炮弹对象并画出, 并实现炮弹的碰撞反弹

利用返回物体矩形区域判断物体是否相交实现碰撞检测

飞机死亡的爆炸效果通过导入十二张图片然后轮播实现

使用Date打印存活时间

代码实现

Constant

package com.game;

/**

*

* @author 漫磋嗟

* 设置游戏窗口常量,便于统一修改

*/

public class Constant {

static final int CONSTANT_WIDTH = 800;

static final int CONSTANT_HEIGHT = 800;

}

MyFrame

package com.game;

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.util.ArrayList;

import java.util.Date;

/**

*

* @author 漫磋嗟

* 游戏主窗口

*/

public class MyFrame extends Frame {

//传入图片作为成员变量

Image bgImg = GameUtil.getImage("images/bc.jpg");

Image planeImg = GameUtil.getImage("images/plane.png");

Plane plane = new Plane(planeImg, 360, 750, 5); //新建飞机对象

ArrayList shellList = new ArrayList(); //新建炮弹数组

Explode explode;//新建爆炸对象

Date startTime = new Date(); //游戏开始时间

Date endTime; //游戏结束时间

@Override

public void paint(Graphics g) {

g.drawImage(bgImg, 0, 0, null); //画背景

plane.drawSelf(g); //画飞机

//画出容器里的所有炮弹

for(int i=0;i

Shell b = shellList.get(i);

b.draw(g);

//飞机和炮弹的碰撞检测

boolean boom = b.getRect().intersects(plane.getRect());

if(boom) {

plane.live = false;

//只进行一次爆炸动画

if(explode == null) {

explode = new Explode(plane.x,plane.y);

}

explode.draw(g);

}

}

//打印游戏结果

if(!plane.live) {

if(endTime == null) {

endTime = new Date();

}

int period = (int)((endTime.getTime()-startTime.getTime())/1000);

printInfo(g, "你存活了"+period+"秒", 50, 230, 300, Color.red);

}

}

//打印信息

public void printInfo(Graphics g, String s, int size, int x, int y, Color color) {

Color c = g.getColor();

g.setColor(color);

Font f = new Font("楷体",Font.BOLD,size);

g.setFont(f);

g.drawString(s, x, y);

g.setColor(c);

}

//增加键盘监听

class KeyMonitor extends KeyAdapter {

@Override

public void keyPressed(KeyEvent e) {

plane.addDirection(e);

}

@Override

public void keyReleased(KeyEvent e) {

plane.minusDirection(e);

}

}

//定义一个不断重画窗口的内部类

class PaintThread extends Thread {

public void run() {

while(true) {

repaint();

try {

Thread.sleep(40);

} catch (InterruptedException e) {

e.printStackTrace();

}

}

};

}

public void launchFrame() {

setTitle("打飞机");

setSize(Constant.CONSTANT_WIDTH,Constant.CONSTANT_HEIGHT);

setVisible(true);

setLocationRelativeTo(null); //窗口居中

setResizable(false); //窗口不可拉伸

//增加关闭窗口监听

addWindowListener(new WindowAdapter() {

@Override

public void windowClosing(WindowEvent e) {

System.exit(0);

}

});

//启动重画线程

new PaintThread().start();

//增加键盘的监听

addKeyListener(new KeyMonitor());

//初始化生成炮弹

for(int i=0; i<40; i++) {

Shell b = new Shell();

shellList.add(b);

}

}

public static void main(String[] args) {

MyFrame f = new MyFrame();

f.launchFrame();

}

//双缓冲技术 解决闪烁问题

private Image offScreenImage = null;

public void update(Graphics g) {

if(offScreenImage == null)

offScreenImage = this.createImage(Constant.CONSTANT_WIDTH,Constant.CONSTANT_HEIGHT);

Graphics gOff = offScreenImage.getGraphics();

paint(gOff);

g.drawImage(offScreenImage, 0, 0, null);

}

}

GameUtil

package com.game;

import java.awt.Image;

import java.awt.image.BufferedImage;

import java.io.IOException;

import java.net.URL;

import javax.imageio.ImageIO;

/**

*

* @author 漫磋嗟

* 用于导入图片的工具类

*/

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;

}

}

GameObject

package com.game;

import java.awt.Graphics;

import java.awt.Image;

import java.awt.Rectangle;

/**

*

* @author 漫磋嗟

* 游戏中的物体类

*/

public class GameObject {

Image img;

double x,y;

int width,height;

int speed;

//画自己

public void drawSelf(Graphics g) {

g.drawImage(img, (int)x, (int)y, null);

}

public GameObject() {

}

public GameObject(Image img, double x, double y) {

super();

this.img = img;

this.x = x;

this.y = y;

}

public GameObject(Image img, double x, double y, int width, int height, int speed) {

super();

this.img = img;

this.x = x;

this.y = y;

this.width = width;

this.height = height;

this.speed = speed;

}

//返回物体对应矩形区域 用于碰撞检测

public Rectangle getRect(){

return new Rectangle((int)x,(int) y, width, height);

}

}

Plane

package com.game;

import java.awt.Graphics;

import java.awt.Image;

import java.awt.event.KeyEvent;

/**

*

* @author 漫磋嗟

* 游戏中的飞机类

*/

public class Plane extends GameObject {

boolean left,right,down,up;

boolean live = true;

public Plane(Image img, double x, double y, int speed) {

super(img,x,y);

this.speed = speed;

//设置为宽度和高度为图片的高度宽度 便于碰撞检测

this.width = img.getWidth(null);

this.height = img.getHeight(null);

}

public void drawSelf(Graphics g) {

if(live) {

super.drawSelf(g);

if(left) {

x -= speed;

}

if(right) {

x += speed;

}

if(up) {

y -= speed;

}

if(down) {

y += speed;

}

}else {

}

}

//改变飞机的方向

public void addDirection(KeyEvent e) {

switch (e.getKeyCode()) {

case KeyEvent.VK_LEFT:

left = true;

break;

case KeyEvent.VK_RIGHT:

right = true;

break;

case KeyEvent.VK_UP:

up = true;

break;

case KeyEvent.VK_DOWN:

down = true;

break;

default:

break;

}

}

public void minusDirection(KeyEvent e) {

switch (e.getKeyCode()) {

case KeyEvent.VK_LEFT:

left = false;

break;

case KeyEvent.VK_RIGHT:

right = false;

break;

case KeyEvent.VK_UP:

up = false;

break;

case KeyEvent.VK_DOWN:

down = false;

break;

default:

break;

}

}

}

Shell

package com.game;

import java.awt.Color;

import java.awt.Graphics;

/**

*

* @author 漫磋嗟

* 游戏中的炮弹类

*/

public class Shell extends GameObject {

double degree;

public Shell() {

x = 400;

y = 300;

width = 10;

height = 10;

speed = 5;

//随机生成炮弹角度

degree = Math.random()*Math.PI*2;

}

public void draw(Graphics g) {

//将外部传入对象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(y<35 || y>Constant.CONSTANT_HEIGHT-height) {

degree = -degree;

}

if(x<0 || x>Constant.CONSTANT_WIDTH-width) {

degree = Math.PI-degree;

}

//返回给外部,变回以前的颜色

g.setColor(c);

}

}

Explode

/**

*

* @author 漫磋嗟

* 飞机的爆炸效果

*/

public class Explode {

double x,y;

static Image[] imgs = new Image[12];

static {

for(int i=0; i<12; i++) {

imgs[i] = GameUtil.getImage("images/explode/e"+(i+1)+".gif");

imgs[i].getWidth(null);

}

}

int count;

public void draw(Graphics g) {

if(count<12) {

g.drawImage(imgs[count], (int)x, (int)y, null);

count++;

}

}

public Explode(double x, double y) {

this.x = x;

this.y = y;

}

}

总结

使用ArrayList存储炮弹对象

建立一个导入图片的私有类和便于改变窗口长宽的常量类

游戏内物体坐标 (x, y) 一定要设置为double类型, 否则碰撞检测会出错

bug: 飞机没有边界 爆炸效果会出现卡顿或两次

希望能够有 PlaneGame2.0

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值