C # server WeChat games - multiplayer online role-playing (d)

Creative Commons License Copyright: Attribution, allow others to create paper-based, and must distribute paper (based on the original license agreement with the same license Creative Commons )

C # server WeChat games - multiplayer online role-playing (d)

Time, space and matter, that's all the universe, the world up and running on your server now.
- Uncle Mao

The first work of GameServer.

In the previous years, the service side of GameServerthe start and did not make any real work, just notice GameMonitorthat it has started. The punch equivalent to our work, and then fill doze in their seats ...... Now, let's see what need do it live.

First of all, we know that GameServerthe three main functions:

  1. Let the game run up
  2. Receive and process client requests sent,
  3. The information customers need to send back to the client

Now let's deal with 让游戏跑起来the work. Behind the two work with the client to complete the development of the future together.
So, we have a Gamecategory for it.
Then the Gameclass you want to create a space, to control time and space to mobilize material.
Yes, create a new project in VS program inside, type Class Library(.NET Framework), name GameLib, and then automatically generated Class1renamed Game.

Also in the new category to save the global information G, in Gthe definition of a static member inside GlobeTime, this is our time in the game inside. Any action of the game world should be based on this time scale.
For all of the content in the world, time , are equal, not just in the game.

When the game class is created, the time to zero, start all over again ...... this can be done only inside game.

Next, create a new class GameWorldthat is space our game world
because we are doing a 2D game, so space is constituted by a number of maps, and therefore also need a GameMapclass.
To create another GameObjectThis is the space content

With global time, Gamethere must also be one GameWorld, but GameWorldthere are a bunch GameMap, and then GameMapinside there are a bunch GameObject, so, these classes should look like this:

public class G
    {
        public static uint GlobeTime;
    }
public class Game
    {
        private readonly GameWorld gWorld;
        public Game()
        {
            G.GlobeTime = 0;
            gWorld = new GameWorld();
        }
    }
class GameWorld
    {
        private readonly List<GameMap> gMaps;
        public GameWorld()
        {
            gMaps = new List<GameMap>();
        }
    }
class GameMap
    {
        private readonly List<GameObject> gObjects;
        public GameMap()
        {
            gObjects = new List<GameObject>();
        }
    }
class GameObject
    {
        public GameObject()
        {
        }
    }

When the game server GameServerstartup, we need to let the game run, it would need to access Gamethe class, so to GameMonitoradd a project reference GameLib, select the right GameMonitor, select 添加-> 引用-> 'Project', then to GameLibtick tick, OK. And then GameServerinside to add a line using GameLib;on it.

To GameServeradd a member private readonly Game gGame, this is our game.

In GameServerthe StartUpmethod which, added gGame.Run(), so that the game ran up. VS will remind gGamenot Runthis method, it does not matter, then select Run alt+ enter, automatically generate a can.

GameServer.csinside:

 public void StartUp()
        {
            if (Status == 0)
            {
                gGame.Run();
                Status = 1;
                LOG("GameServer启动成功");
            }
            else
            {
                LOG("GameServer当前处于启动状态,请勿重复启动");
            }                
        }
        public void ShutDown()
        {
            if (Status == 1)
            {
                gGame.Stop();
                Status = 0;
                LOG("GameServer停机成功");
            }
            else
            {
                LOG("GameServer当前处于停机状态,无需再次停机");
            }
        }

Game.cs inside:

        public void Run()
        {
            
        }

        public void Stop()
        {
            
        }

Next, we add a running thread for the game, because the run Well, you need to have to run, you need a separate thread to do repetitive work, this way, we also need a game state flag. So that the game can stop the run from the outside.
To monitor all this, we also need GameServera LOGway to pass to Game.
So, Gamecome to this:

public class Game
    {
        private readonly GameWorld gWorld;
        private Thread RunThread;
        private bool IsRunning;
        private Action<string> LOG;
        public Game(Action<string> LOGFUN)
        {
            G.GlobeTime = 0;
            gWorld = new GameWorld();
            RunThread = null;
            IsRunning = false;
            LOG = LOGFUN;
            LOG("Game类创建成功");
        }

        public void Run()
        {
            
            IsRunning = true;
            if (RunThread == null)
            {
                RunThread = new Thread(() =>
                {
                    while (IsRunning)
                    {
                        LOG("Game 正在运行");
                        string[] buff = new string[1024000];
                        for (int i = 0; i < 1024000; i++)
                        {
                            buff[i] = "test data "+i;
                        }
                    }
                    LOG("Game 即将停止");
                });
            }
            RunThread.Start();
        }

        public void Stop()
        {
            IsRunning = false;
            while (RunThread != null && RunThread.ThreadState != ThreadState.Stopped)
            {
                LOG("Game 正在停止,请稍候");
            }
            RunThread = null;
            GC.Collect();//简单回收一下,为下次启动腾出资源。
            LOG("Game 成功停止");
        }
    }

Then GameServercome to this:

class GameServer
    {
        private readonly MainForm Monitor;
        private readonly Game gGame;
        public int Status;
        public GameServer(MainForm monitor)
        {
            Status = 0;
            Monitor = monitor;
            LOG("GameServer创建成功");
            gGame = new Game(LOG);
        }

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

    }

I added the code segment occupies the content of the resource in the run inside:

string[] buff = new string[1024000];
for (int i = 0; i < 1024000; i++)
{
    buff[i] = "test data "+i;
}

When debugging memory monitoring through intuitive panel may see GC.Collect()the need.

Let the world run up

Next, GameWorldalso adjust, plus LOGreferences, and pass in the constructor inside Gameof LOG.
Now, to GameWorldadd a key way to class - heartbeat ( HeartBeat), use it to complete the operation of the world.
To GameWorldcreate a List<GameMap> gMapsused to store the world space (map).
And so on, to GameMapcreate a List<GameObject> gObjectsused to store the content of this map.

Finally, in Gamethe Run"dead loop" which let GameWorldstart heartbeat.

Gameclass

……

        public Game(Action<string> LOGFUN)
        {
            G.GlobeTime = 0;
            gWorld = new GameWorld(LOGFUN);
            RunThread = null;
            IsRunning = false;
            LOG = LOGFUN;
            LOG("Game类创建成功");
        }
……
        public void Run()
        {
            
            IsRunning = true;
            if (RunThread == null)
            {
                RunThread = new Thread(() =>
                {
                    while (IsRunning)
                    {
                        if (G.GlobeTime % 1000 == 0)
                        {
                            gWorld.HeartBeat();                            
                        }
                        _ = G.GlobeTime > 10000000 ? G.GlobeTime = 0 : G.GlobeTime++;

                    }
                    LOG("Game 即将停止");
                });
            }
            RunThread.Start();
        }

Heartbeat frequency to every 1000 GlobeTimeunits, if you later feel too slow or too fast, and then make their own adjustments. In short, the world's smallest unit of time is 1000 times GlobeTime, and anything not even think about crossing ~~

GameWorldclass

    class GameWorld
    {
        private readonly List<GameMap> gMaps;
        private Action<string> LOG;
        public GameWorld(Action<string> LOGFUN)
        {
            gMaps = new List<GameMap>();
            LOG = LOGFUN;
            LOG("GameWorld类创建成功");
        }

        internal void HeartBeat()
        {
            LOG("GameWorld正在心跳 " + G.GlobeTime);
        }
    }

Debugging a bit, feeling the pulse of the world's heartbeat.
Debugging effect
Well, the world began to have heart, each heartbeat but what to do with it? Next we discuss in detail.

Previous: C # server WeChat games - multiplayer online role-playing (three)
Next: C # server WeChat games - multiplayer online role-playing (V)

See the demo game results with micro-channel scan

Entrance demo

Guess you like

Origin blog.csdn.net/foomow/article/details/92080828