Files
functional-programming-snake/fsharp/solutions/View.fs
T

39 lines
1.4 KiB
FSharp

/// m06 view: the picture is plain data (a list of shapes); drawing it is somebody else's job (m07).
module Snake.View
open Snake.Model
/// A thing to draw.
type Shape =
| Rect of x: int * y: int * w: int * h: int * color: string
| Text of x: int * y: int * text: string * color: string * size: int * align: string
/// A picture: shapes drawn in order.
type Scene = Shape list
let CELL = 20
let private text x y str size align = Text(x, y, str, "#ffffff", size, align)
// One cell, inset by 1px so neighbouring segments show a gap.
let private cell (p: Point) color =
Rect(p.X * CELL + 1, p.Y * CELL + 1, CELL - 2, CELL - 2, color)
let private overlay (state: GameState) : Scene =
let cx = state.Width * CELL / 2
let cy = state.Height * CELL / 2
let banner title hint = [ text cx cy title 32 "center"; text cx (cy + 30) hint 16 "center" ]
match state.Status with
| Paused -> banner "Paused" "Press Space to resume"
| GameOver -> banner "Game Over" "Press R to restart"
| Won -> banner "You Win!" "Press R to restart"
| Playing -> []
let view (state: GameState) : Scene =
[ Rect(0, 0, state.Width * CELL, state.Height * CELL, "#111111") ]
@ (state.Apple |> Option.map (fun a -> cell a "#e53935") |> Option.toList)
@ (state.Snake |> List.mapi (fun i p -> cell p (if i = 0 then "#7cb342" else "#43a047")))
@ [ text 6 18 $"Score: {state.Score}" 16 "left" ]
@ overlay state