功能过剩?
我正在通过限制自己不使用 set! 来学习一些 Gambit-C 方案中的函数式编程。我认为使用这个环境编写一个小 OpenGL 游戏可能会很有趣,这似乎很适合游戏开发。
然而,在使用 OpenGL 和 GLUT 时,似乎很难坚持函数式风格并避免全局状态。我认为这本身并不是游戏编程的基本限制,但基于回调的 API(例如 GLUT)似乎不太适合函数式编程。
例如,我试图将世界视为一个变异状态向量流,它是时间步长和用户输入事件的交错列表的函数。这个想法看起来似乎还可以,但是用异步编程来实现似乎并不容易。例如,我必须为 GLUT 的显示函数注册一个回调,它应该能够以某种方式访问此流中的“当前”项目。与此同时,没有任何东西可以通过从中获取来推动流向前发展。
理想情况下,我需要一些“外部”GLUT 的东西,一个主要函数,它在某种程度上依赖于(也许是单子)在某个时刻执行的各种 GLUT 函数。如何围绕 GLUT 开发这种类型的游戏引擎,或者换句话说,我如何才能最成功地将 GLUT 与我的引擎隔离?是否可以让 GLUT 为外部过程生成这样一个交错的事件列表?例如,Haskell 如何处理这个问题?
I'm learning a bit of functional programming in Gambit-C Scheme by restricting myself to not using set!. I thought it might be fun to write a little OpenGL game using this environment, which seems to lend itself well to game development.
However, it seems to be difficult to stick to a functional style and avoid global state when using OpenGL and GLUT. I don't think this is a fundamental limitation of game programming, per se, but a callback-based API such as GLUT does not seem to work well with functional programming.
For example, I'm trying to think of the world as a stream of mutating state vectors which is a function of an interleaved list of timestep and user input events. This idea seems to be okay, but it doesn't seem to go easily with asynchronous programming. For instance, I have to register a callback for GLUT's display function, which should somehow be able to access the "current" item in this stream. Meanwhile, there's nothing to drive the stream forward by taking from it.
Ideally, I'd need something that is sort of "outside" GLUT, a main function which somehow depends (perhaps monadically) on the various GLUT functions having been executed at some point. How could such a style of game engine be developed around GLUT, or another way to ask is how could I most successfully isolate GLUT from my engine? Is it possible to have GLUT generate such an interleaved list of events to an outside procedure? How does Haskell handle this, for instance?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
您将很难实现功能性图形系统。甚至 Haskell 与 GLUT 的绑定也通过 IO monad 使用命令式编程。我听过的最接近您想要做的事情是函数响应式编程,但图书馆还没有准备好迎接黄金时段,并且严重缺乏实际的教程。
You're going to have a very hard time implementing a functional graphics system. Even the Haskell bindings to GLUT use imperative programming, through the
IO
monad. The closest thing I've heard to what you're trying to do is Functional Reactive Programming, but the libraries aren't ready for prime-time yet and there's a severe lack of real-world tutorials for it.您可以查看 FieldTrip 库,了解有关函数式图形的一些想法。
You could look at the FieldTrip library for some ideas on functional graphics.
对于像 openGL 这样的状态机来说,它具有状态是非常重要的!
当副作用是将一组内容绘制到屏幕上时,我不明白如何进行无副作用的函数式编程。
It's pretty fundemental to a state machine like openGL that it has state!
I don't see how you can have side-effect free functional programming when the side effect is drawing a collection of stuff to the screen.
写下这个问题让我思考了一下,我开始怀疑答案是否在于利用协同例程。如果游戏是由 GLUT 空闲和显示调用触发的功能协同例程,则这可以很好地将游戏逻辑与 GLUT 架构分开。比如,很有可能是那一套!无法避免,但如果设置了 GLUT 回调!仅修改正在输入到协同例程中的流,这可能会创建一个非常好的边界。对此有什么想法吗?在了解更多之前,我必须获得更多协同例程的经验。
Having written this question made me think about it a little, and I'm starting to wonder if the answer lies in exploiting co-routines. If the game is a functional co-routine which is triggered by GLUT idle and display calls, this would very nicely separate the game logic from GLUT's architecture. For example, it's very likely that set! cannot be avoided, but if the GLUT callbacks used set! only to modify the stream which is being fed into a co-routine, this might create a very nice boundary. Any thoughts on this? I'll have to get more experience with co-routines before knowing more..