java项目 后日方舟小游戏
一、 需求分析
1.1项目简介
项目为了一款多人实时联机对战格斗游戏。
需求分析:1.当下随着年轻人的生活压力增大,部分玩家对游戏的需求重心开始从大型3a制作转向轻量化随开随停的小游戏。2. 同时,多数年轻人玩游戏主要是为了缓解自身的生活压力,或是为了满足与朋友联络的社交需求。为此本项目拟设计一款轻量便捷化的游戏,本游戏将采用开放房间的模式(同时在线游戏人数不受上限),任何可以人都可以随时加入游戏,进行车轮反复对战,随开随停,游戏时长弹性可变,可以满足休息娱乐的目的
大致玩法:
当服务器启动后会自动创建一个房间,房间中最多同时在线人数不受上线,玩家可随时加入房间或退出房间,玩家在房间中的存活时长将作为胜利与否的依据。本游戏将依据玩家加入阵营的顺序自动分为红,蓝两阵营,只有不同阵营的人才能够相互造成伤害。更多细节还将在下文介绍。
以下为用户进行操作的用例图
- 玩家加入游戏后可以通过主机ip连接到指定房间号
接着输入玩家的信息后和选择的英雄
输入邀请码正确后可成功进入房间进行大混战
- 玩家可以利用键盘wasd进行人物移动
按下j键进行攻击(根据选择人物的不同,人物的血量,攻击力,攻击模式,立绘,语音将有所差别)
1。2 功能结构概述
结构功能图如下
表1.1 后日方舟小游戏功能结构概述图
分别介绍每个功能模块要实现的功能(客户端和服务器端分别介绍)
客户端:
1.绘制人物选择界面,并利用正则表达式对用户输入的数据进行规范
2.客户端连接服务器:客户端将首先于服务器建立TCP/IP的通信,确认建立连接后客户端将会向服务区传送自己UDP通信端口,同时服务器也会告知客户端服务器自己的UDP端口,之后TCP/IP的通信连接将会断开。
3.收发服务器信息:TCP/IP的通信连接断开之后,客户端可以通过刚刚接收到的UDP端口向服务器的端口发送数据。同时客户端会有专门的线程接收服务器转发而来的数据。
4. 客户端将会根据目前已经接收到的数据绘制战斗场景,人物动图,根据角色操作播放不同的人物语音
5.用户可以通过键盘操作自己的角色,并进行走位和攻击
6.客户端根据用户操作播放相应的背景音乐和人物语音
7.客户端将会查询数据库中的相关邀请码,判定用户是否被邀请进入游戏
8. 客户端将根据用户是否确认邮件的选项,自动为填入邮箱的玩家发送相关的信息。
服务器端:
- 1. 将会首先利用TCP/IP协议利用socket套接字与每个客户端直接建立连接并交换端口号,服务器保存每个客户端的端口号
- 2. 服务器将会专门设立线程用于接收所有客户端的信息,并将该信息转发给所有的客户端,同时服务器会令设线程专门接收客户端的角色的死亡信息,如果死亡,将不会在为该客户端进行信息的转发
- 3. 服务器的GUI界面上将会显示客户端的连接信息,便于查询连接信息
- 4. 服务端界面上将绘制游戏主题相关的动图
- 5. 服务器端同时将每个玩家的作战信息写入数据库
- 6. 服务器同时对游戏的运行状况进行记录,并根据事先写好的配置文件写入到日志中
二、 系统的设计
2。1 相关技术应用
|
序号 |
技术 |
应用场景 |
说明 |
|
1. |
Java绘图双缓冲技术 |
绘制小人的动图的时候,发现小人的图片会发生闪烁 |
通过覆写update方法,将原有的清屏代码改写,从而解决屏闪问题,同时还可以通过双缓冲技术实现小人动图的绘制 |
|
2.。 |
使用Git和Github进行版本管理 |
版本功能完善的过程中为了做好备份,使用Git和Github用于管理项目 |
在多次开发的过程中,常常有多个功能需要改善,因为思路不完善和能力不够,常常出现一个功能没完善,而先去完成了另一个功能的情况,这种情况下,使用git进行分支版本管理会使代码更为高效 |
|
3. |
Audioinput和clip类播放音乐 |
主要用于播放人物语音和背景音乐 |
单独写一个音乐播放器类,当人物攻击一定次数的时候会播放人物语音,此外当游戏界面打开的时候,也会播放背景音乐 |
|
4. |
MySQL使用 |
主要使用MySQL进行战斗开始时邀请码的管理,以及战斗结束的时候战斗记录的统计 |
1。在数据库中存放着两张表,一张表管理着所有的邀请码,参与玩家的人输入邀请码之后才可以进入游戏 2。此外还设计了一个战斗信息记录表,他将记录每个玩家的id,连接端口号以及每个玩家的生存时长 |
|
5. |
工具类的设计 |
设计了管理数据库的包和音乐播放类的包,正则表达式的包,邮件发送的包 |
包中分别存放了管理数据库的工具,用于直接链接数据库并插入或查询特定的数据。音乐播放类的包用于直接调用播放音乐,不需要初始化 |
|
6. |
邮件的发送 |
玩家可以选择是否愿意在战斗结束后在邮箱里接收到自己的对战信息。 |
1.首先在官网下载对应所需要使用的jar包,修改JDK的配置文件,利用SSL协议登录发送端的邮箱之后向用户填入的邮箱端发送邮件。 |
|
7. |
类加载器和反射 |
用于直接获取类的信息 |
在加载数据库的Driver的时候,我们可以通过反射来加载管理数据库类的信息(forName方法),加载日志管理的Manager的过程中我们组需要使用类加载器.同时在我们需要加载图片类的时候也需要使用到类加载器, |
|
8. |
正则表达式的使用 |
用于对邀请码的输入进行矫正 |
邀请码的格式设计必须满足21开头的8位数字,加上“-”再加上三个英文数字结尾的格式要求。例如“21301148-gxc”,在满足要求之后,才会进一步连接数据库进行判断
|
|
9. |
学习使用JUL日志,并自行撰写配置文件 |
用于记录服务器端的接受记录 |
服务器端往往容易发生差错,且信息容易遗漏,通过撰写配置文件在控制台和外部文件处都利用日志进行记录 |
|
10. |
基于UDP通信协议的多态 |
为了规范化客户端和包之间的通信,设计了一个Msg接口作为协议/传输规范,所有的信息传输都将遵照这个规范进行传送 |
设计了一个Msg接口,并且针对该接口细化了实现了8个不同种类的message,客户端和服务端之间将会严格地通过使用这八种不同的message传输信息 |
|
11. |
策略模式 |
策略模式使得代码可以在不影响到客户端的情况下发生变化 |
将常用的方法分装为接口如在为每个人物设计攻击方式的时候,都需要大量改写攻击方式的代码,因此采用策略模式设计攻击方式的接口 |
|
12 |
使用懒汉式 单例模式 |
主要用于初始化配置文件信息 |
主要用在LOGGER日志的配置中,使用的单例模式之后,只用读取一次配置信息即可 |
|
13 |
前端CSS基础和PS技术 |
绘制人物素材需要大量的像素级图片素材以及语音素材 |
通过在谷歌浏览器按下F12可以查看网页的源代码,用过修改部分网页的代码,可以在相关网站上获得一部分所需的游戏素材。 并通过PS技术对图片进行处理,得到可以使用的图片素材 |
|
14 |
HashMap应用 |
处理图片素材的调用关系 |
主要用于匹配不同图片素材和不同的方向变量,方便管理,并且能够加快查找的速度 |
|
15. |
Vector应用 |
为了处理多线程场景,减少并发的冲突,我们采用Vector这种线程安全的类
|
Vector数组中的添加和提取方法的源码中是有同步锁的,这保证了线程的安全。 |
|
16 |
Enum类的运用 |
利用Enum定义一个管理人物不同的方向和不同状态的类 |
人物移动仅仅只包含上下左右,为了实现左上,左下,右上,右下,我设计了Enum,里面包含了人物移动的不同状态,这些状态中,包扣左上左下,等,之后在根据这些标记进行处理即可,同时人物静止分为左静止,右静止,左攻击,右攻击等多个状态,我们将这些状态都写入定义的Enum类中
|
|
17 |
DatagramSocket和bytearrayinputstream的使用, |
用于UDP的通信 |
在客户端和服务器的连接中,主要利用UDP通信实时传输变更消息,其中datagrampacket可以一次性打包所需要的文件进行传输,arrayinoutstream则可以利用自带的缓冲流加快读取速度 |
|
18 |
Toolkit |
用于获取本地素材 |
加载图片素材的时候使用 |
|
19 |
占位符的使用 |
主要用于传送数据库信息的时候使用 |
先利用占位符占住需要添加信息的位置,接着再添加我们需要的信息 |
|
20 |
Rectangle类的使用 |
主要用于边界判定 |
利用类中所带的insert方法判定是否进入边界 |
|
21 |
学习使用Joptiondialog中的messagedialog,confirmdialog,inputdialog |
利用消息对话框从用户处获得邮箱的输入 |
使用messagedialog,inputdialog等用以和用户进行消息交互 |
2。2 各模块详细设计和处理流程
总体逻辑交互:
图2.1服务器端与客户端的系统用例图
客户端与客户端之间并不会有直接联系,客户端发生操作时会直接把信息传送到服务器,服务器则会把所有收到的信息全部转发给每个客户端。每个客户端在收到发来的信息之后调用客户端内的方法进行分析,最后根据解包得来的信息进行画图。
客户端:
对于客户端而言,客户端的核心组成在于客户端的绘图界面CharacterClientGUI和用于处理网络连接信息的类NetClient
对于绘图界面CharacterClientGUI的绘图信息主要分为两部分:第一部分为自己客户端内部控制的人物的属性变化带来的影响所需要的绘图,列如玩家按下移动或攻击的键,绘图界面都会直接进行相应并进行图形的绘制,同样的,对于爆炸效果,飞行物的绘制都将直接在客户端图形界面内进行完成
图2.2客户端接受内部的变化信息绘图
客户端绘图的第二部分为客户端外部信息传入所带来的变化:
首先得先介绍外部信息传输的接口:
为了加快通信速度,我们再传输数据的时候不会一次性传输全部对象,相反地,我们根据每一次情况变化地不同,分类了总共八种情况,每种情况都对应了一种特殊的事件,而每个事件只需要传输对应的数据即可。
表2.3 Msg接口设计
这种设计方法能够极大地帮助我们减少所需要传输的数据量
以下为图形客户端CharacterClientGUI和网络连接客户端对八种外部输入地信息的处理
表2.4 客户端接受外部信息绘图
图形客户端通过同时处理外部信息和内部信息进行画图,同时,对于如果自身控制的英雄信息发生改变,也会通过自身的NetClient发送给服务器
客户端处理信息流程图
以上便是客户端的绘图信息接收原理,
表2.5 客户端收发信息流程图
服务器端:
对于服务器端而言,除了一些基本记录数据的类以外,主要依托内部类实现的两个线程进行管理,其中UDPThread线程负责不断接受udp端口发送来的信息,而HeroDeadUDPThread则主要负责监听hero的死亡事件,如果死亡,则会将hero移除client数组
表2.6 服务器端的内部类实现
2。3 包结构说明
说明客户端和服务器端设计了哪些包,主要完成什么功能
表2.7包的设计
|
序号 |
包名 |
功能说明 |
|
1. |
clientServer.Strategy |
客户端的策略包,利用策略模式,将人物的攻击模式判定抽象出来 |
|
2. |
clientServer.character_attribute |
客户端包中的character_attribute包,主要用于存放角色的属性 |
|
3 |
clientServer.Media |
客户端包的media包,主要用于存放多媒体文件 |
|
4 |
clientServer.myclient |
客户端的核心的功能包,包括客户端的图形界面绘制和客户端与服务器端的连接业务处理包 |
|
5 |
clientServer.Protocol |
客户端的协议包,里面定义了接口,客户端和服务器端的通信会遵从这里面的协议 |
|
6 |
ServerSide |
处理服务器的GUI绘制逻辑判定 |
|
7 |
serverSide. Img |
服务器端的素材包, |
|
8 |
MyTool |
独立于客户端和服务器端之外存在的工具包,里面写了会用到的工具类 |
|
9 |
Mytool.AudioPlayTool |
用于音乐播放的工具包 |
|
10 |
Mytool.MyEmailTool |
用于邮件发送的工具包 |
|
11 |
Mytool.MyloggerTool |
用于日志记录的工具包 |
|
12 |
Mytool.RegExpTool |
用于正则表达式判定的工具包 |
|
13 |
Mytool.SQLTool |
用于数据区查询和修改的工具包 |
2。4类的设计
按客户端和服务器端分开写
表2.7客户端类的设计
|
序号 |
包名 |
类名 |
功能描述 |
|
1 |
clientServer.character_attribute |
Character |
用于存放角色类的信息 |
|
2. |
clientServer.character_attribute |
Dir |
自定义的enum类,用于判别区分角色的方向 |
|
3. |
clientServer.character_attribute |
Explode |
爆炸特效的属性 |
|
4. |
clientServer.character_attribute |
Missle |
飞行物的属性 |
|
5 |
clientServer.Meida.explode |
无 |
存放爆炸的图片绘制 |
|
6 |
clientServer.Meida.images |
无 |
存放不同人物的图片绘制 |
|
7 |
clientServer.Meida.missle |
无 |
导弹飞行物的图片 |
|
8 |
clientServer.Media.music |
无 |
背景音乐的播放 |
|
9 |
clientServer.myclient |
CharacterClientGUI |
用于进行战斗场景,图片,飞行物,爆炸等特效的绘制 |
|
10 |
clientServer.myclient |
NetClient |
用于客户端和服务端之间的链接通信 |
|
11 |
clientServer.Protocol |
HeroalreadyExistMSG |
向服务器发送英雄早已存在的消息
|
|
12 |
clientServer.Protocol |
HeroDeadMsg |
向服务器发送英雄死亡的消息 |
|
13 |
clientServer.clientServer.Protocol |
HeroMoveMsg |
向服务器发送英雄移动的消息 |
|
14 |
clientServer.Protocol |
HeroNewMsg |
向服务器发送英雄新生的消息 |
|
15 |
clientServer.Protocol |
HeroReduceBloodMsg |
向服务器发送硬性扣血的消息
|
|
16 |
clientServer.Protocol |
MissleDeadMsg |
向服务器发送飞行物死亡的消息 |
|
17 |
clientServer.Protocol |
MissleDeadMsg |
向服务器发飞行物产生的消息
|
|
18 |
clientServer.Protocol |
MSG |
接口,规范了所有实现接口的类都应该实现parse和send的方法 |
|
19 |
clientServer.Strategy.event |
CharacterHitEvent |
角色被攻击的时间
|
|
20 |
clientServer.Strategy.event |
CharacterHitListener |
(接口)角色被攻击的监听器 |
|
21 |
clientServer.Strategy |
Fire |
接口 表示人物攻击 |
|
22 |
clientServer.Strategy |
FireAction |
接口 表好人物的攻击方式 |
- Character类主要实现了人物移动的键盘监听事件,locate方法根据人物的状态给人物的状态变量赋值,draw方法实现了血条的绘画,move方法实现了人物的移动判定,同时继承了actionToevent的接口,在人物类中判定该人物是否被击中,fire方法调用了人物的攻击方法,其中包含了不同人物不同的攻击逻辑
- Dir是自定义的状态变量,用于判定人物的状态
- Explode主要负责爆炸的绘制
- Missle类中主要实现导弹(飞行物)的绘制,移动,同时写有是否击中敌人的判定方法
- CharacterClient 主要利用paint和repaint进行客户端图形的绘制,同时launchFrame一个用于和玩家进行交互的窗口,获得玩家的游戏信息,以及玩家选择的角色信息,实现语音的播放,同时也能获取玩家电子邮件,便于后续电子邮件的发送,同时还会根据玩家的选择不同弹出不同的游戏提示信息
- NetClient 的parse方法主要用于接受服务器数据,并调用Msg的方法进行解析获得数据,同时
- Msg接口定义了parse方法和send方法,其中parse方法将会利用多态性质,对每个不同的信息类进行解析,send方法将根据多态处理不同情况下数据的收发
- Fire 和FireAction为接口,利用策略模式的写法
- NormalFireAction实现了FireAction接口,我们将在这里根据人物角色的不同,实现不同的攻击方式判定
表2-8服务器端类的设计
|
序号 |
包名 |
类名 |
功能描述 |
|
1. |
serverSide. Img |
无 |
存放服务器端gui图片 |
|
2. |
ServerSide |
ClientAttribute |
用于存放将要写入到数据库的信息属性 |
|
3. |
ServerSide |
GameServer |
服务器的业务逻辑判断端口 |
|
4. |
ServerSide |
ServerGUI |
用于显示服务器的图片 |
- ClientAttribute的toString方法将会决定报告生成的样式,同时里面的属性主要将用于数据库的记录
- GameServer主要用TCP/IP协议和各个客户端确立连接之后,使用UDP协议进行信息传输
- ServerGUI 的paint 和 repaint方法主要用于显示客户端的连接信息便于监听,同时还将用于展示动图的播放
表2-9 工具类包的类的设计
|
序号 |
包名 |
类名 |
功能描述 |
|
1. |
Mytool.AudioPlayTool |
MusicPlayer |
用于播放音乐 |
|
2. |
Mytool.MyEmailTool |
SendEmail |
用于收发邮件 |
|
3. |
Mytool.MyloggerTool |
LoggerTool |
用于进行日志的记录 |
|
4. |
Mytool.RegExpTool |
LoggerTool |
用正则表达式进行格式的判断 |
|
5 |
Mytool.SQLTool |
SQLToolForFight |
用数据库存储信息 |
|
6 |
Mytool.SQLTool |
SQLToolForInvite |
查询数据里的邀请码信息 |
2。5 模块核心数据结构和数据存贮设计说明
模块使用的核心数据结构设计说明。比如文件储存格式,数据库表,数组或集合等,以及它们应用在什么地方。
1.日志的时间输出配置
主要用在服务器端运行状态的记录上
2.数据表库
主键设为num,num设置为自行递增的,战斗信息记录表,ip为服务器的ip地址,UDP-port记录了客户端的端口号,id记录了客户端的id信息标注,SurvivalTime主要用于记录玩家的存活时长,Name是用来记录玩家自己为自己的角色取得名字的。
3.邀请码格式设计
21\\d{6}\\-\\w{3} 例如21301148-gxc,要求前8位必须为数字,前两位必须为符号,同时再跟上斜杠再跟上小写字母,(实际上是学号-姓名)
三、 攻克的难点及解决方案
1.人物绘图素材的获取,首先因为人物的素材来自于游戏,并且在设计初期就定下了绘制小人动图的目标,因此这也导致了我们的小人素材很难直接通过网络搜索获得,为了获取游戏素材,我们只能通过自学前端的知识,在wiki界面上通过使用谷歌浏览器按下f12直接查看网络的源码,接着在源代码里直接爬取需要的图片(以下为示例图)
2. 小人的绘制 ,人物的绘制要求必须得到的素材背景为透明的,为此我们只能自学ps技术抠图,并除去背景图层蒙版来获得想要的图案,此外因为每个小人的动作都十分丰富,包括左站立,右站立,左攻击,右攻击,左行走,右行走,加上每个动作都必须是动图绘制,因此仅仅是绘制三个人物角色(泥岩,w,阿米娅),便处理了整整200多张素材,同时,因为java的绘图策略是在左上角绘图,因此这要求每张图片二点人物相对位置必须严格地相对于左上角不变,这也无疑加大了绘图的难度。另外,因为我们要绘制的是动图,我们采取的策略是在刷新的时候更换绘图的下标,通过这种方式完成人物动图的绘制。
3.对小人的控制操作的不同步:事实上这是所有对战游戏都必须要考虑的一个难点,也是客户端与服务器端之间连接的重点,例如,如何使得人物在按下方向键后能够自动默认朝向最后按下的方向,这看似是一个很简单的问题,但是由于键盘监听事件仅仅只针对于当前的的客户端GUI,我们又该如何保证在不同的客户端之间人物的朝向是一致的呢?这就意味着我们的人物方向判定设计必须从键盘监听的逻辑的层面上脱离出来,而是采用一种标记的思想,监听器响应监听事件之后利用布尔变量记录下来,接着再根据这个布尔变量确定人物的状态,最后在通过人物的状态来进行画图,我们通过这种记录事件的标记做法来判定人物的状态,也是为了满足同一个代码在别的客户端绘制非本机角色的时候具有一定的兼容性,这做法倒颇有结绳记事的味道。
4.关于同一线程之间的画图问题,这个问题源自和同学的讨论,我们在一个窗口中调用另一个窗口的启动方法,接着把本窗口给关闭,会出现什么样的现象?答案是新产生的窗口不会被绘制(或只绘制出来白屏)这个问题起初困扰我们好久,最后我们发现,其实不同的窗口之间是有从属关系的,我们可以理解为新产生的窗口附属于主窗口,例如我们调用新窗口的启动方法之后,本窗口关闭,我们可以理解为主线程进入了休眠,那么那个新窗口自然显示功能会有限制,解决方法1.:我们需要给新窗口一个单独的线程进行绘制,这样即使主线程被关闭了,新窗口仍然能够保证正常的绘制。方法2:我们事实上可以调换主次的概念,只要保证关掉的是次窗口就可以了(有些偷换概念的嫌疑),也就是说在类加载的时候就利用类加载器把主窗口和此窗口同时都new出来,把需要附属确认的功能加在附属窗口,主窗口虽然存在,但是不可见,需要可见的时候显示可见即可,也就是说,要在开始的时候就完成两个窗口的绘制,不要在最后才绘制,同样能够避免这样的情况。
5.学习数据库连接的时候无法连接,错误码1045
解决方法为重启数据库之后我们进入data文件,找到.err文件,找到自己之前设计的密码(或者在配置文件里写上跳过密码验证的步骤)接着登陆进去之后,我们更改密码alter user 'root'@'localhost' identified by '123456';就可,(12346是我乱写,不是我数据库的密码!)原因猜测,登录账号、密码、服务器名称、数据库名称登录错误导致不能连接,这个问题比较常见,仔细检查好所填信息是否正确,可能是在配置的时候配置文件写的有些许误差。此外,因为数据库安装在本机,服务器名可以用“.”或“(local)”来代替减少些误差;如果是安装在局域网的其它计算机上,可以用IP地址作为服务器名
6.java图片路径搜索问题:跟着网上的资料敲代码的时候,在使用Toolkit.getDefaultToolkit().getImage(Panel.class.getResource())导入图片的时候,网上的资料中的加载方法可以正常运行,我的代码运行时却报空指针。后来尝试过换用ImageIO.read方法加载,换了加载方式就可行了,由此可见不是机器的问题,后来再自习研究,发现, 老师用的是java8,我用的是java11(切成java8就能正常运行)。从java9开始,定位资源的方式发生了变化。getResource()只会在调用该方法的module内定位资源。这是由于getResource()受getResourceAsStream()中规则的约束,这在之前的版本里是没有的,因此这对资源的摆放也有了要求, 从找到的资料来看,似乎需要具体指定<MY_CLASS>.class.getResource(),也就是说写成Panel.class.getResource或Class.class.getResource(),这里的<MY_CLASS>应该就是官方文件里说的named module,相对应地,Panel和Class这种不是由用户定义的就是unnamed module。所以我在这里把代码写成:Toolkit.getDefaultToolkit().getImage(MyPanel.class.getResource("/niyan1.jpg"));如此便能够成功加载出来
7.绘制图像的时候,我们发先第一次的图像绘制往往不会成功,而第二次之后的图像则能够绘制成功了,例如这样的写法,会发现图片加载不出来
后来经过查阅资料可以知道,drawImage的时只有在调用的时候才会加载图片,因此可能无法加载出来,所以我们的做法是在第一次调用前就加载一次
我们在看不见的地方绘一次图,就能保证在之后的图形调用中,都能够重新加载了
- 7. swing动图显示
如何在程序中画图往往是一个难点,这里我给出两种解决办法,1.因为在swing的jlabel组件是支持前端语法的,你可以使用前端显示的方式把gif图加载上去,同时,事实上直接读取也没什么问题. 比方说是重写paintComponent(Graphics g)或paint(Graphics g)方法,
public class ShowGifPanel extends JPanel{
ImageIcon image = new ImageIcon("/root/opt/loading.gif");
@Override
public void paint(Graphics g) {
g.drawImage(image.getImage(), 0, 0, this);
}
然而,不要企图通过这样简单的处理达到理想的效果。如果你这样做的话马上会发现gif的刷新率往往非常快,看上去gif图片帧刷新很快,或者应该说太快了,对内存损耗也很大。为此,本人使用了一种最笨,也是工作量最大的方法,那便是一张张循环播放我们要画的图片,因为gif或是动画效果的图片本质还是一帧一帧的连续播放,所以只要把每一帧都处理出来,也便能实现动画效果。如果之后也有想做类似游戏的学弟,这种方法也权当做给你们的参考吧
- 8. 学习发送邮件的时候发现出现SSl的报错
这个报错多半是系统报错,同时因为我使用的是利用qq邮箱进行发送信息的方式,而qq存在一个设置SSL加密的方法,而当我们在代码中开启允许SSL加密的允许之后,是事实上我们的jdk配置里可能并未允许这项权限,因此,我么可以通过搜索java的安全配置文件,接着以管理员身份取消SSL的disabled设置 (也就是允许SSL),接着再次启动,发现能够重新正常运行了。
- 9. 类加载器的缓存机制
类加载器主要有三种加载方式1.全盘加载2, 父类委托加载,3,缓存加载机制. 缓存机制将会保证所有加载过的 Class 都会被缓存,当程序中需要使用某个 Class 时,类加载器先从缓存区中搜寻该 Class,只有当缓存区中不存在该 Class 对象时,系统才会读取该类对应的二进制数据,并将其转换成 Class 对象,存入缓存区中。这就是为什么修改了 Class 后,必须重新启动 JVM,程序所作的修改才会生效的原因,希望这点对未来的学弟们有点帮助哈.
尚未解决的问题:
1.网上购买了华为的服务器,Centos系统,一核,学了些基础的linux语法,下载了java的jdk,jar包传上去以后会显示打不开虚拟机,或者缺少相应的类,
在网络连接的时候8888和3306(数据库)的相应安全组也授权的开了,可能因为学的东西太少,目前暂时链接不上。
2.通过网络资料学习了线程池
以上为手敲代码,按照原先设计,我们可以可以利用线程池管理人物最大埋下的地雷数,这就要求我们可以把地雷单独做成一个线程,每隔一定时间减少生命值,并且将地雷线程拿线程池管理,但是在进一步学习中,发现其实并没有在开一个线程的必要,可以吧判定逻辑写在paint方法里,省去了多开一个线程的时间,思路上也更简洁,所以后来秉持着简洁性,不为了用而用的原则,把线程池优化掉了
四、 创新点说明
- 游戏模式的创新:采用多人联机的大混战模式,玩家可以多次加入同一个房间进行游戏,随开随停,同时房间中进行混战的游戏人数不受上线,双人,多人皆可游玩。
- 游戏中的每个角色都有自己不同的攻击方式判定,有不同的血量和攻击力,有不同语音和立绘图案,差异化设计。
- 关于对于游戏的公平性考量:因为我们的游戏判定逻辑设置在客户端上(因为技术原因,还没有学会在服务器端进行逻辑判断的方法),那么如何在客户端及进行角色死亡判定便成为了整个游戏设计的重点,这是因为如果设计的有差错的话,可能会出现在一个客户端玩家a存活,在另一个客户端玩家a死亡的情况。那么我们应该如何避免这样的情况存在呢?为了保证公平性,我们做了以下处理
3.1 为了公平,首先要做的事情便是加快客户端转发信息的速度。毕竟连35ms到10ms的延时差距也会对公平造成影响,因此,我们要做的便是加快信息的传输输出。为此我们选择在初步建立tcp/ip通信之后,双方交换端口信息确保连接建立之后采用udp通信,以来udp通信只管发送的特点使其不用经过tcp通信繁杂的3次握手4次挥手的操作,因此在较为安全的网络通道,这种方式能够更好的降低延时,其二tcp通信和TCP/IP协议下的通信相比还有一个优势,也即tcp通信可以实现多对一,一对多的转发方式,而tcp通信仅仅只能实现一对一的方式,这意味则会在进行多人通信的时候,TCP/IP协议下我们必须接收到一个信息,就开创一个线程,即使是用线程池解决多客户端连接的情况,其传输速度仍然不如udp通信。
3.2 优化信息的传输策略,相比于普通的传输整个对象数据,我们优化的策略在于一次性只穿输入需要的数据,为此,我们分类讨论了整个游戏中会出现的情况,设计了八种信息传输的方式,这八种信息之间的交互传输足以代表整个游戏中所发生的情况变化,同时,因为信息被分为八类,我们在传输数据的时候只需要传输我们所需要的变更的数据即可,不需要在直接传输整个对象,着能够更好的帮助我们提升速度
3.3 同时,我们还可以进一步优化传输的策略,列如当我们按下移动方向键盘时,不同于传统的一收到信息直接传输数据,我们采用一旦人物状态改变,在传输数据的方式进行传送,具体怎么实现?例如一个人按下d两秒,每秒刷新50次,则按照前者逻辑,总共需要传输100次d键被按下的数据,相反,如果采用状态改变在传输数据的方式,我们只需要传输首,末的信息作标记即可,这意味着,我们只需要传输两次信息,同时在其他客户端中,得益于之前设计的人物状态类,人物在不接受到别的数据时不会改变现有的状态(类似于物理的惯性)人物只需按照前一帧的逻辑移动即可。这种判定方式,能进一步帮我们加快信息的传输速度。
五、 用户使用手册
- 首先启动服务器
其中服务器的红圈部分会显示客户端的连接信息
- 登录客户端
点击客户端后随即显示如上界面,并播放游戏的背景音乐
用户在ServerIP处输入目标服务器的IP,这里我们填的是本机,
HeroName处填的是用户的游戏名称,用户之后可以在游戏中通过改名字识别自己是哪一个角色,该信息随后也会被记录到数据库中,
ChooseHero处可以下拉选择英雄
每当你选择了指定角色之后
会随机切换不同对应人物的立绘,同时还会播放人物的对应语音台词作为被选中的回应
选择好角色,你需要填入相关的邀请码(一般要联系管理员获取),你可以使用21301148-gxc 或者内测邀请码 a 进入游戏
如果邀请码错误,会弹出提示 同理,若服务器IP错误
若成功登录,战斗小助手会弹出是否需要邮件记录的提示
若选择是,则需要填入您的邮箱
点击确定后,或者选择不填入邮箱,将会直接开始游戏
之后系统将为你生成你的游戏角色:
首先,人物上方的是你的血条,血条为零时将会死亡
血条的颜色代表你的阵营,同阵营的人不会被彼此的攻击所影响到,阵营将根据加入顺序自动分配,当你死后,你可以重新打开客户端加入同一局战斗,因此该游戏是一款没有结尾的无休止的多人大乱斗模式,您可以和您的伙伴们一起游戏,随开随停。
而你要做的唯一事情,便是在乱斗中存活最长的时间,无论是追着人打,或者走位避战,都是存活的策略。
游戏人物介绍:
,
该角色名为泥岩,攻击方式为近战攻击,以上为部分游戏截图
该角色有较高的血量和防御力,和能够快速击败敌人的能力
然而该角色的攻击范围较窄(身旁周围八格)
该角色有专属的信息的语音出发机制和频率,欢迎进游戏体验
请理智走位并操控她活到最后
该角色名为w,该角色的方式为陷阱攻击
该角色能够在原地防止一个地雷,地雷持续5秒钟
将会对第一个碰到地雷的人造成伤害
该角色的地雷数无限制,在多人混战中,地雷类工具具有绝对优势,注意地雷的持续时间只有5秒,请把握好实际释放
该角色名为阿米娅
该角色血量较少,但攻击方式为远程攻击
可以向正前方,斜上,斜下方向发射法术技能
该技能在碰到敌人或者碰到墙壁后会消失
因此请灵活掌握释放的时机
该角色同样配备专属语音,欢迎登录游戏体验!
如果被击败 则会弹出窗口
于此同时,您的相关信息将会被记录到数据库中(管理员可查询)
同时,如果您先前填写了相关邮件信息
您还可以在邮件中收到作战信息战报
六、 心得体会
求学论道, 博学之,审问之,慎思之,明辨之,笃行之。你我皆是默默无闻饱尝寒舍十年苦而求学之人,其中或有心酸苦楚,也便只有我们自己知晓。诚然,小学期很苦,很难,对我们每个人而言都是巨大的挑战,但也希望各位未来的学弟,学妹们不要畏惧这份挑战,我们学的技术知识并不是为了闭门造车,我们终究要把自己所学的知识应用到实践中,与社会的潮流接轨,为此还希望各位不要将小学期当成不得不完成的任务,而是一场等待你许久的历练。你完全可以在小学期中发挥自己独有的创造和灵气,做自己喜欢做,爱好做的东西,体验游戏设计开发中常遇到的问题和挑战。我认为小学期的意义还不仅在于考核这么简单,他还在与帮助我们实际体验真实游戏开发中所会遇到的问题和挑战,帮助你提前熟习游戏开发这条路。我们常说,人生中有很多试错的机会,而大学往往是试错成本最低的阶段,而这次的小学期,事实上也是一个精心为你准备的试错机会。为此还希望各位能多多挑战自己,多多尝试汲取新的知识,在不同的领域学习,以期拨开迷雾,窥见未来自己的模样。
本次小学期,相信大家都会或多或少遇到困难与挑战,这是正常现象,但最重要的,是在这个过程中锻炼自己解决问题的能力,希望各位不要畏难,不要太过恐惧,多多与自己的老师,同学交流,就算做不出来,也能学到许多受益匪浅的知识。路漫漫其修远兮,愿各位上下而求索,即使道路狭窄,也愿各位能找到属于自己的光亮。

浙公网安备 33010602011771号