F # game development: changing state variables

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()

In the above code example, I create a circle and let it move by pressing the arrow keys. The state variable represents the position of the circle represented by the Vector2f object (part of the SFML library)

My question relates to the end of the code segment, where I find the key pressed, and then move the circle. From C # background, this part of my code seems bad.

In C #, I would just do the following:

switch (pressedKey) {
    case Keyboard.Key.Up:
         shape.Position.Y -= 0.1f;
    // etc, etc
}
  • Does these new Vector2f objects create unnecessary overhead compared to how I would change the state variable in C #?

  • Is there a better way to do this?

+4
source share
2 answers

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()
+4

, , , . .

vector2, , # ( , ).

+2

Source: https://habr.com/ru/post/1529231/


All Articles