# Getting Started with boids4R

`boids4R` simulates flocking and swarm dynamics in R. The core objects are renderer-neutral: they describe boids, rules, worlds, and recorded frames.

    library(boids4R)

    sim <- boids_scenario("schooling_2d", n = 80, steps = 20, seed = 12)
    frames <- as.data.frame(sim)
    head(frames)
    #>   frame time         id species           x           y z          vx
    #> 1     0    0 boid-00001    boid -2.19958677  1.25804205 0 -0.02683391
    #> 2     0    0 boid-00002    boid  0.34519521  0.01271507 0  0.05059609
    #> 3     0    0 boid-00003    boid -1.90403899 -0.89780400 0  0.13404070
    #> 4     0    0 boid-00004    boid  0.01672697 -0.69175552 0  0.15357851
    #> 5     0    0 boid-00005    boid -0.46988986 -0.23499981 0 -0.07141984
    #> 6     0    0 boid-00006    boid  0.56104504  0.15811094 0  0.21125602
    #>            vy vz      speed
    #> 1  0.02341728  0 0.03561499
    #> 2 -0.40515990  0 0.40830688
    #> 3 -0.13518897  0 0.19037586
    #> 4 -0.29706520  0 0.33441604
    #> 5  0.09770255  0 0.12102306
    #> 6 -0.10675316  0 0.23669674

The same frame table can be handed to visualization packages. If `ggWebGL` 0.4.0 or later is installed, the optional adapter creates point and velocity-vector primitives with exact timeline controls.

    if (requireNamespace("ggWebGL", quietly = TRUE) &&
        utils::packageVersion("ggWebGL") >= "0.4.0") {
      ggWebGL::ggWebGL(as_ggwebgl_spec(sim), height = 440)
    }

For larger examples, see the scenario gallery and custom simulation workflow vignettes. They show obstacle corridors, predator avoidance, parameter sweeps, and mixed-species 3D runs using the same renderer-neutral frame output.

To generate a standalone WebGL page for an external browser:

    stopifnot(
      requireNamespace("ggWebGL", quietly = TRUE),
      utils::packageVersion("ggWebGL") >= "0.4.0"
    )

    sim <- boids4R::boids_scenario("murmuration_3d", n = 400, steps = 150, seed = 1)

    spec <- boids4R::as_ggwebgl_spec(sim)
    spec$render$timeline$autoplay <- TRUE
    spec$render$timeline$speed <- 2

    w <- ggWebGL::ggWebGL(spec, height = 520)

    htmlwidgets::saveWidget(w, "boids_murmuration.html", selfcontained = FALSE)
    browseURL(normalizePath("boids_murmuration.html"))

To see trajectories, not only moving current positions, use cumulative line trails:

    frames <- as.data.frame(sim)
    keep <- unique(frames$id)[1:120]
    trail <- frames[frames$id %in% keep, ]

    line_layer <- ggWebGL::ggwebgl_layer_lines(
      trail,
      x = "x", y = "y", z = "z",
      group = "id",
      colour = "#334155",
      alpha = 0.08,
      width = 0.7,
      frame = "frame",
      time = "time"
    )

    point_layer <- ggWebGL::ggwebgl_layer_points(
      frames,
      x = "x", y = "y", z = "z",
      colour = "#2563eb",
      alpha = 0.45,
      size = 2,
      id = "id",
      frame = "frame",
      time = "time"
    )

    spec <- ggWebGL::ggwebgl_spec(
      list(line_layer, point_layer),
      webgl = list(
        view = ggWebGL::ggwebgl_view("3d", controller = "orbit", projection = "perspective")
      ),
      timeline = ggWebGL::ggwebgl_timeline(
        frames = sort(unique(frames$frame)),
        filter = "cumulative",
        autoplay = TRUE,
        speed = 2
      )
    )

    htmlwidgets::saveWidget(ggWebGL::ggWebGL(spec, height = 520), "boids_trails.html")
    browseURL(normalizePath("boids_trails.html"))