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
0
投稿
猜你喜欢
- 一、ServletConfig讲解1.1、配置Servlet初始化参数在Servlet的配置文件web.xml中,可以使用一个或多个<
- 1:首先。创建一个springboot项目,这里我使用以及构建好基本框架的脚手架,打开是这个样子:Result类:已经封装好了三种返回类型的
- 前言今天的文章从下面这张图片开始,这张图片Java开发们应该很熟悉了我们都知道无锁状态是对象头是有位置存储hashcode的,而变为偏向锁状
- 一般文本文件我们以日志文件.log文件为例:import java.io.BufferedReader; import java.io.Fi
- Bitmap (android.graphics.Bitmap)Bitmap是Android系统中的图像处理的最重要类之一。用它可以获取图像
- 使用 DateFormat 格式化日期、时间DateFormat 也是一个抽象类,它也提供了如下几个类方法用于获取 DateFormat 对
- 绝大部分知识与实例来自O'REILLY的《Java网络编程》(Java Network Programming,Fourth Edi
- 项目背景我们开发过程中会碰到这样一类问题,就是数据层或三方接口返回的Bean对象需要转换重新装换一下我们需要的对象。我们通常的做法就是通过g
- 一、背景新做了一个的需求,需要在SpringBoot项目中引入了多个依赖,然后就感觉idea下载依赖包的时间很漫长,然后我就网上找了解决办法
- SpringBoot 2.1.4 错误处理机制springboot的自动配置中帮我们配置了相关的错误处理组件,例如访问一个不存在的页面,就会
- 一般来说,修改框架的源代码是极其有风险的,除非万不得已,否则不要去修改。但是今天却小心翼翼的重构了Mybatis官方提供的与Spring集成
- import java.awt.AlphaComposite;import java.awt.Color;import java.awt.F
- 简介Android给我们提供了一种轻量级的异步任务类AsyncTask。该类中实现异步操作,并提供接口反馈当前异步执行结果及进度,这些接口中
- 1、什么是反射?在java开发中有一个非常重要的概念就是java反射机制,也是java的重要特征之一。反射的概念是由Smith在1982年首
- 一、Java把这些不同来源和目标的数据都统一抽象为数据流。Java语言的输入输出功能是十分强大而灵活的。在Java类库中,IO部分的内容是很
- 前言先放一个官网吧,其实本案例就是根据官网案例来的,只是进行了修改配置。Mybatis-plus官网一、搭建一个springboot项目&n
- Java8已经发布很多年了,但是很多人在开发时仍然坚持使用着Date和SimpleDateFormat进行时间操作。SimpleDateFo
- 树的结构说得差不多了,现在我们来说说一种数据结构叫做哈希表(hash table),哈希表有是干什么用的呢?我们知道树的操作的时间复杂度通常
- .c 源程序 ----- 编译 ----- 链接 ---- exe ----运行 -------->程序翻译环境和执行环境翻译环境:源
- Comparable 比较器,内置定义的比较方法,实现比较 较简单Comparator 策略模式,需要定义不同的策略和比较的对象,实现比较