NodeJS实现的一个多人同时在线移动鼠标的小游戏
NodeJS实现的一个多人同时在线移动鼠标的小游戏
最近因为项目需要,所以研究了一下nodejs的websocket实现,socket.io,这是nodejs后台应用websocket广泛使用的框架
准备工作
- 安装socket.io,使用命令
npm install socket.io
- windows系统的话,需要vc编译环境,因为安装
socket.io
的时候,会编译vc代码
游戏基本原理
-
服务器监听客户端的连接
-
客户端连接成功时候,绑定页面移动鼠标事件,事件里处理发送当前坐标给服务器
-
服务器保存一个全局的坐标对象,并以客户端唯一编号为键值
-
有新连接来的时候,把坐标广播给其它客户端
-
客户端断开连接的时候,服务端删除它的坐标信息,并广播给其它客户端
开始实现服务端代码
scoket.io建立服务器监听的时候,需要依赖一个http连接,用来处理升级协议用,所以也需要一个http模块,代码如下
var http = require('http'),
io = require('socket.io');
var app = http.createServer().listen(9091);
var ws = io.listen(app);
然后定义一个全局的坐标对象
var postions = {};
开始监听客户端的连接,并新增广播函数(其实可用socket.io自带的广播方法io.sockets.broadcast.emit),核心代码如下
ws.on('connection', function(client){
// 广播函数
var broadcast = function(msg, cl){
for(var k in ws.sockets.sockets){
if(ws.sockets.sockets.hasOwnProperty(k)){
if(ws.sockets.sockets[k] && ws.sockets.sockets[k].id != cl.id){
ws.sockets.sockets[k].emit('position.change', msg);
}
}
}
};
console.log('\033[92m有新的连接来:\033[39m', postions);
// 客户端连接成功之后,就发送其它客户端的坐标信息
client.emit('position.change', postions);
// 接收客户端发送消息
client.on('position.change', function(msg){
// 目前客户端的消息就只有坐标消息
postions[client.id] = msg;
// 把消息广播给其它所有的客户端
broadcast({
type: 'position',
postion: msg,
id: client.id
}, client);
});
// 接收客户端关闭连接消息
client.on('close', function(){
console.log('close!');
// 删除客户端,并通知其它客户端
delete postions[client.id];
// 把消息广播给其它所有的客户端
broadcast({
type: 'disconnect',
id: client.id
}, client);
});
// 断开连接
client.on('disconnect', function(){
console.log('disconnect!');
// 删除客户端,并通知其它客户端
delete postions[client.id];
// 把消息广播给其它所有的客户端
broadcast({
type: 'disconnect',
id: client.id
}, client);
})
// 定义客户端异常处理
client.on('error', function(err){
console.log('error->', err);
})
});
分析上面的代码,关键点在于
- 新的客户端连接成功,发送其它客户端的坐标信息
- 客户端更新坐标信息的时候,通知其它客户端
- 客户端断开连接,通知其它客户端
- 广播消息类型分为修改坐标与移除坐标
编写客户端html页面
由于socket.io
是自定义的框架,所以客户端需要引用socket.io.js,这个js可以从socket.io
模块里查找,路径一般为node_modules\socket.io\node_modules\socket.io-client\dist
,里面有合并与压缩两个版本,开发的时候可以用合并版.
完整代码如下
<!DOCTYPE html>
<html>
<head>
<title>socket.io 多人同时在线互动 例子</title>
<meta charset="utf-8">
</head>
<body>
<script type=“text/javascript” src=“socket.io.js”></script>
<script type=“text/javascript”>
var ws = io.connect(‘http://localhost:9091/’);
var isfirst;
ws.on('connect', function(){
console.log(ws);
// 开始绑定mousemove事件
document.onmousemove = function(ev){
if(ws.socket.transport.isOpen){
ws.emit('position.change', { x: ev.clientX, y: ev.clientY });
}
}
})
ws.on('position.change', function(data){
// 开始同时在线的别的客户端
if(!isfirst){
isfirst = true;
// 第一条消息是收到别个所有客户端的坐标
for(var i in data){
move(i, data[i]);
}
}else{
// 否则,要不就是别个断开连接的消息,或者别个更新坐标的消息
if('position' == data.type){
move(data.id, data.postion);
}else{
remove(data.id);
}
}
})
ws.on('error', function(){
console.log('error:', ws);
ws.disconnect();
})
function move(id, pos){
var ele = document.querySelector('#cursor_' + id);
if(!ele){
// 不存在,则创建
ele = document.createElement('img');
ele.id = 'cursor_' + id;
ele.src = 'img/cursor.png';
ele.style.position = 'absolute';
document.body.appendChild(ele);
}
ele.style.left = pos.x + 'px';
ele.style.top = pos.y + 'px';
}
function remove(id){
var ele = document.querySelector('#cursor_' + id);
ele.parentNode.removeChild(ele);
}
</script>
</body>
</html>
页面中的img/cursor.png
,可以这里找到,cursor.png,这里也有很多其它的鼠标图标,前端的原理比较简单,简单的分析如下
- 连接成功时,绑定页面mousemove事件,里面处理发送新坐标消息
- 收到消息根据消息类型,处理是修改其它客户端消息,还是移除其它客户端消息
- 定义添加其它客户端cursor图标与移除cursor图标
- 处理客户端异常消息,并添加断开连接,以让服务端移除坐标信息
运行例子
- 保存服务器代码为io_multigame.js
- 保存客户端代码为io_multigame.html
- 运行服务器代码
node io_multigame.js
- 打开多个
io_multigame.html
页面,即可看到效果
总结
写的比较随意,参考了了不起的nodejs
,这是一本好书,想了解nodejs
的朋友们,可以看看这本书。
NodeJS实现的一个多人同时在线移动鼠标的小游戏
最近因为项目需要,我研究了一下NodeJS的WebSocket实现。Socket.IO是一个广泛使用的框架,它使得WebSocket的使用变得简单。
准备工作
-
安装Socket.IO 使用以下命令安装:
npm install socket.io
-
Windows系统注意事项 Windows用户需要安装VC编译环境,因为安装Socket.IO时会编译一些VC代码。
游戏基本原理
- 服务器监听客户端连接
- 客户端连接成功时,绑定页面移动鼠标事件
- 服务器保存一个全局的坐标对象
- 有新连接来时,把坐标广播给其他客户端
- 客户端断开连接时,服务端删除其坐标信息,并广播给其他客户端
实现服务端代码
首先,我们需要一个HTTP服务器来处理WebSocket的升级协议:
var http = require('http');
var io = require('socket.io');
var app = http.createServer().listen(9091);
var ws = io.listen(app);
接着,定义一个全局的坐标对象:
var positions = {};
然后,开始监听客户端的连接:
ws.on('connection', function(client) {
// 广播函数
var broadcast = function(msg, cl) {
for (var k in ws.sockets.sockets) {
if (ws.sockets.sockets.hasOwnProperty(k)) {
if (ws.sockets.sockets[k] && ws.sockets.sockets[k].id !== cl.id) {
ws.sockets.sockets[k].emit('position.change', msg);
}
}
}
};
console.log('\033[92m有新的连接来:\033[39m', positions);
// 客户端连接成功后,发送其他客户端的坐标信息
client.emit('position.change', positions);
// 接收客户端发送的消息
client.on('position.change', function(msg) {
positions[client.id] = msg;
// 广播给其他所有客户端
broadcast({
type: 'position',
position: msg,
id: client.id
}, client);
});
// 接收客户端关闭连接的消息
client.on('close', function() {
console.log('close!');
delete positions[client.id];
broadcast({
type: 'disconnect',
id: client.id
}, client);
});
// 断开连接
client.on('disconnect', function() {
console.log('disconnect!');
delete positions[client.id];
broadcast({
type: 'disconnect',
id: client.id
}, client);
});
// 定义客户端异常处理
client.on('error', function(err) {
console.log('error->', err);
});
});
编写客户端HTML页面
客户端需要引用socket.io.js
文件,该文件位于node_modules/socket.io/node_modules/socket.io-client/dist
目录下。以下是完整的HTML代码:
<!DOCTYPE html>
<html>
<head>
<title>Socket.IO 多人同时在线互动 例子</title>
<meta charset="utf-8">
</head>
<body>
<script type="text/javascript" src="/socket.io/socket.io.js"></script>
<script type="text/javascript">
var ws = io.connect('http://localhost:9091/');
var isFirst;
ws.on('connect', function() {
console.log(ws);
// 开始绑定mousemove事件
document.onmousemove = function(ev) {
if (ws.socket.transport.isOpen) {
ws.emit('position.change', { x: ev.clientX, y: ev.clientY });
}
}
});
ws.on('position.change', function(data) {
if (!isFirst) {
isFirst = true;
// 第一条消息是收到其他所有客户端的坐标
for (var i in data) {
move(i, data[i]);
}
} else {
// 否则,要不就是其他断开连接的消息,或者其他更新坐标的消息
if ('position' === data.type) {
move(data.id, data.position);
} else {
remove(data.id);
}
}
});
ws.on('error', function() {
console.log('error:', ws);
ws.disconnect();
});
function move(id, pos) {
var ele = document.querySelector('#cursor_' + id);
if (!ele) {
// 不存在,则创建
ele = document.createElement('img');
ele.id = 'cursor_' + id;
ele.src = 'img/cursor.png';
ele.style.position = 'absolute';
document.body.appendChild(ele);
}
ele.style.left = pos.x + 'px';
ele.style.top = pos.y + 'px';
}
function remove(id) {
var ele = document.querySelector('#cursor_' + id);
ele.parentNode.removeChild(ele);
}
</script>
</body>
</html>
运行例子
- 保存服务器代码为
io_multigame.js
- 保存客户端代码为
io_multigame.html
- 运行服务器代码:
node io_multigame.js
- 打开多个
io_multigame.html
页面,即可看到效果。
总结
这个示例展示了如何使用NodeJS和Socket.IO实现一个简单的多人在线移动鼠标的小游戏。通过客户端的鼠标移动事件,将坐标发送到服务器,再由服务器广播给其他客户端,从而实现多人互动的效果。希望对大家有所帮助!
为了实现一个多人同时在线移动鼠标的小游戏,我们可以使用Node.js结合socket.io
来实现客户端和服务端之间的实时通信。下面是简化版的服务端和客户端代码,以实现这个功能。
服务端代码
// server.js
const http = require('http');
const io = require('socket.io');
const app = http.createServer().listen(9091);
const ws = io.listen(app);
let positions = {};
ws.on('connection', function(client) {
console.log('New connection:', client.id);
// 发送当前所有客户端的位置信息给新连接的客户端
client.emit('position.change', positions);
// 更新位置
client.on('position.change', function(pos) {
positions[client.id] = pos;
ws.emit('position.change', positions);
});
// 客户端断开连接
client.on('disconnect', function() {
console.log('Client disconnected:', client.id);
delete positions[client.id];
ws.emit('position.change', positions);
});
});
客户端HTML代码
<!-- index.html -->
<!DOCTYPE html>
<html>
<head>
<title>Socket.IO Mouse Game</title>
<meta charset="UTF-8">
<script src="/socket.io/socket.io.js"></script>
</head>
<body>
<img id="cursor" src="img/cursor.png" style="position:absolute;">
<script>
const ws = io.connect('http://localhost:9091');
ws.on('connect', () => {
console.log('Connected to server');
document.onmousemove = (ev) => {
ws.emit('position.change', { x: ev.clientX, y: ev.clientY });
};
});
ws.on('position.change', (data) => {
for (let id in data) {
if (id !== ws.id) {
const cursor = document.getElementById(`cursor_${id}`);
if (!cursor) {
const newCursor = document.createElement('img');
newCursor.id = `cursor_${id}`;
newCursor.src = 'img/cursor.png';
newCursor.style.position = 'absolute';
document.body.appendChild(newCursor);
}
const pos = data[id];
document.getElementById(`cursor_${id}`).style.left = `${pos.x}px`;
document.getElementById(`cursor_${id}`).style.top = `${pos.y}px`;
}
}
});
</script>
</body>
</html>
运行步骤
- 保存服务端代码到
server.js
。 - 保存客户端代码到
index.html
。 - 确保你的图片
img/cursor.png
在同一目录下。 - 在终端中运行
node server.js
启动服务器。 - 打开浏览器访问
http://localhost:9091/index.html
,并尝试在不同的窗口或标签页中打开它。
这样,当多个用户同时访问这个游戏时,他们的鼠标位置会在所有用户的屏幕上显示。