Stick Figure Animation NetLogo Model

Produced for the book series "Artificial Intelligence";

Author: W. J. Teahan; Publisher: Ventus Publishing Aps, Denmark.

powered by NetLogo

view/download model file: Stick-Figure-Animation.nlogo

WHAT IS IT?

This model allows you to create your own stick figure animations and export them to files for importing latter on, or export them to QuickTime movie files. The model was inspired by the Pivot Stick Figure Animator application created by Peter Bone.


THE INTERFACE

The Interface buttons are defined as follows:

- start-recording: This resets the animation sequence.

- record-this-frame: This takes a snapshot of whatever is currently on the screen, and adds it as a next frame to the animation sequence.

- play-frames: This will play (once) all the frames recorded in the animation sequence. The delay between playing each frame in the sequence is specified by the frame-delay slider. Which frame is being played is shown by the frame-number monitor.

- play forever: This will play the recorded frames repeatedly.

- show-all-frames: This shows all recorded frames superimposed on top of one another with their frame numbers shown.

- create-new-figure: This draws a new stick figure on the screen at the mouse's current position when the mouse is next clicked. The colours of the stick figure are specified by the head-colour, point-colour and line-colour sliders.

- select-object: This allows the user to select an object (the head of a stick figure or one of its pivot points) so that it can be moved.

- erase-object: This allows the user to erase an object.

- select-region: This allows the user to select multiple objects inside a rectangular region in order to move them.

- erase-region: This allows the user to erase objects inside a region.

- export-animation: This exports the animation to a file on disk so that it can be imported at a latter date. (Note: This will not work from an applet. Download the model file, and run it directly).

- import-animation: This imports the animation from a file already saved on disk. (Note: This will not work from an applet. Download the model file, and run it directly).

- export-movie: This exports the animation to a QuickTime movie file. The movie frame rate is specified by the movie-frame-rate slider. (Note: This will not work from an applet. Download the model file, and run it directly).

- draw-text: This allows the user to draw some text at the mouse's current position when the mouse is next clicked. The text that is drawn is specified by the text-string box and its font size and colour is specified by the text-size and text-colour sliders.


HOW IT WORKS

Each stick figure is drawn using three breeds of agents - a head turtle agent for representing the head; a point turtle agent for representing the stick figure's pivot points; and a line link agent for representing the body and limbs. In addition, a text turtle agent breed is used for drawing the text.

Recording is done by making use of NetLogo's show-turtle and hide-turtle commands. Only the current frame's agents are shown - the other recorded agents are hidden. Copies of the turtle agents and link agents from all the old recorded frames remain in the environment. These copies are stored in specific recording agent breeds - recorded-heads, recorded-points, recorded-lines and recorded-texts - so that the current frame's agents can easily be distinguished from the recorded frame's agents.
These recorded agents also have an additional variable - frame, hframe, lframe or tframe - that is used to store the frame number when they were recorded.

When the animation is played back, the procedure executes a while loop for each frame number. This procedure repeatedly hides all agents first, then only the recorded agents with the current frame number are shown.


HOW TO USE IT

Use the start-recording button to start recording the animation sequence. Add as many new stick figures as you want using the create-new-figure button. Move these figures around or delete them using the editing buttons - select-object, erase-object, select-region and erase-region.

Each time you want a particular screen to be recorded for the animation, press the record-this-frame button. Nothing is recorded until this button is pressed - the movement of the objects around while they are being edited will not end up being recorded in the animation sequence. You can play the animation sequence once by pressing the play-frames button, or have it loop continuously by pressing the play forever button.

When you are satisfied with the animation, either save it to disk using the export-animation button so that it can loaded latter using the import-animation button, or export it to a QuickTime movie using the export-movie button.


WHAT IS ITS PURPOSE?

This model has been inspired by the endless variety and sheer creativity of the countless stick figure animations that can be found in YouTube. The style of the model is reminiscent of the public domain Pivot Stick Figure Animator program created by Peter Bone.

Its purpose is to show how to do basic key-frame animation. A further purpose is to illustrate how movement is fundamental to an agent in an environment and can be used to distinguish its type of behaviour. The movement of the stick figure's body & head (a manifestation of its embodiment) can also be decomposed down to movement of individual parts of its body & head.


THINGS TO TRY

Try creating elaborate stick figure animations. You are only limited by your imagination. If you get stuck, look at some stick figure animations on YouTube.


EXTENDING THE MODEL

Try allowing the user to add other objects such as trees, cars and buildings.

A quick look in YouTube will show that one particular variety of animation occurs frequently - stop-frame animation using Lego characters, especially Lego Star Wars. Alter this model to show Lego figures as well as stick figures (such as Lego Clone Troopers and a Lego Yoda).

Once this is done, then you can try creating an alternate Star Wars universe where the familiar Star Wars characters fight against the invading Stick Figures.


RELATED MODELS

See the Stick Figure Walking model.


CREDITS AND REFERENCES

To refer to this model in publications, please use:

Teahan, W. J. (2010). Stick Figure Animation NetLogo model.
Artificial Intelligence. Ventus Publishing Aps.


PROCEDURES

; Stick Figure Animation model.
;
; Key frame animation of a stick figure walking.
;
; Copyright 2010 William John Teahan. All Rights Reserved.
;

breed [points point]   ; points associated with with the stick figure
breed [heads head]     ; for drawing the head

breed [texts text]     ; for writing text

breed [region-sides region-side]       ; the four sides of the selection square

breed [recorded-points recorded-point] ; points recorded for latter playback
breed [recorded-heads recorded-head]   ; heads recorded for latter playback
breed [recorded-texts recorded-text]   ; texts recorded for latter playback

undirected-link-breed [lines line]     ; links for drawing the body and limbs
undirected-link-breed [recorded-lines recorded-line] ; lines recorded for latter playback

points-own
[ child ]              ; used for recording lines between points

recorded-points-own
[ frame ]              ; number of frame the recorded point is associated with
recorded-heads-own
[ hframe ]             ; number of frame the recorded head is associated with
recorded-texts-own
[ tframe ]             ; number of frame the recorded text is associated with
recorded-lines-own
[ lframe ]              ; number of frame the recorded line is associated with

globals
[ frames               ; how many frames so far
  frame-number         ; the current frame-number
  exporting-movie      ; true if exporting animation as a movie
  selected ]           ; agentset of currently selected objects

to start-recording

  if (frames > 0)
  [ if not user-yes-or-no? "Do you really wish to delete the current recording and start again?"
    [ stop ]]
  
  clear-all
  set frames 0 ; no frames so far
  set exporting-movie false
  
  set-default-shape points "circle"  ; this is the shape of the points
  set-default-shape heads "circle 2" ; this is the shape of the stick figures' heads

  set-default-shape recorded-points "circle"  ; this is the shape of the recorded points
  set-default-shape recorded-heads "circle 2" ; this is the shape of the recorded stick figures' heads

  set-default-shape region-sides "line" ; this is the shape of the selected region sides
  
  ;; initially, no turtles are selected
  set selected no-turtles
end

to record-this-frame
; records current "frame" by copying all the agents and links,
; making them all invisible, after setting their frame number
; for latter play back

  let this-child nobody
  let that-child nobody
  let this-colour white
  let this-thickness 1
  let this-frame 0
  
  ask points
  [ ; record all current points in this frame for posterity
    hatch-recorded-points 1 ; make a copy of this point
    [ set frame frames ; store the frame number
      hide-turtle ; hide this point for now
      set this-child self ]
    set child this-child ; store pointer to allow copying of links latter
  ]

  ask points
  [ ; record all their links for posterity as well
    set this-child child
    ask my-links
    [ ; copy this link
      set that-child [child] of other-end
      set this-colour color
      set this-thickness thickness
      ask this-child ; make a recording of this link
      [ create-new-recorded-line that-child this-colour this-thickness frames ]
    ]
  ]

  ask heads
  [ ; record all current heads in this frame for posterity
    hatch-recorded-heads 1 ; make a copy of this head
    [ set hframe frames ; store the frame number
      hide-turtle ] ; hide this head for now
  ]

  ask texts
  [ ; record all current texts in this frame for posterity
    hatch-recorded-texts 1 ; make a copy of this text
    [ set tframe frames ; store the frame number
      hide-turtle ] ; hide this text for now
  ]
  
  set frames frames + 1
end

to create-new-line [ this-turtle colour this-thickness this-frame ]
; for setting up the link

  create-line-with this-turtle
  [
    set thickness this-thickness
    set color colour
  ]
end

to create-new-recorded-line [ this-turtle colour this-thickness this-frame ]
; for setting up a recorded link

  create-recorded-line-with this-turtle
  [
    set lframe this-frame
    set thickness this-thickness
    set color colour
    hide-link
  ]
end

to play-frames
; creates an animation by playing all the frames that have been
; recorded as invisible turtles and links
  
  set frame-number 0
  while [frame-number < frames]
  [ ; display all the frames in sequence
    ask turtles [ hide-turtle ] ; hide all turtles first
    ask links [ hide-link ]     ; hide the links as well

    ask recorded-heads with [hframe = frame-number]
    [ show-turtle ]
    ask recorded-points with [frame = frame-number]
    [ show-turtle ]
    ask recorded-texts with [tframe = frame-number]
    [ show-turtle ]
    ask recorded-lines with [lframe = frame-number]
    [ show-link ]

    display
    if (exporting-movie)
      [ movie-grab-view ]

    wait frame-delay
    
    set frame-number frame-number + 1
  ]
  
  ; reset to current non-recorded agents

  ask turtles [ hide-turtle ] ; hide all turtles first
  ask links [ hide-link ]     ; hide the links as well

  ask heads [ show-turtle ]
  ask points [ show-turtle ]
  ask texts [ show-turtle ]
  ask lines [ show-link ]    
end

to show-all-frames
;; for showing where all the turtle and link agents are
;; (for debugging purposes)

  ; hide everything first
  ask turtles [ hide-turtle ]
  ask links [ hide-link ]
  
  ask recorded-points
  [ show-turtle
    set label (word frame) ]
  ask recorded-heads
  [ show-turtle
    set label (word hframe) ]
  ask recorded-lines
  [ show-link
    set label (word lframe) ]
end

to import-animation
; imports a saved animation
  import-world user-file
end

to export-animation
; exports an animation
  export-world user-new-file
end

to export-movie
; exports the animation as a Quick time movie
  movie-start user-new-file
  movie-set-frame-rate movie-frame-rate

  set exporting-movie true
  play-frames
  set exporting-movie false

  movie-close  
end

to create-new-text
  set label-color text-colour
  set size 0 ; only want to see the label, not the turtle
  set label text-string
  setxy mouse-xcor mouse-ycor
  while [mouse-down?] [
    display
    setxy mouse-xcor mouse-ycor
  ]
end

to draw-text
  if mouse-down? [
      create-texts 1 [ create-new-text ]
  ]
end

to-report create-figure [xpos ypos head-size body-size]
;; creates a stick figure at xpos ypos
  let me nobody
  
  create-heads 1 
  [
    set size head-size
    set color head-colour
    setxy xpos ypos + body-size + head-size / 2
  ]

  let half-size body-size / 2
  let third-size body-size / 3

  let neck create-new-point xpos (ypos + body-size) 2 point-colour frames
  let bottom create-new-point xpos ypos 2 point-colour frames

  let left-elbow create-new-point (xpos - half-size) (ypos + half-size) 2 point-colour frames
  let right-elbow create-new-point (xpos + half-size) (ypos + half-size) 2 point-colour frames
  let left-hand create-new-point (xpos - body-size + 3) ypos 2 point-colour frames
  let right-hand create-new-point (xpos + body-size - 3) ypos 2 point-colour frames

  let left-knee create-new-point (xpos - third-size) (ypos - 2 * third-size) 2 point-colour frames
  let right-knee create-new-point (xpos + third-size) (ypos - 2 * third-size) 2 point-colour frames
  let left-foot create-new-point (xpos - 2 * third-size) (ypos - 4 * third-size) 2 point-colour frames
  let right-foot create-new-point (xpos + 2 * third-size) (ypos - 4 * third-size)  2 point-colour frames

  ask neck [ create-new-line bottom line-colour 1.5 frames ]
  ask neck [ create-new-line left-elbow line-colour 1 frames ]
  ask neck [ create-new-line right-elbow line-colour 1 frames ]

  ask left-elbow  [ create-new-line left-hand line-colour 1 frames ]
  ask right-elbow [ create-new-line right-hand line-colour 1 frames ]

  ask bottom [ create-new-line left-knee line-colour 1 frames ]
  ask bottom [ create-new-line right-knee line-colour 1 frames ]

  ask left-knee  [ create-new-line left-foot line-colour 1 frames ]
  ask right-knee [ create-new-line right-foot line-colour 1 frames ]
  
  report me
end

to create-new-figure
; creates a new figure at the mouse's position

  if (mouse-down?)
    [ let figure (create-figure mouse-xcor mouse-ycor 8 12)
      display
      stop ]
end

to delete-new-figure
; deletes the last figure

  ask max-n-of 10 points [who]
  [ set color green ]
  display
end

to-report create-new-point [xpos ypos this-size this-colour this-frame]
; creates a new point in the stick figure
  let me nobody
  
  create-points 1
  [
    set me self
    set size this-size
    set color this-colour
    setxy xpos ypos
  ]

  report me
end

to erase-object
; erases an object

  if mouse-down? [
    let candidate min-one-of turtles with [hidden? = false] [distancexy mouse-xcor mouse-ycor]
    if [distancexy mouse-xcor mouse-ycor] of candidate < 1
      [ ask candidate [ die ]]
    display
  ]
end

to select-object
;; selects an object in the environment and "watches" it
  if mouse-down? [
    let candidate min-one-of turtles with [hidden? = false] [distancexy mouse-xcor mouse-ycor]
    if [distancexy mouse-xcor mouse-ycor] of candidate < 1 [
      ;; The watch primitive puts a "halo" around the watched turtle.
      watch candidate
      while [mouse-down?] [
        ;; If we don't force the display to update, the user won't
        ;; be able to see the turtle moving around.
        display
        ;; The subject primitive reports the turtle being watched.
        ask subject [ setxy mouse-xcor mouse-ycor ]
      ]
      ;; Undoes the effects of watch.
      reset-perspective
    ]
  ]
end

to erase-region
;; erases the selected region
  ask selected [ die ]
  ask region-sides [ die ]
  display
  set selected no-turtles
  ;;handle-select
end

to select-region
  if mouse-down? [
    ifelse selected? mouse-xcor mouse-ycor
      [ handle-drag
        deselect ]
      [ handle-select ]
  ]
end

to handle-select
  ;; remember where the mouse pointer was located when
  ;; the user pressed the mouse button
  let old-x mouse-xcor
  let old-y mouse-ycor
  while [mouse-down?] [
    select old-x old-y mouse-xcor mouse-ycor
    ;; update the view, otherwise the user can't see
    ;; what's going on
    display
  ]
  ;; if no turtles are selected, kill off
  ;; the selection square and start over
  if not any? selected [ deselect ]
end

to handle-drag
  ;; remember where the mouse pointer was located when
  ;; the user pressed the mouse button
  let old-x mouse-xcor
  let old-y mouse-ycor
  if selected? old-x old-y [
    while [mouse-down?] [
      let new-x mouse-xcor
      let new-y mouse-ycor
      ;; we need to move both the selected turtles and the sides
      ;; of the selection square by the same amount that the
      ;; mouse has moved.  we do this by subtracting the current
      ;; mouse coordinates from the previous mouse coordinates
      ;; and adding the results to the coordinates of the turtles
      ;; and sides.
      ask selected
        [ setxy xcor + new-x - old-x
                ycor + new-y - old-y ]
      ask region-sides
        [ setxy xcor + new-x - old-x
                ycor + new-y - old-y ]
      set old-x new-x
      set old-y new-y
      ;; update the view, otherwise the user can't see
      ;; what's going on
      display
    ]
  ]
end

to deselect
  ask region-sides [ die ]
  ask selected [ set color point-colour ]
  set selected no-turtles
end

to select [x1 y1 x2 y2]   ;; x1 y1 is initial corner and x2 y2 is current corner
  deselect  ;; kill old selection square
  make-side x1 y1 x2 y1
  make-side x1 y1 x1 y2
  make-side x1 y2 x2 y2
  make-side x2 y1 x2 y2
  set selected turtles with [selected? xcor ycor and hidden? = false] 
  ask selected [ set color red ]
end

to make-side [x1 y1 x2 y2]
  ;; for each side, one thin line shape is created at the mid point of each segment
  ;; of the bounding box and scaled to the proper length
  create-region-sides 1 [
    set color gray
    setxy (x1 + x2) / 2
          (y1 + y2) / 2
    facexy x1 y1
    set size 2 * distancexy x1 y1
  ]
end

;; helper procedure that determines whether a point is
;; inside the selection square
to-report selected? [x y]
  if not any? region-sides [ report false ]
  let y-max max [ycor] of region-sides   ;; largest ycor is where the top is
  let y-min min [ycor] of region-sides   ;; smallest ycor is where the bottom is
  let x-max max [xcor] of region-sides   ;; largest xcor is where the right side is
  let x-min min [xcor] of region-sides   ;; smallest xcor is where the left side is
  ;; report whether the input coordinates are within the square
  report x >= x-min and x <= x-max and
         y >= y-min and y <= y-max
end
;
; Copyright 2010 by William John Teahan.  All rights reserved.
;
; Permission to use, modify or redistribute this model is hereby granted,
; provided that both of the following requirements are followed:
; a) this copyright notice is included.
; b) this model will not be redistributed for profit without permission
;    from William John Teahan.
; Contact William John Teahan for appropriate licenses for redistribution for
; profit.
;
; To refer to this model in publications, please use:
;
; Teahan, W. J. (2010).  Stick Figure Walking NetLogo model.
;   Artificial Intelligence. Ventus Publishing Aps.
;