《计算机网络系统实践》报告详解.docx
- 文档编号:29813769
- 上传时间:2023-07-27
- 格式:DOCX
- 页数:36
- 大小:537.09KB
《计算机网络系统实践》报告详解.docx
《《计算机网络系统实践》报告详解.docx》由会员分享,可在线阅读,更多相关《《计算机网络系统实践》报告详解.docx(36页珍藏版)》请在冰豆网上搜索。
《计算机网络系统实践》报告详解
《计算机网络系统实践》报告
2015年09月
基于Java的网络版坦克大战游戏设计
1、设计要求
1.1设计目的
(1)熟悉开发工具(JAVA)的基本操作;
(2)掌握windows/Linux应用程序的编写过程;
(3)对于Socket编程建立初步的概念。
1.2设计要求
(1)熟悉SocketAPI主要函数的使用;
(2)掌握相应开发工具对SocketAPI的封装;
(3)设计并实现一对一网络版小游戏,如:
Tic-Tac-Toe、五子棋等。
我选择了网络版坦克大战的设计。
2、开发环境与工具
2.1编程语言:
JAVA
Java语言是一种跨平台,适合于分布式计算环境的面向对象编程语言。
JAVA现在主要用在WEB开发,手机游戏及一些平台游戏的开发,因为它具有很好的跨平台性,在手机等各种电子产品上应用非常广泛。
2.2运行环境:
JDK1.6
2.3开发工具:
MyEclipse10
MyEclipse,是在eclipse基础上加上自己的插件开发而成的功能强大的企业级集成开发环境,主要用于Java、JavaEE以及移动应用的开发。
MyEclipse的功能非常强大,支持也十分广泛,尤其是对各种开源产品的支持相当不错。
2.4网络建立:
socket
网络上的两个程序通过一个双向的通信连接实现数据的交换,这个连接的一端称为一个socket。
Socket的英文原义是“孔”或“插座”。
作为BSDUNIX的进程通信机制,取后一种意思。
通常也称作"套接字",用于描述IP地址和端口,是一个通信链的句柄,可以用来实现不同虚拟机或不同计算机之间的通信。
在Internet上的主机一般运行了多个服务软件,同时提供几种服务。
每种服务都打开一个Socket,并绑定到一个端口上,不同的端口对应于不同的服务。
Socket正如其英文原意那样,像一个多孔插座。
一台主机犹如布满各种插座的房间,每个插座有一个编号,有的插座提供220伏交流电,有的提供110伏交流电,有的则提供有线电视节目。
客户软件将插头插到不同编号的插座,就可以得到不同的服务。
3、设计原理
联机通信机制
网络编程,简单地理解就是两台计算机相互通信。
其基本模型就是客户机/服务器模型,也就是通信双方中的一方必须提供一个固定的位置,而另一方只需要知道这个固定的位置,并且建立两者之间的联系,然后完成数据交换。
这里提供固定位置的一方通常称为服务器,而建立联系的一方称为客户端。
Socket(中文意思为插座),基于客户机/服务器的Soctet通信模式如图3.1所示:
图3.1基于客户机/服务器的Soctet通信模式图
当客户程序需要与服务器程序通讯的时候,客户程序在客户机创建一个socket对象,Socket类有几个构造函数。
两个常用的构造函数是Socket(InetAddressaddr,intport)和Socket(Stringhost,intport),两个构造函数都创建了一个基于Socket的连接服务器端流套接字的流套接字。
两个函数都通过参数port获得服务器的端口号。
假设已经建立连接了,网络API将在客户端基于Socket的流套接字中捆绑客户程序的IP地址和任意一个端口号,否则两个函数都会抛出一个IOException对象。
如果创建了一个Socket对象,那么它可能通过调用Socket的getInputStream()方法从服务程序获得输入流读传送来的信息,也可能通过调用Socket的getOutputStream()方法获得输出流来发送消息。
在读写活动完成之后,客户程序调用close()方法关闭流和流套接字。
四、系统功能描述及软件模块划分
4.1系统功能描述
4.1.1单机版人机对战
A)玩家通过上、下、左、右键来控制坦克的八个方向:
上、下、左、右、左上、右上、左下、右下;
B)出现十个敌方坦克,自由运动并发射炮弹;
C)玩家通过“control”键发射炮弹;
D)打中敌方或被敌方打中,死亡;
E)碰撞时死亡。
4.1.2网络对战模式
在人机在人机对战模式中实现功能基础上,增加以下功能实现网络对战功能:
A)添加网络功能,使两台或者多台不同计算机的玩家通过一定的网络连接,加入到游戏中;
B)能够自动分组选择阵营,一红一篮双方交替进入游戏,填写自己的游戏信息,各个玩家之间实现网络对战功能,并且同是一方的坦克不能相互攻击;
C)玩家ID是自动分配的,采用递加的模式。
4.1.3总体功能设计
坦克大战游戏主要实现玩家参加游戏的整个流程,整个网络版坦克大战游戏流程图如图4.1所示:
图4.1网络坦克大战游戏流程
4.2软件模块划分
4.2.1TankClient类基本功能分析
TankClient类是整个系统的核心部分,它承担整个系统的所有可实现功能的调度工作。
是整个游戏运行的场所。
TankClient类设计流程图如图4.2所示:
图4.2TankClient类设计流程
TankClient类是主类,通过调用其他类中封装的方法来使整个系统运行起来,下面显示TankClient与各个类之间的关系如图4.3所示:
图4.3游戏系统类关联图
4.2.2Tank类基本功能分析
Tank类中,封装了一些变量属性,包括坦克自己的大小(WIDTH,HRIGHT),运动速度(SPRRD_X:
在x轴方向的速度;SPEED_Y:
在Y轴方向的速度)、生命值控制(life)、坦克编号(id)、坦克名(name)、方向控制(dir)、生死控制(live)等。
Tank类中没有main函数,不是主类,它当中只封装一些变量属性和静态方法,被TankClient类调用来实现坦克的一系列动作。
Tank类中的主要方法罗列如下:
(1)getRect()方法
publicRectanglegetRect(){
returnnewRectangle(x,y,this.WIDTH,this.HEIGHT);
}
Rectangle类是碰撞检测的辅助类,通过得到子弹的x,y坐标和宽高度,检测两个矩形是否碰撞(相交);
(2)draw()方法:
负责将所有的活动在屏幕上画出来;
(3)move()方法:
主要负责控制坦克的移动,包括8个方向(左,左上,上,右上,右,右下,下,左下)的控制以及给坦克一个移动的速度;
(4)keyPressed()方法:
设定使用键盘的“↑”“↓”“←”“→”键控制坦克移动;
(5)keyReleased()方法:
处理按键抬起事件,抬起“CTRL”键时,发射炮弹并加入新炮弹,能够逐一发射每一发炮弹、抬起“A”键可以发射超级炮弹等功能;
(6)locationDirection()方法:
定义了炮筒方向,可以向八个方向发射炮弹;
(7)fire()方法:
处理发送子弹的方法;
(8)bumpWithWall()方法:
主要负责处理坦克撞墙事件;
(9)bumpWithTank()方法:
主要到负责处理坦克和坦克相撞事件;
4.2.3Missile类基本功能分析
Misslile(子弹)类和Tank类一样,只封装一些变量属性和静态方法,主要变量包括:
子弹自己的大小(WIDTH,HRIGHT),运动速度(SPRRD_X:
在x轴方向的速度;SPEED_Y:
在Y轴方向的速度)、子弹标示(ID)、所属坦克的id号(TankId用于网络版)等。
Misslie类持有一个TankClient类(大管家)的引用tc,TankClient类要执行发射炮弹操作时调用Missile类中的方法。
Misslie类中的主要方法如下:
(1)draw()方法:
负责画出子弹的所有活动;
(2)move()方法:
先判断方向再移动,并给它一定的移动速度;
(3)getRect()方法:
负责取得子弹的外切方形,为碰撞检测做准备;
(4)hitTan()方法:
检测子弹是否撞到坦克,若撞到返回true,否则返回false;
(5)hitTanks()方法:
检测是否撞到一系列坦克中的一个;
(6)hitWall()方法:
检测子弹和墙是否相撞。
4.2.4Explode类基本功能分析
Explode(爆炸)类也是一个只封装自己的变量和方法的外部包装类,没有main方法,供TankClient主类需要时调用它的draw()方法,当子弹击中坦克时需要产生爆炸。
4.2.5服务器类基本功能分析
TankServer(服务器)类主要负责在网络对战游戏时维护各个在线玩家的基本信息,并动态的维护玩家列表。
联机模式下类关系图如图4.4所示:
4.4联机模式类关联图
4.2.6信息传送类基本功能分析
信息传送类就是用来封装客户端和服务器端的交互信息。
将网络中传递的众多信息封装成可序列化的类,将会使程序有很好的可扩展性。
五、设计步骤
5.1单机版的坦克大战游戏(人机对战)
5.1.1主程序:
TankClient
代码如下:
publicclassTankClientextendsFrame{
privatestaticfinallongserialVersionUID=5865157849989504064L;
publicstaticfinalintGAME_WIDTH=800;
publicstaticfinalintGAME_HEIGHT=600;
publicstaticint[]SCORE={0,0,0};
Randomr=newRandom();
TankmyTank1=newTank(750,550,Tank.Direction.STOP,this,1);
TankmyTank2=newTank(50,550,Tank.Direction.STOP,this,2);
Wallw1=newWall(200,100,200,10,this);
Wallw2=newWall(200,100,10,200,this);
Wallw3=newWall(200,300,200,10,this);
Wallw4=newWall(400,300,10,200,this);
Wallw5=newWall(200,490,200,10,this);
Wallw6=newWall(500,100,10,400,this);
Wallw7=newWall(500,490,200,10,this);
Bloodb=newBlood();
List
List
ImageoffScreenImage=null;//定义背后的虚拟图片
publicvoidpaint(Graphicsg){
//g.drawString("MissilesCount:
"+missiles.size(),10,50);
//g.drawString("ExplodesCount:
"+explodes.size(),10,70);
//g.drawString("TanksCount:
"+tanks.size(),10,90);
g.setColor(Color.orange);
g.drawString("P1P2",10,40);
g.drawString("LC:
发射一枚普通的子弹。
",10,60);
g.drawString("KV:
九个方向的超级炮弹。
",10,80);
g.drawString("JB:
埋下一颗地雷等他踩.",10,100);
g.drawString("F2F3:
购买一辆全新的坦克。
",10,140);
g.drawString("P1的剩余坦克数:
"+myTank1.getLives(),600,50);
g.drawString("P2的剩余坦克数:
"+myTank2.getLives(),600,70);
g.drawString("P1的分数:
"+SCORE[1],600,90);
g.drawString("P2的分数:
"+SCORE[2],600,110);
g.drawString("剩余的坦克波数:
"+Tank.win,600,130);
myTank1.collidesWithWall(w1);
myTank2.collidesWithWall(w2);
myTank1.collidesWithWall(w3);
myTank2.collidesWithWall(w4);
myTank1.collidesWithWall(w5);
myTank2.collidesWithWall(w6);
myTank1.collidesWithWall(w7);
myTank2.collidesWithTank(myTank1);
myTank1.collidesWithTank(myTank2);
for(inti=0;i Missilem=missiles.get(i); m.hitTank(myTank1); m.hitTank(myTank2); m.hitWall(w1); m.hitWall(w2); m.hitWall(w3); m.hitWall(w4); m.hitWall(w5); m.hitWall(w6); m.hitWall(w7); m.draw(g); } for(inti=0;i Explodee=explodes.get(i); e.draw(g); } myTank1.draw(g); myTank2.draw(g); w1.draw(g); w2.draw(g); w3.draw(g); w4.draw(g); w5.draw(g); w6.draw(g); w7.draw(g); if(myTank1.getLife()<40||myTank2.getLife()<40){ myTank1.eat(b); myTank2.eat(b); b.draw(g); } } //用update截住paint publicvoidupdate(Graphicsg){ if(offScreenImage==null){ offScreenImage=this.createImage(GAME_WIDTH,GAME_HEIGHT); } GraphicsgOffScreen=offScreenImage.getGraphics(); Colorc=gOffScreen.getColor(); gOffScreen.setColor(Color.black); gOffScreen.fillRect(0,0,GAME_WIDTH,GAME_HEIGHT); gOffScreen.setColor(c); paint(gOffScreen); g.drawImage(offScreenImage,0,0,null); } publicvoidlaunchFrame(){ this.setLocation(200,80); this.setSize(GAME_WIDTH,GAME_HEIGHT); this.setTitle("TankWar----WrittenBySmall_Light"); this.addWindowListener(newWindowAdapter(){ publicvoidwindowClosing(WindowEvente){ System.exit(0); } }); this.setBackground(Color.black); this.setResizable(false);//不可以调整窗口大小 this.addKeyListener(newKeyMonitor()); this.setVisible(true); newThread(newPaintThread()).start(); } //主函数 publicstaticvoidmain(String[]args){ TankClienttc=newTankClient(); tc.launchFrame(); } //多线程,画图 privateclassPaintThreadimplementsRunnable{ publicvoidrun(){ while(true){ repaint(); try{ Thread.sleep(40); }catch(InterruptedExceptione){ e.printStackTrace(); } } } 5.1.2信息传输TankNewMsg(TankMoveMsg和TankDeadMsg与此模块基本相同,暂不贴出了) 代码如下: /** *代表坦克诞生的消息类@authormashibing */ publicclassTankNewMsgimplementsMsg{ intmsgType=Msg.TANK_NEW_MSG; Tanktank; TankClienttc; /** *根据tank的信息构建消息 *@paramtank */ publicTankNewMsg(Tanktank){ this.tank=tank; } /** *根据消息产生的场所构建新的消息 *@paramtc */ publicTankNewMsg(TankClienttc){ this.tc=tc; } /** *发送相关的消息 *@paramds通过该socket发送数据 *@paramIP数据的目标IP *@paramudpPort数据的目标端口 */ publicvoidsend(DatagramSocketds,StringIP,intudpPort){ ByteArrayOutputStreambaos=newByteArrayOutputStream(); DataOutputStreamdos=newDataOutputStream(baos); try{ dos.writeInt(msgType); dos.writeInt(tank.id); dos.writeInt(tank.x); dos.writeInt(tank.y); dos.writeInt(tank.dir.ordinal()); dos.writeBoolean(tank.good); }catch(IOExceptione){ e.printStackTrace(); } byte[]buf=baos.toByteArray(); try{ DatagramPacketdp=newDatagramPacket(buf,buf.length, newInetSocketAddress(IP,udpPort)); ds.send(dp); }catch(SocketExceptione){ e.printStackTrace(); }catch(IOExceptione){ e.printStackTrace(); } } /** *分析接收到的消息数据 *@paramdis接收到的消息数据的输入流 */ publicvoidparse(DataInputStreamdis){ try{ intid=dis.readInt(); if(tc.myTank.id==id){ return; } intx=dis.readInt(); inty=dis.readInt(); Dirdir=Dir.values()[dis.readInt()]; booleangood=dis.readBoolean(); //System.out.println("id: "+id+"-x: "+x+"-y: "+y+"-dir: "+ //dir+"-good: "+good); booleanexist=false; for(inti=0;i Tankt=tc.tanks.get(i); if(t.id==id){ exist=true; break; } } if(! exist){ TankNewMsgtnMsg=newTankNewMsg(tc.myTank); tc.nc.send(tnMsg); Tankt=newTank(x,y,good,dir,tc); t.id=id; tc.tanks.add(t); } }catch(IOExceptione){ e.printStackTrace(); } } } 5.1.3爆炸explode 代码如下: publicvoiddraw(Graphicsg){ if(! live){ tc.explodes.remove(this); return; } Colorc=
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 计算机网络系统实践 计算机网络 系统 实践 报告 详解