前言
《飞机大战-III》是一款融合了街机、竞技等多种元素的经典射击手游。华丽精致的游戏画面,超炫带感的技能特效,超火爆画面让你肾上腺素爆棚,给你带来全方位震撼感受,体验飞行战斗的无限乐趣。
游戏是用java语言实现,采用了swing技术进行了界面化处理,设计思路用了面向对象思想。
主要需求
基于Java Swing,以飞机大战为原形,以抗日电视剧《亮剑》中的“李云龙”为主题,实现菜单、选关、难度、等级、技能等功能。
主要设计
①进入游戏后,请按下shift键(将键盘改为英文模式)
②技能为数字1(攻击)、2(治愈)、3(蓄气)
③数字4、5、6、7、8为创意音效,空格键为暂停
④使用1、2技能会消耗相应的技能蓝条,3技能消耗一定血量恢复一定蓝
⑤触碰游戏中随机出现的降落伞弹药可以回蓝
⑥触碰游戏中随机出现的闪光粒子可以随机更换1技能特效,且血量与蓝加2
⑦由鼠标控制角色位置,角色会自动发射相应等级的子弹
⑧每打败一个boss,角色升一级,子弹同行升级
⑨每过一关,角色血量和蓝自动增大并加满
⑩按下空格暂停游戏
本游戏该版本共三个关卡和三种难度,任君挑选
功能截图
游戏开始
选择战机
开始游戏
代码实现
游戏面板类,把各游戏对象集中绘制到此面板
public class GamePanel extends JFrame {
// Keypoint 基本变量定义
Image offScreenImage = null; // 定义双缓存
int width = 1250, height = 725; // 窗口宽高
public static int state = 0; // Keypoint 游戏状态 0未开始 1运行 2暂停 3通关失败 4通关成功
public static int score = 0; // 游戏分数
public static int count = 1; // 游戏绘制次数(计时作用)
static int enemyFrequency = 30; // 敌机出现频率(不同关卡速率不同)
static int enemyShellFrequency = 40; // 敌机子弹出现频率(不同关卡速率不同)
static int planeShellFrequency = 20; // 战机子弹出现频率(不同关卡速率不同)
public static int enemyCount = 1; // 记录敌机敌机出现数量
static int bossAppear = 50; // 定义出现多少敌机后boss出现
public static boolean skill_release = false; // 判定技能是否已经释放
static boolean play_BOSS_sound = true; // 调控boss出场音效只播放一次
static boolean play_warn_sound = true; // 调控boss出场预警音效只播放一次
static boolean end = true; // 调控失败或胜利音效只播放一次
static boolean T = false; // 失败或胜利时按T退出游戏
public static boolean R = false; // 返回主界面
static boolean play = true; // 调控按纽二(点击播放,再点击暂停)
static boolean prearranged = true; // 动态效果预加载
public static boolean MAAppear = false; // 神兽出现
public static boolean MAExist = false; // 神兽存在否
public static boolean plane_create = false; // 飞机创建
// 难度
static int skillConsume = 2; // 2 5 10 用技能消耗蓝
static int skillRecovery = 100; // 100 150 999 回蓝速度
static int lifeRecovery = 50; // 50 90 500 回血速度
// Keypoint 元素实体定义
// 背景实体类
public GameObject backGroundObj = new BackGround(GameUtils.bgImg, 0, -1900, 2, this);
// 战机实体类
public GameObject planeObj = new Plane(GameUtils.planeImg, 600, 550, 70, 100, 0, this);
// boss实体类
public GameObject BOSSObj = null;
// 神兽实体类
public GameObject mAnimalsObj = null;
// Keypoint 按钮声明
JButton button1 = new JButton("开始游戏");
JButton button2 = new JButton("听听歌吧");
JButton button3 = new JButton("退出游戏");
JButton button4 = new JButton("选择难度\\关卡");
JButton button5 = new JButton("游戏说明");
JButton button6 = new JButton("选择战机");
JPanel frame = new JPanel(); // 按钮面板
// Keypoint 音效声明
Sound sound = new Sound(GameUtils.run_no1); // 背景音乐1(亮剑)
// Sound sound2 = new Sound(GameUtils.run_no2); // 开始按钮(开炮)
Sound sound3 = new Sound(GameUtils.run2_no1); // 第二关背景音乐(无人机群)
Sound sound4 = new Sound(GameUtils.basic_no5); // 背景音乐2(枪林弹雨)
public GamePanel() {
// Keypoint 开始界面按钮
frame.setLayout(null);
Sound s = new Sound(GameUtils.basic_no9); // 按纽二切歌
button1.setIcon(new ImageIcon(GameUtils.button_start)); // 开始界面按钮一
button1.setBounds(530, 350, 245, 70);
frame.add(button1);
button1.addActionListener(e -> {
if (!Popup.select) {
// 如果返回主界面没有选择关卡,默认初始化第一关
GamePanel.bossAppear = 50;
BOSS.number = 0;
GamePanel.play_BOSS_sound = true;
Plane.lock = false;
Plane.plane_level = 1;
}
state = 1;
s.stop();
sound.start();
sound.loop();
new Sound(GameUtils.run_no2).start();
});
button2.setIcon(new ImageIcon(GameUtils.button_selection_plane)); // 开始界面按钮二
button2.setBounds(530, 435, 245, 70);
frame.add(button2);
button2.addActionListener(e -> new Popup_SelectPlane());
button3.setIcon(new ImageIcon(GameUtils.button_selection)); // 开始界面按钮三
button3.setBounds(530, 520, 245, 70);
frame.add(button3);
button3.addActionListener(e -> new Popup());
button4.setIcon(new ImageIcon(GameUtils.button_exit)); // 开始界面按钮四
button4.setBounds(530, 605, 245, 70);
frame.add(button4);
button4.addActionListener(e -> System.exit(0));
button5.setIcon(new ImageIcon(GameUtils.button_explain)); // 开始界面按钮五
button5.setBounds(20, 20, 45, 45);
frame.add(button5);
button6.setIcon(new ImageIcon(GameUtils.button_select)); // 开始界面按钮二
button6.setBounds(20, 80, 45, 45);
frame.add(button6);
button6.addActionListener(e -> {
if (play) {
sound.stop();
s.start();
s.loop();
play = false;
} else {
s.stop();
sound.start();
play = true;
}
});
button1.addMouseListener(new MouseAdapter() {
@Override
public void mouseEntered(MouseEvent e) {
new Sound(GameUtils.basic_no10).start();
}
});
button2.addMouseListener(new MouseAdapter() {
@Override
public void mouseEntered(MouseEvent e) {
new Sound(GameUtils.basic_no10).start();
}
});
button3.addMouseListener(new MouseAdapter() {
@Override
public void mouseEntered(MouseEvent e) {
new Sound(GameUtils.basic_no10).start();
}
});
button4.addMouseListener(new MouseAdapter() {
@Override
public void mouseEntered(MouseEvent e) {
new Sound(GameUtils.basic_no10).start();
}
});
button5.addMouseListener(new MouseAdapter() {
@Override
public void mouseEntered(MouseEvent e) {
new Sound(GameUtils.basic_no11).start();
JOptionPane.showMessageDialog(null,
"亲爱的云龙战士,欢迎来到开炮大陆!!\n" +
"-----------------------------------------------------2021-12-01-----------------------------------------------------\n" +
"下面是操作说明:\n" +
" ①进入游戏后,请按下shift键(将键盘改为英文模式)\n" +
" ②技能为数字1(攻击)、2(治愈)、3(蓄气)\n" +
" ③数字4、5、6、7、8为创意音效,空格键为暂停\n" +
" ④使用1、2技能会消耗相应的技能蓝条,3技能消耗一定血量恢复一定蓝\n" +
" ⑤触碰游戏中随机出现的降落伞弹药可以回蓝\n" +
" ⑥触碰游戏中随机出现的闪光粒子可以随机更换1技能特效,且血量与蓝加2\n" +
" ⑦由鼠标控制角色位置,角色会自动发射相应等级的子弹\n" +
" ⑧每打败一个boss,角色升一级,子弹同行升级\n" +
" ⑨每过一关,角色血量和蓝自动增大并加满\n" +
" ⑩按下空格暂停游戏\n" +
"本游戏该版本共三个关卡和三种难度,任君挑选\n" +
"-----------------------------------------------------2021-12-07-----------------------------------------------------\n" +
"更新:\n" +
" ①在暂停、失败、胜利界面可以按’R‘返回主界面,按‘T’退出游戏\n" +
" ②新增在暂停界面按‘O’进入商店\n" +
" ③w s a d上下左右控制神兽移动\n" +
"-----------------------------------------------------2021-12-08-----------------------------------------------------\n" +
"更新:\n" +
" ①敌机会根据战机的位置进行跟踪移动\n" +
" ②修改部分技能效果\n" +
"-----------------------------------------------------2021-12-11-----------------------------------------------------\n" +
"更新:\n" +
" ①新增初始菜单选择战机功能\n" +
"-----------------------------------------------------2021-12-13-----------------------------------------------------\n" +
" ①修复一些已知问题\n" +
"-------------------------------------------------------------------------------------------------------------------------\n" +
"\n" +
"注意事项:\n" +
" 如果在游戏中遇到任何问题,请关闭重启!!!\n" +
"\n" +
" Developer: 涛\n", "※游戏说明", JOptionPane.PLAIN_MESSAGE);
}
});
button6.addMouseListener(new MouseAdapter() {
@Override
public void mouseEntered(MouseEvent e) {
new Sound(GameUtils.basic_no10).start();
}
});
if (prearranged) {
Explode explodeObj = new Explode(1000, -1000);
GameUtils.explodeList.add(explodeObj);
GameUtils.removeList.add(explodeObj);
Explode2 explodeObj2 = new Explode2(1000, -500);
GameUtils.explodeList2.add(explodeObj2);
GameUtils.removeList.add(explodeObj2);
Explode3 explodeObj3 = new Explode3(1000, -200);
GameUtils.explodeList3.add(explodeObj3);
GameUtils.removeList.add(explodeObj3);
prearranged = false;
}
this.add(frame); // 把开始界面按钮添加进主面板
launch();
}
// Keypoint 启动
public void launch() {
this.setFocusable(true);
this.setVisible(true);
this.setBounds(0, 0, width, height);
this.setTitle("云龙开炮4.0");
this.setIconImage(GameUtils.icon); // 程序图标
this.setResizable(false);
this.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
// 将游戏对象添加到大集合
GameUtils.gameObjList.add(backGroundObj);
GameUtils.gameObjList.add(planeObj);
// 鼠标监听
this.addMouseListener(new MouseAdapter() {
@Override
public void mouseClicked(MouseEvent e) {
System.out.println("鼠标监听按下 ——> " + e.getButton());
if (e.getButton() == 3) {
System.out.println("释放技能1"); // 释放技能(攻击)
Skill.release = true;
Skill.number = 1;
}
}
});
// Keypoint 键盘监听(暂停、释放技能)
this.addKeyListener(new KeyAdapter() {
@Override
public void keyPressed(KeyEvent e) {
super.keyPressed(e);
switch (e.getKeyCode()) {
case 32: // 空格暂停
switch (state) {
//运行改为暂停
case 1:
System.out.println("游戏暂停");
state = 2;
sound.stop();
sound3.stop();
sound4.stop();
break;
//暂停改为运行
case 2:
System.out.println("继续游戏");
state = 1;
sound.start();
if (Plane.plane_level == 2) {
sound3.start();
}
sound4.start();
break;
}
break;
case 49: // 1 释放技能(攻击)
if (Plane.plane_skill >= 5) {
System.out.println("释放技能1(攻击)");
Skill.release = true;
Skill.number = 1;
}
break;
case 50: // 2 释放技能(治疗)
if (Plane.plane_skill >= 5) {
System.out.println("释放技能2(治疗)");
Skill.release = true;
Skill.number = 2;
}
break;
case 51: // 3 蓄气
System.out.println("释放技能3(蓄气)");
Skill.release = true;
Skill.number = 3;
break;
case 52: // 4 音效
new Sound(GameUtils.skill_no10).start();
break;
case 53: // 5 音效
new Sound(GameUtils.skill_no11).start();
break;
case 54: // 6 音效
new Sound(GameUtils.skill_no12).start();
break;
case 55: // 7 音效
new Sound(GameUtils.skill_no13).start();
break;
case 56: // 8 音效
new Sound(GameUtils.skill_no14).start();
break;
case 82: // 监听R键
if (state == 2 || state == 3 || state == 4)
R = true;
break;
case 84: // 监听T键
if (state == 2 || state == 3 || state == 4)
T = true;
break;
case 79: // 监听O键
if (state == 2) {
new Popup_Shop();
}
break;
case 87: // W
if (mAnimalsObj != null) {
MAnimals.Direction = 1;
}
break;
case 83: // S
if (mAnimalsObj != null) {
MAnimals.Direction = 2;
}
break;
case 65: // A
if (mAnimalsObj != null) {
MAnimals.Direction = 3;
}
break;
case 68: // D
if (mAnimalsObj != null) {
MAnimals.Direction = 4;
}
break;
default:
System.out.println("键盘监听按下 ——> " + e.getKeyCode());
break;
}
}
});
// Keypoint 刷新屏幕
while (true) {
if (state > 0) {
repaint();
if (state == 1)
createObj();
}
try {
Thread.sleep(10); // 10ms刷新一次
} catch (Exception e) {
e.printStackTrace();
}
}
}
public void init() {
state = 0; // Keypoint 游戏状态 0未开始 1运行 2暂停 3通关失败 4通关成功
score = 0; // 游戏分数
count = 1; // 游戏绘制次数(计时作用)
enemyFrequency = 30; // 敌机出现频率(不同关卡速率不同)
enemyShellFrequency = 40; // 敌机子弹出现频率(不同关卡速率不同)
planeShellFrequency = 20; // 战机子弹出现频率(不同关卡速率不同)
enemyCount = 1; // 记录敌机敌机出现数量
bossAppear = 50; // 定义出现多少敌机后boss出现
skill_release = false; // 判定技能是否已经释放
play_BOSS_sound = true; // 调控boss出场音效只播放一次
play_warn_sound = true; // 调控boss出场预警音效只播放一次
end = true; // 调控失败或胜利音效只播放一次
T = false; // 失败或胜利时按T退出游戏
play = true; // 调控按纽二(点击播放,再点击暂停)
prearranged = true; // 动态效果预加载
MAAppear = false; // 神兽出现
Plane.goldNumber = 0; // 金币数
Plane.plane_life = 100;
Plane.plane_skill = 100;
frame.setVisible(true); // 隐藏按钮
if (BOSSObj != null) {
// 初始化boss
BOSSObj.setX(-500);
BOSSObj.setY(700);
GameUtils.removeList.add(BOSSObj);
BOSS.number = 0;
BOSSObj = null;
}
if (mAnimalsObj != null) {
// 初始化神兽
mAnimalsObj.setX(-500);
mAnimalsObj.setY(700);
GameUtils.removeList.add(mAnimalsObj);
mAnimalsObj = null;
GamePanel.MAExist = false;
}
Popup.select = false; // 初始化选项按钮
// 清空画板残留图像
GameUtils.gameObjList.clear();
GameUtils.gameObjList.add(backGroundObj);
// 初始化战机
Plane.plane_number = 1;
plane_create = true;
repaint();
}
// Keypoint 绘制
@Override
public void paint(Graphics g) {
// Keypoint 双缓冲
// 创建和容器一样大小的Image
if (offScreenImage == null)
offScreenImage = this.createImage(width, height);
Graphics gImage = offScreenImage.getGraphics(); // 获得该图片的画布
gImage.fillRect(0, 0, width, height); // 填充画版
// Keypoint 根据状态关闭音效
if (state == 2 || state == 3 || state == 4) {
sound.stop();
sound3.stop();
sound4.stop();
}
// Keypoint 游戏状态
switch (state) {
case 0: // 游戏未开始
sound.start();
sound.loop();
gImage.drawImage(GameUtils.coverImg, 0, 0, null);
// Keypoint 将按钮获取焦点的方法放在面板的重绘代码中(防止闪烁)
button1.requestFocus();
button2.requestFocus();
button3.requestFocus();
button4.requestFocus();
button5.requestFocus();
button6.requestFocus();
break;
case 1: // 游戏开始
// Keypoint 创建战机对象
if (plane_create) {
GameUtils.removeList.add(planeObj);
Image img = null;
int w = 0;
int h = 0;
switch (Plane.plane_number) {
case 1:
w = 120;
h = 68;
img = GameUtils.planeImg;
break;
case 2:
w = 120;
h = 89;
img = GameUtils.planeImg2;
break;
case 3:
w = 70;
h = 100;
img = GameUtils.planeImg3;
break;
}
planeObj = new Plane(img, 600, 550, w, h, 0, this);
plane_create = false;
GameUtils.gameObjList.add(planeObj);
}
sound4.start();
sound4.loop();
frame.setVisible(false); // 隐藏按钮
GameUtils.gameObjList.addAll(GameUtils.explodeList); // 动态效果绘制添加
GameUtils.gameObjList.addAll(GameUtils.explodeList2);
GameUtils.gameObjList.addAll(GameUtils.explodeList3);
// 绘制所有游戏对象
try {
for (GameObject object : GameUtils.gameObjList)
object.paintSelf(gImage);
} catch (Exception ignored) {
// FIXME 空指针异常(暂不处理)
}
GameUtils.gameObjList.removeAll(GameUtils.removeList); // 消失对象删除(防止占据内存过大)
/* FIXME
* System.out.println("removeList1111:" + GameUtils.removeList.size());
* System.out.println("gameObjList1111:" + GameUtils.gameObjList.size());
* System.out.println("removeList2222:" + GameUtils.removeList.size());
* System.out.println("gameObjList2222:" + GameUtils.gameObjList.size());
* 目前看来应该是列表GameUtils.removeList内存无法清理,导致内存堆积
* 下次试试全用GameUtils.gameObjList.remove(Object o);
* 代替GameUtils.removeList.add(); GameUtils.gameObjList.removeAll(GameUtils.removeList);
*/
// boss出现预警
if (enemyCount > bossAppear - 10 && enemyCount < bossAppear && BOSSObj == null) {
if (play_warn_sound) {
new Sound(GameUtils.basic_no12).start();
play_warn_sound = false;
}
gImage.drawImage(GameUtils.warning, 520, 100, null);
}
break;
case 2: // 游戏暂停
gImage.drawImage(GameUtils.gamePauseImg, 5, 20, null);
gImage.setColor(Color.black);
gImage.setFont(new Font("微软雅黑", Font.BOLD, 20));
gImage.drawString("‘R’Menu ‘T’Exit ‘O’Shop", 430, 700);
if (T) {
System.exit(0);
} // 按T退出
if (R) {
init();
R = false;
} // 按R返回主界面
break;
case 3: // 游戏失败
// 背景音乐关闭
gImage.drawImage(GameUtils.gameFailureImg, 0, 0, null);
// 改变画笔的颜色
gImage.setColor(Color.white);
//改变文字大小和样式
gImage.setFont(new Font("微软雅黑", Font.BOLD, 60));
//添加文字
gImage.drawString(score + "", 220, 268);
gImage.drawString(Plane.plane_level + "", 334, 360);
gImage.drawString(Plane.plane_life + "", 334, 500);
gImage.drawString(Plane.plane_skill + "", 334, 575);
gImage.setColor(Color.pink);
gImage.drawString("您选择的难度为" + Popup.level + ",", 545, 348);
gImage.drawString("恭喜您在第" + Plane.plane_level + "级时被打爆,", 545, 448);
gImage.drawString("可以说是十分菜!", 545, 548);
gImage.setColor(Color.orange);
gImage.setFont(new Font("微软雅黑", Font.BOLD, 50));
gImage.drawString("‘R’返回主菜单 ‘T’退出游戏", 200, 700);
if (end) {
new Sound(GameUtils.basic_no7).start();
end = false;
}
if (T) {
System.exit(0);
} // 按T退出
if (R) {
init();
R = false;
} // 按R返回主界面
break;
case 4: // 游戏胜利
// 绘画胜利界面文字
gImage.drawImage(GameUtils.gameVictoryImg, 5, 20, null);
gImage.setColor(Color.white);
// 得分
gImage.setFont(new Font("微软雅黑", Font.BOLD, 100));
gImage.drawString(score + "", 200, 380);
// 剩余蓝/红
gImage.setFont(new Font("微软雅黑", Font.BOLD, 60));
gImage.drawString(Plane.plane_life + "", 334, 535);
gImage.drawString(Plane.plane_skill + "", 334, 610);
// 评价
gImage.setColor(Color.pink);
gImage.setFont(new Font("微软雅黑", Font.BOLD, 60));
gImage.drawString("恭喜您在" + Popup.level + "模式中,", 560, 368);
gImage.drawString("成功将敌人打爆,", 560, 468);
gImage.drawString("可以说是十分犀利啊!", 560, 568);
// R 退出
gImage.setColor(Color.orange);
gImage.setFont(new Font("微软雅黑", Font.BOLD, 50));
gImage.drawString("‘R’返回主菜单 ‘T’退出游戏", 200, 700);
// 播放胜利音效(只播放一次)
if (end) {
new Sound(GameUtils.basic_no8).start();
end = false;
}
if (T) {
System.exit(0);
} // 按T退出
if (R) {
init();
R = false;
} // 按R返回主界面
break;
}
// Keypoint 将缓冲区绘制好的图形整个绘制到容器的画布中
g.drawImage(offScreenImage, 0, 0, null);
count++; // 画面绘制次数自增
}
// Keypoint 生成游戏对象
public void createObj() {
// Keypoint 生成我方子弹
if (planeObj != null && count % planeShellFrequency == 0) {
Image img = null;
int x = planeObj.getX();
if (Plane.plane_number == 1 || Plane.plane_number == 2) {
x = planeObj.getX() + 22;
}
int y = planeObj.getY();
int w = 0;
int h = 0;
int s = 0;
switch (Plane.plane_level) {
case 1:
img = GameUtils.planeShellImg;
x += 25;
y -= 10;
w = 21;
h = 40;
s = 8;
break;
case 2:
planeShellFrequency = 15;
img = GameUtils.planeShellImg2;
x += 18;
y -= 15;
w = 28;
h = 27;
s = 10;
break;
case 3:
planeShellFrequency = 12;
img = GameUtils.planeShellImg3;
x += 18;
y -= 15;
w = 45;
h = 27;
s = 13;
break;
case 4:
planeShellFrequency = 12;
img = GameUtils.planeShellImg4;
x += 3;
y -= 30;
w = 65;
h = 33;
s = 13;
break;
case 5:
planeShellFrequency = 12;
img = GameUtils.planeShellImg5;
x -= 36;
y -= 45;
w = 150;
h = 114;
s = 13;
break;
}
GameUtils.planeShellList.add(new PlaneShell(img, x, y, w, h, s, this));
GameUtils.gameObjList.add(GameUtils.planeShellList.get(GameUtils.planeShellList.size() - 1));
}
// Keypoint 生成敌方子弹
if (count % enemyShellFrequency == 0 && BOSSObj != null) {
Image img = null;
int x = BOSSObj.getX();
int y = BOSSObj.getY();
int w = 0;
int h = 0;
int s = 0;
switch (BOSS.number) {
case 1:
img = GameUtils.enemyShellImg;
x += 110;
y += 92;
w = 47;
h = 40;
s = 6;
break;
case 2:
enemyShellFrequency = 25;
img = GameUtils.enemyShellImg2;
x += 50;
y += 130;
w = 25;
h = 25;
s = 8;
break;
case 3:
enemyShellFrequency = 25;
img = GameUtils.enemyShellImg3;
x += 60;
y += 145;
w = 51;
h = 51;
s = 8;
break;
case 4:
enemyShellFrequency = 30;
img = GameUtils.enemyShellImg4;
x += 60;
y += 90;
w = 105;
h = 50;
s = 6;
break;
case 5:
enemyShellFrequency = 30;
img = GameUtils.enemyShellImg5;
x += 55;
y += 100;
w = 135;
h = 140;
s = 8;
break;
}
GameUtils.enemyShellList.add(new EnemyShell(img, x, y, w, h, s, this));
GameUtils.gameObjList.add(GameUtils.enemyShellList.get(GameUtils.enemyShellList.size() - 1));
}
// Keypoint 生成敌机
if (count % enemyFrequency == 0) {
Image img = null;
int w = 0;
int h = 0;
int s = 0;
switch (Plane.plane_level) {
case 1:
img = GameUtils.enemy1Img;
w = 128;
h = 128;
s = 6;
break;
case 2:
sound3.start();
sound3.loop();
enemyFrequency = 22;
img = GameUtils.enemy2Img;
w = 63;
h = 46;
s = 9;
break;
case 3:
enemyFrequency = 17;
img = GameUtils.enemy2Img;
w = 63;
h = 46;
s = 12;
break;
case 4:
sound3.stop();
enemyFrequency = 25;
img = GameUtils.enemy3Img;
w = 100;
h = 57;
s = 8;
break;
case 5:
enemyFrequency = 25;
img = GameUtils.enemy4Img;
w = 120;
h = 57;
s = 8;
break;
}
// x = (int) (Math.random() * 9) * 138; // 敌机生成时随机x坐标
GameUtils.enemyList.add(new Enemy(img, (int) (Math.random() * 9) * 138, -100, w, h, s, this));
GameUtils.gameObjList.add(GameUtils.enemyList.get(GameUtils.enemyList.size() - 1));
enemyCount++;
}
// Keypoint 生成敌机2(第三关)
if (count % 40 == 0 && (BOSS.number == 4 || BOSS.number == 5)) {
Image img;
int w, h, s;
if (BOSS.number == 4) {
img = GameUtils.enemy4Img;
w = 120;
h = 57;
s = 7;
} else {
img = GameUtils.enemy3Img;
w = 100;
h = 57;
s = 6;
}
GameUtils.enemyList.add(new Enemy(img, (int) (Math.random() * 9) * 138, -100, w, h, s, this));
GameUtils.gameObjList.add(GameUtils.enemyList.get(GameUtils.enemyList.size() - 1));
enemyCount++;
}
// Keypoint 生成BOSS
if (enemyCount % bossAppear == 0 && BOSSObj == null) {
play_warn_sound = true;
BOSS.number += 1;
Image img = null;
int w = 0;
int h = 0;
int s = 0;
switch (BOSS.number) {
case 1:
if (play_BOSS_sound) {
new Sound(GameUtils.run_no3).start();
play_BOSS_sound = false;
}
img = GameUtils.bossImg;
w = 234;
h = 170;
s = 3;
bossAppear = 100;
break;
case 2:
if (!play_BOSS_sound) {
new Sound(GameUtils.run2_no2).start();
play_BOSS_sound = true;
}
img = GameUtils.bossImg2;
w = 125;
h = 157;
s = 4;
bossAppear = 100;
break;
case 3:
if (play_BOSS_sound) {
new Sound(GameUtils.run2_no3).start();
play_BOSS_sound = false;
}
img = GameUtils.bossImg3;
w = 151;
h = 165;
s = 5;
bossAppear = 90;
break;
case 4:
if (!play_BOSS_sound) {
new Sound(GameUtils.run3_no3).start();
play_BOSS_sound = true;
}
img = GameUtils.bossImg4;
w = 234;
h = 98;
s = 6;
bossAppear = 80;
break;
case 5:
if (play_BOSS_sound) {
new Sound(GameUtils.run3_no4).start();
play_BOSS_sound = false;
}
img = GameUtils.bossImg5;
w = 234;
h = 114;
s = 6;
break;
}
BOSSObj = new BOSS(img, 250, 30, w, h, s, this);
GameUtils.gameObjList.add(BOSSObj);
}
// Keypoint 生成礼物
if (count % 500 == 0) {
// x = (int) (Math.random() * 9) * 138; 礼物生成时随机x坐标
GameUtils.giftList.add(new Gift(GameUtils.giftImg1, (int) (Math.random() * 9) * 138, -100, 60, 102, 4, this));
GameUtils.gameObjList.add(GameUtils.giftList.get(GameUtils.giftList.size() - 1));
}
// Keypoint 生成礼物2(随机技能)
if (count % 850 == 0) {
GameUtils.giftList2.add(new Gift2(GameUtils.giftImg2, (int) (Math.random() * 9) * 138, -100, 65, 63, 5, this));
GameUtils.gameObjList.add(GameUtils.giftList2.get(GameUtils.giftList2.size() - 1));
}
// Keypoint 绘制技能
if (Skill.release) {
Skill.release = false;
skill_release = true;
assert planeObj != null;
int x = planeObj.getX();
int y = planeObj.getY();
int w = 0;
int h = 0;
int s = 0;
Image img = null;
// Keypoint 标准技能
switch (Skill.number) {
case 1:
if (Plane.plane_skill >= skillConsume) {
Plane.plane_skill -= skillConsume;
// Keypoint 随机技能
switch (Gift2.number) {
case 4:
x -= 40;
y -= 40;
w = 133;
h = 180;
s = 15;
img = GameUtils.skillImg4; // 雷电火卷 -1
new Sound(GameUtils.skill_no2).start();
break;
case 5:
x -= 50;
y -= 20;
w = 166;
h = 201;
s = 10;
img = GameUtils.skillImg5; // 火龙卷 -1 (跟随战机x移动)
new Sound(GameUtils.skill_no7).start();
break;
case 6:
x -= 60;
y -= 20;
w = 201;
h = 166;
s = 20;
img = GameUtils.skillImg6; // 闪电刃 -1
new Sound(GameUtils.skill_no3).start();
break;
case 7:
x -= 60;
y -= 80;
w = 201;
h = 201;
s = 5;
img = GameUtils.skillImg7; // 黑洞 -3
new Sound(GameUtils.skill_no4).start();
break;
case 8:
x -= 40;
y -= 80;
w = 157;
h = 165;
s = 10;
img = GameUtils.skillImg8; // 火星球 -2 (跟踪boss)
new Sound(GameUtils.skill_no6).start();
break;
case 9:
x -= 40;
y -= 50;
w = 166;
h = 201;
s = 15;
img = GameUtils.skillImg9; // 星耀光环 -1
new Sound(GameUtils.skill_no5).start();
break;
case 10:
default:
x -= 60;
y -= 10;
w = 200;
h = 93;
s = 12;
img = GameUtils.skillImg1; // 不死鸟 -1
new Sound(GameUtils.skill_no1).start();
break;
}
}
break;
case 2:
if (Plane.plane_skill >= skillConsume) {
Plane.plane_skill -= skillConsume;
x -= 60;
y -= 20;
img = null;
new Sound(GameUtils.skill_no8).start();
}
break;
case 3:
x -= 15;
img = GameUtils.skillImg3;
new Sound(GameUtils.skill_no9).start();
break;
}
GameUtils.skillList.add(new Skill(img, x, y, w, h, s, this));
GameUtils.gameObjList.add(GameUtils.skillList.get(GameUtils.skillList.size() - 1));
Skill.release = false;
}
// Keypoint 神兽
if (MAAppear) {
MAAppear = false;
Image img = null;
int w = 63;
int h = 63;
int s = 0;
switch (MAnimals.MAnimalsNumber) {
case 1:
s = 5;
img = GameUtils.commodityImg1;
break;
case 2:
s = 8;
img = GameUtils.commodityImg2;
break;
case 3:
s = 15;
img = GameUtils.commodityImg3;
break;
}
assert planeObj != null;
mAnimalsObj = new MAnimals(img, planeObj.getX(), planeObj.getY(), w, h, s, this);
GameUtils.gameObjList.add(mAnimalsObj);
MAExist = true;
}
// Keypoint 飞机回血/回蓝
if (count % lifeRecovery == 0 && Plane.plane_life < Plane.record_plane_life)
Plane.plane_life++;
if (count % skillRecovery == 0 && Plane.plane_skill < Plane.record_plane_skill)
Plane.plane_skill++;
}
}
商店类
public class Popup_Shop extends JFrame {
boolean buy = false;
int price1 = 500, price2 = 799, price3 = 888, price4 = 800, price5 = 800;
public Popup_Shop() {
new Sound(GameUtils.basic_no11).start();
init();
}
public void init() {
// 说明
JLabel jLabel = new JLabel("选择购买商品:");
jLabel.setFont(new Font("acetone-family", Font.BOLD, 15));
jLabel.setBounds(10, 10, 200, 20);
JLabel jLabel2 = new JLabel("-------------------- 当前金币数:" + Plane.goldNumber + " --------------------");
jLabel2.setFont(new Font("acetone-family", Font.BOLD, 15));
jLabel2.setBounds(130, 150, 800, 20);
// 标签文字
JRadioButton option1 = new JRadioButton("吞天紫金貂(" + price1 + "$)");
JRadioButton option2 = new JRadioButton("九幽冥凤(" + price2 + "$)");
JRadioButton option3 = new JRadioButton("太虚古龙(" + price3 + "$)");
JRadioButton option4 = new JRadioButton("血量+1(" + price4 + "$)");
JRadioButton option5 = new JRadioButton("技能+1(" + price5 + "$)");
option1.setBounds(5, 40, 132, 20);
option2.setBounds(140, 40, 120, 20);
option3.setBounds(265, 40, 120, 20);
option4.setBounds(385, 40, 120, 20);
option5.setBounds(505, 40, 120, 20);
// 单选
ButtonGroup group = new ButtonGroup();
group.add(option1);
group.add(option2);
group.add(option3);
group.add(option4);
group.add(option5);
// 标签图片
JLabel commodity1 = new JLabel(new ImageIcon(GameUtils.commodityImg1));
JLabel commodity2 = new JLabel(new ImageIcon(GameUtils.commodityImg2));
JLabel commodity3 = new JLabel(new ImageIcon(GameUtils.commodityImg3));
JLabel commodity4 = new JLabel(new ImageIcon(GameUtils.commodityImg4));
JLabel commodity5 = new JLabel(new ImageIcon(GameUtils.commodityImg5));
commodity1.setBounds(45, 80, 63, 63);
commodity2.setBounds(165, 80, 63, 63);
commodity3.setBounds(285, 80, 63, 63);
commodity4.setBounds(405, 80, 63, 63);
commodity5.setBounds(525, 80, 63, 63);
// 购买按钮
JPanel jPanel = new JPanel();
JButton button = new JButton("购买");
button.setFont(new Font("acetone-family", Font.BOLD, 20));
jPanel.setLayout(null);
button.setBounds(255, 180, 90, 50);
jPanel.add(button);
jPanel.setVisible(true);
// 将组件添加进面板
this.add(jLabel);
this.add(jLabel2);
this.add(option1);
this.add(option2);
this.add(option3);
this.add(option4);
this.add(option5);
this.add(commodity1);
this.add(commodity2);
this.add(commodity3);
this.add(commodity4);
this.add(commodity5);
this.add(jPanel);
// 面板设置
this.setTitle("超级神秘商店");
this.setVisible(true);
this.setResizable(false);
this.setSize(630, 280);
this.setLocationRelativeTo(null);
this.repaint();
// 监听
button.addActionListener(e -> {
if (option1.isSelected() && Plane.goldNumber >= price1) {
buy = true;
if (!GamePanel.MAExist) {
Plane.goldNumber -= price1;
MAnimals.MAnimalsNumber = 1;
GamePanel.MAAppear = true;
System.out.println("购买:吞天紫金貂(" + price1 + "$)");
}
} else if (option2.isSelected() && Plane.goldNumber >= price2) {
buy = true;
if (!GamePanel.MAExist) {
Plane.goldNumber -= price2;
MAnimals.MAnimalsNumber = 2;
GamePanel.MAAppear = true;
System.out.println("购买:九幽冥凤(" + price2 + "$)");
}
} else if (option3.isSelected() && Plane.goldNumber >= price3) {
buy = true;
if (!GamePanel.MAExist) {
Plane.goldNumber -= price3;
MAnimals.MAnimalsNumber = 3;
GamePanel.MAAppear = true;
System.out.println("购买:太虚古龙(" + price3 + "$)");
}
} else if (option4.isSelected() && Plane.goldNumber >= price4) {
buy = true;
Plane.goldNumber -= price4;
Plane.record_plane_life += 5;
Plane.plane_life += 100;
System.out.println("购买:(" + price4 + "$)");
} else if (option5.isSelected() && Plane.goldNumber >= price5) {
buy = true;
Plane.goldNumber -= price5;
Plane.record_plane_skill += 5;
Plane.plane_skill += 100;
System.out.println("购买:技能+1(" + price5 + "$)");
}
new Sound(GameUtils.basic_no10).start();
// 提示弹窗
boolean select = (option1.isSelected() || option2.isSelected() || option3.isSelected() || option4.isSelected() || option5.isSelected());
if (!select) {
JOptionPane.showMessageDialog(null, "请选择所需商品!", "超级神秘商店温馨提醒", JOptionPane.WARNING_MESSAGE);
} else if (!buy) {
JOptionPane.showMessageDialog(null, "兄弟,金币不足啊!", "超级神秘商店温馨提醒", JOptionPane.ERROR_MESSAGE);
} else if ((option1.isSelected() || option2.isSelected() || option3.isSelected()) && GamePanel.MAExist) {
JOptionPane.showMessageDialog(null, "已存在一只神兽,不可贪多哦~", "超级神秘商店温馨提醒", JOptionPane.ERROR_MESSAGE);
} else {
JOptionPane.showMessageDialog(null, "购买成功!!" + "剩余金币:" + Plane.goldNumber, "超级神秘商店温馨提醒", JOptionPane.INFORMATION_MESSAGE);
this.dispose();
}
});
}
}
总结
通过此次的《飞机大战-III》游戏实现,让我对swing的相关知识有了进一步的了解,对java这门语言也有了比以前更深刻的认识。
java的一些基本语法,比如数据类型、运算符、程序流程控制和数组等,理解更加透彻。java最核心的核心就是面向对象思想,对于这一个概念,终于悟到了一些。
源码获取
点赞,关注博主后,私聊博主免费获取
今天是持续写作的第 12 / 100 天。
可以关注我,点赞我、评论我、收藏我啦。
转载:https://blog.csdn.net/qq_40869977/article/details/123055593