JAVASCRIPT开发HTML5游戏--斗地主(网络对战PART4)
继之前用游戏引擎(青瓷引擎)做了斗地主单机版游戏之后,这里分享下使用socket.io来实现网络对战,代码可已放到github上,在此谈谈自己整个的开发思路吧。

(点击图片进入游戏体验)
前文链接:
javascript开发HTML5游戏--斗地主(单机模式part1)
javascript开发HTML5游戏--斗地主(单机模式part2)
javascirpt开发HTML5游戏--斗地主(单机模式part3)
本文章为网络对战第一部分内容。主要内容如下:
- 简介
- 服务端项目搭建
- 客户端准备
- 桌位管理
- 游戏流程
一、简介
多人对战游戏,我用Nodejs做开发服务端,使用socket.io做通讯。整个斗地主游戏流程是一样的,只是单机版啥都要自己做,网络版更多交给服务器,自己主要就是游戏界面展示了,先看看整个服务器的大致结构:

服务器中用Nodejs的mysql模块做mysql数据库存储,这里并不是非常必要的,只是我尝试使用熟悉这个东西,这里我只是存了个uid在客户端浏览器缓存中,所以也不能真正达到持久化作用。如果要做持久化应该是要做个用户登陆了,这里引擎给我们提供了微信支持,后面优化完善可以考虑加入微信登陆来保存用户数据。
二、服务端项目搭建
对于Nodejs项目的搭建建,还是比较简单的,简单说明下项目搭建,在工作区下创建个目录landlordServer,作为项目目录。然后用命令行进入到该目录下,加入Nodejs的socket.io和mysql模块,命令如下:
npm install socket.io
npm install mysql
出于之前编写java服务端的习惯,我在项目目录下创建了src目录,用于放置代码。在src下创建server.js作为入口脚本,加入socket.io的端口监听,然后就可以用Nodejs来启动了。这样子我们的服务端也算是搭建完成了,相对java还真是简易,接下来就可以写逻辑代码了。由于用了Nodejs,小弟对这个也不算非常熟悉,不过它的模块化用起来感觉很像java类,一个文件一个类这样的形式,这个类需要什么就import进来,Nodejs是require,这样的话就不用去考虑脚本先后的问题。
三、客户端项目准备
客户端需要有socket.io.js的客户端文件,这个文件在服务端项目中 node_modules/socket.io-client /路径下,找到它并把它丢到客户端Scripts下就可以了,这里我是放到了Scripts/operation目录下,因为青瓷引擎也是基于Nodejs开发的,所以这里只要在Scripts也不需要声明其他什么引用即可使用。
四、桌位管理
桌位
在网络对战斗地主中,都是三个玩家一桌,这样的形式,有一些斗地主游戏还会把桌位合成再分为房间,再到大厅。我这里的实现只有桌位,一开始服务器启动是没有任何桌位的,有玩家进入创建桌位,后面的玩家进来就是进未满员的桌位,找不到再创建新桌位,如果有一个桌位玩家全部离开了,就把该桌位删除。这些事情都交给桌位管理器DeskMgr.js。我用的是一个desks对象来缓存座位信息,利用了js中对象可以是当成一个Map使用。socket.io还提供了一个分组功能,差不多是一个房间的概念,我把每一桌的玩家都加入到同一个分组中,这个分组的标识也就是这个桌位的桌位号,当然玩家退出的时候也要退出该分组。每个桌位有三个阶段:
- 等待阶段:这个阶段中等待玩家加入并全部准备
- 抢地主阶段:就抢地主
- 玩牌阶段:
座位
每个桌位上都需要有3个座位,这里不仅是方便统计,也是为了方便确认先后顺序。同时是用一个对象当做Map使用来存放三个座位,分别名为p1、p2、p3,这样顺序也就很容易确认,比如p1出了牌,轮到下家时,可以写个获取下家座位号的方法,然后得到p2,去通知p2出牌。
玩家
相比单机下的玩家信息,服务器上的玩家需要有其他属性:
- 桌位号:用于确定玩家在哪一桌;
- 座位号:用于确定玩家在哪一个座位;
- 是否准备:玩家是否处于准备状态;
- socketId:玩家连接的socket的id,在玩家初次加入到游戏的时候记录下来,方便需要单独给该玩家广播消息的时候用到;
- 状态:用于标记玩家是否离线
五、游戏流程
整个游戏流程跟单机模式是差不多的,只是网络对战是由服务器来做发牌、轮换等操作,相当三个人在斗地主,有一个助手替他们发牌,告诉他们轮到谁抢地主,轮到谁出牌,谁赢了,这样,细分下服务器做的操作如下:
准备阶段
玩家加入与退出:当有玩家加入的时候,服务器会返回给玩家的客户端他所在桌位的信息,还有该玩家得到的桌位号。这样在客户端就可以显示出整个桌位的信息了,其实就是显示左右边玩家的名字。除此之外,如果该桌位还有其他玩家,还需要给其他玩家广播有新玩家加入的消息。退出(点击退出、刷新、关闭页面)时如果该桌位还有其他玩家也需要进行广播通知。
玩家准备:每次玩家切换准备状态时判断玩家所在桌位是否有3个玩家准备了,符合条件就可以开始发牌了,这里都准备后就已经进入了抢地主阶段。发牌由服务器来进行,所以原有的发牌代码还需要搬一份到服务器上去,发完牌后分别通知给每一位玩家,给玩家对应的手牌信息,还要随机生成哪一位座位号玩家先开始抢地主,这样客户端收到开始游戏信息后就播放发牌动画,播放完毕后如果是自己先开始抢地主就显示抢地主操作的按钮。
抢地主阶段
抢地主:玩家叫分后将数据(主要是玩家叫的分数和玩家信息)发给服务器,服务器处理后,将当前叫分交给下一家,广播给当前桌位所有玩家,通知他们上一家叫分多少,还有现在轮到谁叫分抢地主了。这样的客户端就可以显示相应信息,每个玩家根据自己的座位号显示上家叫分和当前叫分,是自己就显示叫分的操作按钮。确定地主后再发生底牌信息给每个玩家,客户端接收到消息后将底牌显示出来。
退出/断线:在这个阶段退出的话我做的处理是直接结束游戏回到准备阶段。因为地主还没有确定,也无法进行出牌,直接结束是比较好的做法,再让AI帮离线玩家叫分也是可以的,这就看开发者想怎么做了,对于离开的玩家也可以进行减分处罚。
出牌阶段
玩家出牌:出牌阶段的轮换跟逻辑抢地主差不多,主要是在客户端渲染会有所差异。玩家将出的牌发给服务器,服务器判断玩家出牌后是否还有手牌,有就继续下家出牌,没有就判定该玩家胜利。这跟单机版逻辑都是一样的,只是这里服务器来做控制了。
退出/断线:在出牌阶段退出后,只有该桌位还有在线玩家,游戏就不会结束,离开的玩家会有AI代为出牌。为了让断线玩家会有回来的时间,AI第一次出牌会延迟出牌,这个使用定时器很容易实现。等玩家重连之后如果这个计时器还没执行再去把这个计时器取消了。
断线重连:这个问题一开始我比较没思路,自己想了个方法实现,不知道算不算好的。实现思路:在出牌阶段,有玩家离开了,就将这个玩家加入到一个离线列表中。当有玩家加入游戏后,不再是直接分配桌位,而是先去查离线列表,如果找到了,就进到原来的桌位,没有找到再去匹配桌位。这样找到了桌位信息,就可以在客户端显示当前游戏的状况。玩家要是直到游戏结束都没有重连,游戏结束时将本桌离线的玩家从离线列表删除。或者一桌玩家都离线了,那就全部都从离线列表删除。
游戏结束
有玩家完牌后,服务器给所有玩家广播有人游戏结束,发送计算完后的玩家分数、没出完玩家的手牌信息以及胜利玩家最后出的一手牌,该桌位回到准备阶段。客户端我的处理是先显示剩下手牌,最后一手牌等信息,添加个定时器,3秒后游戏界面才渲染成准备阶段状态。
遇到的问题
我在开发过程中,遇到过个问题,控制台一直提示死循环,在报错的地方查了好久,也没发现异样。后面跟进socket.io源码才发现,是当我要发送给客户端的数据中,有一个循环引用的问题,其实在我里面有个对象存着计时器,这样将这个数据对象转换成json时,转换代码就会陷入死循环。这个问题虽然不大,我也知道这种情况会引起转换异常,但是不容易发现,一开始没有引起我的注意,在此记录下。网络对战的斗地主就介绍到这里,有需要改进望提出,互相学习。
JAVASCRIPT开发HTML5游戏--斗地主(网络对战PART4)的更多相关文章
- javascript开发HTML5游戏--斗地主(单机模式part3)
最近学习使用了一款HTML5游戏引擎(青瓷引擎),并用它尝试做了一个斗地主的游戏,简单实现了单机对战和网络对战,代码可已放到github上,在此谈谈自己如何通过引擎来开发这款游戏的. 客户端代码 服务 ...
- javascript开发HTML5游戏--斗地主(单机模式part2)
最近学习使用了一款HTML5游戏引擎(青瓷引擎),并用它尝试做了一个斗地主的游戏,简单实现了单机对战和网络对战,代码可已放到github上,在此谈谈自己如何通过引擎来开发这款游戏的. 客户端代码 服务 ...
- javascript开发HTML5游戏--斗地主(单机模式part1)
最近学习使用了一款HTML5游戏引擎(青瓷引擎),并用它尝试做了一个斗地主的游戏,简单实现了单机对战和网络对战,代码可已放到github上,在此谈谈自己如何通过引擎来开发这款游戏的. 客户端代码 ...
- 青瓷引擎之纯JavaScript打造HTML5游戏第二弹——《跳跃的方块》Part 10(排行榜界面&界面管理)
继上一次介绍了<神奇的六边形>的完整游戏开发流程后(可点击这里查看),这次将为大家介绍另外一款魔性游戏<跳跃的方块>的完整开发流程. (点击图片可进入游戏体验) 因内容太多,为 ...
- HTML5外包注意事项-开发HTML5游戏的九大坑与解决方法剖析
随着移动社区兴起,势必带动HTML5的革命.未来一两年内,HTML5移动游戏必将呈现大爆发趋势. 以下是整理的HTML5游戏研发.市场趋势以及渠道布局和技术解决方案的内容.希望大家能从本文中找到对HT ...
- JS开发HTML5游戏《神奇的六边形》(一)
近期出现一款魔性的消除类HTML5游戏<神奇的六边形>,今天我们一起来看看如何通过开源免费的青瓷引擎(www.zuoyouxi.com)来实现这款游戏. (点击图片可进入游戏体验) 因内容 ...
- JS开发HTML5游戏《神奇的六边形》(二)
近期出现一款魔性的消除类HTML5游戏<神奇的六边形>,今天我们一起来看看如何通过开源免费的青瓷引擎(www.zuoyouxi.com)来实现这款游戏. (点击图片可进入游戏体验) 因内容 ...
- JS开发HTML5游戏《神奇的六边形》(四)
近期出现一款魔性的消除类HTML5游戏<神奇的六边形>,今天我们一起来看看如何通过开源免费的青瓷引擎(www.zuoyouxi.com)来实现这款游戏. (点击图片可进入游戏体验) 因内容 ...
- JS开发HTML5游戏《神奇的六边形》(三)
近期出现一款魔性的消除类HTML5游戏<神奇的六边形>,今天我们一起来看看如何通过开源免费的青瓷引擎(www.zuoyouxi.com)来实现这款游戏. (点击图片可进入游戏体验) 因内容 ...
随机推荐
- 微信小程序——2、配置json文件
配置文件详解 主配置文件app.json 主配置文件位于主目录中,用于进行全局配置.包括页面文件的路径.窗口表现.设置网络超时时间.设置多tab等 下面通过微信最初自带小程序来学习 { "p ...
- TI 实时操作系统SYS/BIOS使用总结
1:概述: SYS/BIOS 是一个可扩展的实时的操作系统.具有非常快速的响应时间(在中断和任务切换时达到较短的延迟),响应时间的确定性,强壮的抢占系统,优化的内存分配和堆栈管理(尽量少的消耗和碎片) ...
- noip 邮票面值设计 - 搜索 - 动态规划
描述 给定一个信封,最多只允许粘贴N张邮票,计算在给定M(N+M<=10)种邮票的情况下(假定所有的邮票数量都足够),如何设计邮票的面值,能得到最大max ,使得1-max之间的每一个邮资值都能 ...
- 使用PopupWindow弹窗提醒
一.新建view.xml 注意里面的控件要一个一个的定义离上一个控件的距离,即margin_top,不然最后的效果是紧缩的 二.在java中定义两个变量 1.View view=null: 2.pop ...
- Python3基础 json.loads 解析json格式的数据,得到一个字典
Python : 3.7.0 OS : Ubuntu 18.04.1 LTS IDE : PyCharm 2018.2.4 Conda ...
- ubuntu下交叉编译imagemagick
环境:ubuntu16.04 交叉编译器版本号:4.8.3 在编译之前要编译以下其依赖的软件或库:freetype,libpng,libxml2,libtiff,libjpeg,zlib,graphv ...
- 移动距离|2015年蓝桥杯B组题解析第八题-fishers
移动距离 X星球居民小区的楼房全是一样的,并且按矩阵样式排列.其楼房的编号为1,2,3... 当排满一行时,从下一行相邻的楼往反方向排号. 比如:当小区排号宽度为6时,开始情形如下: 1 2 3 4 ...
- 常见几种校验方法(CS和校验、CRC16、CRC32、BCC异或校验)
总结一些通讯协议中常用到的几种校验方法: 1.CS和校验(如:标准188协议校验方式) /// <summary> /// CS和校验 /// </summary> /// & ...
- 论文笔记——ThiNet: A Filter Level Pruning Method for Deep Neural Network Compreesion
论文地址:https://arxiv.org/abs/1707.06342 主要思想 选择一个channel的子集,然后让通过样本以后得到的误差最小(最小二乘),将裁剪问题转换成了优化问题. 这篇论文 ...
- js键盘按钮keyCode及示例大全
以功能区分布 以 keycode 编号顺序分布 keycode 0 = keycode 1 = keycode 2 = keycode 3 = keycode 4 = keycode 5 = keyc ...