编写实时多人游戏的最佳方式

时间:2010-10-11 01:42:35

标签: real-time

我不确定这里是否滥用了实时这个术语,但是这个想法是服务器上的许多玩家都有一个城市每秒产生 n 资源。可能有一千个这样的城市。奖励所有玩家城市的最佳方式是什么?

当游戏“直播”时,这样的循环最好的方式是在无限循环中运行吗? (请用这种简单的逻辑忽略明显的错误)

foreach(City c in AllCities){
  if(c.lastTouched < DateTime.Now.AddSeconds(-10)){
    c.resources += (DateTime.Now-c.lastTouched).Seconds * c.resourcesPerSecond;
    c.lastTouched = DateTime.Now;
    c.saveChanges();
  }
}

2 个答案:

答案 0 :(得分:5)

我不认为你想要一个无限循环,因为这会浪费很多CPU周期。这基本上是一种常见的模拟情况Wikipedia Simulation Software,我可以想到几种方法:

  1. 离散时间方法,您可以将时钟递增固定时间并重新计算系统状态。这类似于上面的方法,除了定期计算并删除10秒if子句。
  2. 离散事件方法,其中您有一个中央事件队列,每个队列都有一个按时间排序的时间戳。你睡觉直到下一个事件到期,然后发送它。例如。该事件可能意味着添加单个资源。 Wikipedia Discrete Event Simulation
  3. 每当有人要求资源数量时,都会根据费率,初始时间和当前时间计算出来。当预计查询数量相对于城市数量和经过的时间较小时,这可能非常有效。

答案 1 :(得分:1)

虽然您可以存储每个对象的最后一次打勾时间,但就像您的示例一样,通常更容易获得全局时间步长

while(1) {
  currentTime = now();
  dt = currentTime - lastUpdateTime;

  foreach(whatever)
     whatever.update(dt);

  lastUpdateTime = currentTime;
}

如果您有不同的系统,不需要频繁更新:

while(1) {
  currentTime = now();
  dt = currentTime - lastUpdateTime;

  subsystem.timer += dt
  while (subsystem.timer > subsystem.updatePeriod)  {// need to be careful
       subsystem.timer -= subsystem.updatePeriod;    // that the system.update()
       subsystem.update(subsytem.updatePeriod);      // is faster than the 
  }                                                  // system.period

  // ...
}

(你会注意到几乎是你在每个城市所做的事情)

另一个问题是,使用不同的子系统时钟速率,您可以获得重叠(即在同一帧中勾选许多子系统),从而导致帧时间不一致,这有时可能是一个问题。