10分钟开发一个游戏服务器

前言

  安利一个游戏服务器框架colyseus,使用起来十分简单,只需要一丢丢的代码就可以实现一个状态同步的服务器,10分钟主题,废话不多说,Let’s Rock!

安装&项目设置

  • 使用npm初始化项目
$ npm i -g typescript
$ npm init -y
$ tsc --init
$ npm i colyseus
$ npm i express @types/express @types/node @types/redis

编程ING

先码一遍代码比看着纸想有用. -----鲁迅

  • 入口文件 在主目录下新建一个index.ts文件
import { GameRoom } from './room/GameRoom';
import { Server } from 'colyseus';
import express from 'express';
import http from 'http';

const app = express();

// 初始化游戏服务器
const gameServer = new Server({
    server: http.createServer(app)
});

// 注册房间服务器
gameServer.register('game', GameRoom);

// 开始监听端口
gameServer.listen(3000);
console.log('server is on');
  • 新建一个文件夹room 新建一个GameRoom.ts文件
import { Room, Client } from 'colyseus';
import { PlayerState } from '../entity/PlayerState';

export class GameRoom extends Room<PlayerState> {
    // 房间内的最大人数
    maxClients: number = 2;

    // 房间初始化方法
    onInit(options: any) {
        console.log('ChatRoom onInit');
        // 设置需要更新的状态
        this.setState(new PlayerState());
        // 设置发送频率
        this.setPatchRate(50);
    }

    // 消息收取方法
    onJoin(client: Client) {
        this.state.addPlayer(client);
    }

    // 消息收取方法
    onLeave(client: Client) {
        this.state.removePlayer(client);
    }

    // 消息收取方法
    onMessage(client: Client, data: any): void {
        this.state.movePlayer(client, data.x, data.y);
    }

}
  • 新建一个文件夹entity 新建文件PlayerState.ts和Player.ts

  • PlayerState.ts

import { EntityMap, Client } from 'colyseus';
import { Player } from './Player';

export class PlayerState {
    // EntityMap是colyseus的对象实体模板
    players: EntityMap<Player> = {};

    /**
     * 添加新用户的方法
     *
     * @param {Client} client
     * @memberof PlayerState
     */
    addPlayer(client: Client) {
        let player = new Player(0, 0);
        this.players[client.sessionId] = player;
    }

    /**
     * 删除一个用户的方法
     *
     * @param {Client} client
     * @memberof PlayerState
     */
    removePlayer (client: Client) {
        delete this.players[ client.sessionId ];
    }

    /**
     * 移动用户的方法
     *
     * @param {Client} client
     * @param {number} [x=0]
     * @param {number} [y=0]
     * @memberof PlayerState
     */
    movePlayer(client: Client, x: number = 0, y: number = 0) {
        this.players[client.sessionId].x += x;
        this.players[client.sessionId].y += y;
        if(x > 0){
            this.players[client.sessionId].dir = true;
        } else {
            this.players[client.sessionId].dir = false;
        }
    }
}
  • Player.ts
import { randomChineseName } from '../Utils'
export class Player {
    public name: string;  // 名称
    public x: number;    // x轴的位置
    public y: number;   // y轴的位置
    public dir: boolean; // 玩家的方向(左 false 右 true) 简单定义
    constructor( x: number,  y: number,name?: string) {
        this.x = x;
        this.y = y;
        this.name = name || randomChineseName();
        this.dir = true;
    }
}
  • 根目录新建一个Utils.ts的文件
  • 一些基础工具方法写在这里
  • 现在又一个随机返回一个中文名称的方法
const NAMES: Array<string> = [
    '断笔画墨',
    '默然相爱',
    '旅人不扰',
    '多余温情',
    '云中谁忆',
    '残雪冰心',
    '末世岛屿',
    '桑榆非晚',
    '扉匣与桔',
    '木槿暖夏',
    '空城旧梦',
];

/**
 * 返回随机的中文名
 * 
 * @export
 * @returns {string}
 */
export function randomChineseName(): string {
    return NAMES[~~(NAMES.length * Math.random())];
}

简单分析

  • 不正确的图像架构

  • 一个游戏服务器下面可以开N个房间Room
  • Room中存在一个state的对象,发生变化时候同步到Room下的客户端
  • 使得客户端的状态保持一致
  • 这个就是colyseus实现的状态同步服务器

启动服务器

$ tsc && node ./dist/index.js

简单的客户端

源码地址:https://gitee.com/limo/simple_server
博客地址https://allknowboy.com/posts/a8be8288/

49赞

mark

战略插眼

赞一个!

插眼:slightly_smiling:

mark

插眼一个

mark

mark

站个位置。以后来看

mark

mark

mark

mark

汪~偷偷嘘嘘做个"10分钟开发一个游戏服务器"的记号~

:+1:

mark 一下

666:slightly_smiling:

安利安利

mark