Plop

library(chipmunkbasic)
library(ggplot2)
set.seed(1)

#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Initialize a simulation space
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
cm <- Chipmunk$new(time_step = 0.005, gravity = cpv(0, -30))

#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Add floor with bucket
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
cm$add_static_segment(-70, 0,  70,  0, elasticity = 0.9)
cm$add_static_segment(-20, 0, -30, 20)
cm$add_static_segment( 20, 0,  30, 20)


#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Fetch all the segments. Use for plotting
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
segments_df <- cm$get_static_segments()

ggplot() + 
  geom_segment(data = segments_df, aes(x = x1, y = y1, xend = x2, yend = y2)) + 
  coord_fixed() + 
  theme_void() + 
  theme(legend.position = 'none')

Add some circles

#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Add some circles in the bucket
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Nballs <- 100
for (i in seq_len(Nballs)) {
  cm$add_circle(
    x          = runif(1,  -20,  20), 
    y          = runif(1,  0, 20),
    radius     = runif(1, 1, 3),
    friction   = 0.01,
    elasticity = 0.9
  )
}


#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Add the bowling ball
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
cm$add_circle(
  x        = -70,
  y        = 10,
  radius   = 10,
  mass     = 200,
  vx       = 15,
  vy       = 70,
  friction = 0.01
)

Animate!

  • Advance the state of the simulation
  • get the positions of all the circles
  • Plot everything.
  • Repeat
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Prepare the directory for output images
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
root_dir <- here::here("vignettes")
png_dir  <- file.path(root_dir, "png")
unlink(list.files(png_dir, pattern = "*.png", full.names = TRUE))


steps <- 600; advance <-  6

#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# (1) advance the simulation (2) plot the circles (3) Repeat.
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
for (i in seq_len(steps)) {
  
  if (i  %% 10 == 0) message(i)
  
  cm$advance(advance)
  
  circles <- cm$get_circles()
  large   <- circles[Nballs + 1,]
  circles <- circles[seq_len(Nballs),]
  
  
  p <- ggplot() + 
    geom_point(data = circles, aes(x, y, size = I(2.845*r)), colour = 'black') + 
    geom_point(data = large , aes(x, y), size = 30 , colour = '#002366') + 
    geom_segment(data = segments_df, aes(x = x1, y = y1, xend = x2, yend = y2), colour = 'lightblue') + 
    coord_fixed(xlim = c(-70, 70), ylim = c(0, 100)) + 
    theme_void() +
    theme(legend.position = 'none') 
  

  outfile <- sprintf("vignettes/png/%04i.png", i)
  ggsave(outfile, p, width = 7, height = 7)
}


#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# ffmpeg/gifsicle to create animations
#  - create mp4 from PNG files (use in vignettes)
#  - create gif from mp4 (use in github readme)
#  - simplify gif with gifsicle
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
root_name <- "plop"
mp4_name  <- paste0(root_dir, "/anim/", root_name, ".mp4")
tmp_name  <- tempfile(fileext = ".gif")
gif_name  <- paste0(root_dir, "/anim/", root_name, ".gif")

system(glue::glue("ffmpeg -y -framerate 30 -pattern_type glob -i '{png_dir}/*.png' -c:v libx264 -pix_fmt yuv420p -s 800x800 '{mp4_name}'"))
# system(glue::glue("ffmpeg -y -i '{mp4_name}' -filter_complex 'fps=30,scale=800:-1:flags=lanczos,split [o1] [o2];[o1] palettegen [p]; [o2] fifo [o3];[o3] [p] paletteuse' '{tmp_name}'"))

# system(glue::glue("gifsicle -O99 -o '{gif_name}' -k 128 '{tmp_name}'"))