C#服务端的微信小游戏——多人在线角色扮演(三)

知识共享许可协议 版权声明:署名,允许他人基于本文进行创作,且必须基于与原先许可协议相同的许可协议分发本文 (Creative Commons

C#服务端的微信小游戏——多人在线角色扮演(三)

那些看起来非常复杂的事情,往往都可以分解为若干简单的小元素。学会化繁为简,这是程序猿的基本素质。
——茂叔

上一篇里面,我们提到了服务器端的几个部分:
Game - 游戏类
GameWorld - 世界类
GameServer - 游戏服务类
GameMonitor - 服务器控制界面
AdminWeb - 远程控制界面

建立工程

我们先从GameMonitor 这个部分下手,因为这个部分是控制界面,从这里下手之后,后续的工作可以方便的呈现效果,使得调试起来效率更高。

所以,我们先通过VS建立一个空的方案(Solution),然后添加第一个工程(project),选择工程类型为Windows Forms App (.NET Framework),工程名称为 GameMonitor

GameMonitor

VS会为我们创建一个默认的窗体,名字为Form1,我们把这个窗体更名为MainForm,系统提示是否更改引用时,选择是。

然后在Solution Explorer里找到并双击MainForm.cs,打开窗体设计界面。
在窗体设计界面,在属性对话框里把窗体的Text修改为“游戏监控器”。然后从工具栏拖拽一个Button到窗体的左上角,

选中这个Button,在属性对话框里把Text属性设置为“启动”,把Name属性设置为BTN_Start。这个按钮将用来启动和停止我们的游戏服务。

随后从工具栏里面再拖拽一个TextBoxBTN_Start的下面,将Name设置为TXB_LogMutiline设置为trueFont设置为 Microsoft YaHei, 15.75pt。我眼睛不好,字体设置得比较大,当然,你喜欢也可以设置为其他字体,看着清晰方便就好。

TXB_LogScrollBars设置为Vertical,这样信息多的时候方便上下滚动。然后拉大到填满整个窗体,再把Anchor设置为Top, Bottom, Left, Right,以便它可以随窗体放大缩小。

这个文本框将用来显示我们之后代码运行的情况。

最后效果如下:
窗体效果

在窗体上点击右键选择查看代码(View Code)就可以打开代码编辑窗口,在这里,我们要手动给MainForm窗体类添加一个显示日志信息的方法AddLog。代码如下:

private void AddLog(string msg)
        {
            if (msg != null && msg.Length < 1024 && !msg.Trim(' ').Equals(""))//每次显示的信息不能为空也不能太长
            {
                TXB_Log.Text += "[" + DateTime.Now.ToString("yyyy/MM/dd HH:mm:ss:ffff") + "] " + msg + Environment.NewLine;
                while (TXB_Log.Text.Length>30000)//总的显示字符太长的话,就裁掉一些
                {
                    TXB_Log.Text=TXB_Log.Text.Remove(0, 1024);
                }
                //随时滚动到最下面,方便查看
                TXB_Log.Select(TXB_Log.Text.Length,0);
                TXB_Log.ScrollToCaret();
            }
        }

我们可以在MainFormLoad事件处理程序里面加上欢迎词,在窗体设计界面双击窗体打开代码窗口,在VS自动添加的MainForm_Load方法里面加上

AddLog("欢迎!");

但是这个方法只能在UI线程内调用,其他线程没法用……
所以还应该给它加上方便其他线程调用的代理。

给窗体MainForm类添加两行代码:

public delegate void AddLog_Method(string msg);//定义一个代理类型
public AddLog_Method Delegate_AddLog;//创建一个已定义代理类型的代理对象

在窗体MainForm类的构造函数里,将代理对象Delegate_AddLog指向我们的AddLog方法:

public MainForm()
        {
            InitializeComponent();
            Delegate_AddLog = AddLog;//将代理对象指向方法
        }

然后,我们就可以在任何地方使用Invoke来调用它了。

Invoke(Delegate_AddLog, new object[] { "你好"});

我们把这个语句放在BTN_Start里面去测试一下……在窗体设计窗口双击BTN_Start,VS就会自动把点击事件处理方法给我们加上。我们只需要直接写代码就可以了。

private void BTN_Start_Click(object sender, EventArgs e)
        {            
            AddLog("来自UI线程");
            Task.Run(
                new Action(
                () =>
                {
                    try
                    {
                        Invoke(Delegate_AddLog, new object[] { "来自非UI线程" });
                    }
                    catch{ }
                }
                )
                );
        }

调试效果:调试效果

这样,一个简单的监控窗体就搞定了,下一步可以开始考虑GameServer了。

GameServer

Solution Explorer窗口选中GameMonitor项目,点击右键选择添加->类,添加一个名字为GameServer的类。
然后为这个类添加一个私有成员

private readonly MainForm Monitor;

这是监控窗体的引用。
然后把光标移动到类名上,按 alt+enter调出快捷菜单,选择 Generate constractor 然后点击确定,VS会自动帮我们生成构造函数。
在构造函数中我们还可以发送一条创建成功的日志。

public GameServer(MainForm monitor)
        {
            Monitor = monitor;
            try
            {
                Monitor.Invoke(Monitor.Delegate_AddLog, new object[] { "GameServer创建成功" });
            }
            catch{ }
        }

回到MainForm类,将BTN_Start的相应函数内容改为创建游戏服务器:

private void BTN_Start_Click(object sender, EventArgs e)
        {
            AddLog("启动");
            GameServer server = new GameServer(this);
        }

调试一下,点击启动按钮后一切正常~
调试效果
我们把这个server放到点击响应函数外面去,作为MainForm的成员。然后让它在MainFormMainForm_Load进行实例化,这样就可以让MainForm的其他方法对其进行操作了。

我们再给GameServer 类添加一个状态标志成员Status以及三个方法LOGStartUpShutDown用以表示状态以及显示日志、控制启动和停止。

class GameServer
    {
        private readonly MainForm Monitor;
        public int Status;
        public GameServer(MainForm monitor)
        {
            Status=0;
            Monitor = monitor;
            LOG("GameServer创建成功");
        }
        private void LOG(string msg)
        {
            try
            {
                Monitor.Invoke(Monitor.Delegate_AddLog, new object[] { msg });
            }
            catch{ }
        }
        public void StartUp()
        {
          if (Status == 0)
            {
                Status = 1;
                LOG("GameServer启动成功");
            }
            else
            {
                LOG("GameServer当前处于启动状态,请勿重复启动");
            }
        } 
        public void ShutDown()
        {
          if (Status == 1)
            {
                Status = 0;
                LOG("GameServer停机成功");
            }
            else
            {
                LOG("GameServer当前处于停机状态,无需再次停机");
            }
         } 
    }

然后把MainForm类里面的BTN_Start的相应函数内容改为

private void BTN_Start_Click(object sender, EventArgs e)
        {
            if (server.Status == 0)
                server.StartUp();
            else
                server.ShutDown();
        }

再把BTN_StartText改成启动/停止
调试一下:
调试效果
嗯……挺不错的嘛……

这一篇就写到这里,主要是服务器端框架的搭建,下一篇,我们要深入讨论GameServer的运行机制了。

上一篇:C#服务端的微信小游戏——多人在线角色扮演(二)
下一篇:C#服务端的微信小游戏——多人在线角色扮演(四)

请用微信扫描查看游戏效果演示

演示入口

猜你喜欢

转载自blog.csdn.net/foomow/article/details/92080582