起因
因为沉迷跟对象玩qq小游戏,但是苦于每天看广告又不能跳过,所以我分析了一下小游戏的逻辑就准备自己写一个,最开始本来准备写一个webapp的,但是查询api后发现没有监听websocket事件的api,只能监听message,所以就准备做一个手机web了,技术栈使用vue+node.js(其实是自己只会用js和python,但是写python需要切换思路,就直接都用js了)
过程
使用node的websocket库——socket.io
var http = require('http');
var express = require('express');
var app = express();
var server = http.createServer(app)
var io = require('socket.io')(server);
var mysql = require('./mysql')
app.get('/', function (req, res) {
res.sendFile(__dirname + '/index.html');
});
let users = {}
io.on('connection', function (socket) {
console.log('user connected');
socket.on('login', (name) => {
console.log(users)
if (users[name]) {
socket.emit("repeat");
} else {
socket.name = name;
users[name] = {
name: name,
socket: socket,
};
socket.emit("loginSuccess");
UsersChange(name, true);
}
})
socket.on('new', () => {
io.sockets.emit("start")
})
socket.on('disconnect', () => {
if (socket.name && users[socket.name]) {
delete users[socket.name];
UsersChange(socket.name, false);
}
});
});
server.listen(3000, function () {
console.log('listening on *:3000');
});
function UsersChange(name, flag) {
io.sockets.emit("system", {
name: name,
size: Object.keys(users).length,
flag: flag
});
}
function nowSecond() {
return Math.floor(new Date() / 1000);
}
这里直接先把所有代码都放上来了,因为自己是一边写前端一边考虑后端逻辑处理问题,所以暂时写了这些,而且也考虑以后会不会多人玩我的游戏,所以改了好几遍(考虑要不要引入room),但是最后暂时先定两个人玩,所以就暂时写了这些代码,因为自己习惯最后写注释,所以先说一些重要的东西,当一个客户端连接服务端后会出现一个socket对象,其中有on和emit方法,分别对应监听和发送,同时服务端会给它们每一个客户端发一个socketid作为唯一标识,用来私聊,同时有io.sockets.emit()方法给所有连接的客户端发送信息,因为对战有等级和武器等级,所以我使用了login来方便接下来的一些逻辑处理,服务端代码还未完善
node操作mysql
var mysql = require('mysql')
var connection = mysql.createConnection({
host: xx,
user: xx,
password: xx,
database: xx
});
module.exports = {
//测试数据库连接
connectmsql: function () {
connection.connect((err) => {
if (err) throw err
console.log('连接成功')
});
},
//建表
newtable: function () {
connection.query('CREATE TABLE IF NOT EXISTS `gamebase` (`user` varchar(10) NOT NULL ,`userlevel` int(11) NOT NULL,`firstlevel` int(11) NOT NULL,`secondlevel` int(11) NOT NULL,`thirdlevel` int(11) NOT NULL,PRIMARY KEY (`user`))ENGINE=InnoDB DEFAULT CHARACTER SET=utf8', (error, results) => {
if (error) throw error
})
},
//创建新用户
insertdata: function (name) {
let insert = {
user: name,
userlevel: 1,
firstlevel: 1,
secondlevel: 1,
thirdlevel: 1
}
let sql = 'INSERT INTO gamebase SET ?'
connection.query(sql, insert, (error) => {
if (error) throw error
})
},
//实现升级
upgradedata: function (param, name) {
let upgrade = [param + 'level', name]
let sql = 'UPDATE gamebase SET ' + upgrade[0] + '=' + upgrade[0] + '+1 ' + 'WHERE user = ?'
connection.query(sql, upgrade[1], (error) => {
if (error) throw error
})
},
//异步获取数据库数据,promise封装
selectdata: function (name) {
let promise = new Promise(function (resolve, reject) {
let sql = 'SELECT * FROM gamebase WHERE user=?'
connection.query(sql, name, (error, results) => {
if (error) throw error
if (results) {
resolve(JSON.parse(JSON.stringify(results)))
}
})
})
return promise
}
}
这里值得注意的是node是异步处理,所以针对获取数据库数据,也就是“查”,它不能直接返回结果,有很多方法,比如著名的callback地狱,但是我使用了ES6的promise封装了对应的函数,这样我使用then的回调方法,就可以获取到数据了,而且要非常注意的是connection.query合并参数是参杂引号的,而js原生的合并字符串的方法("+")是会忽略字符串的引号的,在sql语句执行中是一个很大的大坑,有很多处理方法,我这里是使用了两种混合的写法
客户端构建
这里我使用的是封装好的vue-socket.io库,npm引入后使用如下方法挂载
import VueSocketIO from 'vue-socket.io'
Vue.use(new VueSocketIO({
debug: true,
connection: 'http://localhost:3000'
}))
而使用方法如下
export default {
name: 'Home',
components: {
HelloWorld
},
sockets:{
connect(){
console.log('连接成功')
}
}
}
总结
因为我还没有开始写客户端的代码,所以暂时只有这么多代码了,这是个短期或者是长期更的一个文章,之前的网站已经写好了,正在处理bug,等处理好后就部署上线啦,那个个人网站项目完结撒花★,°:.☆( ̄▽ ̄)/$:.°★ 。
Comments | NOTHING