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
。这个按钮将用来启动和停止我们的游戏服务。
随后从工具栏里面再拖拽一个TextBox
到BTN_Start
的下面,将Name
设置为TXB_Log
,Mutiline
设置为true
,Font
设置为 Microsoft YaHei, 15.75pt
。我眼睛不好,字体设置得比较大,当然,你喜欢也可以设置为其他字体,看着清晰方便就好。
把TXB_Log
的ScrollBars
设置为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();
}
}
我们可以在MainForm
的Load
事件处理程序里面加上欢迎词,在窗体设计界面双击窗体打开代码窗口,在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
的成员。然后让它在MainForm
的MainForm_Load
进行实例化,这样就可以让MainForm
的其他方法对其进行操作了。
我们再给GameServer
类添加一个状态标志成员Status
以及三个方法LOG
、StartUp
和ShutDown
用以表示状态以及显示日志、控制启动和停止。
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_Start
的Text
改成启动/停止
调试一下:
嗯……挺不错的嘛……
这一篇就写到这里,主要是服务器端框架的搭建,下一篇,我们要深入讨论GameServer的运行机制了。
上一篇:C#服务端的微信小游戏——多人在线角色扮演(二)
下一篇:C#服务端的微信小游戏——多人在线角色扮演(四)
请用微信扫描查看游戏效果演示