golang – 网络游戏中的主循环

huangapple go评论85阅读模式
英文:

golang - Main loop in network game

问题

我只是一个中文翻译机器人,以下是您要翻译的内容:

我现在只是开始尝试使用Go大约一个星期,对它印象非常好。然而,我仍然有一些问题还没有弄明白。

目前的主要问题是,虽然我已经让连接处理的代码工作了,但我想添加一个独立于连接循环的主游戏循环。如何做到这一点?

package main

import (
  "fmt"
  "net"
  "strconv"
  "time"
  "galaxy"
)

const PORT = 5555

func main() {
  playerFactory := galaxy.NewPlayerFactory()
  
  server, err := net.Listen("tcp", ":" + strconv.Itoa(PORT))
  if server == nil {
    panic("listen failed: " + err.Error() + "\n")
  } else {
    defer server.Close()
  }
  
  // 主循环
  go func() {
    for {   
      // 实体更新
      playerFactory.Update()
    }
  }() // 添加这个会阻塞在goroutine之后的所有代码
  
  // 连接处理
  for {
    conn, err := server.Accept()
    if err != nil {
      fmt.Printf("client error: %s\n", err.Error())
    } else {
      playerFactory.CreatePlayer(conn)
    }
  }

}

目前的写法是主循环运行(这是我想要添加的部分),但连接处理的代码被忽略了。这是使用通道来传递控制的地方吗?我相信对于一个经验丰富的Go程序员来说,解决方案是显而易见的,期待您的答案。

英文:

I've only begun tinkering with Go for about a week now, and am quite impressed with it. However, I'm still having a few issues I can't get my head around yet.

The main problem right now is that while I have the connection handling code working, I want to add a main game loop independent of the connection loop. How does one do this?

package main

import (
  "fmt"
  "net"
  "strconv"
  "time"
  "galaxy"
)

const PORT = 5555

func main() {
  playerFactory := galaxy.NewPlayerFactory()
  
  server, err := net.Listen("tcp", ":" + strconv.Itoa(PORT))
  if server == nil {
    panic("listen failed: " + err.Error() + "\n")
  } else {
    defer server.Close()
  }
  
  // main loop  
  go func() {
    for {   
      // entity updates
      playerFactory.Update()
    }
  }() // adding this just blocks everything after the goroutine
  
  // connection handling
  for {
    conn, err := server.Accept()
    if err != nil {
      fmt.Printf("client error: %s\n", err.Error())
    } else {
      playerFactory.CreatePlayer(conn)
    }
  }

}

With the way it is currently written the main loop runs (this is the part I am trying to add), but the connection handling code gets ignored. Is this where one uses channels to pass control around? I'm sure the solution is apparent to a more seasoned Go programmer, I look forward to your answers.

答案1

得分: 4

如果playerFactory.Update()从不释放CPU(例如通过在资源上阻塞),则不能保证其他goroutine运行。

您可以尝试更改GOMAXPROCS,但这取决于您的CPU数量,问题将在以后出现其他非阻塞的goroutine。

我看不出游戏循环无间断运行的任何理由。最常见的情况是您需要定期执行某些操作。

在这种情况下,您的代码将是

  // 主循环
  go func() {
     timer := time.Tick(100 * time.Millisecond)
     for now := range timer {   
         // 实体更新(您可以使用now进行物理引擎计算)
         // 这将每100毫秒调用一次
         playerFactory.Update()
     }
  }()
英文:

If playerFactory.Update() never releases the CPU (for example by blocking on a resource), there is no guarantee for other goroutines to run

You could try to change GOMAXPROCS but that would depend on your number of CPU and the problem would reappear later with other non blocking goroutines.

And I can't see any reason for a game loop to run without interruption. The most frequent case is when you have to do something at regular interval.

In this case, your code would be

  // main loop  
  go func() {
     timer := time.Tick(100 * time.Millisecond)
     for now := range timer {   
         // entity updates (you could use now for physic engine calculs)
         // this is called every 100 millisecondes
         playerFactory.Update()
     }
  }()

huangapple
  • 本文由 发表于 2012年12月8日 17:03:12
  • 转载请务必保留本文链接:https://go.coder-hub.com/13776030.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定