我已经使用F#(多范式,不纯的,功能优先的语言)编写了一些游戏,方法从OOP到FRP。这是一个广泛的问题,但我会尽力而为。
在功能编程语言中,是否存在一种通用的技术来处理状态(通常)?
我的首选方式是拥有一个代表整个游戏的不可变类型State
。然后,我可以对State
每个刻度更新的当前内容进行可变引用。这不是严格意义上的纯净,但将可变性限制在一个地方。
如果我将整个游戏状态放到所有函数中,那么与全局变量或命令式方法相比,对我没有任何好处。
不对。因为State
类型是不可变的,所以不能有任何旧的组件以不确定的方式改变世界。这解决了该GameObject
方法的最大问题(由Unity推广):难以控制Update
调用顺序。
而且与使用全局变量不同,它很容易进行单元测试和并行化,
您还应该编写帮助程序函数,以接收状态的子属性来解决问题。
例如:
let updateSpaceShip ship =
{
ship with
Position = ship.Position + ship.Velocity
}
let update state =
{
state with
SpaceShips = state.SpaceShips |> map updateSpaceShip
}
这里update
作用于整个状态,但updateSpaceShip
仅SpaceShip
孤立地作用于一个人。
我可以只将相关信息放入函数中,然后返回将为给定输入执行的操作。
我的建议是创建一个Input
可以容纳键盘,鼠标,游戏手柄等状态的类型。然后,您可以编写一个接受a State
并Input
返回next 的函数State
:
let applyInput input state =
// Something
为了让您了解如何将它们组合在一起,整个游戏可能看起来像这样:
let mutable state = initialState ()
// Game loop
while true do
// Apply user input to the world
let input = collectInput ()
state <- applyInput input state
// Game logic
let dt = computeDeltaTime ()
state <- update dt state
// Draw
render state
所以我的问题是我该如何处理功能性编程语言中的大量状态-特别是对于游戏开发?
对于简单的游戏,您可以使用上面的方法(辅助功能)。对于更复杂的事情,您可能想尝试“ 镜头 ”。
与这里的一些评论相反,我强烈建议您使用一种(不纯正的)功能编程语言来编写游戏,或者至少尝试一下!我发现它使迭代更快,代码库更小且错误更不常见。
我也不认为您需要学习monad来用(不纯)FP语言编写游戏。这是因为您的代码很可能会被阻塞并且是单线程的。
如果您正在编写多人游戏,则尤其如此。然后,使用这种方法将使事情变得更加容易,因为它使您可以轻松地序列化游戏状态并通过网络发送。
至于为什么更多的游戏没有这样写...我不能说。但是,在所有编程领域(也许除了金融领域)都是如此,因此,我不会将其用作功能语言不适用于游戏编程的论点。
同样值得一读的是Purely Functional Retrogames。
move()
,您应该传递的是“当前”对象(或它的标识符),再加上它正在通过的世界,然后仅得出当前位置和速度...那么输出就是整个物理世界,或者至少是更改对象的列表。