java实战之飞机大战小游戏(源码加注释)
作者:Henrik-Yao 发布时间:2021-08-01 17:46:08
标签:Java,飞机大战,小游戏,源码
一.工程文件
二.Main.java
主函数,实现类
package ui;
//主函数实现
public class Main {
public static void main(String[] args) {
//创建窗体
GameFrame frame = new GameFrame();
//创建面板
GamePanel panel = new GamePanel(frame);
//调用开始游戏的方法启动游戏
panel.action();
//将面板加入到窗体中
frame.add(panel);
//设置窗体可见
frame.setVisible(true);
}
}
三.GameFrame.java
窗体类,绘制窗体
package ui;
import javax.swing.*;
//创建窗体
public class GameFrame extends JFrame {
//构造方法,初始化窗体属性
public GameFrame(){
//设置标题,来源于JFrame
setTitle("飞机大战");
//设置大小
setSize(512,768);
//设置居中
setLocationRelativeTo(null);
//设置窗体可见
//setVisible(true);
//不允许玩家修改界面大小
//setResizable(false);
//设置默认的关闭选项
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
}
四.GamePanel.java
画布类,用于勾勒元素
package ui;
import javax.swing.*;
import java.awt.*;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.image.BufferedImage;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
//自定义游戏面板
public class GamePanel extends JPanel {
//定义背景图
BufferedImage bg;
BufferedImage heroImg;
BufferedImage epImg;
Hero hero = new Hero();
//敌机集合
List<Ep> eps = new ArrayList<Ep>();
// * 库
List<Fire> fs = new ArrayList<Fire>();
//定义分数
int score;
//设置游戏开关
Boolean gameover=false;
//设置火力
int power = 1;
//Ep ep = new Ep();
public void action(){
//创建线程
new Thread(){
public void run(){
while (true){
if(!gameover){
epEnter();
//调用敌机移动方法
epMove();
//发射 *
shoot();
// * 移动
fireMove();
//判断 * 是否击中敌机
shootEp();
//检测敌机是否撞到主机
hit();
}
//每执行一次,线程休眠一会儿
try {
Thread.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
//重绘界面
repaint();
}
}
}.start();
}
//每执行n次,释放一个敌机
int index = 0;
protected void epEnter(){
index++;
//创建敌机
if(index>=20){
Ep e = new Ep();
//加入集合
eps.add(e);
index = 0;
}
}
int findex = 0;
protected void shoot(){
findex++;
if(findex>=20){
if(power==1){
//创建 *
Fire fire1 = new Fire(hero.x+45,hero.y,1);
//将 * 存入 * 库中
fs.add(fire1);
}
else if(power==2){
//创建 *
Fire fire1 = new Fire(hero.x+15,hero.y,0);
//将 * 存入 * 库中
fs.add(fire1);
//创建 *
Fire fire2 = new Fire(hero.x+75,hero.y,2);
//将 * 存入 * 库中
fs.add(fire2);
}
else{
//创建 *
Fire fire1 = new Fire(hero.x+15,hero.y,0);
//将 * 存入 * 库中
fs.add(fire1);
//创建 *
Fire fire2 = new Fire(hero.x+75,hero.y,2);
//将 * 存入 * 库中
fs.add(fire2);
//创建 *
Fire fire3 = new Fire(hero.x+45,hero.y-10,1);
//将 * 存入 * 库中
fs.add(fire3);
}
//使计数器归0
findex = 0;
}
}
//让敌机移动
protected void epMove(){
for (int i = 0; i < eps.size(); i++) {
Ep e = eps.get(i);
e.move();
}
}
//让 * 移动
protected void fireMove(){
for (int i = 0; i < fs.size(); i++) {
Fire f = fs.get(i);
f.move();
}
}
//判断 * 是否击中敌机
protected void shootEp(){
//遍历所有 *
for (int i = 0; i < fs.size(); i++) {
//获取每一颗 *
Fire f = fs.get(i);
//判断一颗 * 是否击中敌机
bang(f);
}
}
//判断一颗 * 是否击中敌机
protected void bang(Fire f){
for (int i = 0; i < eps.size(); i++) {
//取出每一张敌机
Ep e = eps.get(i);
//判断这个 * 是否击中敌机
if(e.shootBy(f)&&e.type!=15){
//判断敌机是否击中道具机
if(e.type==12){
//火力增加
power++;
//如果火力值大于三,增加血量
if(power>3){
//恢复血量
if(hero.hp<3){
hero.hp++;
}
power = 3;
}
}
//如果敌机被 * 击中
//敌机消失
eps.remove(e);
//删除 *
fs.remove(f);
//增加分数
score += 10;
}
}
}
//检测敌机是否撞到主机
protected void hit() {
for (int i = 0; i < eps.size(); i++) {
//获取每一个敌机
Ep e = eps.get(i);
if(e.shootBy(hero)){
//删除敌机
eps.remove(e);
//主机血量减少
hero.hp--;
//火力恢复初始值
power = 1;
//分数增加
score += 10;
//当主机血量减少到0时游戏结束
if(hero.hp==0){
gameover = true;
}
}
}
}
//构造函数
public GamePanel(GameFrame frame){
//设置背景
bg = App.getImg("/img/bg2.jpg");
//创建鼠标监听
//创建鼠标适配器
MouseAdapter adapter = new MouseAdapter() {
//点击鼠标时会执行的代码
@Override
public void mouseClicked(MouseEvent e) {
//游戏结束时候,点击屏幕时重新开始游戏
if(gameover){
//重新初始化主机
hero = new Hero();
//重置游戏开关
gameover = false;
//分数清0
score = 0;
//清空敌机集合
eps.clear();
//随机背景图
Random random = new Random();
int index = random.nextInt(5)+1;
bg = App.getImg("/img/bg"+index+".jpg");
//重新绘制
repaint();
}
}
//确定需要监听的事件
@Override
public void mouseMoved(MouseEvent e) {
//让主机的横纵坐标等于鼠标的移动坐标
//获取鼠标的横纵坐标
int mx = e.getX();
int my = e.getY();
//传递坐标
if(!gameover){
hero.moveToMouse(mx-114/2,my-93/2);
}
repaint();
}
};
//将适配器加入到 * 中
addMouseListener(adapter);
addMouseMotionListener(adapter);
//使用键盘监听
//创建键盘适配器
KeyListener kd = new KeyListener() {
@Override
public void keyTyped(KeyEvent e) {
}
//当键盘被按下是触发
@Override
public void keyPressed(KeyEvent e) {
int keyCode = e.getKeyCode();
//上键
if(keyCode == KeyEvent.VK_UP){
hero.y-=10;
}
//下键
else if(keyCode == KeyEvent.VK_DOWN){
hero.y+=10;
}
//左键
else if(keyCode == KeyEvent.VK_LEFT){
hero.x-=10;
}
//右键
else if(keyCode == KeyEvent.VK_RIGHT){
hero.x+=10;
}
repaint();
}
@Override
public void keyReleased(KeyEvent e) {
}
};
//将适配器加入窗体的 * 中
frame.addKeyListener(kd);
}
//画图方法
@Override
public void paint(Graphics g) {
super.paint(g);
//画背景
g.drawImage(bg,0,0,null);
//画敌机
for (int i = 0; i < eps.size(); i++) {
Ep ep = eps.get(i);
g.drawImage(ep.img,ep.x,ep.y,null);
}
//画 *
for (int i = 0; i < fs.size(); i++) {
Fire fire = fs.get(i);
g.drawImage(fire.img,fire.x,fire.y,fire.w,fire.h,null);
}
//画分数
g.setColor(Color.white);
g.setFont(new Font("\u6977\u4F53",Font.BOLD,30));
g.drawString("分数:"+score,10,30);
g.drawImage(hero.img,hero.x,hero.y,null);
//画主机血量
for (int i = 0; i < hero.hp; i++) {
g.drawImage(hero.img,380+i*35,5,30,30,null);
}
//画游戏结束
if(gameover){
g.setColor(Color.red);
g.setFont(new Font("楷体",Font.BOLD,35));
g.drawString("GAMEOVER",170,300);
g.setColor(Color.green);
g.setFont(new Font("楷体",Font.BOLD,29));
g.drawString("yh提醒你点击屏幕任意位置重新开始",10,350);
}
repaint();
}
}
五.FlyObject.java
飞行物类,设定飞行物特性
package ui;
import java.awt.image.BufferedImage;
//具有共同特点,故抽离成父类
public class FlyObject {
BufferedImage img;
int x;
int y;
int w;
int h;
}
六.Hero.java
主机类,设定游戏时候操控的飞机属性
package ui;
import java.awt.image.BufferedImage;
//主机
public class Hero extends FlyObject{
//主机血量
int hp;
public Hero(){
img = App.getImg("/img/hero.png");
//确认初始位置
x = 200;
y = 500;
w = img.getWidth();
h = img.getHeight();
hp = 3;
}
public void moveToMouse(int mx,int my){
x = mx;
y = my;
}
}
七.Ep.java
敌机类
package ui;
import javax.swing.*;
import java.awt.image.BufferedImage;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
//敌机类
public class Ep extends FlyObject{
int sp;
//设置敌机类型
int type;
public Ep(){
Random random = new Random();
int index = random.nextInt(15)+1;
type = index;
String path = "/img/ep" + (index<10?"0":"")+index+".png";
img = App.getImg(path);
//确定敌机图片
w = img.getWidth();
x = random.nextInt(512-w);
y = 0;
//设置速度
sp = 17-index;
}
public void move() {
if(type==5){
x -= 5;
y += sp;
}
else if(type==6){
x += 5;
y += sp;
}
else {
y+=sp;
}
}
public boolean shootBy(Fire f) {
Boolean hit = x <= f.x+f.w &&x>f.x-w&&y<=f.y+f.h&&y>f.y-h;
return hit;
}
public boolean shootBy(Hero f) {
Boolean hit = x <= f.x+f.w &&x>f.x-w&&y<=f.y+f.h&&y>f.y-h;
return hit;
}
}
八.Fire.java
* 类
package ui;
public class Fire extends FlyObject{
// * 当前移动方向,0为左上角飞,1垂直飞,2右上角飞
int dir;
//构造方法,初始化 *
public Fire(int hx,int hy,int dir){
//确定 * 的图片
img = App.getImg("/img/fire.png");
//确定图片的大小
w = img.getWidth()/4;
h = img.getHeight()/4;
//确定 * 的位置
x = hx;
y = hy;
this.dir=dir;
}
public void move() {
//左上角飞
if(dir==0){
x -= 1;
y -= 10;
}
//垂直上飞
else if(dir == 1){
y -= 10;
}
//右上角飞
else if(dir == 2){
x += 1;
y -= 10;
}
}
}
九.App.java
方法类
package ui;
import javax.imageio.ImageIO;
import javax.swing.*;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.io.InputStream;
//处理图片的工具类
public class App {
//static可以公用所有对象都共用该方法,并且可以不依赖对象实现
public static BufferedImage getImg(String path){
//io流,输送数据的管道
try {
BufferedImage img = ImageIO.read(App.class.getResource(path));
return img;
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
public static ImageIcon getImg2(String path){
InputStream is;
is = App.class.getClassLoader().getResourceAsStream(path);
try {
return new ImageIcon(ImageIO.read(is));
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
}
十.效果演示
来源:https://blog.csdn.net/qq_50216270/article/details/116091267


猜你喜欢
- 1.导入 EasyExcel Maven包<!--easyexcel 导出excel依赖--><dependency>
- 1.多数元素题目描述思路详解这个思路比较简单,先排序,排序过后遍历如果后一个等于前一个输出就好代码与结果class Solution { &
- 开发Android应用中,随着功能越来越多,启动速度越来越慢。有没有办法让自己应用启动速度快一点呢?方法是人想出来的。先说说我的实现方法:1
- 自定义starterSpringBoot中的starter是一种非常重要的机制,能够抛弃以前繁杂的配置,将其统一集成进 starter,应用
- 众所周知在android7.0,修改了对私有存储的限制,导致在获取资源的时候,不能通过Uri.fromFile来获取uri了我们需要适配7.
- 话不多说,请看下面//C# 代码int year = DateTime.Now.Year;int month = DateTime.Now.
- 环境:VS2019+Qt5.121. CLR库安装 &nb
- 实现代码:// 例如:(new Money(200)).ToString() == "贰佰元"namespace Sky
- 用C#写的一个DVD管理器,供大家参考,具体内容如下(大神勿喷,初学者以借鉴为主)一共分为三个类分别是:DVD(启动类),XinXi(信息类
- 这篇文章主要介绍了Spring StopWatch使用实例详解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,
- 只需要在控件TextBox的keypress事件中写入如下代码即可满足要求:代码如下:if (e.KeyChar == '.'
- 今天学习了Map集合的几种方法,尤其是遍历Map集合感觉尤为重要,所以发出来供大家学习和自己复习以用。众所周知Map集合里存储元素是以键值对
- 本文实现的功能有:1、 初始化游戏窗口2、初始化游戏的界面3、初始化游戏的说明面板4、随机生成下落方块5、方块下落速度变化6、判断方块是否可
- 序本文主要研究一下java9 gc log参数的迁移。统一JVM及GC的Loggingjava9引进了一个统一的日志框架,把gc相关的log
- 我们在k8s集群成功搭建了Prometheus服务。今天,我们将在springboot2.x中使用prometheus记录指标。一、我们需要
- 目录首先必须要有一个个人微信公众号效果图后台路由代码完整代码首先必须要有一个个人微信公众号个人微信公众号相关的接口权限有限,不过用于个人学习
- 任务描述:在一个无向图中,获取起始节点到所有其他节点的最短路径描述Dijkstra(迪杰斯特拉)算法是典型的最短路径路由算法,用于计算一个节
- 写一个简单的mybatis plus插件自动生成代码的例子pom.xml 添加配置<!-- mybatis plus 插件-->
- Activity回顾activity是android程序中最重要的组件之一,它是用户与android用户交互的主要组件,类似于桌面程序的图形
- GlobalLock的作用对于某条数据进行更新操作,如果全局事务正在进行,当某个本地事务需要更新该数据时,需要使用@GlobalLock确保