【基于Cocos Creator+Socket.io的联机对战黑白棋(4)】——资源文件

scripts下的super和cell文件夹可以换成controller和model

socket.io插件本地不用导入,但是1.32有bug打包到web平台没有打包原生的socket.io,所以我自己加了一个socket.io

客户端
https://github.com/potato47/reversi-online
服务端
https://github.com/potato47/reversi-online-server


所有代码

Global.js

window.G = {
    globalSocket:null,//全局
    hallSocket:null,//大厅
    queueSocket:null,//队列
    roomSocket:null,//房间
    gameManager:null,
    chessManager:null,
    stand:null,
}

Constants.js

const STAND = cc.Enum({
    BLACK: 47,
    WHITE: -47
});

const CHESS_TYPE = cc.Enum({
    NONE: -1,
    BLACK: 47,
    WHITE: -47
});

const GAME_STATE = cc.Enum({
    PREPARE: -1,
    PLAYING: -1,
    OVER: -1
});

const DIR = cc.Enum({
    LEFT:-1,
    LEFT_UP:-1,
    UP:-1,
    RIGHT_UP:-1,
    RIGHT:-1,
    RIGHT_DOWN:-1,
    DOWN:-1,
    LEFT_DOWN:-1
});

module.exports = {
    STAND:STAND,
    CHESS_TYPE:CHESS_TYPE,
    GAME_STATE:GAME_STATE,
    DIR:DIR
};

MenuManager.js

这里写代码片cc.Class({
    extends: cc.Component,

    onLoad: function () {
        G.globalSocket = io.connect('127.0.0.1:4747');
        //断开连接后再重新连接需要加上{'force new connection': true}
        G.hallSocket = io.connect('127.0.0.1:4747/hall',{'force new connection': true});
    },

    onBtnStart() {
        G.hallSocket.disconnect();
        cc.director.loadScene('match');
    }
});

MatchManager.js

const Constants = require('Constants');
const STAND = Constants.STAND;
cc.Class({
    extends: cc.Component,

    onLoad: function () {
        G.queueSocket = io.connect('127.0.0.1:4747/queue', { 'force new connection': true });
        G.queueSocket.on('set stand', function (stand) {
            if (stand === 'black') {
                G.stand = STAND.BLACK;
            } else if (stand === 'white') {
                G.stand = STAND.WHITE;
            }
        });
        G.queueSocket.on('match success', function (roomId) {
            cc.log('match success' + roomId);
            G.roomSocket = io.connect('127.0.0.1:4747/rooms' + roomId, { 'force new connection': true });
            G.queueSocket.disconnect();
            cc.director.loadScene('game');
        });
    },

    onBtnCancel() {
        G.queueSocket.disconnect();
        cc.director.loadScene('menu');
    }
});

GameManager.js

const Constants = require('Constants');
const GAME_STATE = Constants.GAME_STATE;
const STAND = Constants.STAND;
const CHESS_TYPE = Constants.CHESS_TYPE;
cc.Class({
    extends: cc.Component,

    properties: {
        gameState: {
            default: GAME_STATE.PREPARE,
            type: GAME_STATE
        },
        turn: {
            default: STAND.BLACK,
            type: STAND
        },
        blackScoreLabel: cc.Label,
        whiteScoreLabel: cc.Label,
        infoPanel: cc.Node,
        infoLabel: cc.Label
    },

    // use this for initialization
    onLoad: function () {
        G.gameManager = this;
        this.infoAnimation = this.infoPanel.getComponent(cc.Animation);
    },

    startGame() {
        this.turn = STAND.BLACK;
        this.gameState = GAME_STATE.PLAYING;
        this.showInfo('start game');
    },

    endGame() {
        let onFinished = () =>{
            G.roomSocket.disconnect();
            cc.director.loadScene('menu');
        }
        this.infoAnimation.on('finished',onFinished,this);
        this.gameState = GAME_STATE.OVER;
        this.showInfo('game over');
    },

    changeTurn() {
        if (this.turn === STAND.BLACK) {
            this.turn = STAND.WHITE;
        } else if (this.turn === STAND.WHITE) {
            this.turn = STAND.BLACK;
        }
    },

    forceChangeTurn() {//无子可下换边
        this.showInfo('force change turn');
        this.changeTurn();
    },

    updateScore() {
        let chessCount = G.chessManager.getChessCount();
        let blackChess = chessCount[0];
        let whiteChess = chessCount[1];
        this.blackScoreLabel.string = blackChess + '';
        this.whiteScoreLabel.string = whiteChess + '';
    },

    showInfo(type) {
        let chessCount = G.chessManager.getChessCount();
        let blackChess = chessCount[0];
        let whiteChess = chessCount[1];
        if (type === 'start game') {
            if (G.stand === STAND.BLACK) {
                this.infoLabel.string = '你是蓝色方\n执黑棋先手';
            } else if (G.stand === STAND.WHITE) {
                this.infoLabel.string = '你是红色方\n执白棋后手';
            }
        } else if (type === 'game over') {
            if (blackChess > whiteChess) {
                this.infoLabel.string = '游戏结束\n黑棋胜';
            } else if (blackChess < whiteChess) {
                this.infoLabel.string = '游戏结束\n白棋胜';
            } else if (blackChess === whiteChess) {
                this.infoLabel.string = '游戏结束\n平局';
            }
        } else if (type === 'force change turn') {
            if (G.stand === STAND.BLACK) {
                this.infoLabel.string = '黑方无子可下\n请白方下子';
            } else if (G.stand === STAND.WHITE) {
                this.infoLabel.string = '白方无子可下\n请黑方下子';
            }
        }
        this.infoAnimation.play();
    }

});

ChessManager.js

const Constants = require('Constants');
const CHESS_TYPE = Constants.CHESS_TYPE;
const STAND = Constants.STAND;
const GAME_STATE = Constants.GAME_STATE;
cc.Class({
    extends: cc.Component,

    properties: {
        COL: 8,
        ROW: 8,
        chessPrefab: cc.Prefab,
        chesses: []
    },

    // use this for initialization
    onLoad: function () {
        G.chessManager = this;
        this.chessWidth = this.node.width / this.COL;
        for (let x = 0; x < this.COL; x++) {
            this.chesses[x] = [];
            for (let y = 0; y < this.ROW; y++) {
                let chessNode = cc.instantiate(this.chessPrefab);
                chessNode.parent = this.node;
                chessNode.width = this.chessWidth - 5;
                chessNode.height = this.chessWidth - 5;
                chessNode.position = cc.p(this.chessWidth / 2 + x * this.chessWidth, this.chessWidth / 2 + y * this.chessWidth);
                let chess = chessNode.getComponent('Chess');
                chess.coor = cc.p(x, y);
                this.chesses[x][y] = chess;
                this.addTouchEvent(chess);
            }
        }
        this.chesses[3][3].type = CHESS_TYPE.BLACK;
        this.chesses[3][4].type = CHESS_TYPE.WHITE;
        this.chesses[4][4].type = CHESS_TYPE.BLACK;
        this.chesses[4][3].type = CHESS_TYPE.WHITE;
        G.gameManager.startGame();
        let self = this;
        G.roomSocket.on('update chessboard', function (chessCoor) {
            self.fallChess(self.chesses[chessCoor.x][chessCoor.y]);
        });
        G.roomSocket.on('change turn', function () {
            G.gameManager.changeTurn();
        });
        G.roomSocket.on('force change turn', function () {
            G.gameManager.forceChangeTurn();
        });
    },

    addTouchEvent(chess) {
        let self = this;
        chess.node.on('touchend', function (e) {
            if (G.gameManager.gameState === GAME_STATE.PLAYING && G.gameManager.turn === G.stand) {
                if (chess.type === CHESS_TYPE.NONE) {
                    for (let dir = 1; dir <= 8; dir++) {
                        if (self.judgePass(G.gameManager.turn, chess, dir)) {
                            self.fallChess(chess);
                            G.roomSocket.emit('update chessboard', chess.coor);
                            break;
                        }
                        if (dir === 8) {
                            return;
                        }
                    }

                }
            }
        });
    },

    fallChess(chess) {
        if (G.gameManager.turn === STAND.BLACK) {
            chess.type = CHESS_TYPE.BLACK;
        } else if (G.gameManager.turn === STAND.WHITE) {
            chess.type = CHESS_TYPE.WHITE;
        }
        for (let dir = 1; dir <= 8; dir++) {
            if (this.judgePass(G.gameManager.turn, chess, dir)) {
                this.changePass(chess, dir);
            }
        }
        G.gameManager.updateScore();
        G.gameManager.changeTurn();
        this.judgeWin();
    },

    nearChess(chess, dir) {
        switch (dir) {
            case 1://left
                if (chess.coor.x !== 0) {
                    return this.chesses[chess.coor.x - 1][chess.coor.y];
                }
                break;
            case 2://left up
                if (chess.coor.x !== 0 && chess.coor.y !== this.ROW - 1) {
                    return this.chesses[chess.coor.x - 1][chess.coor.y + 1];
                }
                break;
            case 3://up
                if (chess.coor.y !== this.ROW - 1) {
                    return this.chesses[chess.coor.x][chess.coor.y + 1];
                }
                break;
            case 4://right up
                if (chess.coor.x !== this.COL - 1 && chess.coor.y !== this.ROW - 1) {
                    return this.chesses[chess.coor.x + 1][chess.coor.y + 1];
                }
                break;
            case 5://right
                if (chess.coor.x !== this.COL - 1) {
                    return this.chesses[chess.coor.x + 1][chess.coor.y];
                }
                break;
            case 6://right down
                if (chess.coor.x !== this.COL - 1 && chess.coor.y !== 0) {
                    return this.chesses[chess.coor.x + 1][chess.coor.y - 1];
                }
                break;
            case 7://down
                if (chess.coor.y !== 0) {
                    return this.chesses[chess.coor.x][chess.coor.y - 1];
                }
                break;
            case 8://left down
                if (chess.coor.x !== 0 && chess.coor.y !== 0) {
                    return this.chesses[chess.coor.x - 1][chess.coor.y - 1];
                }
                break;

            default:
                break;
        }
        return null;
    },

    judgePass(stand, chess, dir) {
        let tempChess = chess;
        tempChess = this.nearChess(chess, dir);
        if (tempChess === null) {
            return false;
        }
        while (tempChess.type === -stand) {
            tempChess = this.nearChess(tempChess, dir);
            if (tempChess === null) {
                return false;
            }
            if (tempChess.type == stand) {
                return true;
            }
        }
        return false;
    },

    changePass(chess, dir) {
        let tempChess = this.nearChess(chess, dir);
        while (tempChess.type === -G.gameManager.turn) {
            tempChess.type = chess.type;
            tempChess = this.nearChess(tempChess, dir);
        }
    },

    judgeMoveAble(stand) {//判断stand是否有可落子的地方
        let tryChess = null;
        for (let x = 0; x < this.COL; x++) {
            for (let y = 0; y < this.ROW; y++) {
                tryChess = this.chesses[x][y];
                if (tryChess.type === CHESS_TYPE.NONE) {
                    for (let dir = 1; dir <= 8; dir++) {
                        if (this.judgePass(stand, tryChess, dir)) {
                            return true;
                        }
                    }
                }
            }
        }
        return false;
    },

    judgeWin() {
        let selfMoveAble = this.judgeMoveAble(G.gameManager.turn);
        let oppoMoveAble = this.judgeMoveAble(-G.gameManager.trun);
        if (selfMoveAble) {
            return;
        } else if (!selfMoveAble && oppoMoveAble) {
            cc.log('can not move next turn');
            G.gameManager.forceChangeTurn();
            G.roomSocket.emit('force change turn');
        } else if (!selfMoveAble && !oppoMoveAble) {
            cc.log('both can not move someone win');
            G.gameManager.endGame();
        }
    },

    getChessCount(){
        let blackChess = 0;
        let whiteChess = 0;
        for (let x = 0; x < this.chesses.length; x++) {
            for (let y = 0; y < this.chesses[x].length; y++) {
                if (this.chesses[x][y].type === CHESS_TYPE.BLACK) {
                    blackChess++;
                } else if (this.chesses[x][y].type === CHESS_TYPE.WHITE) {
                    whiteChess++;
                }
            }
        }
        return [blackChess,whiteChess];
    }
});

Chess.js

const Constants = require('Constants');
const CHESS_TYPE = Constants.CHESS_TYPE;
cc.Class({
    extends: cc.Component,

    properties: {
        pics:{
            default:[],
            type:[cc.SpriteFrame]
        },
        _type:CHESS_TYPE.NONE,
        type:{
            get(){
                return this._type;
            },
            set(value){
                this._type = value;
                if(value === CHESS_TYPE.BLACK){
                    this.getComponent(cc.Sprite).spriteFrame = this.pics[0];
                }else if(value === CHESS_TYPE.WHITE){
                    this.getComponent(cc.Sprite).spriteFrame = this.pics[1];
                }else{
                    this.getComponent(cc.Sprite).spriteFrame = null;
                }
            }
        },
        coor:cc.p(0,0),//坐标
        chance:0//周围可翻转棋子的可能性
    },

    onLoad(){
        this.type = CHESS_TYPE.NONE;
    }

});

reversi-server.js

'use strict'

let app = require('express')();
let server = require('http').Server(app);
let io = require('socket.io')(server);

server.listen(4747, function() {
    console.log('listening on:4747');
});

let MAX = 30;//最大支持连接房间数
let hall = null;//大厅
let queue = null;//匹配队列
let rooms = [];//游戏房间

function Hall() {
    this.people = 0;
    this.socket = null;
}

function Room(){
    this.people = 0;
    this.socket = null;
}

function Queue(){
    this.people = 0;
    this.socket = null;
}

hall = new Hall();

queue = new Queue();

for(let n = 0;n < MAX;n++){
    rooms[n] = new Room();
}

function getFreeRoom(){
    for(let n = 0;n < MAX;n++){
        if(rooms[n].people === 0){
            return n;
        }
    }
    return -1;
}

io.people = 0;
io.on('connection',function(socket){
    io.people++;
    console.log('someone connected');
    socket.on('disconnect',function(){
        io.people--;
        console.log('someone disconnected');
    });
})

hall.socket = io.of('/hall').on('connection', function(socket) {

    hall.people++;

    console.log('a player connected.There are '+hall.people+' people in hall');

    hall.socket.emit('people changed',hall.people);

    socket.on('disconnect',function(){
        hall.people--;
        console.log('a player disconnected.There are '+hall.people+' people in hall');
        hall.socket.emit('people changed',hall.people);
    });
});

queue.socket = io.of('/queue').on('connection',function(socket){

    queue.people++;

    console.log('someone connect queue socket.There are '+queue.people+' people in queue');

    if(queue.people === 1){
        socket.emit('set stand','black');
    }else if(queue.people === 2){
        socket.emit('set stand','white');
        let roomId = getFreeRoom();
        console.log(roomId+"roomId");
        if(roomId >= 0){
            queue.socket.emit('match success',roomId);
            console.log('match success.There are '+queue.people+' people in queue');
        }else{
            console.log('no free room!');
        }
    }

    socket.on('cancel match',function(){
        queue.people--;
        console.log('someone cancel match.There are '+queue.people+' people in queue');
    });

    socket.on('disconnect',function(){
        queue.people--;
        console.log('someone disconnected match.There are '+queue.people+' people in queue');
    });

});

for(let i = 0;i < MAX;i++){
    rooms[i].socket = io.of('/rooms'+i).on('connection',function(socket){

        rooms[i].people++;
        console.log('some one connected room'+i+'.There are '+rooms[i].people+' people in the room');

        socket.on('update chessboard',function(chessCoor){
            socket.broadcast.emit('update chessboard',chessCoor);
        });

        socket.on('force change turn',function(){
            socket.broadcast.emit('force change turn');
        });

        socket.on('disconnect',function(){
            rooms[i].people--;
            console.log('someone disconnected room'+i+'.There are '+rooms[i].people+' people in the room');
        });

    });
}
  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值