展示素材
下载地址
文件只需要这些,项目源码已发布、PlaneWar.rar(0积分下载)
源码:
Airplane
package cn.pln.war;
import java.awt.image.BufferedImage;
public class Airplane extends FlyingObject
implements Score{
//定义存储小敌机的图片的静态数组
private static BufferedImage[] images;
//静态初始化块中,为小敌机的数组赋值
static {
//初始化数组长度为5
images=new BufferedImage[5];
images[0]=readImage("airplane0.png");
//images[1]=readImage("bom1.png");
for(int i=1;i<images.length;i++) {
images[i]=readImage("bom"+i+".png");
}
}
//定义小敌机的类
//定义属性
private int step;//速度
public Airplane() {
super(48,50);
step=3;
}
//输出信息的方法
public void show() {
System.out.println("宽:"+width+
",高:"+height);
System.out.println("x:"+x+",y:"+y);
System.out.println("速度:"+step);
}
public void step() {
y+=step;
}
int index=1;
public BufferedImage getImage() {
//如果小敌机活着
if(isLife()) {
//返回小敌机图片
return images[0];
}else if(isDead()) {
//如果小敌机是死的
BufferedImage img=images[index];
index++;
//如果是最后一次爆炸图片
if(index==images.length) {
state=REMOVE;
}
return img;
}
//如果既不是活着也不是死了
return null;
}
//Score接口中的方法实现
public int getScore() {
//击中小敌机给1分
return 1;
}
}
Award
package cn.pln.war;
public interface Award {
//奖励接口
//表示击中该单位
//会获得奖励
//定义奖励对应的数字
int LIFE=1;
int DOUBLE_FIRE=0;
//返回奖励的方法
int getAward();
}
Bee
package cn.pln.war;
import java.awt.image.BufferedImage;
import java.util.Random;
public class Bee extends FlyingObject
implements Award{
private static BufferedImage[] images;
static {
images=new BufferedImage[5];
images[0]=readImage("bee0.png");
for(int i=1;i<images.length;i++) {
images[i]=readImage("bom"+i+".png");
}
}
//横向速度(左右)
private int xStep;
//纵向速度(上下)
private int yStep;
public Bee() {
super(60,51);
xStep=2;
yStep=2;
}
public void show() {
System.out.println("宽:"+width
+",高:"+height);
System.out.println("x:"+x+",y:"+y);
System.out.println("x速度:"+xStep
+",y速度"+yStep);
}
public void step() {
y+=yStep;
x+=xStep;
//奖励机碰左壁或右壁
//都需要修改x轴运行方法
if(x>=World.WIDTH-this.width || x<=0) {
xStep*=-1;
}
}
int index=1;
public BufferedImage getImage() {
if(isLife()) {
return images[0];
}else if(isDead()) {
BufferedImage img=images[index];
index++;
if(index==images.length) {
state=REMOVE;
}
return img;
}
return null;
}
//Award接口中的方法实现
public int getAward() {
//随机产生一个0~1的数字返回
//0奖励火力值,1奖励生命值
Random ran=new Random();
return ran.nextInt(2);
}
}
BigAirplane
package cn.pln.war;
import java.awt.image.BufferedImage;
public class BigAirplane extends FlyingObject
implements Score{
private static BufferedImage[] images;
static {
images=new BufferedImage[5];
images[0]=readImage("bigairplane0.png");
for(int i=1;i<images.length;i++) {
images[i]=readImage("bom"+i+".png");
}
}
private int step;
public BigAirplane() {
super(66,89);
step=2;
}
public void show() {
System.out.println("宽:"+width
+",高:"+height);
System.out.println("x:"+x+",y:"+y);
System.out.println("速度:"+step);
}
public void step() {
y+=step;
}
int index=1;
public BufferedImage getImage() {
if(isLife()) {
return images[0];
}else if(isDead()) {
BufferedImage img=images[index];
index++;
if(index==images.length) {
state=REMOVE;
}
return img;
}
return null;
}
public int getScore() {
return 3;
}
}
Bullet
package cn.pln.war;
import java.awt.image.BufferedImage;
public class Bullet extends FlyingObject {
//声明一个保存子弹图片的静态对象
private static BufferedImage image;
static {
//静态块中加载子类的图片
image=readImage("bullet.png");
}
private int step;
public Bullet(int x,int y) {
super(8,20,x,y);
step=2;
}
public void show() {
System.out.println("宽:"+width+",高:"+height);
System.out.println("x:"+x+",y:"+y);
System.out.println("速度:"+step);
}
public void step() {
y-=step;
}
public BufferedImage getImage() {
//子弹如果活着
if(isLife()) {
//返回图片
return image;
}else if(isDead()) {
//如果死了,直接消失
state=REMOVE;
}
//消失了就返回null
return null;
}
//重写父类中编写的出界方法
public boolean outOfBounds() {
//子弹是完全移出至窗体上方
return y<-this.height;
}
}
FlyingObject
package cn.pln.war;
import java.awt.Graphics;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.util.Random;
import javax.imageio.ImageIO;
public abstract class FlyingObject {
//定义飞行物状态的三个常量
public static final int LIFE=0;//活着
public static final int DEAD=1;//死了的
public static final int REMOVE=2;//消失了
//定义当前对象的状态的属性
protected int state=LIFE;//默认开始是活着的
//父类中定义所有子类共有的属性
protected int width;
protected int height;
protected int x;
protected int y;
//小敌机,大敌机,奖励机使用的构造
//原因是这三类对象的x和y轴是不需要参数的
public FlyingObject(int width,int height) {
Random ran=new Random();
this.width=width;
this.height=height;
x=ran.nextInt(400-width);
y=-height;
}
//天空\子弹\英雄级的构造
public FlyingObject(int width,
int height,int x,int y) {
this.width=width;
this.height=height;
this.x=x;
this.y=y;
}
public void show() {
System.out.println("宽:"+width
+",高:"+height);
System.out.println("x:"+x+",y:"+y);
}
//将程序中需要的图片读取到内存中的方法
public static BufferedImage
readImage(String fileName) {
//读取图片到对象
BufferedImage img;
try {
img = ImageIO.read(
FlyingObject.class.getResource(fileName)
);
return img;
} catch (IOException e) {
e.printStackTrace();
throw new RuntimeException();
}
}
//判断当前对象是活着的
public boolean isLife() {
return state==LIFE;
}
//判断当前对象是死了的
public boolean isDead() {
return state==DEAD;
}
//判断当前对象是消失的
public boolean isRemove() {
return state==REMOVE;
}
//父类中编写抽象方法step
//所有的飞行物都会移动:移动方法
public abstract void step();
//这个方法是对象获得自己图片的方法
public abstract BufferedImage getImage();
//将一个图片绘制到窗体
public void paintObject(Graphics g) {
//在画板上绘制指定图片
g.drawImage(getImage(),x,y,null);
}
//定义飞行物出界的抽象方法
//默认定义小敌机大敌机奖励机出界的方法
public boolean outOfBounds() {
//返回真表示真出界了
//y轴大于了窗体的高.即出界
return y>World.HEIGHT;
}
//定义判断飞行物碰撞的方法
//this:子弹\英雄机 other:敌机
public boolean hit(FlyingObject other) {
//定义碰撞范围的四个点
int x1=other.x-this.width;
int x2=other.x+other.width;
int y1=other.y-this.height;
int y2=other.y+other.height;
//如果子弹或英雄机在这四个点之内
//返回真
return this.x>x1 && this.x<x2
&&
this.y>y1 && this.y<y2;
}
//定义一个状态修改DEAD的方法
public void goDead() {
this.state=DEAD;
}
}
Hero
package cn.pln.war;
import java.awt.image.BufferedImage;
public class Hero extends FlyingObject {
private static BufferedImage[] images;
static {
images=new BufferedImage[2];
images[0]=readImage("hero0.png");
images[1]=readImage("hero1.png");
}
//生命值
private int life;
//火力值(双排炮)
private int doubleFire;
public Hero() {
super(97,139,400/2-97/2,420);
life=3;//英雄级初始3条命
doubleFire=30;//初始没有火力值
}
public void show() {
System.out.println("宽:"+width+",高:"+height);
System.out.println("x:"+x+",y:"+y);
System.out.println("生命值:"+life);
System.out.println("火力值:"+doubleFire);
}
//英雄机随鼠标移动,step方法做空实现即可
public void step() {
}
//英雄机
int index=0; //index:6
public BufferedImage getImage() {
int i=index%2; //i:1
index++;
return images[i];
//return images[index++%2];
}
//英雄机开炮的方法
public Bullet[] shoot() {
Bullet[] bs=null;
//定义一个英雄机的四分之一宽
//方便子弹的x轴定位
int tx=this.width/4-2;
int ty=20;//20是子弹的高度
//根据英雄机的火力值,开炮
if(doubleFire>0) {//双
bs=new Bullet[2];//定义长度为2的
bs[0]=new Bullet(this.x+tx,this.y-ty);//左侧子弹
bs[1]=new Bullet(this.x+3*tx,this.y-ty);//右侧子弹
doubleFire--;//减少火力值
}else {//单
bs=new Bullet[1];//定义长度为1的
bs[0]=new Bullet(this.x+2*tx,this.y-ty);
}
return bs;
}
//英雄机移动的方法
public void moveTo(int x,int y) {
//将x看做是鼠标的x轴
//将y看做是鼠标的y轴
//将鼠标位置调整到英雄机中心
this.x=x-this.width/2;
this.y=y-this.height/2;
}
//加命方法
public void addLife() {
life++;
}
//加火力方法
public void addDoubleFire() {
doubleFire+=20;
}
//返回命的方法
public int getLife() {
return life;
}
//减命
public void subLife() {
life--;
}
//清空火力
public void clearFire() {
doubleFire=0;
}
}
Score
package cn.pln.war;
public interface Score {
//得分接口,表示击中该类型的单位后
//会加分
//获得加分的方法
int getScore();
}
Sky
package cn.pln.war;
import java.awt.Graphics;
import java.awt.image.BufferedImage;
public class Sky extends FlyingObject {
private static BufferedImage image;
static {
image=readImage("background.png");
}
private int step;
private int y1;//第二张背景图的y坐标
public Sky() {
super(400,700,0,0);
step=1;
y1=-700;
}
public void show() {
System.out.println("宽:"+width+",高:"+height);
System.out.println("x:"+x+",y:"+y+",y1:"+y1);
System.out.println("速度:"+step);
}
public void step() {
y+=step;
y1+=step;
//如果天空移出窗体
//将这个天空重置到窗体上方
if(y>=World.HEIGHT) {
y=-World.HEIGHT;
}
if(y1>=World.HEIGHT) {
y1=-World.HEIGHT;
}
}
public BufferedImage getImage() {
return image;
}
//天空(背景)对象是一个对象要画两张图
//父类中绘制方法只画了一张
//在天空类中要对父类的绘制方法进行重写
public void paintObject(Graphics g) {
//重写的方法要绘制两张图
g.drawImage(getImage(),x,y,null);
g.drawImage(getImage(),x,y1,null);
}
}
World
package cn.pln.war;
import java.util.Arrays;
import java.util.Random;
import java.awt.Graphics;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.image.BufferedImage;
import java.util.Timer;
import java.util.TimerTask;
import javax.swing.JFrame;
import javax.swing.JPanel;
//World继承JPanel表示成为了一个面板
public class World extends JPanel {
//定义窗口的宽和高的常量
public static final int WIDTH=400;
public static final int HEIGHT=700;
//定义游戏状态的常量
public static final int START=0;//开始
public static final int RUNNING=1;//运行
public static final int PAUSE=2;//暂停
public static final int GAME_OVER=3;//结束
//定义当前游戏状态
private int state=START;//默认开始状态
//定义三个状态下对应的图片
private static BufferedImage startImg;
private static BufferedImage pauseImg;
private static BufferedImage gameoverImg;
//在类加载时将图片加载到对象中
static {
startImg=FlyingObject.
readImage("start.png");
pauseImg=FlyingObject.
readImage("pause.png");
gameoverImg=FlyingObject.
readImage("gameover.png");
}
//分数属性
private int score=0;
Hero hero=new Hero();
Sky sky=new Sky();
//定义出现多次的对象的数组
FlyingObject[] enemy= {};
Bullet[] bullets= {};
//定义游戏开始的方法
public void start() {
//编写英雄机随鼠标移动的代码
//鼠标监听器对象
MouseAdapter l=new MouseAdapter() {
//重写MouseAdapter类中的鼠标移动方法
public void mouseMoved(MouseEvent e) {
if(state==RUNNING) {
int x=e.getX();//获得鼠标x轴位置
int y=e.getY();//获得鼠标y轴位置
hero.moveTo(x, y);//让英雄机移动
}
}
//重写鼠标单击时运行的方法
public void mouseClicked(MouseEvent e) {
//根据当前状态,切换成另一个状态
switch(state) {
//当开始状态时,切换到运行状态
case START:
state=RUNNING;
break;
//当游戏结束时,切换到开始状态
case GAME_OVER:
state=START;
//游戏重新开始,数据要重置
score=0;
sky=new Sky();
hero=new Hero();
enemy=new FlyingObject[0];
bullets=new Bullet[0];
break;
}
}
//重写鼠标移出时运行的方法
public void mouseExited(MouseEvent e) {
if(state==RUNNING) {//如果是运行状态
state=PAUSE;//切换成暂停
}
}
//重写鼠标移入时运行的方法
public void mouseEntered(MouseEvent e) {
if(state==PAUSE) {//如果是暂停状态
state=RUNNING;//切换成运行状态
}
}
};
//在鼠标移动事件和鼠标滑动事件上
//注册这个监听器
this.addMouseListener(l);
this.addMouseMotionListener(l);
//定义计时器
Timer timer=new Timer();
//定义运行间隔(数字越小,速度越快)
int interval=30;
//创建定时任务
TimerTask task=new TimerTask() {
public void run() {
if(state==RUNNING) {
moveAction();
enemyEnterAction();
shootAction();
outOfBoundsAction();
hitAction();
//System.out.println(bullets.length);
heroHitAction();
gameOverAction();
}
repaint();
}
};
//启动计时器
timer.schedule(task, interval,interval);
}
//定义一个判断游戏结束的方法
public void gameOverAction() {
//如果英雄机生命值下降到0或以下
if(hero.getLife()<=0) {
//游戏状态变为结束
state=GAME_OVER;
}
}
//定义英雄机和敌机碰撞的方法
public void heroHitAction() {
//遍历所有敌机
for(int i=0;i<enemy.length;i++) {
FlyingObject f=enemy[i];
if(hero.isLife() && f.isLife()
&& hero.hit(f)) {
//如果敌机和英雄机碰撞
//敌机死,英雄机减命减火力
f.goDead();
hero.subLife();
hero.clearFire();
}
}
}
//定义子弹击中敌机的方法
public void hitAction() {
//遍历所有子弹
for(int i=0;i<bullets.length;i++) {
//获得当前子弹
Bullet b=bullets[i];
//遍历所有敌机
for(int j=0;j<enemy.length;j++) {
//获得当前敌机
FlyingObject f=enemy[j];
//判断是否相撞(活子弹撞活敌机)
if(b.isLife() && f.isLife() && b.hit(f)) {
//子弹和敌机都得死
b.goDead();
f.goDead();
//如果击中的是得分的敌机
if(f instanceof Score) {
//安装游戏规则加分
Score s=(Score)f;
score+=s.getScore();
}
//如果击中的是有奖励的敌机
if(f instanceof Award) {
Award a=(Award)f;
//获得奖励机的奖励类型
int type=a.getAward();
//根据不同奖励值获得对应的奖励
switch(type) {
case Award.DOUBLE_FIRE:
hero.addDoubleFire();
break;
case Award.LIFE:
hero.addLife();
break;
}
}
//如果击中了敌机,
//当前子弹就不需要循环了
break;
}
}
}
}
//定义飞行物出界的方法
public void outOfBoundsAction() {
int index=0;//1)复制当前元素2)新数组长度
//定义新数组
FlyingObject[] newarr=
new FlyingObject[enemy.length];
//遍历敌机数组
for(int i=0;i<enemy.length;i++) {
//获取当前敌机对象
FlyingObject f=enemy[i];
//判断是否出界
if(!f.outOfBounds()&&!f.isRemove()) {
//如果没出界并且不是移除状态
//将当前对象放入新数组中
newarr[index]=f;
index++;
}
}
//将新数组缩容(可能)后赋值给enemy
enemy=Arrays.copyOf(newarr, index);
//子弹出界的判断,思路和敌机相同
index=0;//index重置归零
Bullet[] bs=new Bullet[bullets.length];
for(int i=0;i<bullets.length;i++) {
Bullet b=bullets[i];
if(!b.outOfBounds()&&!b.isRemove()) {
bs[index]=b;
index++;
}
}
bullets=Arrays.copyOf(bs, index);
}
//定义子弹进场的方法
int shootIndex=0;
public void shootAction() {
shootIndex++;
if(shootIndex%30==0) {
Bullet[] bs=hero.shoot();
//数组扩容bs的长度
bullets=Arrays.copyOf(bullets,
bullets.length+bs.length);
//将要进场的子弹,追加到扩容后数组的尾部
System.arraycopy(bs, 0, bullets,
bullets.length-bs.length,
bs.length);
}
}
//定义敌机进场的方法
int enterIndex=0;
public void enemyEnterAction() {
enterIndex++;
if(enterIndex%10==0) {
//获得随机产生的敌机
FlyingObject fly=makeEnemy();
//将现有的敌机数组扩容1
enemy=Arrays.copyOf(enemy,
enemy.length+1);
//将生成的fly,存放到扩容后数组的
// 最后一个位置
enemy[enemy.length-1]=fly;
}
}
//随机产生敌机的方法
public FlyingObject makeEnemy() {
FlyingObject fly=null;
//随机生成一种敌机,赋给fly
Random ran=new Random();
int num=ran.nextInt(100);//0~99随机数
if(num<40) {//40%几率产生小敌机
fly=new Airplane();
}else if(num<80) {//40%几率产生大敌机
fly=new BigAirplane();
}else {//剩下的20%产生奖励机
fly=new Bee();
}
return fly;
}
//定义所有敌机移动的方法
public void moveAction() {
sky.step();
//所有敌机移动
for(int i=0;i<enemy.length;i++) {
enemy[i].step();
}
//子弹移动
for(int i=0;i<bullets.length;i++) {
bullets[i].step();
}
}
//这个方法是重写JPanel的
//方法名固定
//功能是将Wrold类中所有对象
//绘制到窗体上
public void paint(Graphics g) {
//一定要先画背景
sky.paintObject(g);
hero.paintObject(g);
//循环遍历敌机数组和子弹数组画在窗体上
for(int i=0;i<enemy.length;i++) {
enemy[i].paintObject(g);
}
for(int i=0;i<bullets.length;i++) {
bullets[i].paintObject(g);
}
//将分数和英雄机生命值显示在窗体上
g.drawString("SCORE:"+score,10,25);
g.drawString("LIFE :"+hero.getLife(),
10, 45);
//根据状态在窗体上显示图片
switch(state) {
case START:
g.drawImage(startImg,0,0,null);
break;
case PAUSE:
g.drawImage(pauseImg,0,0,null);
break;
case GAME_OVER:
g.drawImage(gameoverImg,0,0,null);
}
}
public static void main(String[] args) {
//实例化World类对象w
World w=new World();
//实例化窗口,标题为飞机大战
JFrame frame=new JFrame("飞机大战");
//将World面板放入frame窗口
frame.add(w);
//设定窗口大小
frame.setSize(400, 700);
//设置窗口关闭时,运行的程序结束
frame.setDefaultCloseOperation(
JFrame.EXIT_ON_CLOSE);
//设置窗口的默认位置(居中)
frame.setLocationRelativeTo(null);
//显示窗口(自动调用paint方法)
frame.setVisible(true);
//使用w调用start方法
w.start();
}
}