项目地址:https://github.com/jrainlau/draw-something
下载 & 运行
git clone git@github.com:jrainlau/draw-something.git
cd draw-something && npm install
node ws-server.js // 开启websocket服务器
npm run dev // 运行客户端程序
然后浏览器打开localhost:8080即可
效果预览:
整体架构
因为闲得慌,一直和朋友在玩你画我猜之类的小游戏,突然想到能不能自己也做一个呢,反正闲着也是闲着,同时正好可以学习一下websocket的用法。
首先分析整体架构部分:
可以看到,整体架构非常简单,仅仅是一台服务器和两个客户端。
- WebSocket服务器:提供数据同步,内容分发功能,采用nodejs写成。
- 绘图画布:进行绘图的区域,同时能够获取关键词,其绘制的内容会同步到猜图画布中。
- 猜图画布:同步自绘图画布,输入框能够提交关键词,检测答案是否正确。
下面来看具体的代码实现。
WebSocket服务器
服务器采用node.js
进行搭建,使用了ws
库实现websocket功能。新建一个名为ws-socket.js
的文件,代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 |
/*** ws-socket.js ***/ 'use strict' // 实例化WebSocketServer对象,监听8090端口 const WebSocketServer = require('ws').Server , wss = new WebSocketServer({port: 8090}) // 定义关键词数组 let wordArr = ['Monkey', 'Dog', 'Bear', 'Flower', 'Girl'] wss.on('connection', (ws) => { console.log('connected.') // 随机获取一个关键词 let keyWord = ((arr) => { let num = Math.floor(Math.random()*arr.length) return arr[num] })(wordArr) // 当服务器接收到客户端传来的消息时 // 判断消息内容与关键词是否相等 // 同时向所有客户端派发消息 ws.on('message', (message) => { console.log('received: %s', message) if (message == keyWord) { console.log('correct') wss.clients.forEach((client) => { client.send('答对了!!') }) } else { console.log('wrong') wss.clients.forEach((client) => { client.send(message) }) } }) // 服务器初始化时即向客户端提供一个关键词 wss.clients.forEach((client) => { client.send('keyword:' + keyWord) }) }) |
使用方法基本按照ws
库的文档即可。其中ws.on('message', (message) => { .. })
方法会在接收到从客户端传来消息时执行,利用这个方法,我们可以从绘图画布不断地向服务器发送绘图位点的坐标,再通过.send()
方法把坐标分发出去,在猜图画布中获取坐标,实现绘图数据的同步。
客户端结构
作为客户端,我选择了vue
进行开发,原因是因为vue
使用简单快速。事先说明,本项目仅仅作为日常学习练手的项目而非vue的使用,所以有蛮多地方我是图方便暴力使用诸如document.getElementById()
之类的写法的,以后有机会再改成符合vue
审美的代码吧~
客户端结构如下:
1 2 3 4 5 6 7 8 9 10 11 |
| |-- script | |-- components | | |-- drawing-board.vue | | |-- showing-board.vue | | | |-- App.vue | | | |-- index.js | |-- index.html |
详细代码请直接浏览项目,这里仅对关键部分代码进行剖析。
绘图画布
位于./script/components/
的drawing-board.vue
文件即为绘图画布组件。首先我们定义一个Draw
类,里面是所有绘图相关的功能。