Skip to content
Jim edited this page Oct 10, 2024 · 42 revisions

https://andymation.squarespace.com

README

Background

A flipbook is a series of drawings that are shown one after the other to give the illusion of movement.

In this homework, we'll make a simple flipbook animation program.

Take half an hour or so to experience some simple animation software:

We know we need to store a lot of data, but we don't know how much. How many drawings? How many strokes per drawing? How many points per stroke?

I guess we could just make some REALLY BIG arrays, but that seems...potentially sus.

Maybe instead we can try using arrays that grow (and shrink).

Enter, the array list!

Math

Mirroring about vertical and horizontal lines

  • Mirroring the point $(x, y)$ about the line $x = a$ gives $(-(x - a) + a, y) = (2a - x, y)$
  • Mirroring the point $(x, y)$ about the line $y = b$ gives $(x, -(y - b) + b) = (x, 2b - y)$

Java

ArrayList<ElementType>

  • Java's ArrayList<ElementType> is generic, which means you get to choose what type ElementType is.
    • ArrayList<Point> stroke = new ArrayList<>(); is a list of points, storing a single stroke.
    • ArrayList<ArrayList<Point>> page = new ArrayList<>(); is a list of lists of points, aka a list of strokes, aka a page (of the flipbook)
    • ArrayList<ArrayList<ArrayList<Point>>> flipbook = new ArrayList<>(); is a list of lists of lists of points, aka a list of lists of strokes, aka a list of pages, aka a flipbook
    • ...

Point

  • My Point class is super simple
    • Point point = new Point(x, y); makes a new point with coordinates $(x, y)$
    • point.x, point.y are the point's $x$ and $y$ coordinates

User Interface

Simple Example

  • flipbook.size() is 1
  • currentFrame is 0
  • the flipbook consists of...
    • a single blank page
     |
     V
     0
    [ ]
  • the user draws the letter 'A'
     |
     V
     0
    [A]
  • the user presses S
          |
          V
     0    1 
    [A]  [ ]

More Advanced Example

  • flipbook.size() is 4
  • currentFrame is 2
  • there flipbook consists of...
    • page with drawing of the letter A on page 0
    • page with drawing of the letter B on page 1
    • page with drawing of the letter C on page 2
    • page with drawing of the letter E on page 3
               |
               V      
    [A]  [B]  [C]  [E]
    
  • the user presses S ("save"), which inserts a blank page and takes us to it
    • flipbook.size() is 5
    • currentFrame is 3
                    |
                    V      
    [A]  [B]  [C]  [ ]  [E]
    
  • the user draws a D
                    |
                    V      
    [A]  [B]  [C]  [D]  [E]
    
  • the user presses . ("next page")
                         |
                         V      
    [A]  [B]  [C]  [D]  [E]
    
  • the user presses .
    • NOTE: the flipbook is treated as circular (it "wraps around")
     |
     V      
    [A]  [B]  [C]  [D]  [E]
    
  • the user presses , ("previous page")
                         |
                         V      
    [A]  [B]  [C]  [D]  [E]
    

Reference

YouTube Link: https://youtu.be/s7KWD2pG-Qk

out

TODO

  • A-

    • Update Cow
    • Draw the drawing on the current page in BLACK
    • Click and drag to draw strokes
      • HINT: You should create a new stroke when mousePressed is true
      • HINT: You should add points to the stroke when mouseHeld is true
    • Press S to insert a new blank page of immediately after the current page, and go to it
    • Press . (period) to go to the next page
      • NOTE: Treat the animation as circular
        • HINT: You can use MODULO(x, y), which is like x % y but works for negative x
    • Press , (comma) to go to the previous page
      • NOTE: Again, treat the animation as circular
    • Press P to play (or pause, if the animation is currently playing)
      • HINT: You will want something like a boolean paused; variable
      • NOTE: Like the Reference, your animation should play slowly enough that you can actually see what's going on!
        • HINT: Use a frame or time variable so that you only "flip the page" about once every three Cow frames
        • NOTE: You may NOT use Thread.sleep(...); or similar; we want the app to remain responsive
    • Call HW04_drawTimeline(int numPagesTotal, int currentPageIndex); to draw the timeline (you will have to fill in the arguments yourself)
    • Copy over your code that draws the pause / play icons (⏯️) from HW01
  • A

    • Press X to mirror the drawing on the current page (NOT all pages) horizontally about the line $x = 128.0$
    • Press Y to mirror the drawing on the current page (NOT all pages) vertically about the line $y = 128.0$
    • Press O to toggle drawing basic, two-frame onion skinning.
      • Draw the page two pages before the current page in YELLOW
        • HINT: MODULO(..., flipbook.size())
      • Draw the page one page before the current page in ORANGE
      • Draw the page one page after the current page in BLUE
      • Draw the page two pages after the current page in CYAN
      • NOTE: For all of the above, make sure your code does something reasonable when there are fewer than 5 pages
      • NOTE: Treat the animation as circular
      • NOTE: You may NOT repeat a bunch of code
      • Draw some little symbol in the lower left to indicate if onion skinning is toggled on
  • A+

  • A++ (105)

    • Upgrade the mini map timeline; inspo:
      • Scroll (two finger drag on laptop) to scroll through the timeline
        • NOTE: Hot new Cow.java feature -- double mouseScrollAmount;
      • Click to select current page
      • Click and drag to rearrange pages

Starter Code

import java.util.ArrayList;
class HW04 extends Cow {

	static class Point {
		double x;
		double y;

		Point(double x, double y) {
			this.x = x;
			this.y = y;
		}
	};

	public static void main(String[] arguments) {

		// TODO

		canvasConfig(0.0, 0.0, 256.0, 256.0);
		while (beginFrame()) {

			// TODO

			// HW04_drawTimeline(numPagesTotal, currentPageIndex);
		}
	}

}

HINT

Where do I start?

You'll definitely want to build up this app step by step. I would personally start by making it so the user can draw a single stroke (a list of points).

Here is some code that shows you how to work with Point, drawLine(...), and ArrayList. You will need to change it a lot (there will be a for loop for sure.)

public static void main(String[] arguments) {
    ArrayList<Point> foo = new ArrayList<Point>();
    foo.add(new Point(0.0, 0.0));
    foo.add(new Point(64.0, 128.0));
    while (beginFrame()) {
        drawLine(foo.get(0).x, foo.get(0).y, foo.get(1).x, foo.get(1).y);
        drawLine(foo.get(1).x, foo.get(1).y, mouseX, mouseY);
    }
}
How should I structure my code? What functions should I add?

I did all of the A until onion skinning in main(); then I added function something like this:

static void drawPage(ArrayList<ArrayList<ArrayList<Point>>> flipbook, int pageIndex, Color color);
How do I access the last element in a list? (**NOTE:** It's possible to solve the homework without doing this, but you may possibly find it useful.)
list.get(list.size() - 1)
Clone this wiki locally