---
title: "Animation"
output: rmarkdown::html_vignette
vignette: >
  %\VignetteIndexEntry{Animation}
  %\VignetteEngine{knitr::rmarkdown}
  %\VignetteEncoding{UTF-8}
---

```{r, include = FALSE}
knitr::opts_chunk$set(
  collapse = TRUE,
  comment = "#>"
)
```

```{r setup, echo = FALSE}
library(nara)
```


Animating with `{nara}` is simply a matter of generating and displaying 
multiple images - hopefully quickly enough to look smooth.

There are two approaches:

1. Render all the images into a list, and then save as a video file e.g. `.gif`, `.mp4`
2. Display the images to a fast graphics device


## Render to a video file

To render to a video file, `{nara}` use `nrs_to_gif()` and `nrs_to_mp4()`.
These functions are simple wrappers around the 
[`{magick}`](https://cran.r-project.org/package=magick) package.

The code below:

* sets up `N` circles with positions and velocities
* for each frame
    * create a new image
    * advance the circle positions
    * draw circles
    * add image to the list of all images
* saves the list of images to a `.gif`

```{r eval=FALSE}
library(nara)
w <- 320
h <- 200

set.seed(1)
N <- 20
xs   <- runif(N, 0, w)
ys   <- runif(N, 0, h)
rs   <- runif(N, 2, 6)  
vx   <- rnorm(N, sd = 3)
cols <- sample(heat.colors(N))

# Storage for animation frames
anim <- list()

for (i in seq(30)) {
  # create image
  nr <- nr_new(w, h, fill = 'grey90')
  
  # update the x position and wraparound
  xs <- xs + vx
  xs <- ifelse(xs < 0, xs + w, xs)
  xs <- ifelse(xs > w, xs - w, xs)
  
  # draw circles
  nr_circle(nr, xs, ys, rs, cols)
  
  # store animatino frame
  anim[[i]] <- nr  
}

nrs_to_gif(anim, "working/demo.gif")
# nrs_to_mp4(anim, "working/demo.mp4")
```


## Render to a fast graphics device

If your graphics device updates fast enough, then you can show images on this
device quickly and have the appearance on smooth animation.

A major problem for most platforms: **Rstudio and Positron graphics devices 
are not fast enough to do this**

Instead, if you are wanting to use a built-in graphics device, the
`x11()` device is the preferred graphics output for animation.

`x11()` device is supported on macos, linux and windows (where it a lightweight 
wrapper around the standard `windows()` device).

A good way to setup this device for fast animation is to:

1. Call `x11()`
2. Set the type to double buffered Cairo rendering `type = 'dbcairo'`
3. Disable the *display list* as there's no need to record graphics operations
4. Use `dev.hold()` and `dev.flush()` calls to synchronise the drawing command
   with the graphics display update (this can prevent tearing).
5. A small pause may be needed in the loop, otherwise things might go *too* fast!

See code below for an example:

```{r eval=FALSE}
x11(..., type = 'dbcairo', antialias = 'none')
dev.control(displaylist = 'inhibit')

for (i in seq(nframes)) {
  nr <- generate_image_somehow()
  dev.hold()
  plot(nr)
  dev.flush()
  Sys.sleep(0.03) # Sleep maybe?
}
```


Note: Particular platforms may have differing parameters to give good results for
realtime animation - you might need to experiment to get the best out of your 
platform.

















