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
}
  • 创建这些新的Vector2f对象是否会导致不必要的
    与我将修改状态变量的方式相比的开销
    C#?
  • 有更好的方法吗?
  • 最佳答案

    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/

    10-11 20:34