《计算机网络系统实践》报告基于Java的网络版坦克大战游戏设计.doc

上传人:仙人指路1688 文档编号:2387263 上传时间:2023-02-17 格式:DOC 页数:33 大小:529KB
返回 下载 相关 举报
《计算机网络系统实践》报告基于Java的网络版坦克大战游戏设计.doc_第1页
第1页 / 共33页
《计算机网络系统实践》报告基于Java的网络版坦克大战游戏设计.doc_第2页
第2页 / 共33页
《计算机网络系统实践》报告基于Java的网络版坦克大战游戏设计.doc_第3页
第3页 / 共33页
《计算机网络系统实践》报告基于Java的网络版坦克大战游戏设计.doc_第4页
第4页 / 共33页
《计算机网络系统实践》报告基于Java的网络版坦克大战游戏设计.doc_第5页
第5页 / 共33页
点击查看更多>>
资源描述

《《计算机网络系统实践》报告基于Java的网络版坦克大战游戏设计.doc》由会员分享,可在线阅读,更多相关《《计算机网络系统实践》报告基于Java的网络版坦克大战游戏设计.doc(33页珍藏版)》请在三一办公上搜索。

1、计算机网络系统实践报告设计题目:网络版小游戏坦克大战学生姓名:学 号: 专业班级:物联网工程12-1班2015年09月基于Java的网络版坦克大战游戏设计一、 设计要求1.1设计目的 (1)熟悉开发工具(JAVA)的基本操作; (2)掌握windows/Linux应用程序的编写过程; (3)对于Socket编程建立初步的概念。1.2设计要求 (1)熟悉Socket API 主要函数的使用; (2)掌握相应开发工具对Socket API 的封装; (3)设计并实现一对一网络版小游戏,如:Tic-Tac-Toe、五子棋等。 我选择了网络版坦克大战的设计。二、 开发环境与工具 2.1 编程语言:JA

2、VA Java 语言是一种跨平台,适合于分布式计算环境的面向对象编程语言。JAVA现在主要用在WEB开发,手机游戏及一些平台游戏的开发,因为它具有很好的跨平台性,在手机等各种电子产品上应用非常广泛。 2.2 运行环境:JDK1.6 2.3 开发工具:My Eclipse 10 MyEclipse,是在eclipse 基础上加上自己的插件开发而成的功能强大的企业级集成开发环境,主要用于Java、Java EE以及移动应用的开发。MyEclipse的功能非常强大,支持也十分广泛,尤其是对各种开源产品的支持相当不错。 2.4 网络建立:socket 网络上的两个程序通过一个双向的通信连接实现数据的交

3、换,这个连接的一端称为一个socket。 Socket的英文原义是“孔”或“插座”。作为BSD UNIX的进程通信机制,取后一种意思。通常也称作套接字,用于描述IP地址和端口,是一个通信链的句柄,可以用来实现不同虚拟机或不同计算机之间的通信。在Internet上的主机一般运行了多个服务软件,同时提供几种服务。每种服务都打开一个Socket,并绑定到一个端口上,不同的端口对应于不同的服务。Socket正如其英文原意那样,像一个多孔插座。一台主机犹如布满各种插座的房间,每个插座有一个编号,有的插座提供220伏交流电, 有的提供110伏交流电,有的则提供有线电视节目。 客户软件将插头插到不同编号的插

4、座,就可以得到不同的服务。三、 设计原理联机通信机制网络编程,简单地理解就是两台计算机相互通信。其基本模型就是客户机/服务器模型,也就是通信双方中的一方必须提供一个固定的位置,而另一方只需要知道这个固定的位置,并且建立两者之间的联系,然后完成数据交换。这里提供固定位置的一方通常称为服务器,而建立联系的一方称为客户端。Socket(中文意思为插座),基于客户机/服务器的Soctet通信模式如图3.1所示:创建Socket类的对象指定服务器端公认的Socket地址和端口在Socket上监听客户端的链接请求接收客户端的请求信息解释并处理请求信息向服务器发出请求向服务器端发送链接请求创建Socket类

5、对象客户端将处理结果返回给客户端接收服务结果服务请求服务响应服务器端图3.1 基于客户机/服务器的Soctet通信模式图当客户程序需要与服务器程序通讯的时候,客户程序在客户机创建一个socket对象,Socket类有几个构造函数。两个常用的构造函数是 Socket(InetAddress addr, int port) 和 Socket(String host, int port),两个构造函数都创建了一个基于Socket的连接服务器端流套接字的流套接字。两个函数都通过参数port获得服务器的端口号。假设已经建立连接了,网络API将在客户端基于Socket的流套接字中捆绑客户程序的IP地址和任

6、意一个端口号,否则两个函数都会抛出一个IOException对象。如果创建了一个Socket对象,那么它可能通过调用Socket的 getInputStream()方法从服务程序获得输入流读传送来的信息,也可能通过调用Socket的 getOutputStream()方法获得输出流来发送消息。在读写活动完成之后,客户程序调用close()方法关闭流和流套接字。四、系统功能描述及软件模块划分 4.1 系统功能描述 4.1.1单机版人机对战 A)玩家通过上、下、左、右键来控制坦克的八个方向:上、下、左、右、左上、右上、左下、右下; B)出现十个敌方坦克,自由运动并发射炮弹; C)玩家通过“cont

7、rol”键发射炮弹; D)打中敌方或被敌方打中,死亡; E)碰撞时死亡。 4.1.2网络对战模式 在人机在人机对战模式中实现功能基础上,增加以下功能实现网络对战功能: A)添加网络功能,使两台或者多台不同计算机的玩家通过一定的网络连接,加入到游戏中; B)能够自动分组选择阵营,一红一篮双方交替进入游戏,填写自己的游戏信息,各个玩家之间实现网络对战功能,并且同是一方的坦克不能相互攻击; C)玩家ID是自动分配的,采用递加的模式。 4.1.3总体功能设计坦克大战游戏主要实现玩家参加游戏的整个流程,整个网络版坦克大战游戏流程图如图4.1所示:初 始 化游戏模式单 机对 战产生敌方坦克玩家坦克判断胜负

8、玩家一玩家二玩家一玩家二敌方坦克我方坦克判断胜负结 束随机分配阵营图4.1 网络坦克大战游戏流程 4.2 软件模块划分 4.2.1TankClient类基本功能分析 TankClient类是整个系统的核心部分,它承担整个系统的所有可实现功能的调度工作。 是整个游戏运行的场所。TankClient类设计流程图如图4.2所示:开始初始化坦克对战双方玩家坦克由键盘控制移动发射炮弹碰撞检测(坦克和子弹)不处理同角色坦克产生爆炸不同角 色坦克判断胜负结束图4.2 TankClient类设计流程TankClient类是主类,通过调用其他类中封装的方法来使整个系统运行起来,下面显示TankClient与各个

9、类之间的关系如图4.3所示:TankClient类(主类)Tank类(我方)Tank类(敌方)New参数1New参数2调用Missile类打中调用Explode类产程爆炸判断胜负键盘控制移动键盘控制移动打击图4.3 游戏系统类关联图 4.2.2 Tank类基本功能分析 Tank类中,封装了一些变量属性,包括坦克自己的大小(WIDTH,HRIGHT),运动速度(SPRRD_X:在x轴方向的速度;SPEED_Y:在Y轴方向的速度)、生命值控制(life)、坦克编号(id)、坦克名(name)、方向控制(dir)、生死控制(live)等。Tank类中没有main函数,不是主类,它当中只封装一些变量属

10、性和静态方法,被TankClient类调用来实现坦克的一系列动作。Tank类中的主要方法罗列如下: (1)getRect()方法public Rectangle getRect() return new Rectangle(x, y, this.WIDTH, this.HEIGHT); Rectangle类是碰撞检测的辅助类,通过得到子弹的x,y坐标和宽高度,检测两个矩形是否碰撞(相交); (2)draw()方法:负责将所有的活动在屏幕上画出来; (3)move()方法:主要负责控制坦克的移动,包括8个方向(左,左上,上,右上,右,右下,下,左下)的控制以及给坦克一个移动的速度; (4)key

11、Pressed()方法:设定使用键盘的“”“”“”“”键控制坦克移动; (5)keyReleased()方法:处理按键抬起事件,抬起“CTRL”键时,发射炮弹并加入新炮弹,能够逐一发射每一发炮弹、抬起“A”键可以发射超级炮弹等功能; (6)locationDirection()方法:定义了炮筒方向,可以向八个方向发射炮弹; (7)fire()方法:处理发送子弹的方法; (8)bumpWithWall()方法:主要负责处理坦克撞墙事件; (9)bumpWithTank()方法:主要到负责处理坦克和坦克相撞事件; 4.2.3 Missile类基本功能分析 Misslile(子弹)类和Tank类一样

12、,只封装一些变量属性和静态方法,主要变量包括:子弹自己的大小(WIDTH,HRIGHT),运动速度(SPRRD_X:在x轴方向的速度;SPEED_Y:在Y轴方向的速度)、子弹标示(ID)、所属坦克的id号(TankId用于网络版)等。Misslie类持有一个TankClient类(大管家)的引用tc,TankClient类要执行发射炮弹操作时调用Missile类中的方法。Misslie类中的主要方法如下:(1) draw()方法:负责画出子弹的所有活动;(2) move()方法:先判断方向再移动,并给它一定的移动速度;(3) getRect()方法:负责取得子弹的外切方形,为碰撞检测做准备;(

13、4) hitTan()方法:检测子弹是否撞到坦克,若撞到返回true,否则返回false;(5) hitTanks()方法:检测是否撞到一系列坦克中的一个;(6) hitWall()方法:检测子弹和墙是否相撞。 4.2.4 Explode类基本功能分析Explode(爆炸)类也是一个只封装自己的变量和方法的外部包装类,没有main方法,供TankClient主类需要时调用它的draw()方法,当子弹击中坦克时需要产生爆炸。 4.2.5 服务器类基本功能分析TankServer(服务器)类主要负责在网络对战游戏时维护各个在线玩家的基本信息,并动态的维护玩家列表。联机模式下类关系图如图4.4所示:

14、TankServer类TankClient 1类类TankClient 2类类New参数1New参数2调用Missile类调用Explode类产程爆炸判断胜负Tank类(我方)Tank类(敌方)打中打击4.4 联机模式类关联图 4.2.6 信息传送类基本功能分析 信息传送类就是用来封装客户端和服务器端的交互信息。将网络中传递的众多信息封装成可序列化的类,将会使程序有很好的可扩展性。 五、设计步骤5.1 单机版的坦克大战游戏(人机对战) 5.1.1主程序:TankClient 代码如下:public class TankClient extends Frame private static fi

15、nal long serialVersionUID = 5865157849989504064L;public static final int GAME_WIDTH = 800;public static final int GAME_HEIGHT = 600;public static int SCORE = 0, 0, 0 ;Random r = new Random();Tank myTank1 = new Tank(750, 550, Tank.Direction.STOP, this, 1);Tank myTank2 = new Tank(50, 550, Tank.Directi

16、on.STOP, this, 2);Wall w1 = new Wall(200, 100, 200, 10, this);Wall w2 = new Wall(200, 100, 10, 200, this);Wall w3 = new Wall(200, 300, 200, 10, this);Wall w4 = new Wall(400, 300, 10, 200, this);Wall w5 = new Wall(200, 490, 200, 10, this);Wall w6 = new Wall(500, 100, 10, 400, this);Wall w7 = new Wall

17、(500, 490, 200, 10, this);Blood b = new Blood();List missiles = new ArrayList();List explodes = new ArrayList();Image offScreenImage = null;/ 定义背后的虚拟图片public void paint(Graphics g) / g.drawString(Missiles Count: + missiles.size(), 10, 50);/ g.drawString(Explodes Count: + explodes.size(), 10, 70);/ g

18、.drawString(Tanks Count: + tanks.size(), 10, 90);g.setColor(Color.orange);g.drawString(P1 P2, 10, 40);g.drawString(L C: 发射一枚普通的子弹。, 10, 60);g.drawString(K V: 九个方向的超级炮弹。, 10, 80);g.drawString(J B: 埋下一颗地雷等他踩., 10, 100);g.drawString(F2 F3: 购买一辆全新的坦克。, 10, 140);g.drawString(P1的剩余坦克数 : + myTank1.getLives

19、(), 600, 50);g.drawString(P2的剩余坦克数 : + myTank2.getLives(), 600, 70);g.drawString(P1的分数 : + SCORE1, 600, 90);g.drawString(P2的分数 : + SCORE2, 600, 110);g.drawString(剩余的坦克波数 : + Tank.win, 600, 130);myTank1.collidesWithWall(w1);myTank2.collidesWithWall(w2);myTank1.collidesWithWall(w3);myTank2.collidesWit

20、hWall(w4);myTank1.collidesWithWall(w5);myTank2.collidesWithWall(w6);myTank1.collidesWithWall(w7);myTank2.collidesWithTank(myTank1);myTank1.collidesWithTank(myTank2);for (int i = 0; i missiles.size(); i+) Missile m = missiles.get(i);m.hitTank(myTank1);m.hitTank(myTank2);m.hitWall(w1);m.hitWall(w2);m.

21、hitWall(w3);m.hitWall(w4);m.hitWall(w5);m.hitWall(w6);m.hitWall(w7);m.draw(g);for (int i = 0; i explodes.size(); i+) Explode e = 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.g

22、etLife() 40) myTank1.eat(b);myTank2.eat(b);b.draw(g);/ 用update截住paintpublic void update(Graphics g) if (offScreenImage = null) offScreenImage = this.createImage(GAME_WIDTH, GAME_HEIGHT);Graphics gOffScreen = offScreenImage.getGraphics();Color c = gOffScreen.getColor();gOffScreen.setColor(Color.black

23、);gOffScreen.fillRect(0, 0, GAME_WIDTH, GAME_HEIGHT);gOffScreen.setColor(c);paint(gOffScreen);g.drawImage(offScreenImage, 0, 0, null);public void launchFrame() this.setLocation(200, 80);this.setSize(GAME_WIDTH, GAME_HEIGHT);this.setTitle(TankWar-Written By Small_Light);this.addWindowListener(new Win

24、dowAdapter() public void windowClosing(WindowEvent e) System.exit(0););this.setBackground(Color.black);this.setResizable(false);/ 不可以调整窗口大小this.addKeyListener(new KeyMonitor();this.setVisible(true);new Thread(new PaintThread().start();/主函数public static void main(String args) TankClient tc = new Tank

25、Client();tc.launchFrame();/多线程,画图private class PaintThread implements Runnable public void run() while (true) repaint();try Thread.sleep(40); catch (InterruptedException e) e.printStackTrace(); 5.1.2 信息传输 TankNewMsg(TankMoveMsg和TankDeadMsg与此模块基本相同,暂不贴出了) 代码如下:/* * 代表坦克诞生的消息类 author mashibing */publi

26、c class TankNewMsg implements Msg int msgType = Msg.TANK_NEW_MSG;Tank tank;TankClient tc;/* * 根据tank的信息构建消息 * param tank */public TankNewMsg(Tank tank) this.tank = tank;/* * 根据消息产生的场所构建新的消息 * param tc */public TankNewMsg(TankClient tc) this.tc = tc;/* * 发送相关的消息 * param ds 通过该socket发送数据 * param IP 数据

27、的目标IP * param udpPort 数据的目标端口 */public void send(DatagramSocket ds, String IP, int udpPort) ByteArrayOutputStream baos = new ByteArrayOutputStream();DataOutputStream dos = new DataOutputStream(baos);try dos.writeInt(msgType);dos.writeInt(tank.id);dos.writeInt(tank.x);dos.writeInt(tank.y);dos.writeIn

28、t(tank.dir.ordinal();dos.writeBoolean(tank.good); catch (IOException e) e.printStackTrace();byte buf = baos.toByteArray();try DatagramPacket dp = new DatagramPacket(buf, buf.length,new InetSocketAddress(IP, udpPort);ds.send(dp); catch (SocketException e) e.printStackTrace(); catch (IOException e) e.

29、printStackTrace();/* * 分析接收到的消息数据 * param dis 接收到的消息数据的输入流 */public void parse(DataInputStream dis) try int id = dis.readInt();if (tc.myTank.id = id) return;int x = dis.readInt();int y = dis.readInt();Dir dir = Dir.values()dis.readInt();boolean good = dis.readBoolean();/ System.out.println(id: + id

30、+ -x: + x + -y: + y + -dir: +/ dir + -good: + good);boolean exist = false;for (int i = 0; i tc.tanks.size(); i+) Tank t = tc.tanks.get(i);if (t.id = id) exist = true;break;if (!exist) TankNewMsg tnMsg = new TankNewMsg(tc.myTank);tc.nc.send(tnMsg);Tank t = new Tank(x, y, good, dir, tc);t.id = id;tc.t

31、anks.add(t); catch (IOException e) e.printStackTrace(); 5.1.3爆炸explode 代码如下:public void draw(Graphics g) if(!live) tc.explodes.remove(this);return;Color c = g.getColor();g.setColor(Color.ORANGE);g.fillOval(x, y, diametersstep, diametersstep);g.setColor(c);step +;if(step = diameters.length) live = fa

32、lse;5.2 建立Server,建立Client并和Server连接 TankServer的代码如下:服务端程序 主要代码:public class TankServer private static int ID = 100;/* * TCP的监听端口 */public static final int TCP_PORT = 8888;/* * UDP的监听端口 */public static final int UDP_PORT = 6666;List clients = new ArrayList();/* * 启动服务器 */public void start() new Threa

33、d(new UDPThread().start();ServerSocket ss = null;try ss = new ServerSocket(TCP_PORT); catch (IOException e) e.printStackTrace();while (true) Socket s = null;try s = ss.accept();DataInputStream dis = new DataInputStream(s.getInputStream();String IP = s.getInetAddress().getHostAddress();int udpPort =

34、dis.readInt();Client c = new Client(IP, udpPort);clients.add(c);DataOutputStream dos = new DataOutputStream(s.getOutputStream();dos.writeInt(ID+);/ s.close();System.out.println(A Client Connect! Addr- + s.getInetAddress() + : + s.getPort()+ -UDP Port: + udpPort); catch (IOException e) e.printStackTr

35、ace(); finally if (s != null) try s.close();s = null; catch (IOException e) e.printStackTrace();public static void main(String args) new TankServer().start();private class Client String IP;int udpPort;public Client(String IP, int udpPort) this.IP = IP;this.udpPort = udpPort;private class UDPThread i

36、mplements Runnable byte buf = new byte1024;public void run() DatagramSocket ds = null;try ds = new DatagramSocket(UDP_PORT); catch (SocketException e) e.printStackTrace();System.out.println(UDP thread started at port : + UDP_PORT);while (ds != null) DatagramPacket dp = new DatagramPacket(buf, buf.le

37、ngth);try ds.receive(dp);for (int i = 0; i clients.size(); i+) Client c = clients.get(i);dp.setSocketAddress(new InetSocketAddress(c.IP,c.udpPort);ds.send(dp);System.out.println(a packet received!); catch (IOException e) e.printStackTrace();5.3客户端发送UDP端口,取得自己的ID号 (java.util.UUID) 服务器端保存客户端信息核心代码如下:p

38、ublic void connect(String IP, int port) this.IP = IP;try ds = new DatagramSocket(udpPort); catch (SocketException e) e.printStackTrace();Socket s = null;try s = new Socket(IP, port);DataOutputStream dos = new DataOutputStream(s.getOutputStream();dos.writeInt(udpPort);DataInputStream dis = new DataIn

39、putStream(s.getInputStream();int id = dis.readInt();tc.myTank.id = id;if (id % 2 = 0)tc.myTank.good = false;elsetc.myTank.good = true;TankNewMsg msg = new TankNewMsg(tc.myTank);send(msg);new Thread(new UDPRecvThread().start();/* * 发送消息 * param msg 待发送的消息 */public void send(Msg msg) msg.send(ds, IP,

40、TankServer.UDP_PORT);private class UDPRecvThread implements Runnable byte buf = new byte1024;public void run() while (ds != null) DatagramPacket dp = new DatagramPacket(buf, buf.length);try ds.receive(dp);parse(dp);System.out.println(a packet received from server!); catch (IOException e) e.printStackTrace();private void parse(DatagramPacket dp) ByteArrayInputStream bais = new ByteArrayInputStream(buf, 0, dp.getLength();DataInputStream dis = new DataInputStream(bais);int msgType = 0;try msgType = dis.readInt();

展开阅读全文
相关资源
猜你喜欢
相关搜索
资源标签

当前位置:首页 > 建筑/施工/环境 > 项目建议


备案号:宁ICP备20000045号-2

经营许可证:宁B2-20210002

宁公网安备 64010402000987号