java飞机大战代码(java飞机大战项目描述)

亲爱的同学们,大家好。今天我要分享一个java的小项目——飞机大战,编写过程中要用到我们最熟悉的eclipse来编写一个窗口程序,实现这个飞机大战的游戏。以下是游戏界面截图:

java飞机大战代码(java飞机大战项目描述)

分享前,要声明几点内容:

一、本游戏源码非原创,只是本人通过视频学习的方式一点一点的编写而成,所以在网上还是可以搜索到相关的源码的。

二、源码的内容已经做好相关详细注释,这些注释是个人编写程序中自己的思考和理解,希望这些注释能够帮助大家看懂。

三、因为时间有限,部分功能还没有完善,例如英雄飞机与敌机的碰撞,具体的得分接口等等细节性功能还未写好,但是主要的功能已经编写完成,可以用作正常的使用,暂且称为飞机大战v1.0

好了,讲完了这些,那么接下来让我们进入正题吧。

我们知道,java这种程序语言是以面向对象这种思想来设计程序的,所以我们要讲的飞机大战也是以面向对象的思想来编写的。

在飞机大战游戏中,我们主要设计的对象有6个,分别为大敌机、小敌机、小蜜蜂、子弹、天空、以及玩家掌握的英雄机。所以我们需要分别创建6个类(Airplane、BigAirplane、Bee、Sky、Bullet、Hero),以及创建一个放共有属性的超类FlyingObject、放主程序的World(带main)

程序某个功能的设计思想:

1) 先写行为:

a) 对象所特有的行为,设计在对象类中

b) 所有对象特有的行为,设计在超类中

2) 窗口调用:

a) 定时触发的,设计在定时器中调用

b) 事件触发的,设计在侦听器中调用

整体步骤:

一).创建6个对象类,并创建World类测试

二).给6个对象添加构造方法,并测试

三).设计数组对象:

a)设计小敌机数组,大敌机数组,小蜜蜂数组,子弹数组,并测试

b)设计FlyingObject超类,并给6个对象继承

c)给FlyingObject超类设计两个构造方法,6个对象分别调用

四).向上造型数组(多态)、重写step、画窗口

a)将小敌机数组大敌机数组小蜜蜂数组向上造型为Flyingob数组

b)在6个对象类中重写step()

c)画窗口//无需掌握

.

五).遵循一个原则:数据私有,行为公开,继承用protected

a)给类中成员添加访问控制修饰符,数据私有行为公开

b)给6个对象类添加图片属性

六).设定主窗口为常量宽高,给对象获取图片

a). 在world主窗口中定义WIDTH和HEIGHT的常量

b).将FlyingObject的step方法作为抽象方法,同时将6个类的step重写

c)画对象

1)想画对象需要获取对象的图片,每个对象都获取图片

意味着获取图片为共有行为,所以设计在超类中

每个对象获取图片的行为不同(有的一张,两张,五张等等),所以设计为抽象方法

————-在FlyingObject中设计抽象方法getImage()获取对象的图片

2)

获取图片时需要去考虑对象的状态,因为不同状态下获取的图片是不一样的。

对象状态分:活着的、死了的、 删除的

每个对象都有状态,所以讲状态设计到超类中,一般为常量——–FLyingObject中设计LIFE/DEAD/REMOVE常量,state表示当前状态

获取图片时需要去判断对象的状态,而每个对象都能判断状态

所以判断状态为共有行为,设计在FLyingObject中

每个对象判断状态的行为都一样,所以设计为普通方法

3)—-在6个派生类中重写getImage();获取图片

3.1天空Sky直接返回image

3.2子弹Bullet:

3.2.1若活着的,直接返回image

3.2.2若死了的,改为删除状态

3.3英雄机Hero:

3.3.1若活着,返回image[0]image[1]的来回切换

3.4小敌机Airplane:

3.4.1若活着的,返回images[0]

3.4.2若死了,返回images[1]-images[4]轮换,4后删除

3.5大敌机与小敌机一致

3.6小蜜蜂与小敌机一致

17下 2:11:17

4)前3步获取图片,则可以开画了,每个对象都能画

画对象图片行为都是一样的,所以将画对象的行为设计在超类中,且设计为普通方法paintObject()实现画对象

————-在超类中设计普通方法paintObject()实现画对象

5)天空需要画两张图,所以需要在Sky中重写paintObject()方法,画两张图片

6)画对象行为写好后,在窗口上调用即可。

七).敌人入场、子弹入场、飞行物移动

1. 敌人入场

a) 敌人是由窗口产生的,所以在World类中设计了nextOne()生成敌人

b) 敌人入场是定时发生的,所以在run中调用了enterAction()实现敌人入场

enterAction:

每400毫秒,获取敌人对象,enemies扩容,装到最后一个元素上

2. 子弹入场:

a)子弹由英雄机发射出来的,所以在Hero类中生成了shoot()生成子弹

b)子弹入场是定时发生的,所以在run中调用了shootAction()实现子弹入场

shootAction:

每300毫秒获取子弹对象,bullets扩容,数组的追加

3. 飞行物移动:

a) 飞行物移动行,为为共有行为,所以在超类中设计超类抽象方法Step,在派生类重写step()

b) 飞行物移动是定时发生的,所以在run中调用stepAction()实现天空、敌人、子弹移动,

计算机中的坐标:

X坐标:左-右

Y坐标:上-下

来一个敌人,给enemies扩一个容,将敌人装到最后一个元素上

假设enemies中有5个敌人

来一个敌人,

Paint()的调用方式:

Frame.setVisible(true);

Repaint();

敌人入场:是由窗口产生的(World类中)

子弹入场:是由英雄机发射的,属于特有行为(Hero类)

飞行物移动:是共有行为,放在超类中

定时器:定时自动发生

Timer

Timertask

Timer.schedule(new Timertask(){

},10,10);TimerTask,long,long,使用匿名内部类

第一个10:从程序启动到第一次出发的时间间隔

第二个10:从第一次触发到第二次触发的时间间隔

从第二次触发到第二次触发的时间间隔

从第三次触发到第二次触发的时间间隔

八).实现英雄机随鼠标移动,删除越界的敌人和子弹,设计两个接口

1.英雄机随着鼠标动

1)英雄机随着鼠标动为英雄机的行为,在Hero中设计moveTo()

2)英雄机随着鼠标动为事件触发的,所以在侦听器重写mouseMoved(),mouseMoved中获取鼠标的x和y坐标,英雄机动

2.删除越界的敌人和子弹:

1)在超类中设计outOfBounds()检测敌人是否越界,在Bullet中重写outOfBounds()检测子弹是否越界

2)删除越界是定时发生的,在run()中调用outOfBoundsAction():

声明不越界的敌人或子弹数组,遍历敌人或子弹数组,获取对象

判读若对象不越界,则将对象添加到不越界的敌人或是子弹数组中

将不越界的敌人或子弹数组复制到enemies/bullets中

3.设计接口

设计Enemy得分接口,在小敌机大敌机中实现接口

设计Award奖励接口,在小蜜蜂中实现接口

9.子弹与敌人的碰撞

a)在FlyingObject中设计hit()实现碰撞检测

b)在FlyingObject中设计goDead()实现飞行物去死

c)在Hero中设计addLife()增命或者增加火力值

以下是源码:

package cn.tedu.shoot;//小敌机类

import java.awt.image.BufferedImage;//引入存图片类

//定义小敌机,飞行物,小敌机的移动方式通过y坐标来移动

public class Airplane extends FlyingObject implements Enemy {

private static BufferedImage[] images;//定义图片类数组

static {

images = new BufferedImage[5];

for(int i=0;i<images.length;i ) {

images[i] = loadImage(“airplane” i “.png”);

}

}

private int speed;//移动速度

//构造开始

public Airplane(){//构造函数

super(49,36);

speed = 2;//飞行物移动数值

}

//重写step,代表飞行物移动方式

public void step() {

y =speed;//y 代表向下

}

//重写getImage()获取方法

int index = 1;//死了的下标

public BufferedImage getImage() {//每10毫秒走一次,来回切换

if(isLife()) {

return images[0];

}else if(isDead()) {

BufferedImage img = images[index ];

if(index == images.length) {

state =REMOVE;

}

return img;

}

return null;//删除状态,返回null

}

//实现接口

public int getScore() {

return 1;//子弹打掉小敌机,得1分

}

}

大敌机:

package cn.tedu.shoot;

import java.awt.image.BufferedImage;//引入存图片类

//大敌机的移动方式通过y坐标来移动

public class BigAirplane extends FlyingObject implements Enemy {

private static BufferedImage[] images;//定义图片类数组

static {

images = new BufferedImage[5];

for(int i=0;i<images.length;i ) {

images[i] = loadImage(“bigAirplane” i “.png”);

}

}

private int speed;//移动速度

public BigAirplane(){

super(69,99);

speed = 2;//飞行物移动数值

}

//重写step,代表飞行物移动方式

public void step() {

y =speed;//y 代表向下

}

int index = 1;//死了的下标

public BufferedImage getImage() {//每10毫秒走一次,来回切换

if(isLife()) {

return images[0];

}else if(isDead()) {

BufferedImage img = images[index ];//获取爆破图

if(index == images.length) {//若到了最后一张,执行删除

state =REMOVE;

}

return img;//REMOVE之后以上循环不满足,直接返回null

}

return null;//删除状态,返回null

}

//实现接口

public int getScore() {

return 3;//子弹打大敌机之后,得3分

}

}

小密峰:

package cn.tedu.shoot;

import java.awt.image.BufferedImage;//引入存图片类

import java.util.Random;

//小蜜蜂的移动方式通过xy坐标来移动

public class Bee extends FlyingObject implements Award {

private static BufferedImage[] images;//定义图片类数组

static {

images = new BufferedImage[5];

for(int i=0;i<images.length;i ) {

images[i] = loadImage(“bee” i “.png”);

}

}

private int xSpeed;//x坐标的移动速度

private int ySpeed;//y坐标的移动速度

private int awardType;//奖励机制

//构造方法//

public Bee(){

super(60,50);

xSpeed = 1;

ySpeed = 2;

Random rand = new Random();

awardType = rand.nextInt(2);//产生0-1之间的随机数,随机获得奖励

}

//重写step方法

public void step() {

x =xSpeed;//向左或者向右移动

y =ySpeed;//向下移动

if(x<=0 || x>=World.WIDTH-this.width) {//判断小蜜蜂是否越界,若越界则反方向移动

xSpeed*=-1;//改变正负,数值不变

}

}

int index = 1;//死了的下标

public BufferedImage getImage() {//每10毫秒走一次,来回切换

if(isLife()) {

return images[0];

}else if(isDead()) {

BufferedImage img = images[index ];

if(index == images.length) {

state =REMOVE;

}

return img;

}

return null;//删除状态,返回null

}

//奖励机制

public int getAwardType() {

return awardType;//返回奖励类型

}

}

子弹:

package cn.tedu.shoot;

import java.awt.image.BufferedImage;//引入存图片类

//子弹,是飞行物,利用y坐标进行移动

public class Bullet extends FlyingObject {

private static BufferedImage image;//定义图片类

static {

image = loadImage(“bullet.png”);

}

private int speed;

//构造方法

public Bullet(int x,int y){

super(8,14,x,y);

speed = 3;

}

//重写step

public void step() {

y-=speed;//子弹向上移动

}

//重写抽象类getImage

public BufferedImage getImage() {

if(isLife()) {

return image;

}else if(isDead()){

state =REMOVE;}

return null;

}

//重写outOfBounds(),判断敌人是否越界(子弹)

public boolean outOfBounds(){

return this.y<=-this.height;//子弹的y小于等于负的子弹的高,即为越界

}

}

天空:

package cn.tedu.shoot;

import java.awt.Graphics;

import java.awt.image.BufferedImage;//引入存图片类

//天空,飞行物体,利用y跟y1进行移动

public class Sky extends FlyingObject {

private static BufferedImage image;//定义图片类

static {

image = loadImage(“background.png”);

}

private int speed;//移动速度

private int y1; //界面有两张图,第2张图的y坐标

//构造开始

public Sky(){

super(World.WIDTH,World.HEIGHT,0,0);

speed = 1;

y1 = -World.WIDTH;

}

public void step() {

y =speed;//两张图片往下移动

y1 =speed;

if(y>=World.WIDTH) {//当y>=窗口的高

y = -World.WIDTH;//则修改y的值为负的窗口的高

}

if(y1>=World.WIDTH) {

y1 = -World.WIDTH;

}

}

//重写抽象类getImage

public BufferedImage getImage() {

return image;//直接返回iamge

}

/*重写画笔方法,画对象,画对象的方式都是一样的,所以为普通方法*/

public void paintObject(Graphics g){

g.drawImage(getImage(),x,y,null);//不要求掌握

g.drawImage(getImage(),x,y1,null);

}

}

英雄机:

package cn.tedu.shoot;

import java.awt.image.BufferedImage;//引入存图片类

//英雄飞机

public class Hero extends FlyingObject {

private static BufferedImage[] images;//定义图片类数组

static {

images = new BufferedImage[2];

images[0] = loadImage(“hero0.png”);

images[1] = loadImage(“hero1.png”);

}

private int life;//表示生命值

private int doubleFire;//表示火力值

//构造开始

public Hero() {

super(97,124,140,400);

life = 3;

doubleFire = 0;

}

//英雄飞机随着鼠标动x,y:鼠标的x坐标和y坐标

public void moveTo(int x,int y) {

this.x = x-this.width/2;//以英雄机的中心为鼠标点

this.y = y-this.height/2;

}

public void step() {

}

int index = 0;//活着的下标

public BufferedImage getImage() {//每10毫秒走一次,来回切换

if(isLife()) {return images[index %images.length];}//实现hero0-1的切换,两张图的切换.

return null;

}

//英雄机发射子弹(生成子弹对象)

public Bullet[] shoot() {

int xStep = this.width/4;// 1/4英雄机的宽

int yStep = 20;//固定的20

if(doubleFire>0) {//双倍火力,2发子弹

Bullet[] bs = new Bullet[2];

bs[0] = new Bullet(this.x 1*xStep,this.y-yStep);//给子弹的位置赋值

bs[0] = new Bullet(this.x 3*xStep,this.y-yStep);

doubleFire-=2;

return bs;

}else {//单倍火力,1发子弹

Bullet[] bs = new Bullet[1];

bs[0] = new Bullet(this.x 2*xStep,this.y-yStep);

return bs;

}

}

//增加命

public void addLife() {

life ;

}

//增加火力值

public void addBouleFire() {

doubleFire =40;

}

}

超类:

package cn.tedu.shoot;

import java.util.Random;//引用随机数类

import java.awt.image.BufferedImage;//引入存图片类

import javax.imageio.ImageIO;//读写图片

import java.awt.Graphics;//画对象类

/*飞行物开始*/

public abstract class FlyingObject {//超类成员需要被派生类访问,用protected

static final int LIFE = 0;//活着的状态

static final int DEAD = 1;//死了的

static final int REMOVE = 2;//删除的

protected int state = LIFE;//表示当前状态,默认为活着的

protected int width;//宽

protected int height;//高

protected int x;//x坐标

protected int y;//y坐标

//给小敌机、大敌机、小蜜蜂提供的

public FlyingObject(int width,int height){

this.width = width;

this.height = height;

Random rand = new Random();//随机数对象

x = rand.nextInt(World.WIDTH-this.width);//x的值在0-(WIDHT-width)直接随机出现

y = -this.height;//负的小敌机的高,进场在外边

}

//给英雄机、天空、子弹提供的

public FlyingObject(int width,int height,int x,int y){

this.width = width;

this.height = height;

this.x = x;

this.y = y;

}

//飞行物移动

public abstract void step();

//获取图片方法,只看参数,不看对象,得传参

public static BufferedImage loadImage(String fileName){

//异常处理

try {//试异常

BufferedImage img =ImageIO.read(FlyingObject.class.getResource(fileName));//同包下读取图片

return img;

}catch(Exception e) {//抓异常

e.printStackTrace();

throw new RuntimeException();

}

}

//读取图片 方法

public abstract BufferedImage getImage();

//判断对象的状态是否是活着的

public boolean isLife() {

return state==LIFE;//当前状态是LIFE说明活着的

}//判断对象是否死了

public boolean isDead() {//当前状态是DEAD说明是死了的

return state==DEAD;

}//判断对象是否删除

public boolean isRemove() {//当前的状态是REMOVE是删除的

return state==REMOVE;

}

/*画笔方法,画对象,画对象的方式都是一样的,所以为普通方法*/

public void paintObject(Graphics g){

g.drawImage(this.getImage(),this.x,this.y,null);//不要求掌握

}

//判断敌人是否越界(小敌机,大敌机,小蜜蜂)

public boolean outOfBounds(){

return this.y>=World.HEIGHT;//敌人的y大于等于窗口高,即为越界

}

//检测当前敌人与子弹/英雄机碰撞other

public boolean hit(FlyingObject other) {

int x1 = this.x-other.width;//x1:敌人的x坐标-子弹/英雄机的宽

int x2 = this.x this.width;//x2:敌人的x坐标 敌人的宽

int y1 = this.y-other.height;//y1:敌人的y-子弹/英雄机的y

int y2 = this.y this.height;//y2:敌人的y 敌人的高

int x = other.x;//子弹/英雄机的x

int y = other.y;//子弹/英雄机的y

return x>=x1&&x<=x2&&y>=y1&&y<=y2;//x在x1、x2之间,y在y1y2之间时即为碰撞

}

//碰撞后飞行物去死

public void goDead() {

state = DEAD;//将对象状态改为DEAD

}

}

主程序:

package cn.tedu.shoot;

import javax.swing.JFrame;//框架

import javax.swing.JPanel;//面板

import java.awt.Graphics;//画对象类

import java.util.TimerTask;//定时任务

import java.util.Timer;//引入定时器

import java.util.Random;

import java.util.Arrays;//数组扩容

import java.awt.event.MouseAdapter;//监听器,无须理解

import java.awt.event.MouseEvent;//事件处理,无须理解

public class World extends JPanel {//把这些内容放在面板上

static final int WIDTH = 400;

static final int HEIGHT = 700;

private Sky sky = new Sky();//天空

private Hero hero = new Hero();//英雄机

private FlyingObject[] enemies = {};/*Airplane[] as; BigAirplane[] bas;Bee[] bs;有相同功能写成FlyingObject的数组,发生向上造型*/

private Bullet[] bullets = {};//子弹数组

/*产生敌人对象,小蜜蜂大敌机小敌机*/

public FlyingObject nextOne(){//产生随机的敌人,并返回

Random random = new Random();

int type =random.nextInt(20);//控制概率,产生0-19的数字

if(type<5){

return new Bee();

}else if(type<13){

return new Airplane();

}else{

return new BigAirplane();

}

}

//敌人入场计数

int enterIndex = 0;

public void enterAction(){//敌人入场方法,10毫秒走一次

enterIndex ;//每10毫秒增1

if(enterIndex`==0){//每400(10*40)毫秒走一次

FlyingObject obj = nextOne();//获取敌人,有返回值的方法必须要接受=

enemies = Arrays.copyOf(enemies,enemies.length 1);//每增加一个敌人,数组扩容1

enemies[enemies.length-1] = obj;//将obj赋值给enemies的最后一个元素

}

}

//子弹入场

int shootIndex = 0;//子弹入场计数

public void shootAction() {

shootIndex ;//每10个毫秒增1

if(shootIndex5==0) {//每300(10*30)毫秒走一次

Bullet[] bs = hero.shoot();

bullets = Arrays.copyOf(bullets,bullets.length bs.length);//每增加一个敌人,数组扩容(bs的长度)

System.arraycopy(bs,0,bullets,bullets.length-bs.length,bs.length);//数组的追加

}

}

//飞行物移动

public void stepAction() {//10毫秒走一次

sky.step();//天空移动

for(int i=0;i<enemies.length;i ) {

enemies[i].step();

}

for(int i=0;i<bullets.length;i ) {

bullets[i].step();

}

}

//删除越界的子弹和敌人

public void outOfBoundsAction(){//每10个毫秒走一次

int index = 0;//控制下标,表示不越界敌人的个数

FlyingObject[] enemyLives = new FlyingObject[enemies.length];

for(int i=0;i<enemies.length;i ){//遍历所有的敌人

FlyingObject f = enemies[i];//创建一个新的数组对象

if(!f.outOfBounds()){//表示不越界

enemyLives[index] = f;//将不越界的敌人装到另一个数组中

index ;

}

}

enemies = Arrays.copyOf(enemyLives,index);//将不越界敌人的数组enemyLives复制给enemies数组

//删除子弹

index = 0;

Bullet[] bulletsLives = new Bullet[bullets.length];

for(int i =0;i<bullets.length;i ){

Bullet bs = bullets[i];

if(!bs.outOfBounds()){

bulletsLives[index] = bs;

index ;

}

}

bullets = Arrays.copyOf(bulletsLives,index);

}

//子弹与敌人的碰撞

public void bulletBangAction() {//每10个毫秒走一次

for(int i=0;i<bullets.length;i ) {//遍历所有的子弹

Bullet b = bullets[i];//获取每个子弹

for(int j=0;j<enemies.length;j ) {//遍历所有的敌人

FlyingObject f = enemies[j];//获取所有敌人

if(b.isLife() &&f.isLife() && f.hit(b)) {//要是

b.goDead();

f.goDead();

}

}

}

}

public void action() {//测试代码

//无需掌握

MouseAdapter l = new MouseAdapter(){//匿名内部类,侦听器对象

public void mouseMoved(MouseEvent e){//重写mouseMoved(),鼠标移动

int x = e.getX();//获取鼠标的xy坐标

int y = e.getY();

hero.moveTo(x, y);

}

};

this.addMouseListener(l);//处理鼠标的操作事件

this.addMouseMotionListener(l);//处理鼠标滑动

Timer timer = new Timer();//创建定时器对象

int interval = 10;//以10毫秒为单位

timer.schedule(new TimerTask(){

public void run(){//重写匿名内部类里的抽象方法,表示定时干的事情(每10毫秒)

enterAction();//敌人入场

shootAction();//子弹入场

stepAction();//飞行物移动

outOfBoundsAction();//飞行物越界删除

bulletBangAction();//子弹与敌人的碰撞

//System.out.println(bullets.length);

repaint();//调用paint,将敌人画出来

}

},interval,interval);//设定定时任务

}

//将敌人画出

public void paint(Graphics g){//重写JPnel的paint方法

sky.paintObject(g);//画天空

hero.paintObject(g);//画英雄机

for(int i=0;i<enemies.length;i ){//画敌人

enemies[i].paintObject(g);

}

for(int i=0;i<bullets.length;i ){//画子弹

bullets[i].paintObject(g);

}

}

public static void main(String[] args) {

JFrame frame = new JFrame();

World world = new World();//静态main无法访问实例变量,所以要先new个对象

frame.add(world);

frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

frame.setSize(World.WIDTH,World.HEIGHT);

frame.setLocationRelativeTo(null);

frame.setVisible(true);//1)设计窗口可见 2)尽快调用paint()

world.action();//启动程序的执行

}

}

奖励接口:

package cn.tedu.shoot;

//奖励接口

public interface Award {

public int DOUBLE_FIRE = 0;//火力值

public int LIFE = 1;//命

//奖励方法

public int getAwardType();//返回0或1,得到火力值或者是命

}

得分接口:

package cn.tedu.shoot;

//得分接口

public interface Enemy {

public int getScore();//得分方法

}

发表评论

登录后才能评论