如何在 Haskell 中最好地同步游戏引擎和网络服务器?
我正在设计一个小型足球游戏,其中游戏引擎(计算玩家移动等)在服务器上运行,渲染和键盘/鼠标处理由客户端完成。对于服务器(Haskell),我想使用
- Happstack 进行客户端-服务器通信
- Yampa / Reanimate 用于游戏引擎
每隔 20ms 左右,客户端应通过 HTTP GET 向服务器发送键盘和鼠标事件,接收当前游戏状态(JSON -编码球和球员位置)并渲染它。我正在考虑使用 SDL 基础设施进行游戏循环、输入处理和渲染。
服务器基本上运行两个线程:happstack 服务器接收 HTTP GET,将键盘/鼠标命令放入队列中,从第二个队列读取当前游戏状态并应答 HTTP GET 请求。
第二个线程运行 Yampa 游戏引擎,如 扬帕Arcade paper:游戏引擎尽快计算新一轮(无滴答声)并将结果放入渲染队列中。
一般问题:这看起来像一个可行的架构吗?
具体问题:如何设计服务器端渲染队列:是否会使用 Chan 来实现这一点?如果游戏引擎的平均速度比客户端的“滴答”速度快,队列就会变得越来越长。陈可怎么处理这件事呢?
非常欢迎您的评论!
I am designing a little soccer game where the game engine (that computes player moves etc.) runs on a server, and rendering and keyboard/mouse handling is done by the client. For the server (Haskell) I want to use
- Happstack for client-server communication
- Yampa / Reactimate for the game engine
Every 20ms or so, the client should send keyboard and mouse events to the server via HTTP GET, receive the current game status (JSON-encoded ball and player positions) and render it. I am thinking about using SDL infrastructure for the game loop, input handling and rendering.
The server basically runs two threads: A happstack server receives the HTTP GET, puts the keyboard / mouse commands in a queue, reads the current game status from a second queue and answers the HTTP GET request.
The second thread runs a Yampa game engine, as described in the Yampa Arcade paper: The game engine computes the new round as quickly as possible (no ticks) and puts the result in the render queue.
General question: Does this look like a feasible architecture?
Specific question: How would one design the server side rendering queue: Would one use a Chan for this? If the game engine is quicker on average than the "ticking" on the client side, the queue will get longer and longer. How could this be handled with Chan?
Your comments are very welcome!
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
你能多解释一下游戏本身吗?当我想到足球游戏时,我想到的是一种需要实时反馈的游戏,其中输入应该立即处理,并且我希望玩家输入信息能够立即通过网络发送。 20 毫秒是一个相当大的延迟,我相信当玩家按住按键试图移动他/她的角色时,它可能会感觉很不稳定,就像某些类型的垃圾收集器所经历的那样。
我也不明白为什么你会想在这样的游戏中使用 HTTP(任何游戏),几乎所有游戏都使用 UDP,我可能会针对你的游戏类型采用这条路线。 本教程看起来非常适合学习此类内容。
我还会质疑您选择的网络数据格式,为什么您想要一种在接收/发送时需要进行重要解析/格式化的格式?我认为频繁发送大量数据会增加大量时间。如果我要使用字符串,我会尝试使用最简单的格式,需要很少的解析。我要开发的相关系统是一个使用套接字进行通信的多进程实时系统,最初它使用xml字符串作为网络数据格式,效率非常低,而且所有进程都在同一台机器上。
关于扬帕和服务器端渲染,因此如果我们将游戏上下文中的 FRP 视为实现游戏逻辑的手段我相信大多数网络游戏都有服务器和实体客户实体。通常,可渲染的对象是客户端实体,不可渲染的对象是服务器实体,我猜某些实体在这两者上都有表示。因此,在这种情况下,您可能希望在服务器和服务器上都运行 Yampa。客户端,我会尽量避免与服务器端渲染相关的任何事情。我认为可渲染对象应该主要粘在客户端。您想要来自服务器的渲染命令是否有特定原因?
Could you explain a bit more about the game itself. When I think of a soccer game I think of a game that requires real-time feed-back where input should be handled instantaneously and I would expect player input information to be sent over the network immediately. 20ms is quite a delay and I believe would be noticeable when the player holds down the key trying to move his/her character it will probably feel jerky the kind of jerky-ness experienced with certain types of garbage collectors.
I also do not understand why you would want to use HTTP for such a game (any game for that matter), almost all games use UDP and I would probably go down this route for your type of game. This tutorial looks great for learning about that kind of stuff.
I would also question your choice of network data format, why would you want a format that would require non-trivial parsing/formating when receiving/sending? I'd imagine that sending lots of data and frequently this would add up significant time. If I was going to use strings I would try to use the simplest format that requires very minimal parsing. On related system that I would work on it was a multi-process real-time system using sockets to communicate, and originally it used xml strings as network data format and it was terribly inefficient and all the processes where all on the same machine.
Regarding Yampa & server-side rendering, so if we think of FRP in the context of games as means of implementing game logic & entities I believe most networked games have server & client entities. Typically objects that are renderable are client entities and non-renderable are server entities, and I guess that some entities have representation on both. So in that case you probably want to have Yampa running on both the server & the client side and I would try to avoid anything related to rendering on the server-side. renderable objects should predominately stick to the client side I believe. Is there a specific reason why you want to have render commands coming from the server?
如果您只想提供最新的游戏状态,请不要使用 chan 或队列,请使用示例变量: http://hackage.haskell.org/packages/archive/base/latest/doc/html/Control-Concurrent-SampleVar.html
If you only want to ever give the latest game state, don't use a chan or a queue, use a samplevar: http://hackage.haskell.org/packages/archive/base/latest/doc/html/Control-Concurrent-SampleVar.html
如果您感兴趣,我还曾经用 Haskell 编写过一个类似的基于服务器客户端的足球游戏。您可以在 github (服务器,客户端)。由于当时我还是一个 Haskell 初学者,我遇到了一些有关线程的问题(以及 在博客上介绍它们)并且从未真正完成该项目,但您至少可以从代码中看到如何不这样做。 (最后我放弃了服务器-客户端架构并编写了 freekick2。)我确实认为该架构不过,它本身是可行的。
然而,就像 snk_kid 所写的那样,我不知道你为什么要使用 HTTP。要让它在网络上运行而没有(明显的)延迟,您可能必须使用 UDP 以及客户端预测 (这里一些信息材料)。
In case you're interested, I also wrote a similar server-client based soccer game in Haskell once. You can find the source code at github (server, client). As I was quite a Haskell beginner back then, I ran into some problems regarding threading (and blogged about them) and never really finished the project, but you can at least see from the code how not to do it. (In the end I ditched the server-client architecture and wrote freekick2.) I do think the architecture itself is feasible, though.
However, like snk_kid writes, I don't know why you'd want to use HTTP. To have it running across a network without (noticeable) latency, you'll probably have to use UDP as well as client side prediction (here's some informative material).