Untitled
unknown
fsharp
5 months ago
3.1 kB
9
Indexable
#r "nuget:DIKU.Canvas" open Canvas open Color open System open Asteroids.Vectors open Asteroids.RandomGenerator open Asteroids.Asteroids let width = 400 let height = 400 let center = (200.0, 200.0) let speed = 5.0 // Moth type definition type Moth(pos: Vec, hdng: float) = member val pos = pos with get, set member val heading = hdng with get, set member this.draw = let x, y = this.pos filledEllipse yellow 5.0 5.0 |> translate x y // Random heading change (between -10 and 10 degrees) let randomHeadingChange () : float = GetRandomRange (-10.0) 10.0 * Math.PI / 180.0 // Wrap the moth's position if it goes off screen (cyclic movement) let wrap (v: Vec) : Vec = let x, y = v let x' = if x < 0.0 then float width + x elif x > float width then x - float width else x let y' = if y < 0.0 then float height + y elif y > float height then y - float height else y (x', y') // Move a moth in the direction of its heading let move (pos: Vec) (heading: float) : Vec = let dx = cos(heading) * speed let dy = sin(heading) * speed add pos (dx, dy) |> wrap // Adjust the moth's heading to point towards the light (lamp position) let adjustHeadingToLight (pos: Vec) (target: Vec) : float = let dx, dy = sub target pos ang (dx, dy) // Define the state of the simulation type State = { lamp: bool; moths: Moth list } // Initial moths with random positions and random headings let initialMoths = [ Moth((5.0, 7.0), GetRandomRange 0.0 360.0) Moth((100.0, 100.0), GetRandomRange 0.0 360.0) Moth((50.0, 50.0), GetRandomRange 0.0 360.0) Moth((100.0, 50.0), GetRandomRange 0.0 360.0) Moth((50.0, 100.0), GetRandomRange 0.0 360.0) ] // Draw function to render the simulation let draw (state: State) = let lamplight = if state.lamp then filledEllipse white 10.0 10.0 |> translate 200.0 200.0 else filledEllipse blue 10.0 10.0 |> translate 200.0 200.0 let mothDrawings = state.moths |> List.map (fun m -> m.draw) make (List.fold onto lamplight mothDrawings) // React function to handle key press and timer events let react (state: State) (ev: Event) : State option = match ev with | Key ' ' -> { state with lamp = not state.lamp } // Toggle the lamp when spacebar is pressed | TimerTick -> let target = (200.0, 200.0) let updatedMoths = state.moths |> List.map (fun m -> // If the lamp is on, adjust the heading to the light if state.lamp then m.heading <- adjustHeadingToLight m.pos target else m.heading <- m.heading + randomHeadingChange() // Randomly change heading when lamp is off m.pos <- move m.pos m.heading m) { state with moths = updatedMoths } | _ -> state |> Some // Initial state with lamp off and the initial list of moths let initialstate = { lamp = false; moths = initialMoths } // Start the simulation let interval = Some 100 interact "moth sim" width height interval draw react initialstate
Editor is loading...
Leave a Comment