Untitled
unknown
fsharp
a year ago
3.1 kB
10
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