feat(fsharp): m11 pong capstone (model, rules, view, app) with tests
Co-Authored-By: Claude Opus 5.5 <[email protected]>
This commit is contained in:
co-authored by
Claude Opus 5.5
parent
038a375027
commit
1d0b8c3a5c
@@ -0,0 +1,75 @@
|
||||
/// m11 pong model: the same ideas as the snake model, for a different game.
|
||||
module Snake.Pong.Model
|
||||
|
||||
open Snake.Model
|
||||
|
||||
/// The ball's direction of travel, one cell per frame on each axis.
|
||||
type Velocity = { Dx: int; Dy: int }
|
||||
|
||||
/// Which of the player's two keys are being held down right now.
|
||||
type Held = { Up: bool; Down: bool }
|
||||
|
||||
type Score = { Player: int; Cpu: int }
|
||||
|
||||
// RequireQualifiedAccess: write `PongStatus.Playing`, `Paddle.Up`, `PongAction.Frame`, so these cases never get
|
||||
// mixed up with the snake's `Playing`, `Up` and `Frame`.
|
||||
[<RequireQualifiedAccess>]
|
||||
type PongStatus =
|
||||
| Playing
|
||||
| Over
|
||||
|
||||
/// The two keys that move the player's paddle.
|
||||
[<RequireQualifiedAccess>]
|
||||
type Paddle =
|
||||
| Up
|
||||
| Down
|
||||
|
||||
/// A whole match. Positions are in cells: `Ball` is a cell of the 80x50 court; `Player` and `Cpu` are the y of the
|
||||
/// top cell of each paddle. `Seed` is the unsigned 32-bit random seed used to pick the direction of each serve.
|
||||
type PongState =
|
||||
{ Ball: Point
|
||||
Vel: Velocity
|
||||
Player: int
|
||||
Cpu: int
|
||||
Held: Held
|
||||
Score: Score
|
||||
Status: PongStatus
|
||||
Seed: uint32
|
||||
Frame: int }
|
||||
|
||||
/// Everything that can happen in a match, as data.
|
||||
[<RequireQualifiedAccess>]
|
||||
type PongAction =
|
||||
| Press of Paddle
|
||||
| Release of Paddle
|
||||
| Frame
|
||||
| Restart
|
||||
|
||||
// The court, in cells.
|
||||
let W = 80
|
||||
let H = 50
|
||||
|
||||
/// Pixels per cell.
|
||||
let PCELL = 8
|
||||
|
||||
/// Paddle height in cells.
|
||||
let PADDLE = 8
|
||||
|
||||
/// Column of the player's paddle (left) and of the cpu's paddle (right).
|
||||
let PLAYER_X = 2
|
||||
let CPU_X = 77
|
||||
|
||||
/// Points needed to win the match.
|
||||
let WIN = 5
|
||||
|
||||
let initialPong (seed: uint32) : PongState =
|
||||
{ Ball = { X = 40; Y = 25 }
|
||||
Vel = { Dx = 1; Dy = 1 }
|
||||
Player = 21
|
||||
Cpu = 21
|
||||
Held = { Up = false; Down = false }
|
||||
// `Score.Player` says which record is meant: PongState has Player and Cpu fields too.
|
||||
Score = { Score.Player = 0; Cpu = 0 }
|
||||
Status = PongStatus.Playing
|
||||
Seed = seed
|
||||
Frame = 0 }
|
||||
Reference in New Issue
Block a user