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 sample I create a circle and let it move around by pressing arrow keys. The state variable in question is the position of the circle, represented by a Vector2f object (part of the SFML library)
My question relates to the end of the code segment, where I find the pressed key and then move the circle. From a C# background this part of my code seems bad.
In C# I would simply do the following:
switch (pressedKey) {
case Keyboard.Key.Up:
shape.Position.Y -= 0.1f;
// etc, etc
}
Does creating these new Vector2f objects cause unnecessary overhead compared to the way I would modify the state variable in C#?
Is there a better way of doing this?
This sound is usually considered to be an allophone of /h/, which is pronounced in different ways depending upon its context; Japanese /h/ is pronounced as [ɸ] before /u/. In Welsh orthography, ⟨f⟩ represents /v/ while ⟨ff⟩ represents /f/. In Slavic languages, ⟨f⟩ is used primarily in words of foreign (Greek, Latin, or Germanic) origin.
In countries such as the United States, the letter "F" is defined as a failure in terms of academic evaluation. Other countries that use this system include Saudi Arabia, Venezuela, and the Netherlands. In the hexadecimal number system, the letter "F" or "f" is used to represent the hexadecimal digit fifteen (equivalent to 15 10 ).
In the Etruscan alphabet, 'F' probably represented /w/, as in Greek, and the Etruscans formed the digraph 'FH' to represent /f/.
It is often doubled at the end of words. Exceptionally, it represents the voiced labiodental fricative / v / in the common word "of". F is the twelfth least frequently used letter in the English language (after C, G, Y, P, B, V, K, J, X, Q, and Z ), with a frequency of about 2.23% in words.
1) This is a performance question which is always case specific. The answer in this case is No. If you are doing this to 10,000 objects in a loop then yes, use mutable data. In general making things immutable allows you to make easier assumptions about their behavior which is hugely important.
2) Here is a possible direction you can go with this code.
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()
I think if you are worried about the overhead of creating a small object corresponding to a keypress, you are worrying about the wrong thing. The number of keypresses is relatively small.
By changing your vector2 type, you can make it possible to write code similar to the C# code ( essentially, you make the backing store variables mutable).
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With