缘起
大概是大三暑假的时候吧,当时突然想起自己童年玩的一款棋类游戏,网上搜了搜也没有可以在线对战的,恰巧当时会一点前端的知识,于是就想着当个项目刚好练练手吧。小时候一般会和小伙伴,找来石头当狼,杏核当羊,然后在院子里用粉笔画上棋盘,就开始大战了。当时也没有手机拍照,在网上找到一张图,大家想象下吧,哈哈。
应该是很久之前流传下来的游戏了,但现在应该也不会有人再玩了,还是很可惜的。至于为什么突然想起说这个事,因为下周六要去字节跳动面试前端了,竟然要面临人生的第一次找工作了,没啥经验,这几天就多整理整理知识点吧。
行动
说实话当时对前端真的就只是了解的程度(虽然现在也是),也没做过什么项目,但是我们可以面向谷歌/github 编程呀。
第一步就先做一个单机版的狼吃羊吧,怎么做呢,怎么画棋呢?怎么控制走动呢。于是找到了中国象棋的 js 实现。
然后只需要解决三件事。
怎么响应用户对棋子的点击?
开始自己的想法是根据坐标判断点击是不是在某个矩形区域内。参考上边的 github ,学到了一个更简单粗暴的方法,每个棋子用图片表示,然后每个图片添加响应事件即可。
根据什么显示棋子位置?
直接用一个二维数组,1 代表显示图片,0 代表不显示即可。
怎么制定棋走的规则?
简单粗暴些,由于狼吃羊只有两种角色,棋盘的位置点也不多。直接根据每个点写它具体的规则即可。当时就是为了快点写出来,麻不麻烦也没考虑,有时候无脑暴力真的是最省脑子的方法,关键它还有用。
毕竟是快两年前的事情了,印象深的就是上边的了,然后就是一些细节的东西了,边调边改吧,自己就开始写了,一点一点最后完成了单机版的。也就是只能两个人在一台手机上玩。当然这个时代,大家更喜欢联网一起玩游戏。
WebSocket 初见
网上对战的棋类游戏, 这怎么做呀?网上找的 js 棋类都是单机的,这可怎么办呀,ctrl + C , ctrl + V 大法不好使了呀?
这可不行,让我思考一下,两个人互相下棋,我们只需要互相传一下自己走棋的位置,就传一个坐标即可。这么简单的数据,怎么传呢?大一暑假写 MFC 的时候用过 socket,但这是 JS 呀,咋办嘞。
传数据,互相传数据,聊天室呀!我要是学会了聊天室传数据,这狼吃羊改改不就行了,于是,嘿嘿嘿,又被我找到了一个项目。
太多了,找到了一个符合自己的,然后就是学起来了。于是就了解到了 websocket 和 node.js。
WebSocket 探究
前端数据的传输我们都用的 HTTP 协议,HTTP 协议的一个特征就是,客户端向服务端情况数据,服务端返回数据给客户端。也就是客户端不问,服务端并不会理会客户端。
那么我们的聊天室用 HTTP 协议怎么实现呢?我打开聊天框,我怎么知道啥时候会有消息过来,我总不能不停的去问服务端吧!
传统轮训(Traditional Polling)
bingo!你说出了一种解决方案,传统轮训(Traditional Polling),用一个定时器,每隔一段时间就像服务器请求一下。
1 | setInterval(function() { |
但。。。太不优雅了吧,万一服务器 10 分钟都没消息,那我每隔 10 秒访问一次,也太浪费时间了吧。于是,又诞生了一种方案。
长轮训(Long Polling)
长轮训(Long Polling),客户端向服务器查询数据,服务器如果没有新数据,之前的话就立刻告诉客户端我没有新数据。而现在的话,服务器端保持这个连接,然后有了新数据以后再传回给客户端。然后客户端收到数据,再次向服务端要数据,服务端有数据的话就给客户端,没有的话就保持住连接直到有了,然后重复上边的过程。
聊天室似乎可以实现了,早期的 web QQ 大概就是这种策略吧。但是,现在还是客户端请求,服务端才给回复,服务端能不能主动点,有了消息直接发给客户端,非得等客服端去要吗?有方法的!
WebSocket
我们的主角出现了,是他,就是他,实现了客户端和服务端互相主动发送数据,服务端终于主动了起来。
首先 WebSoket 通过 HTTP 协议建立连接,然后就可以互相发数据了,底层用的 TCP。那么干脆让我们看一下,聊天室怎么实现吗,当然直接贴别人的代码吧,哈哈。
协议只是一些规范,我们还需要去实现它,怎么实现 WebSocket 呢?本着不重复造轮子(自己也实现不了呀)的原则,我们直接用别人的库吧,socket.io ,已经帮我们实现好了,我们根据它提供的 API 用就好了。还有一个好处是这个库还兼容不支持 Websocket 的浏览器,自动改成长轮训或者其他算法。直接把 socket.io 官网给的例子贴过来。
客户端 index.html
1 |
|
就不用服务器跑了,所以建立连接的时候,上边写的是 127.0.0.1。然后把本地当作服务器端,看下服务器段的代码。
服务端 index.js
1 | var app = require('express')(); |
即使没有学过他的 API,也差不多可以看懂吧。是事件驱动的,on 监听事件,emit 发送事件,这样就完成了服务器端和客户端的互相交流信息。
咦,等一下,服务器端怎么跑程序呀,js 不是运行在浏览器里吗?这就得靠 node.js 了。有了它,我们再也不需要把 js 只跑到浏览器中了,因此 js 的领域从前端也扩展到了后端,真的是万事皆可 js。
看一下效果吧。
首先把 index.js 跑起来,监听客服端的请求。
然后浏览器打开两个聊天页面。
在第一个页面发送消息。
打开第二个页面,会发现收到了第一个页面的消息。
完结,撒花。完结,撒花。等等等等等!我们不是做聊天室,我们是要做狼吃羊。对不起,有点激动。
我们理一下,现在已经可以互相传东西了,那么我们只需要一台服务器做中转,A 和 B 对战。A 把消息传给服务器,服务器转给 B。B 把消息传给服务器,服务器转给 A。思想有了,然后就是看一看 socket.io 的 API,用起来就可以了。不过一些创建房间,记录对方的 id 的一些逻辑还是挺烧脑的。
再探 web Socket
监测下网络,让我们看一下 web Socket 到底怎么连接的。
看到了一个 websocket 类型的,让我们看下细节。
值得注意的是,建立连接使用的是 HTTP 协议,状态码是 101,第一次遇到。然后就是 WebSocket 一些相关的字段,目的就是试探对方是否支持 WebSocket,试探成功的话,双方就会建立长连接,就可以互相发送消息了。
结束
就这样,地球上第一款 Web 大型棋类益智对战游戏「狼吃羊」诞生了!在线试玩地址:http://game.windliang.cc,用手机打开,PC 端没有适配。当然,界面和图标的设计还得感谢下女朋友,哈哈哈哈哈。