飞机大战设计基本流程
1.窗口显示 JFrame
2.画板/面板 JPanel
public static void main(String[] args) {
JFrame window = new JFrame("飞机大战"); //创建对象 并设定窗口的标题
GamePanel g = new GamePanel();
window.add(g);
g.action();
window.setSize(WIDTH, HEIGHT); //设置窗口的长宽
window.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE); //设置窗口的关闭
window.setLocationRelativeTo(null); //窗口居中
window.setVisible(true); //显示窗口
}
原生的 JPanel 中, 不能自定义绘画,只能画按钮, 输入框.. 等一些组件
功能加强 -> 自定义类继承 JPanel
3.图片读取
1.硬盘中有图片文件
2.将硬盘中的图片文件, 读取到JVM内存中, 成一个对象
InputOutput -> IO
类名.class -> 所有的类加载到方法区中,对应一个Class对象
通过重复使用一下语句,可以将图片读入内存中
airplane = ImageIO.read(FlyGame.class.getResourceAsStream("res/airplane.png"));
4.程序的设计
类的设计
飞机大战:
拥有相似的需求: 自己的飞机, 敌机, 小蜜蜂, 子弹
子类 extends 父类
自己的飞机: Hero
敌机: Airplane
小蜜蜂: Bee
子弹: Bullet - 有参的构造方法
大敌机: BigPlane
以上类中相同的成员变量, 和相同的方法, 提取出来
父类: FlyingObject
int x, int y, 图片, int width, int height
move() - 移动
5.补充父类中的构造方法
FlyingObject(int x, int y, BufferedImage img, int life) {
this.img = img;
this.width = img.getWidth();
this.height = img.getHeight();
this.x = x;
this.y = y;
this.life = life;
}
6.在主程序中创建各种对象进行测试测试
7.写入各个飞行物类的move方法
@Override
public void move() {
setY(getY() + y_speed);
setX(getX() + x_speed);
if (getX() > FlyGame.WIDTH - FlyGame.bee.getWidth() - 10) {
x_speed = -x_speed;
} else if (getX() < 0) {
x_speed = -x_speed;
}
}
8.主程序中: 添加定时器
a.生成新的飞行物(小蜜蜂, 敌机, 大敌机)
b.移动所有飞行物
d.发射子弹 - 属于英雄机的行为 - 写在Hero类中
e.移动所有子弹
c.判断飞行物和子弹越界
f.判断子弹和飞行物碰撞
g.英雄机移动 - move - 鼠标控制
h.英雄机和敌机碰撞
i.判断游戏是否结束
z.重画
public void action() {
//TimerTask 需要重复的代码
//long 定时器开始的时间
//long 时间间隔
time.schedule(new TimerTask() {
@Override
public void run() {
if (state == RUNING) {
//创建敌机
createFlyingObject();
//创建敌机的移动
paintFlyMove();
//创建子弹
createBullet();
//创建子弹的移动
bulletMove();
//越界处理
outOfBoundsAction();
//碰撞
boonAction();
}
//重新绘制
repaint();
}
}, 1000, 30);
}
9.添加鼠标监听事件 - 监听器 - 接口
单击\移动\鼠标移出界面\鼠标移入界面
窗口/画板.addMouseListener -> 单击\鼠标移入\鼠标移出
窗口/画板.addMouseMotionListener -> 鼠标移动
注意:
接口功能太多, 选择性使用功能, 提供了一个适配器 - 抽象类
MouseAdapter - 抽象类, 将所有接口方法空实现
//创建一个鼠标的适配器
MouseAdapter Mouse = new MouseAdapter() {
//重写鼠标点击
@Override
public void mouseClicked(MouseEvent e) {
//判断状态
if (state == START) {
state = RUNING;
} else if (state == GAMEOVER) { //若游戏结束
state = START;
//重新生成英雄机、飞行物、子弹
hero = new Hero();
flyings = new ArrayList<>();
flyBullet = new ArrayList<>();
}
}
//重写鼠标移入窗口 实现继续游戏
@Override
public void mouseEntered(MouseEvent e) {
if (state == PAUSE) {
state = RUNING;
}
}
//重写鼠标移出窗口 实现暂停
@Override
public void mouseExited(MouseEvent e) {
if (state == RUNING) {
state = PAUSE;
}
}
//重写鼠标的移动 并实现使用鼠标控制英雄机
@Override
public void mouseMoved(MouseEvent e) {
if (state == RUNING) {
hero.setX(e.getX() - FlyGame.hero0.getWidth() / 2);
hero.setY(e.getY() - FlyGame.hero0.getHeight() / 2);
bullet.setX(hero.getX());
bullet.setY(hero.getY());
}
}
};
10.游戏状态的设置
a.初始状态 start
b.运行状态 running
c.暂停状态 pause
d.游戏结束 gameover
start -> 鼠标单击 -> running
running -> 移出 -> pause-> hero.getLife()==0 -> gameover
pause -> 鼠标移入 -> running
gameover -> 鼠标单击 -> start
//判断窗口当前状态,并输出相应的图片
switch (state) {
case START:
g.drawImage(FlyGame.start, 0, 0, this);
break;
case GAMEOVER:
g.drawImage(FlyGame.gameover, 0, 0, this);
break;
case PAUSE:
g.drawImage(FlyGame.pause, 0, 0, this);
break;
}
11.奖励类型: [火力加成], 生命值加成
// 发射子弹并生成新的子弹
public Bullet[] shoot() {
Bullet[] bullets;
if (doubleFire == 0) {
bullets = new Bullet[1];
bullets[0] = new Bullet(this.getX() + this.getWidth() / 2, this.getY());
} else {
bullets = new Bullet[2];
bullets[0] = new Bullet(this.getX() + this.getWidth() / 4, this.getY());
bullets[1] = new Bullet(this.getX() + this.getWidth() / 4 * 3, this.getY());
doubleFire--;
}
return bullets;
}
12.碰撞
子弹和飞行物的碰撞: 要么加分, 要么奖励
飞行物和英雄机的碰撞: 减英雄机生命值
private void boonAction() {
for (int i = 0; i < flyBullet.size(); i++) {
FlyingObject bul = flyBullet.get(i);
for (int j = 0; j < flyings.size(); j++) {
FlyingObject fly = flyings.get(j);
//敌机和子弹的碰撞
if (bul.getX() > fly.getX() && bul.getX() < fly.getX() + fly.getWidth()
&& bul.getY() > fly.getY() && bul.getY() < fly.getY() + fly.getWidth()) {
flyBullet.remove(i);
fly.flyLife();
if (fly.getLife() == 0) {
flyings.remove(j);
//利用接口实现分数的累加
if (fly instanceof Enemy) {
Enemy enemy = (Enemy) fly;
hero.addScore(enemy.getScore());
}
//利用接口实现奖励机制
if (fly instanceof Award) {
Award award = (Award) fly;
if (award.getAwardType() == Award.ADD_LIFE)
hero.addLife();
else {
hero.addDoubleFire();
}
}
}
i--;
j--;
break;
}
//敌机和英雄机的碰撞
if (hero.getX() + FlyGame.hero0.getWidth() / 2 > fly.getX()
&& hero.getX() + FlyGame.hero0.getWidth() / 2 < fly.getX() + fly.getWidth()
&& hero.getY() < fly.getY() && hero.getY() + FlyGame.hero0.getHeight() > fly.getY()) {
flyings.remove(j);
j--;
hero.setLife(hero.getLife() - 1);
if (hero.getLife() == 0) {
state = GAMEOVER;
break;
}
}
}
}
}
实现代码:Github链接:
https://github.com/923677975/flygame.git