基于Java的飞机雷电射击游戏的设计实现(Eclipse开发)

news2024/11/26 8:24:26

目 录
摘 要 I
Abstract II
1 引言 3
1.1 项目背景 3
1.2 电脑游戏的发展历史 3
1.3国内游戏项目研究现状 5
1.4项目主要工作 6
1.5本文组织结构 7
1.6 电脑游戏的策划 7
2 开发平台与开发技术 8
2.1 Eclipse 8
2.2 Eclipse平台 8
2.3 Java 9
2.4游戏图形界面的开发基础 11
2.5Java游戏中的基本框架 14
3 雷电游戏模块设计 16
3.1 用户需求分析 16
3.2 可行性分析 16
3.3 总体设计原则 17
3.4 功能模块设计 18
3.4.1 游戏状态控制功能 18
3.4.2 游戏难度的调整 18
3.4.3 游戏界面绘画功能 18
3.4.4 玩家游戏控制功能 19
3.5 关键技术 19
4 雷电功能实现 20
4.1 游戏程序设计的思路 20
4.1.1 游戏的素材选择 20
4.1.2 游戏中子弹、飞机的实现 20
4.1.3 多线程应用的途径 20
4.2 游戏首页的实现 22
4.2.1 界面实现 22
4.2.2 流程图 22
4.2.3 核心代码 23
4.3 游戏开始模块的实现 24
4.3.1 界面实现 24
4.3.2 流程图 25
4.3.3 核心代码 26
4.4 发射子弹模块的实现 27
4.4.1 界面实现 27
4.4.2 流程图 28
4.4.3 核心代码 28
5 系统测试 31
5.1 测试的定义及其重要性 31
5.1.1 测试的定义 31
5.1.2 测试的重要性 31
5.2 测试实例的研究与选择 32
5.3 测试结果 35
总结和展望 37
参考文献 38
致 谢 39
1.4 项目主要工作
本次项目开发是基于JAVA的雷电游戏。
此雷电游戏通俗来说就是我方飞机和敌方之间的对决,先要做的应该是通过一个界面来达到装载整个游戏,然后就是我方飞机的移动方式(也就是通过键盘来移动),接着就是生成我方飞机的子弹(依据子弹类型的不同有不同的实现形式),准备就绪后会有敌方飞机的出现,每一个飞机会对应发射不同种类的子弹,最后是我方飞机通过键盘进行移动、射击,显示出游戏结果,然后结束游戏。
该雷电应该满足以下一些要求:
(1)游戏状态控制功能
在进行游戏的设计时,我们应该考虑到,如何进行游戏状态的划分。简单来说,我们需要设置开始,并且要考虑到游戏中断,以及中断后回到游戏中。玩家点击开始之后,程序会调用启动页面的代码,然后进入游戏,在游戏的过程中,玩家如果由于其它工作需要离开时,可以将其中断,比如单击空格键,当需要恢复游戏现场时,再单击空格键,就可以继续游戏,当自己控制的飞机被击毁时,会有游戏结束的显现。
(2)游戏难度的调整
随着游戏的进行、关卡的提高,敌机的速度会越来越快、敌方飞机的数目会越来越多、子弹数量也会越快且越多。此时,带给游戏玩家的视觉冲击变得更强,需要玩家更加冷静地去躲闪以及攻击敌机。
(3)游戏界面绘画功能
游戏主屏主要用来输出用户对我方的控制与敌方的动作显示。在游戏屏幕的左下角有全屏爆破次数的显示,这相当于游戏玩家的特殊技能,可以瞬间清除当前屏幕上的所有敌机以及子弹,在游戏屏幕的右下角会呈现玩家飞机血条,代表着当前我方飞机的状态。当血条格为空时,表示我方飞机已经被击毁,整个雷电游戏也将结束。
(4)玩家游戏控制功能
对于我方飞机的移动和子弹的发射,游戏用户可以通过控制键盘来控制。飞机的左右移动通过键盘的上、下、左、右键来实现,而我方飞机子弹的释放方式有两种,z键会释放出点状子弹,而x键会释放出线状子弹,可供游戏玩家依据需要自行选择。
3.4 功能模块设计
3.4.1 游戏状态控制功能
雷电的阶段包括开始、暂停、恢复和结束,最先需要等待游戏的加载启动,假若游戏过程中,玩家如果因为特殊事情需要离开可以选择暂停比赛,等到再次回来可以进行比赛的恢复。
3.4.2 游戏难度的调整
随着游戏的进行,游戏的难度会相应的增加,比如敌机的数量会越来越多、敌机子弹的数量也会有所增加,这些都是对玩家造成伤害的因素,这些伤害因素越多,游戏的难度相应就越大,最终每一关卡都有一个怪兽守关,它的血条、子弹都造成了游戏难度的增加。
3.4.3 游戏界面绘画功能
游戏主屏用来输出用户对己方的控制与敌方的动作显示。在屏幕的右下角会有己方飞机的生命值的显示,在游戏的左下角会有全屏爆破的剩余次数显示,通过这些显示,可以增加玩家的游戏体验性,达到一个更加人性化的界面,为用户提供更好的界面舒适度。
3.4.4 玩家游戏控制功能
用户玩家可以通过键盘的上、下、左、右键控制飞机的移动,通过移动来躲避敌方飞机带来的伤害,通过z、x键控制子弹的发射,通过发射子弹来对敌机造成伤害。
3.5 关键技术
(1)游戏美工。游戏中需要使用的游戏素材有自己控制的飞机、敌方飞机、游戏过程当中飞机所产生的子弹、飞机被命中的爆炸图片等。这些素材的选择尤为重要,游戏中清新亮丽的画面可以给玩家带来充足的美感和游戏体验。所以,在这个“雷电”游戏的素材选择中,应挑选一些立体感强的图片,给玩家更大的视觉冲击。
(2)多线程技术的实现。多线程编程能够提供程序两个或两个以上并发执行任务的能力,极大改善程序的响应性能,有效提高资源的利用效率。采取Runnable接口的方法达到定义用户线程的功能,这样既不会对继承其他类有所变化,也不会改变实现其它接口。
(3)用户飞机子弹与敌方飞机的相撞测试。包括自己控制的飞机与敌方飞机或子弹的相撞等。在这一过程中,本文转载自http://www.biyezuopin.vip/onews.asp?id=11237将所有子弹对象的矩形区域与敌机对象的矩形区域逐个以此进行检测,如果出现重叠则说明子弹与敌机发生了碰撞。
(4)游戏地图滚动原理的实现。我们在坐火车时都产生过一种错觉:自己乘坐的火车没有发生移动,但如果旁边有其他火车发生移动,我们就会感到是自己的火车在移动。这种现象与飞机射击类游戏的地图原理类似,即通过背景图片的来回滚动,给游戏玩家一种是自己操纵的飞机向前飞行的感觉。

package com.ideabobo.game.leidian;

import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Image;

import com.ideabobo.game.leidian.Boss;

public class Battle extends Role {
	private static Battle battle = new Battle();

	private int tamaIntCount;

	private float speed;

	private float oldx;

	private float oldy;

	public static float vx;

	public static float vy;
	
	public static boolean keygo = false;

	private float tv[] = { -1F, -7F, 0.0F, -8F, 1.0F, -7F };

	public int power;

	public int powerMax;
	


	public Battle() {
		super(GamePanel.heroImage);
		speed = 3F;
		tamaIntCount = 0;
		x = ((float) app.getWidth() - WIDTH) / 2.0F;
		y = (float) app.getHeight() - HEIGHT * 2.0F;
		power = 600;
		powerMax = power;
	}

	public static Battle getInstance() {
		return battle;
	}

	public void move() {
		oldx = x;
		oldy = y;
		if (Key.left) {
			if (Key.xkey)
				x -= (double) speed / 4D;
			else
				x -= speed;
			if (x <= 0.0F)
				x = 0.0F;
		}
		if (Key.right) {
			if (Key.xkey)
				x += (double) speed / 4D;
			else
				x += speed;
			if (x + WIDTH >= (float) app.getWidth())
				x = (float) app.getWidth() - WIDTH;
		}
		if (Key.down) {
			if (Key.xkey)
				y += (double) speed / 4D;
			else
				y += speed;
			if (y + HEIGHT >= (float) app.getHeight())
				y = (float) app.getHeight() - HEIGHT;
		}
		if (Key.up) {
			if (Key.xkey)
				y -= (double) speed / 4D;
			else
				y -= speed;
			if (y <= 0.0F)
				y = 0.0F;
		}
		//**//--///loonframewrk提供
		vx = x - oldx;
		vy = y - oldy;
		if (tamaIntCount > 0)
			tamaIntCount--;
		if (Key.zkey && tamaIntCount <= 0) {
			for (int i = 0; i < tv.length; i += 2) {
				GamePanel.addList(new BattleBasic(x + WIDTH / 2.0F, y, tv[i],
						tv[i + 1]));
				tamaIntCount = 8;
			}
		}
		if (Key.xkey && !Key.zkey && tamaIntCount <= 0) {
			GamePanel.addList(new BattleBeam(x + WIDTH / 2.0F, y, 0.0F, -8F));
			tamaIntCount = 2;
		}
		if(Key.space){
			if(!keygo){
				GamePanel.skillCount--;
			}
			app.skillAnime();
			
			if(GamePanel.skillCount < 0){
				GamePanel.skillCount = 0;
			}
			if(GamePanel.skillCount>0){
				for (int i = 0; i < GamePanel.list.size(); i++) {
					Role chara1 = (Role) GamePanel.list.get(i);
					if(!(chara1 instanceof Battle) && chara1.x>0 && chara1.y>0 && !(chara1 instanceof BossA)  && !(chara1 instanceof BossB)  && !(chara1 instanceof BossC)){
						GamePanel.list.remove(i);
					}else if((chara1 instanceof BossA)  || (chara1 instanceof BossB)  || (chara1 instanceof BossC)){
						Boss cb = (Boss)chara1;
						cb.power-=50;
					}
				}
			}
			keygo = true;
		}
		
		if(!Key.space){
			keygo = false;
		}
	}

	public boolean checkHit(Role chara) {
		if ((chara instanceof EnemyA) || (chara instanceof EnemyB)|| (chara instanceof EnemyC) || (chara instanceof EnemyShot)) {
			
			if ((x + WIDTH) - 14F > chara.x && x + 14F < chara.x + chara.WIDTH
					&& (y + HEIGHT) - 12F > chara.y
					&& y + 12F < chara.y + chara.HEIGHT) {
				//如果碰到敌人,敌人死亡
				chara.dead();
				//如果碰到子弹血量减少
				if (chara instanceof EnemyBeam){
					power--;
				}
					
				power -= 50;
				if (power <= 0) {
					dead();
					//绘制爆炸图片
					GamePanel.burst = new Burst(x, y);
				}
				return true;
			}
		} else if ((chara instanceof Boss) && (x + WIDTH) - 14F > chara.x + 50F
				&& x + 14F < (chara.x + chara.WIDTH) - 50F
				&& (y + HEIGHT) - 12F > chara.y + 50F
				&& y + 12F < (chara.y + chara.HEIGHT) - 80F) {
			power--;
			if (power <= 0) {
				dead();
				GamePanel.burst = new Burst(x, y);
			}
			return true;
		}
		return false;
	}

	public void setX(float x) {
		this.x = x;
	}

	public void setY(float y) {
		this.y = y;
	}

	public float getWidth() {
		return WIDTH;
	}

	public float getHeight() {
		return HEIGHT;
	}

	public float getX() {
		return x;
	}

	public float getY() {
		return y;
	}

	public Image getImage() {
		return img;
	}

	public int getPower() {
		return power;
	}

	public int getPowerMax() {
		return powerMax;
	}

	public void setPower(int power) {
		this.power = power;
	}

	public void drawPower(Graphics g) {
		g.setColor(Color.white);
		g.drawRect(380, 450, 50, 15);
		g.setColor(Color.red);
		g.fillRect(381, 451,
				(int) ((50D / (double) (float) powerMax) * (double) power) - 1,
				14);
	}
	
	public void drawSkillCount(Graphics g){
		g.setColor(Color.white);
		Font font = new Font("宋体", 1, 20);
		g.setFont(font);
		g.drawString("全屏爆破:" + GamePanel.skillCount, 0, 450);
	}

}

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/4323.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

redis启动和简单使用

redis启动和简单使用 1.redis启动 1.1 找到redis解压的位置,在里面输入cmd回车 1.2 输入redis-server redis.conf指令,然后回车,出现如下界面 注意&#xff1a;该界面不能关闭了 1.3 再进入一次redis解压的位置 输入cmd回车 1.4 输入redis-cli指令后的结果 1.5 补充 当出现…

Flink系列文档-(YY05)-Flink编程API-多流算子

1 多流连接 connect connect连接&#xff08;DataStream,DataStream→ConnectedStreams) connect翻译成中文意为连接&#xff0c;可以将两个数据类型一样也可以类型不一样DataStream连接成一个新的ConnectedStreams。需要注意的是&#xff0c;connect方法与union方法不同&…

Hadoop高手之路3-Hadoop集群搭建

文章目录Hadoop高手之路3-Hadoop集群搭建一、集群的规划二、再准备两台虚拟机作为服务器1. 根据hadoop001克隆出hadoop002和hadoop0032. 配置hadoop002和hadoop0031) 启动hadoop002虚拟机并登录2) 配置ip地址3) 重启网络服务器&#xff0c;查看ip4) 远程连接hadoop0025) 修改主…

数据库自增ID用完了会怎么样?

有主键 如果设置了主键&#xff0c;并且一般会把主键设置成自增。 Mysql里int类型是4个字节&#xff0c;如果有符号位的话就是[-231,231-1]&#xff0c;无符号位的话最大值就是2^32-1&#xff0c;也就是4294967295。 创建一张表&#xff1a; CREATE TABLE test1 (id int(11…

人脸识别技术趋势与发展

人脸辨识 —— 引人入胜 很少有生物辨识技术能像脸部辨识那样激发我们的想象力。 同样&#xff0c;它的到来在 2020 年引发了深刻的担忧和令人惊讶的反应。 脸部辨识的工作原理 脸部辨识是使用脸部辨识或验证人的身份的过程。它根据人的脸部细节捕获、分析和比较模式。 人…

Restful风格的编程

Restful风格的编程1、 Restful简介2、查询用户以及用户详情2.1常用注解2.2查询用户详情3、处理创建请求3.1RequestBody注解3.1.1用途3.1.2语法规范3.2日期类型的处理3.3BindingResult4、用户信息修改与删除4.1用户信息修改4.2案例前端界面后端控制器1、 Restful简介 Restful比…

剑指offer(C++)-JZ69:跳台阶(算法-动态规划)

作者&#xff1a;翟天保Steven 版权声明&#xff1a;著作权归作者所有&#xff0c;商业转载请联系作者获得授权&#xff0c;非商业转载请注明出处 题目描述&#xff1a; 一只青蛙一次可以跳上1级台阶&#xff0c;也可以跳上2级。求该青蛙跳上一个 n 级的台阶总共有多少种跳法&…

【JavaSE】类与对象(上)类是什么?对象是什么?

文章目录面向过程与面向对象认识类和对象创建类类的实例化内存分布注意事项总结面向过程与面向对象 我们说C语言是面向过程的编程语言&#xff0c;而Java是面向对象的编程语言&#xff0c;那究竟什么才是面向过程与面向对象呢&#xff1f;我们举一个例子来帮助大家理解&#x…

PX4飞行测试

文章目录前言一、首次飞行指南飞行入门解锁飞机起飞降落飞行控制/命令辅助飞行任务飞行规划任务设置机体航向设置航点/转弯半径地理围栏故障保护地理围栏地理围栏规划安全点(集结点)创建/定义安全点地形跟随/保持地形跟随地形保持前言 本节包含有关飞行&#xff08;完全配置过…

虚拟主播也带货?直播电商的变与不变

5月6日晚&#xff0c;海外虚拟主播vox在B站开启了中国直播首秀。从最终数据来看&#xff0c;直播1.7小时&#xff0c;营收111万人民币&#xff0c;当晚还登上平台热门首位&#xff0c;这样的直播吸金能力&#xff0c;让不少明星都望尘莫及。 更值得关注的是&#xff0c;直播间…

Matlab:表达式

Matlab&#xff1a;表达式变量数字矩阵运算符数组运算符函数表达式示例变量 与大多数其他编程语言一样&#xff0c;MATLAB 语言提供数学表达式&#xff0c;但与大多数编程语言不同的是&#xff0c;这些表达式涉及整个矩阵。 MATLAB 不需要任何类型声明或维度说明。当 MATLAB …

PyCharm 这40个使用技巧真棒

大家好&#xff0c;今天分享 PyCharm 40个使用技巧&#xff0c;内容有点长&#xff0c;喜欢欢迎收藏、分享、点赞。 废话不多说。我们开始吧&#xff01; 文章目录技术提升第一章&#xff1a;运行调试篇1\. 通过指定参数&#xff0c;执行程序2\. 程序结束了&#xff0c;照样可…

Vue 3 属性绑定细节

在ButtonDemo中默认会把传给这个组件上的所有事件,都传递给Button中的最外层的元素 不管这个最外层的元素是什么!比如下图:在button外面还有一个div,那么传递给最外层的就应该是div,而不是button 最外层为div 想让组件的某一个部分,点击时被触发click事件 现在传递给最…

LeetCode-764. 最大加号标志【动态规划,二维数组】

LeetCode-764. 最大加号标志【动态规划&#xff0c;二维数组】题目描述&#xff1a;解题思路一&#xff1a;动态规划。用一个n*n的数组记录每个点上下左右方向上为1的最小值。最后ans返回数组中最大的加号。解题思路二&#xff1a;优化1。解题思路三&#xff1a;0题目描述&…

word制作多个单位联合发文的文件头

一、前言 word制作多个单位联合发文的文件头&#xff0c;好像不难。但是做起来&#xff0c;却发现&#xff0c;自己的只是储备还是不够&#xff0c;居然花费了1个多小时才搞定....哎 二、遇到问题 开始思路是想使用【分栏】来操作&#xff0c;但是不得其法&#xff0c;搞了一…

驱动开发基础知识

文章目录记录驱动开发前的知识储备工作一、驱动开发环境搭建二、驱动开发框架&#xff08;重点&#xff1a;WDF框架&#xff09;1、前世今生&#xff08;1&#xff09;Vista简介&#xff08;2&#xff09;发展历史2、基于框架的驱动程序的 WDM&#xff08;1&#xff09;驱动程序…

linux(1.nginx基础 2.使用Nginx负载均衡及动静分离)

一.nginx基础 目录 1. Nginx使用场景2. Nginx中的进程 2.1 Nginx中的多进程模型2.2 多进程模式的优点&#xff1a;2.3 缓存3. Ngnix的负载均衡策略 3.1 轮询法3.2 加权轮询3.3 原地址哈希3.4 最小连接数法3.5 Fair3.6 url_hash3. Nginx配置文件4. Nginxtomcat 集群示例 4.1 下…

c++学习-STL常用函数

第八部分-STL常用函数 5.1 常用遍历算法 5.1.1 for_each 5.1.2 transform 5.2 常用查找算法 5.2.1 find 5.2.2 find_if 5.2.3 adjacent_find 面试题中如果出现查找相邻重复元素&#xff0c;记得用stl中的adjacent_find算法 5.2.4 binary_search 5.2.5 count 5.2.6 count_if 5.…

【双十一特辑】爱心代码(程序员的浪漫)-李峋

前言 最近《点燃我温暖你》中李峋的爱心代码超级火&#xff0c;看着特别心动&#xff0c;这不&#xff0c;光棍节快到了&#xff0c;给兄弟们教学一波爱心代码&#xff0c;赶在双十一前表白&#xff0c;让这个双十一不在是孤单一个人&#xff01;目录 前言 C语言简易爱心代码…

final 关键字 —— 限制继承、限制虚函数重写

final 关键字有两个作用&#xff0c;一个是限制继承&#xff0c;一个是限制重写。 目录 1、限制继承 (1) 基类的构造函数设为私有 (2) 基类类名后面加上 final 关键字修饰 2、限制虚函数重写 1、限制继承 限制继承有两种方式&#xff0c;一种是将基类的构造函数设为私有&am…