纷争开始了
文章目录
开发环境
开发工具:eclipse2021-12
JDK版本:JDK15.0.1
前言
展示一下游戏画面
一、代码部分
1.项目结构及下载方法
如图:
链接:https://pan.baidu.com/s/1XGY_HIqsIIKUyP8CLRZsRw
提取码:whp5
2.代码
1.AirPlane.java
AirPlane.java:
package AirPlaneWar;
import java.awt.image.BufferedImage;
public class AirPlane extends FlyingObject implements Enemy{
public static BufferedImage[] images;//定义小敌机图片集
static {
images=new BufferedImage[5];
for(int i=0;i<images.length;i++) {
images[i]=loadImage("/AirPlaneWar/images/airplane"+i+".png");
}
}
private int speed;
public AirPlane() {
super(49, 36);//小敌机的宽度和高度
speed=2;
}
@Override
public int getScore() {
// TODO Auto-generated method stub
return 0;
}
@Override
public void step() {
// TODO Auto-generated method stub
y+=speed;
}
int deadIndex=1;//定义小敌机死了的下标
/* 获得小敌机图片--爆炸效果 */
public BufferedImage getImage() {
if(isLife()) {
return images[0];
}else if(isDead()){
BufferedImage img=images[deadIndex++];
if(deadIndex==images.length) {///判断是否切换到最后一张图片
state=REMOVE;//飞行物移除
}
return img;
}
return null;
}
public boolean outOfBounds() {
return this.y>=ShootGame.jframeHeight;
}
}
2.Award.java
Award.java:
package AirPlaneWar;
/**
* 打中蜜蜂后的接口奖励
* 定义双倍活力或者生命值的奖励类型为0或者1
* -目的是为了随机产生数字0或者1来确定奖励类型
* @author chenz
*
*/
public interface Award {
public int DOUBLE_FIRE=0;//定义双倍火力
public int LIFE=1;//生命值
public int getAward();//获取奖励类型的方法
}
3.Bee.java
Bee.java:
package AirPlaneWar;
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];
for(int i=0;i<images.length;i++) {
images[i]=loadImage("/AirPlaneWar/images/bee"+i+".png");
}
}
private int xSpeed;//x坐标增量
private int ySpeed;//y坐标增量
private int awardType;//奖励类型0或者1
public Bee() {
super(60, 50);
xSpeed=1;
ySpeed=1;
Random rand=new Random();
awardType=rand.nextInt(2);
}
@Override
public int getAward() {
return awardType;
}
@Override
public void step() {
x+=xSpeed;
y+=ySpeed;
if(x<=0||x>=ShootGame.jframeWidth) {
xSpeed*=-1;//改变方向
}
}
int deadIndex=1;
@Override
public BufferedImage getImage() {
if(isLife()) {
return images[0];
}else if(isDead()){
BufferedImage img=images[deadIndex++];
if(deadIndex==images.length) {
state=REMOVE;
}
return img;
}
return null;
}
@Override
public boolean outOfBounds() {
return this.y>ShootGame.jframeHeight;
}
}
4.BigAirPlane.java
BigAirPlane.java:
package AirPlaneWar;
import java.awt.image.BufferedImage;
public class BigAirPlane extends FlyingObject implements Enemy{
public static BufferedImage[] images;
static {
images=new BufferedImage[5];
for(int i=0;i<images.length;i++) {
images[i]=loadImage("/AirPlaneWar/images/bigplane"+i+".png");
}
}
private int speed;
public BigAirPlane() {
super(69, 99);
speed=3;
}
@Override
public void step() {
// TODO Auto-generated method stub
y+=speed;
}
int deadIndex=1;
@Override
public BufferedImage getImage() {
if(isLife()) {
return images[0];
}else if(isDead()) {
BufferedImage img=images[deadIndex++];
if(deadIndex==images.length) {
state=REMOVE;
}
return img;
}
return null;
}
@Override
public boolean outOfBounds() {
return this.y>=ShootGame.jframeHeight;
}
@Override
public int getScore() {
// TODO Auto-generated method stub
return 10;
}
}
5.Bullet.java
Bullet.java:
package AirPlaneWar;
import java.awt.image.BufferedImage;
public class Bullet extends FlyingObject{
public static BufferedImage image;
static {
image=loadImage("/AirPlaneWar/images/bullet.png");
}
/* 当前子弹的坐标增量 */
private int speed=5;
public Bullet(int x, int y) {
super(8, 14, x, y);
}
@Override
public BufferedImage getImage() {
// TODO Auto-generated method stub
if(isLife()) {
return image;
}else if(isDead()) {
state=REMOVE;
}
return null;
}
/* 子弹移动函数 */
@Override
public void step() {
// TODO Auto-generated method stub
y-=speed;
}
@Override
public boolean outOfBounds() {
// TODO Auto-generated method stub
return this.y<=-this.height;
}
}
6.Enemy.java
Enemy.java:
package AirPlaneWar;
/**
* 打中大小敌机以后的奖励
*/
public interface Enemy {
/* 得分 */
public int getScore();
}
7.FlyingObject.java
FlyingObject.java:
package AirPlaneWar;
import java.awt.Graphics;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.util.Random;
import javax.imageio.ImageIO;
import javax.management.RuntimeErrorException;
public abstract class FlyingObject {
/* 定义飞行物的基本属性 */
//飞行的状态
public static final int LIFE=0;//活着
public static final int DEAD=1;//死了
public static final int REMOVE=2;//删除
//定义当前飞行物的初始状态--活着
public int state=LIFE;
/* 定义飞行物的基本属性 */
protected int width;//宽
protected int height;//高
protected int x;//x坐标
protected int y;//y坐标
/**
* 定义不同的构造方法
* 两种
* 1、英雄机、天空、子弹提供的
* 2.大小敌机、蜜蜂提供的
* @param filename
* @return
*/
//定义英雄机、天空、子弹提供的构造方法
public FlyingObject(int width,int height,int x,int y) {
this.width=width;//图片本身的宽度
this.height=height;//图片本身的高度
this.x=x;
this.y=y;
}
/* 定义大小敌机、蜜蜂提供的构造方法 */
public FlyingObject(int width,int height) {
this.width=width;
this.height=height;
//初始化飞行物出现的范围
Random ran=new Random();
x=ran.nextInt(ShootGame.jframeWidth-this.width);
y=-this.height;
}
/* 自定义方法-读取图片的方法 */
public static BufferedImage loadImage(String filename) {
BufferedImage imgBufferedImage;
try {
imgBufferedImage=ImageIO.read(FlyingObject.class.getResource(filename));
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
throw new RuntimeException();
}
return imgBufferedImage;
}
public abstract void step();
public abstract BufferedImage getImage();
public abstract boolean outOfBounds();
public void paintObject(Graphics g) {
g.drawImage(getImage(), x, y, null);
}
/* 碰撞算法:this-敌人 other:子弹或者英雄 */
public boolean hit(FlyingObject other) {
//计算X的最大最小边界
int x1=this.x-other.width;
int x2=this.x+this.width;
//计算Y的最大最小边界
int y1=this.y-other.height;
int y2=this.y+this.height;
//获取英雄机或者子弹的XY坐标
int x=other.x;
int y=other.y;
return (x>=x1)&&(x<=x2)&&(y>=y1)&&(y<=y2);
}
/* 判断是否活着 */
public boolean isLife() {
return state==LIFE;
}
/*判断是否被删除*/
public boolean isRemove() {
return state==REMOVE;
}
/* 判断是否死了 */
public boolean isDead() {
return state==DEAD;
}
//飞行物去死
public void goDead() {
state=DEAD;//死了但是没有删除
}
}
8.Hero.java
Hero.java:
package AirPlaneWar;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.image.BufferedImage;
public class Hero extends FlyingObject{
private static BufferedImage[] images;
static {
images=new BufferedImage[2];
for(int i=0;i<images.length;i++) {
images[i]=loadImage("/AirPlaneWar/images/hero"+i+".png");
}
}
private int life;//定义生命值
private int doubleFire;//定义双倍火力
public Hero() {
super(97,124,150,400);
life=3;
doubleFire=0;//初始为单倍活力
}
/* 英雄机随鼠标移动 */
public void moveTo(int x,int y) {
this.x=x-this.width/2;//减去自身宽度的一半
this.y=y-this.height;
}
public Bullet[] shoot() {
int xStep=this.width/4;//计算英雄机的1/4宽
int yStep=20;//英雄机和子弹之间的距离
if(doubleFire>0) {
Bullet[] bs=new Bullet[3];
bs[0]=new Bullet(this.x+xStep, this.y-yStep);
bs[1]=new Bullet(this.x+2*xStep, this.y-yStep);
bs[2]=new Bullet(this.x+3*xStep, this.y-yStep);
//双倍子弹发射一定量以后自动变为单倍
doubleFire-=2;
return bs;
}else {
Bullet[] bs=new Bullet[1];
bs[0]=new Bullet(this.x+2*xStep, this.y-yStep);
return bs;
}
}
public void paintObject(Graphics g) {
g.drawImage(getImage(), x, y, null);
}
int deadIndex=0;
public BufferedImage getImage() {
// TODO Auto-generated method stub
if(isLife()) {
if(deadIndex==2) {
deadIndex=0;
}
return images[deadIndex++%2];//循环刷新图片,再0与1来回选择,形成英雄机喷火的效果。
}
return null;
}
@Override
public void step() {
// TODO Auto-generated method stub
}
@Override
public boolean outOfBounds() {
// TODO Auto-generated method stub
return false;
}
/* 自定义方法--英雄机减少性命 */
public void substractLife() {
life--;
}
public void addLife() {//英雄机增加性命
life++;
}
public int getLife() {
return life;
}
public void addDoubleFire() {
doubleFire+=40;
}
public void clearDoubleFire() {
doubleFire=0;
}
}
9.ShootGame.java
ShootGame.java:
package AirPlaneWar;
import java.awt.Graphics;
import java.awt.Toolkit;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.image.BufferedImage;
import java.lang.reflect.Array;
import java.util.Arrays;
import java.util.Random;
import java.util.Timer;
import java.util.TimerTask;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class ShootGame extends JPanel{
/* 定义窗口的基本数据 */
public static int width=Toolkit.getDefaultToolkit().getScreenSize().width;//获取屏幕的宽度
public static int height=Toolkit.getDefaultToolkit().getScreenSize().height;//获取屏幕的高度
public static int jframeWidth=400;//窗体的宽度
public static int jframeHeight=700;//窗体的高度
public static int jframeX=width/2-jframeWidth/2;//获取窗体居中的X坐标
public static int jframeY=height/2-jframeHeight/2;//获取窗体居中的Y坐标
/* 窗体、图片都是以坐上角的坐标为起点开始向右和向下扩展的 */
/* 定义实体类 */
private Sky sky=new Sky();//天空
private Hero hero=new Hero();//英雄机
private FlyingObject[] enemies= {};//敌人(大小敌机和蜜蜂)数组
private Bullet[] bullets= {};//子弹数组
/* 生成敌人核心算法 */
public FlyingObject nextOne() {
Random ran=new Random();//实例化随机数对象--随机产生敌人的类型(大、小敌机、蜜蜂)
int type=ran.nextInt(20);//0-20内的随机数来生成对象
if(type<4) {
return new Bee();
}else if(type<12) {
return new AirPlane();//小敌机
}else {
return new BigAirPlane();//大敌机
}
}
/**
* 设置游戏状态
* 启动、运行、暂停、结束
* 默认状态为启动
* @param args
*/
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;//默认状态为启动
/* 定义图片集 */
public static BufferedImage start;//启动图
public static BufferedImage pause;//暂停图
public static BufferedImage gameover;//游戏结束图
/* 加载图片 */
static {
start=FlyingObject.loadImage("/AirPlaneWar/images/start.png");//开始图片
pause=FlyingObject.loadImage("/AirPlaneWar/images/pause.png");//暂停图片
gameover=FlyingObject.loadImage("/AirPlaneWar/images/gameover.png");//结束图片
}
public static void main(String[] args) {
// TODO Auto-generated method stub
JFrame jf=new JFrame();//实例化窗口对象
jf.setTitle("飞机大战==第3版");//设置标题
jf.setBounds(jframeX, jframeY, jframeWidth, jframeHeight);//设置窗体位置以及窗体大小
ShootGame sg=new ShootGame();//实例化当前类对象
jf.add(sg);
jf.setVisible(true);//窗体可见
sg.action();//程序启动
jf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
int enterIndex=0;//敌人入场计数器
public void enterAction() {
enterIndex++;
if(enterIndex%8==0) {
FlyingObject obj=nextOne();//随机生成一个敌人
enemies = Arrays.copyOf(enemies, enemies.length+1);//扩容
enemies[enemies.length-1]=obj;//将敌人放在数组的最后
}
}
int shootIndex=0;//子弹入场计数器
public void shootAction() {
shootIndex++;
if(shootIndex % 10 ==0) {//每300ms走一次
Bullet[] bs=hero.shoot();//获取子弹数组
bullets=Arrays.copyOf(bullets, bullets.length+bs.length);//扩容
//将英雄机发射的子弹数组存进子弹数组中
System.arraycopy(bs, 0, bullets, bullets.length-bs.length, bs.length);
}
}
/* 飞行物移动事件 */
public void stepAction() {
for(int i=0;i<bullets.length;i++) {//子弹移动事件
bullets[i].step();
}
for(int i=0;i<enemies.length;i++) {
enemies[i].step();
}
}
public void outOfBoundsAction() {
int index=0;
FlyingObject[] enemiesLives=new FlyingObject[enemies.length];
for(int i=0;i<enemies.length;i++) {
FlyingObject fo=enemies[i];
if(!fo.outOfBounds()) {
enemiesLives[index++]=fo;
}
}
enemies=Arrays.copyOf(enemiesLives, index);
index=0;
//获取每一个子弹
//定义不越界子弹数组
Bullet[] bulletsLives=new Bullet[bullets.length];
for(int i=0;i<bullets.length;i++) {
Bullet b=bullets[i];
if(!b.outOfBounds()) {
bulletsLives[index]=b;
index++;
}
}
bullets=Arrays.copyOf(bulletsLives, index);
}
public void action() {
MouseAdapter l=new MouseAdapter() {
public void mouseClicked(MouseEvent e) {
// TODO Auto-generated method stub
//根据不同的状态做出不同的结果
switch(state) {
case START:
state=RUNNING;//开始-》运行
break;
case RUNNING:
state=PAUSE;//运行->暂停
break;
case PAUSE:
state=RUNNING;
break;//暂停->运行
case GAME_OVER:
state=START;//结束->启动
break;
}
}
@Override
public void mouseExited(MouseEvent e) {
// TODO Auto-generated method stub
if(state==RUNNING)
state=PAUSE;//运行->暂停
}
@Override
public void mouseMoved(MouseEvent e) {//鼠标移动事件
//判断当前状态是否为运行状态
if(state==RUNNING) {
int x=e.getX();//获取鼠标X轴位置
int y=e.getY();
hero.moveTo(x, y);//英雄机移动到鼠标位置
}
}
@Override
public void mouseEntered(MouseEvent e) {
if(state==PAUSE)
state=RUNNING;//暂停->运行
}
};
this.addMouseListener(l);//添加鼠标监听事件
this.addMouseMotionListener(l);//添加鼠标滑动事件
Timer timer=new Timer();
int intervel=10;//10ms
timer.schedule(new TimerTask() {
@Override
public void run() {
// TODO Auto-generated method stub
if(state==RUNNING) {
enterAction();//大小敌机和蜜蜂入场
shootAction();//子弹入场
stepAction();//飞行物移动
outOfBoundsAction();//删除越界飞行物
bulletBangAction();//
}
repaint();
}
},intervel,intervel);
}
int score=0;//定义玩家得分
public void bulletBangAction() {
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(f.hit(b)&&f.isLife()&&b.isLife()) {
f.goDead();
b.goDead();
if(f instanceof Enemy) {
Enemy en=(Enemy)f;
score+=en.getScore();
}
if(f instanceof Award) {
Award aw=(Award)f;
int type=aw.getAward();//根据奖励类型判断奖励项
switch(type) {
case Award.DOUBLE_FIRE:
hero.addDoubleFire();
break;
case Award.LIFE:
hero.addLife();
break;
}
}
}
}
}
}
public void paint(Graphics g){
// g.drawImage(start, 0, 0, null);
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);//绘制子弹
}
/* 绘制得分 */
g.drawString("SCORE:"+score, 10, 25);
/* 绘制生命值 */
g.drawString("LIFE:"+hero.getLife(), 10, 45);
/* 根据不同状态绘制不同图片 */
switch(state) {
case START:
g.drawImage(start, 0,0, null);
break;
case PAUSE:
g.drawImage(pause,0, 0, null);
break;
case GAME_OVER:
g.drawImage(gameover, 0, 0, null);
break;
}
}
}
10.Sky.java
Sky.java:
package AirPlaneWar;
import java.awt.Graphics;
import java.awt.image.BufferedImage;
public class Sky extends FlyingObject{
public Sky() {
super(ShootGame.jframeWidth, ShootGame.jframeHeight, 0, 0);
// TODO Auto-generated constructor stub
}
public static BufferedImage image;//定义背景图片
/* 静态代码块加载图片 */
static {
image=loadImage("/AirPlaneWar/images/background.png");
}
public BufferedImage getImage() {
return image;
}
public void paintObject(Graphics g) {
g.drawImage(getImage(), x, y, null);
}
@Override
public void step() {
// TODO Auto-generated method stub
}
@Override
public boolean outOfBounds() {
// TODO Auto-generated method stub
return false;
}
}
总结
游戏主要是利用鼠标左键点击开始和暂停,飞机移动到边界以后也会暂停。
飞机一直跟随鼠标移动。
下载连接:
链接:https://pan.baidu.com/s/1XGY_HIqsIIKUyP8CLRZsRw
提取码:whp5