vue+node.js使用socket.io实现对战小游戏(1)

发布于 2020-08-01  246 次阅读


起因

因为沉迷跟对象玩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,等处理好后就部署上线啦,那个个人网站项目完结撒花★,°:.☆( ̄▽ ̄)/$:.°★


浪子三唱,不唱悲歌