400字范文,内容丰富有趣,生活中的好帮手!
400字范文 > Java写泡泡堂网络游戏

Java写泡泡堂网络游戏

时间:2024-06-24 21:30:50

相关推荐

Java写泡泡堂网络游戏

系统实现

代码结构

公共类的介绍

系统中定义了一些公共的类,可以被客户端和服务器端多次使用,这些类里的方法多是静态的。

GameKey.java

这里定义了一些系统级的一些参数,都是静态的。

Util.java

主要定义了4个方法,用户测试时候打印信息的,全屏的,和关闭显示窗口的方法。

MessageManager.java

声明了发送消息和接收消息的两个方法。控制着客户端和服务器端之间的数据交换。

服务器端的开发

服务器端开发是使用JAVA语言中的套接字,采用TCP协议进行通讯的。通讯的数据全部封装在一个Message类里面。这些数据在网络之间传输并在客户端和服务器端进行解析,得到后作出相应的动作。处理流程参考图

服务器端主要用到了java中的网络编程和线程。在构造函数中,利用默认端口创建一个套接字ServerSocket(Port);然后进入一个无限循环来监听网络连接,每当有一个新的客户端连接到服务器,建立一个新的线程来处理该客户请求。之后服务器端继续监听,等待新的客户端连接。

try {serversocket = new ServerSocket(port);System.out.println("Game Server started at:"+ serversocket.getInetAddress().getLocalHost() + ":"+ serversocket.getLocalPort());while (true) {//设置玩家的编号:1-8if (number < 8) {number++;} else {number = 0;continue;}clientsocket = serversocket.accept();System.out.println("Connection from:" + clientsocket);out = new ObjectOutputStream(clientsocket.getOutputStream());ht_out.put(clientsocket, out);ServerThread serverThread = new ServerThread(clientsocket, ht_out,number, out, allMessage);Thread thread = new Thread(serverThread);thread.start();}

ServerThread被启动后,也执行一个无限循环,对连接通道进行监听,如果有该通道发过来的信息,就对相关的信息进行处理,之后把处理后的消息转发给所有玩家。

客户端

首先在程序中定义了几个通用的组件和方法:CenterShowDialog, GameImage.java, ImageButton.java ,ImageLabel.java 和ImagePanel.java

CenterShowDialog:这个类的功能是使显示的图形界面居中。

ImagePanel:定义一个背景为一个image的画板(panel)

GameImage:这里定义了一些对图片操作的类,如创建一个图片等。

ImageButton:定义一个图片按钮(JButton)

ImageLabel:定义一个图片的标签

这些通用的组件和方法供各个模块所公用。一些场景的设置是在它们的基础上进行搭建的。

模块设计

如图所示,游戏客户端总体分为4个大的模块:游戏入口,登陆,游戏大厅,和对战场地。

游戏入口模块

主要类:Game.java

描述:显示一个无标题栏的窗口,提示一些版权信息,如图所示。

游戏声明

首先在它的构造方法中初始化该JFrame的相关属性。在main方法中,先声明一个Game类,创建声明窗口。之后调用Util方法中的showWindow()方法,显示该窗口的动态展开,产生一个动画的效果。窗口将停顿5秒,以便玩家有足够的时间来阅读相关内容。最后调用Util方法中的closeWindow()方法来动态地收缩关闭该窗口。随后创建一个Login类,并将其显示,进入登录模块,同时隐藏该声明信息窗口 。

登陆模块

主要类:Login.java

描述:显示登陆界面并处理相关的鼠标动作,输入玩家名称,密码等,登陆后和服务器建立连接,并发送信息到服务器。(因为不设计到数据库,这里并没有对玩家输入的相关信息进行验证,也没有注册玩家信息的功能)

因设计到对一些组件的监听,并对鼠标事件进行监听,该类实现了相关方法:

public class Login extends JFrame implements ActionListener , mouseMotionListener

构造方法调用init()方法对类进行初始化,这里主要是创建了两个ImageButton : login_bt 和exit_bt,两个文本框:user和password,设置它们被显示的位置和样式,同时为两个ImageButton增加鼠标监听事件。当鼠标点击login_bt时,将触发一个事件,捕捉该事件,并进行处理。

处理过程:从user和password两个文本框得到玩家输入的信息,把这些信息作为属性值赋值给一个新的Message 实体。创建一个和服务器的新的连接,把这个message发送到服务器段。之后创建一个GameHall: new GameHall(msg,in,out);

游戏大厅模块

主要类:GameHall.java

描述:游戏大厅的主界面,同时负责处理玩家一些鼠标事件,并和服务器进行通讯,发送/接受消息。当鼠标触发一些事件时候,对事件的内容进行解析,然后根据不同的事件,创建不同类型的消息,把相关的必要的信息进行封装,最后发给服务器。由服务器进行处理后,服务器发送消息给所有客户端,客户端接收到消息,并对接收到的消息进行处理,来改变大厅场景。

该类中设计到对整个大厅中鼠标和键盘事件的监听,并创建一个主的线程来监听从服务器端发来的消息。因此该类实现了MouseListener, MouseMotionListener, Runnable,KeyListener等接口。

构造方法中调用了init()方法 。初始化大厅用到的一些组件。整个大厅是一个ImagePanel,一个画布。所有的组件都是在这个画布上增加。并为这些组件增加一个监听器来监听它们的动作。之后程序启动主线程,对服务器发来的消息进行监听,并在解析后作出相应的动作。

thread=new Thread(this);

thread.start();

当受到一个消息时,根据消息的类型,作出不同的动作。最后调用paint()方法来刷新主画布从而改变场景。调用paint()方法时,首先把所要玩家都移除,然后重新画整个场景:

removeAllPlayer()

for(Enumeration e=htPlayer.elements();e.hasMoreElements()😉{

Message msg =(Message)e.nextElement();

showPlayer(msg);

}

其中的showPlayer()方发中是根据玩家不同的编号(number)和小组(team)来把玩家的图片画到画布的不同位置。并判断该玩家现在的准备情况,如果准备好了就显示准备状态。

游戏大厅中主要实现了小组的选择,聊天功能,准备和取消准备等功能。

小组的选择:

游戏中的小组分为“蓝队”和“红队”,它们的选择图标都是一个ImageButton。当有鼠标点击它们的动作时,将触发一个鼠标点击事件,这时鼠标监听器将捕捉到该动作。然后创建一个新的消息,把玩家的一些信息赋值给该消息,同时设置消息的类别为“更换小组”,最后发送消息.这里以选择蓝队为例:

Message test=new Message();test.team=GameKey.TEAM_BLUE;test.type=GameKey.MESSAGE_TYPE_CHANGE_TEAM;test.number=meMessage.number;test.UserName=meMessage.UserName;Util.printMessage("Select Team ",test);

当客户端收到Type为GameKey.MESSAGE_TYPE_CHANGE_TEAM (数值为5)的消息时,从保存的所有玩家的信息中得到状态改变的该玩家,并更换它的TEAM,之后还放到HashTable中。

for(Enumeration e=htPlayer.elements();e.hasMoreElements();){Message test =(Message)e.nextElement();if(test.number==msg.number){test.team=msg.team;htPlayer.put(Integer.toString(test.number),test);}}

最后要调用paint()方法来重新刷新该画布,改变场景,使该玩家的颜色显示和选择小组颜色一致。

聊天功能:

原理和小组选择相似,首先玩家在文本框中输入要发送的消息内容,当点击“发送”的图片按钮时,触发一个鼠标动作。监视器拦截该动作,并得到输入文本框中的信息,把它封装到一个消息里面Message。最后发往服务器 。服务器端只是把消息进行转发给所有玩家。玩家的客户端收到消息后,判断该消息的类型,如果是聊天消息,将聊天的内容提取,然后显示在聊天信息板里面。

准备/取消准备功能:

点击准备图片按钮,触发一个事件,然后封装生成一个消息发送到服务器,服务器转发。客户端收到消息后把该玩家的状态改为“准备”。之后判断是否所有玩家都已经准备好,如果都准备好,把全局变量Ready的数值设置为“OK”,然后在主线程里判断这个值从而得到是否所有玩家都已经准备好。都准备好的话就创建一个新的窗口进入对战区。

对战场地模块

主要类:QQPad.java

描述:这个类为游戏大厅的画布,同时处理对战时的主要逻辑,是整个游戏的核心。负责处理了玩家移动,泡泡的放置及引爆,障碍物的清除和胜负判断等多个功能。

当玩家进入大厅时,程序首先要初始化场景,包括对地图和玩家位置的初始化,并为场景增加监听器监听玩家键盘和鼠标的动作,之后启动一个主线程。该线程负责处理玩家的鼠标和键盘动作,并对从服务器端接收到的消息进行处理,从而改变当前的场景。当有一个小组的全部玩家都被消灭后,就判断胜负并显示结果,这次对战就结束,返回到游戏大厅。整体流程如图所示。

以下将对几个主要的流程作详细的介绍。

地图的生成

地图是每个游戏必需的一个元素,地图主要是生成游戏的场景,然后在画布上显示该场景。在开发很多类型的游戏中,地图系统都需要良好的设计,直观的说,我们需要的地图系统仅仅是一个2D数组,然后用最快的方式将数组影射到屏幕上。

地图的设计方式有很多,大多数2D游戏是通过开发的地图编辑器来实现的。而该游戏的设计是首先定义一个地图文件,这个地图文件是用一些0,1等数字表示一种物体。然后在用流对该文件进行读取,把内容读取到一个数组里面。不同的数字就会在场景中显示出不同的物体。

程序中首先在map文件夹下定义好一个“map1.txt”文件,该文件是由0,1,2三种数字组成:

111110010011111

111000210100111

11001210011

100010010101001

101121101010100

00010101011

02101010220

110101010110200

001010101121101

100101010010001

110010102210011

111001012000111

111110010011111

其中,0在场景中显示的是一个空地,1显示的是一个箱子,2显示为一个植物。之后通过流将数据读取到一个数组里面:

while(true){String line=reader.readLine();if(line==null){reader.close();break;}//过滤掉#开头的行if(!line.startsWith("#")){line=line.trim();lines.add(line);width=Math.max(width,line.length());}}height=lines.size();//对数组赋值for(int i=0;i<height;i++){String line=(String)lines.get(i);for(int j=0;j<line.length();j++){int c=(int)line.charAt(j);c=c-48;//把ASC码转化成数字map[j][i]=c;}}

根据初始化好的数组,对数组中每一个元素的值,将显示不同的物体,从而实现地图的初始化。上例中地图数组最终显示到画布中的场景如图所示:

初始化场景:

初始化场景主要是初始化场景中使用到的图片,玩家的位置,为场景中的相关组件增加监听器等。对于玩家的位置的初始化,这里先判断玩家的编号,每个编号对应一个不同的位置。而显示玩家时,是通过地图中的数据来显示的。每一个地图代码代表不同的玩家状态。地图中的一个格子是一个数据,拿map[m][n]=1322 为例, 这个数据“1322”它们组成为: 小组编号+当前朝向+X轴方向的格子数+Y轴方向的格子数。其中小组和朝向的代码制定如下:

玩家的小组: 1 -> 蓝队;2 -> 红队

朝向:1 ->朝北; 2 -> 朝东; 3 -> 朝南; 4 -> 朝西

最后根据该数值,来最终决定该玩家的当前的状态,根据状态中的位置朝向等信息,在场景中显示相应的图片来创造当前状态下玩家的实体。

玩家移动

对战过程处理流程的原理和大厅相似,不过很多是对键盘的监听。当按下键盘的方向键的时候,监听器将捕获该动作,然后将该动作的信息封装为一个消息,在服务器端再对消息进行转发给所有玩家。玩家收到消息,对消息进行解析,得用户的操作,然后改变玩家对应单元格的代码,之后刷新整个画布,玩家的位置将做出变化。其中在移动玩家的时候,要先判断前方是否有障碍物或者是否已经到达了边界,是的话将不能进行移动。

泡泡处理

泡泡的显示也是用一个数组坐标来表示,不过这个是另外建了一个新的数组map2[][],它的大小和场景坐标一样,但是状态只有两种:放置的泡泡和爆炸中的泡泡。

当玩家按下空格建,将会把玩家当前位置出放置一个泡泡,即把map2中的对应状态改为“8”。放置泡泡的时候,其实建立了一个泡泡的线程,为这个泡泡设置位置,然后就启动该线程,当停顿4妙后,将把这个泡泡给引爆。

pad.setBomb(m,n);sleep(sleepTime);//sleepTime=4spad.Bombing(m,n,power);sleep(500);pad.cleanBomb();sleep(1000);pad.cleanPlayer();

引爆时调用了Bombing方法。该方法主要是根据泡泡的威力,把在爆炸范围内的箱子或者玩家给清除。也就是改变坐标的代码。首先要显示一个爆炸时候的图片,之后清楚相关的物体。

for(int i=m;i<=m+power;i++){//向右if(i>=15){break;}if(map[i][n]==2){break;}if(map[i][n]==0){map[i][n]=88;}if(map[i][n]==1){map[i][n]=88;break;}……}

泡泡的爆炸场景显示持续半秒后,将把爆炸范围内的物体(植物除外)的值设置为0,这样在下次刷新场景时将清理被炸掉的物体。

结束判断:

在每次泡泡爆炸后,都要进行一次判断,首先要判断是否有玩家被炸到,如果有就将该玩家的状态设置为’DEAD’,然后判断整个小组是否所有成员都已经dead掉,如果是,则认定该组失败,而对方获胜。游戏结束。

if(myLive==0 && blue_team_alive==true && red_team_alive == true){g.drawImage(deathImg,84,140,this);}if(myTeam==1){if(!blue_team_alive){g.drawImage(lossImg,84,140,this);}if(!red_team_alive){g.drawImage(winImg,84,140,this);}}if(myTeam==-1){if(!red_team_alive){g.drawImage(lossImg,84,140,this);}if(!blue_team_alive){g.drawImage(winImg,84,140,this);}}

测试

因为完全开发一个完整的网络游戏需要巨大的时间和精力上的投入,该程序的主要目的是研究泡泡堂游戏的主体开发原理和流程。在开发过程中还有一些BUG要完善。测试过程中主要精力分析数据在传输过程中数据丢失和对战中玩家坐标的调整上。为了最大可能的增加系统的稳定性,曾大范围的改变了游戏的设计思想,争取做到最优。

通过测试,整个游戏能够很好的完成整个操作流程。并可以实现多人登陆,在游戏大厅进行信息交换,和在对战场地进行对战等功能,达到了预期目标。

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。