Mangos0世界帧同步计算辨析

/**
 * MaNGOS is a full featured server for World of Warcraft, supporting
 * the following clients: 1.12.x, 2.4.3, 3.3.5a, 4.3.4a and 5.4.8
 *
 * Copyright (C) 2005-2015  MaNGOS project 
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 *
 * World of Warcraft, and all World of Warcraft or Warcraft art, images,
 * and lore are copyrighted by Blizzard Entertainment, Inc.
 */


#define WORLD_SLEEP_CONST 50

/// Heartbeat for the World
void WorldRunnable::run()
{
    uint32 realCurrTime = 0;
    uint32 realPrevTime = WorldTimer::tick();

    uint32 prevSleepTime = 0;                               // used for balanced full tick time length near WORLD_SLEEP_CONST

    ///- While we have not World::m_stopEvent, update the world
    while (!World::IsStopped())
    {
        ++World::m_worldLoopCounter;
        realCurrTime = WorldTimer::getMSTime();

        uint32 diff = WorldTimer::tick();

        sWorld.Update(diff);
        realPrevTime = realCurrTime;

        // diff (D0) include time of previous sleep (d0) + tick time (t0)
        // we want that next d1 + t1 == WORLD_SLEEP_CONST
        // we can't know next t1 and then can use (t0 + d1) == WORLD_SLEEP_CONST requirement
        // d1 = WORLD_SLEEP_CONST - t0 = WORLD_SLEEP_CONST - (D0 - d0) = WORLD_SLEEP_CONST + d0 - D0

        if (diff <= WORLD_SLEEP_CONST + prevSleepTime)
        {
            prevSleepTime = WORLD_SLEEP_CONST + prevSleepTime - diff;
            ACE_Based::Thread::Sleep(prevSleepTime);
        }
        else
        {
            prevSleepTime = 0;
        }

    }

}

这里只保留了世界轮询的逻辑。总的实现思路是在world.update前打点,计算了上次update和睡眠的耗时总和,今次的update放生在总和之后,决定了那些逻辑可以进行可以继续挂起。

值得讨论是上面睡眠逻辑的实现。

为了保证游戏足够得流畅,每秒一定要保证足够的计算次数。上面代码里World_Sleep_Const值为50,也就是说每次世界逻辑计算加上睡眠耗时应该在50毫秒上下,这样保证每次能计算20次世界逻辑。


如果上次耗时总和小于(World_Sleep_Const+prevSleepTime),那么小于多少,就睡眠多少,并修改prevSleepTime为小于的数值;否则立刻进入下一轮轮询,并修改prevSleepTime为0。


update的耗时不可能稳定在一个值,表现为时大时小。耗时多,不必睡眠,应该立进入下一次轮询,多余的耗时应该在以后的睡眠时间里扣掉。这样才能在总体上保证每秒20次计算。


if (diff < WORLD_SLEEP_CONST - prevSleepTime) {
 prevSleepTime = WORLD_SLEEP_CONST - prevSleepTime - diff; 
  ACE_Based::Thread::Sleep(prevSleepTime); 
  preSleepTime = 0;
} else { 
  prevSleepTime = preSleepTime + (diff - WORLD_SLEEP_CONST) ; 
}


 






你可能感兴趣的:(页游后台,Debuging,C++)