c# - F# 游戏开发 : Modifying state variables

标签 c# .net f#

open SFML.Graphics
open SFML.Window

let window = new RenderWindow(new VideoMode(200u, 200u), "SFML works!")
let shape = new CircleShape(10.0f, FillColor=Color.Green)
let mutable pressedKey = Keyboard.Key.Unknown

let moveKeys = [ Keyboard.Key.Up; Keyboard.Key.Left;
                 Keyboard.Key.Down; Keyboard.Key.Right ]

let keyPress (e : KeyEventArgs) =
    match e.Code with
    | moveKeys -> pressedKey <- e.Code
    | _ -> pressedKey <- Keyboard.Key.Unknown

let keyRelease (e : KeyEventArgs) =
    let pressedKeys = List.filter (fun key -> Keyboard.IsKeyPressed(key)) moveKeys
    if pressedKeys.IsEmpty then pressedKey <- Keyboard.Key.Unknown
    else pressedKey <- pressedKeys.Head

window.Closed.Add(fun evArgs -> window.Close())
window.KeyPressed.Add(keyPress)
window.KeyReleased.Add(keyRelease)

while window.IsOpen() do
    match pressedKey with
    | Keyboard.Key.Up    -> shape.Position <- new Vector2f(shape.Position.X, shape.Position.Y - 0.1f)
    | Keyboard.Key.Left  -> shape.Position <- new Vector2f(shape.Position.X - 0.1f, shape.Position.Y)
    | Keyboard.Key.Down  -> shape.Position <- new Vector2f(shape.Position.X, shape.Position.Y + 0.1f)
    | Keyboard.Key.Right -> shape.Position <- new Vector2f(shape.Position.X + 0.1f, shape.Position.Y)
    | _ -> ()

    window.DispatchEvents()
    window.Clear()
    window.Draw(shape)
    window.Display()

在上面的代码示例中,我创建了一个圆圈,并通过按箭头键让它四处移动。所讨论的状态变量是圆的位置,由 Vector2f 对象(SFML 库的一部分)表示

我的问题与代码段的末尾有关,我在那里找到按下的键,然后移动圆圈。从 C# 背景来看,我的这部分代码似乎很糟糕。

在 C# 中,我只需执行以下操作:

switch (pressedKey) {
    case Keyboard.Key.Up:
         shape.Position.Y -= 0.1f;
    // etc, etc
}
  1. 创建这些新的 Vector2f 对象是否会导致不必要的 与我修改状态变量的方式相比的开销 C#?

  2. 有更好的方法吗?

最佳答案

1) 这是一个性能问题,总是针对具体情况。在这种情况下,答案是否定的。如果你在一个循环中对 10,000 个对象执行此操作,那么是的,使用可变数据。一般来说,使事物不可变可以让您更轻松地对其行为做出非常重要的假设。

2) 这是您可以使用此代码的可能方向。

open SFML.Graphics
open SFML.Window
open System

type HandleKeyboard(window : RenderWindow) =
    let mutable keyState = Set.empty

    let keyPressedHandle = 
        window.KeyPressed.Subscribe(fun key -> 
            keyState <- keyState.Add key.Code)

    let keyReleasedHandle = 
        window.KeyReleased.Subscribe(fun key -> 
            keyState <- keyState.Remove key.Code)

    let validMovementKey (keyPress : Keyboard.Key) =
        match keyPress with
        | Keyboard.Key.Up
        | Keyboard.Key.Left
        | Keyboard.Key.Down
        | Keyboard.Key.Right -> true
        | _ -> false

    let keyToMovement (keyPress : Keyboard.Key) =
        match keyPress with
        | Keyboard.Key.Up    -> Vector2f( 0.0f, -0.1f)
        | Keyboard.Key.Left  -> Vector2f(-0.1f,  0.0f)
        | Keyboard.Key.Down  -> Vector2f( 0.0f,  0.1f)
        | Keyboard.Key.Right -> Vector2f( 0.1f,  0.0f)
        | _ -> Vector2f(0.0f, 0.0f)

    member this.IsKeyPressed (key : Keyboard.Key) = 
        keyState |> Set.contains key

    member this.GetMovement () =
        keyState
        |> Set.filter validMovementKey
        |> Seq.map keyToMovement
        |> Seq.fold (+) (Vector2f(0.0f, 0.0f))

    interface IDisposable with
        member this.Dispose() =
            keyPressedHandle.Dispose()
            keyReleasedHandle.Dispose()

type SomeState = { 
    position : Vector2f;
    }

let startGame() =
    use window = new RenderWindow(VideoMode(200u, 200u), "SFML works!")
    use shape = new CircleShape(10.0f, FillColor = Color.Green)
    use keyboard = new HandleKeyboard(window)

    window.Closed.Add(fun evArgs -> window.Close())

    let rec mainLoop state =
        window.DispatchEvents()

        if keyboard.IsKeyPressed Keyboard.Key.Escape then
            window.Close()

        let newPosition = state.position + keyboard.GetMovement()
        shape.Position <- newPosition

        if window.IsOpen() then
            window.Clear()
            window.Draw(shape)
            window.Display()

            mainLoop {position = newPosition}

    mainLoop {position = Vector2f(0.0f, 0.0f)}

startGame()

关于c# - F# 游戏开发 : Modifying state variables,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22072603/

相关文章:

.net - 文件有多个属性时如何判断文件是否隐藏

.net - Observable.Timer() 会导致内存泄漏吗?

haskell - Monad 还可以测量副作用

F# 方法重载解析不如 C# 智能?

f# - 与 OCaml 的 'lsr' 和 'asr' 等效的 F# 按位运算符是什么?

c# - 打开不属于项目的 cs 文件时,有什么方法可以使 Intellisense 工作?

c# - 更新 "live"WPF Canvas (折线),当 PointCollection 发生变化时

c# - 为什么最终输出为零 : OOPS sample

c# - 使用C#访问系统目录

c# - 是否存在具有以下二叉搜索树特征的.NET数据结构?