Here you will find the source code for the pirate animation, as described in the upcoming book Graphic Guide to R

Copyright 2018 Antony Lees

Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.
 settings <- function() {
  size(300, 300) 
}

setup <- function() {
  ships <<- list() # list for ships
  for (i in 1:10) {
    ship <- pirate_ship()
    # initialise
    ship <- initialise(ship)
    # Add the object to the list
    ships[[length(ships) + 1]] <- ship 
  }
  # waves
  wave_max_height <<- 20
  wave_min_height <<- 5
  wave_height <<- wave_max_height   
  up <<- 1
  down <<- -1
  wave_direction <<- up

}

draw <- function() {
  # light blue background
  background(102, 205, 170)
  # waves
  noFill()
  # wave y coordinate
  wave_y <- wave_max_height/2
  # while the y coordinate is less than the height of the window
  while (wave_y <= height) {
    # wave x coordinate
    wave_x <- 0
    # while the x coordinate is less than the width of the window
    while (wave_x <= width) {
            # draw a semi-circle arc
            arc(wave_x, wave_y, wave_max_height, wave_height, 0, PI)
            # increase the x coordinate by 20
            wave_x <- wave_x + wave_max_height
    }
    # increase the y coordinate by 20
    wave_y <- wave_y + wave_max_height
  }
  # determine of the waves should be going up or down
  if (wave_height <= wave_min_height) {
    wave_direction = up
  }
  if (wave_height >= wave_max_height) {
    wave_direction = down
  }
  # change the wave height for next time
  wave_height <<- wave_height + wave_direction


  # ships
  for (i in 1:length(ships)) {
    ship <- ships[[i]]
    display(ship)
    ship <- move(ship)
    if (ship$x + ship$length < 0) {
      ship <- initialise(ship)
    }
    ships[[i]] <- ship
  }
}

# pirate ship class
pirate_ship <- function() {
   structure(
     list(
       x = 0,
       y = 0,
       length = 60,
       sails = 0,
       sail_colour = 0,
       porthole_count = 0,
       sail_spacing = 0,
       speed = 0
     ),
    class = "pirate_ship"
  )
}

initialise <- function(obj) { # generic method
  UseMethod("initialise") 
}

initialise.pirate_ship <- function(obj) {
       obj$x <- width
       obj$y <- random(50,350)
       obj$length <- random(40,100)
       obj$sails <- min(obj$length/30,3)
       obj$sail_colour <- color(random(255),random(255),random(255))
       obj$porthole_count <- obj$length/12
       obj$sail_spacing <- obj$length/3
       obj$speed <- obj$length/20
       return(obj)
}

display <- function(obj) { # generic method
  UseMethod("display") 
}

display.pirate_ship <- function(obj) {
  # calculate ship coordinates
  front_of_ship_x_position <- obj$x - (obj$length / 2)
  back_of_ship_x_position <- obj$x + obj$length + (obj$length / 3)

  # ship hull
  # brown lines and fill
  stroke(139, 71, 38)
  fill(139, 71, 38)
  # middle rectangle
  rect(obj$x, obj$y, obj$length, 20)
  # front and back
  triangle(front_of_ship_x_position, obj$y, obj$x, obj$y, obj$x, obj$y + 20)
  triangle(obj$x + obj$length, obj$y, back_of_ship_x_position, obj$y, obj$x + obj$length, obj$y + 20)
  
  # draw the sails
  initial_sail_x_position = obj$x
  for (i in 1:obj$sails) {
    # black lines
    stroke(0)
    # sail
    fill(obj$sail_colour)
    quad(initial_sail_x_position + (obj$sail_spacing * i), obj$y - 40, initial_sail_x_position + (obj$sail_spacing * i) + 10, obj$y - 40, initial_sail_x_position + (obj$sail_spacing * i) + 20, obj$y - 10, initial_sail_x_position + (obj$sail_spacing * i), obj$y - 10)
    # mast
    fill(0)
    line(initial_sail_x_position + (obj$sail_spacing * i), obj$y - 10, initial_sail_x_position + (obj$sail_spacing * i), obj$y)
    line(initial_sail_x_position + (obj$sail_spacing * i), obj$y - 40, initial_sail_x_position + (obj$sail_spacing * i), obj$y - 50)
    
    # flag
    fill(0)
    rect(initial_sail_x_position + (obj$sail_spacing * i), obj$y - 50, 10, 5)
    # jolly roger
    stroke(255)
    line(initial_sail_x_position + (obj$sail_spacing * i) + 2, obj$y - 49, initial_sail_x_position + (obj$sail_spacing * i) + 8, obj$y - 46)
    line(initial_sail_x_position + (obj$sail_spacing * i) + 8, obj$y - 49, initial_sail_x_position + (obj$sail_spacing * i) + 2, obj$y - 46)
  }

  # draw the portholes
  stroke(0)
  for (i in 1:obj$porthole_count) {
    # portholes
    fill(0)
    ellipse(obj$x+(15*(i-1)),obj$y+10,5,5)
  }
}

move <- function(obj) { # generic method
  UseMethod("move") 
}

move.pirate_ship <- function(obj) {
  obj$x <- obj$x - obj$speed
  return(obj)
}