在页游时代,大部分游戏都是通过socket来实现玩家之间的实时通信互动的,在H5时代,利用websocket,我们也同样可以达到这个目的,并且目前websocket的浏览器兼容度已经很高,下面记录一下基于socket.io库来实现H5画板功能的过程,非常的简单方便。
socket.io
socket.io是一个基于Node.js的websocket库,可以方便快捷地在web端建立socket通信。
安装
npm install socket.io
启动服务器
安装好socket.io后,我们建立app.js(服务器的入口程序),添加如下代码:
var app = require('http').createServer(handler)
var io = require('socket.io')(app);
var fs = require('fs');
// socket端口
app.listen(8080);
// 处理请求
function handler(req, res) {
res.writeHead(200);
res.end('Hello World2\n');
}
// 客户端连接的事件处理函数
io.on('connection', function(socket) {
// todo...
});
上面简单的几行代码已经建立了一个socket服务器,并且能处理客户端的连接与收发消息。
建立客户端连接
// 连接socket
var socket = io('http://localhost');
// 监听画图消息
socket.on('draw-event', function(data) {
console.log(data);
// 处理画图消息
if (data.type == 'start') {
onTouchStart(data.x, data.y);
} else if (data.type == 'move') {
onTouchMove(data.x, data.y);
}
});
房间
在同一个房间里的所有用户可以很方便的管理和传递消息,默认情况下,socket.io都是为每个用户创建一间房间,并且房间id存在socket.id属性中。我们在第一个用户进入时取到房间号,然后通过二维码方式让后面的用户扫码,后面的用户通过扫码进入时加入到指定的房间。
前端逻辑:
socket.on('connect', function() {
// 判断是通过扫码进入房间还是房主
if (isHost) {
// 生成二维码
new QRCode(document.getElementById("qrcode"), url + '?r=' + socket.id);
console.log('url', url + '?r=' + socket.id)
} else {
// 发消息给服务器加入房间
socket.emit('sys', {
type: 'join',
roomId: params.r
});
}
});
上面的代码用到了QRCode.js这个前端库生成代码。
后端逻辑:
// 处理系统消息
socket.on('sys', function(data) {
console.log(data);
if (data.type == 'join') {
// 猜的一方进入房间
console.log(socket.id + ' join room: ' + data.roomId);
socket.join(data.roomId);
// 通知房间其它用户
io.in(data.roomId).emit('sys', { type: 'join', roomId: data.roomId });
}
});
画图消息
画图是用canvas的绘图实现的,核心部分代码:
// 笔触移动
$('#canvas').on('touchmove', function(event) {
touch = event.touches[0];
render();
// 发送到后端
socket.emit('draw-event', {
type: 'move',
x: touch.pageX,
y: touch.pageY,
});
}).on('touchstart', function(event) { // 点击屏幕
event.preventDefault();
touch = event.touches[0];
onTouchStart(touch.pageX, touch.pageY);
isTouched = true;
// 发送到后端
socket.emit('draw-event', {
type: 'start',
x: touch.pageX,
y: touch.pageY,
});
}).on('touchend', function(event) { // 离开屏幕
event.preventDefault();
isTouched = false;
touch = null;
});
...
var render = function() {
onTouchMove(touch.pageX, touch.pageY);
};
var onTouchStart = function(x, y) {
context.moveTo(x - canvasOffset.left, y - canvasOffset.top);
};
var onTouchMove = function(x, y) {
context.lineTo(x, y);
context.stroke();
context.moveTo(x - canvasOffset.left, y - canvasOffset.top);
console.log(x, y)
};
后端转发消息给另外的客户端:
socket.on('draw-event', function(data) {
console.log(data);
// 转发画图消息
socket.to(roomId).emit('draw-event', data);
});
接收方处理消息:
socket.on('draw-event', function(data) {
console.log(data);
if (data.type == 'start') {
onTouchStart(data.x, data.y);
} else if (data.type == 'move') {
onTouchMove(data.x, data.y);
}
});
结语
至此,一个简单的通过websocket进行实时通信交互的例子实现了,我们通过扩展细节,可以做成我画你猜的画图游戏,也可以发挥创造力做出更多好玩的交互。