-
Notifications
You must be signed in to change notification settings - Fork 0
HW04
A flipbook is a series of drawings that are shown one after the other to give the illusion of movement.
- Optional Reading: Animator's Survival Kit
In this homework, we'll make a simple flipbook animation program.
- Fun, historical animated gifs: https://reedart.wordpress.com/2013/08/19/animated-gifs-illustrating-traditional-animation-techniques/
Take half an hour or so to experience some simple animation software:
- Make a simple animation in Brush Ninja
- NOTE: You can press
O
to toggle onion skinning
- NOTE: You can press
- Watch a video about DigiCel's FlipBook
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!
- 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's
ArrayList<ElementType>
is generic, which means you get to choose what typeElementType
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 - ...
-
- 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
-
-
flipbook.size()
is1
-
currentFrame
is0
- 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] [ ]
-
flipbook.size()
is4
-
currentFrame
is2
- 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]
- page with drawing of the letter
- the user presses
S
("save"), which inserts a blank page and takes us to it-
flipbook.size()
is5
-
currentFrame
is3
| 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]
YouTube Link: https://youtu.be/s7KWD2pG-Qk
-
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
-
HINT: You should create a new stroke when
- Press
S
to insert a new blank page of immediately after the current page, and go to it- NOTE (ABCE correct behavior): https://youtu.be/ArXLMKMIPIk
- Press
.
(period) to go to the next page-
NOTE: Treat the animation as circular
-
HINT: You can use
MODULO(x, y)
, which is likex % y
but works for negativex
-
HINT: You can use
-
NOTE: Treat the animation as circular
- 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
-
HINT: You will want something like a
- 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())
-
HINT:
- 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
- Draw the page two pages before the current page in YELLOW
- Press
-
A+
- Implement an eraser tool (that deletes whatever stroke you click closest to)
- "Mini map" timeline with tiny versions of each page so you can see and overview the whole animation at once
- Inspo: https://github.com/user-attachments/assets/529a629d-83c8-4ec7-8b61-e3eec689957f
-
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;
-
NOTE: Hot new Cow.java feature --
- Click to select current page
- Click and drag to rearrange pages
- Scroll (two finger drag on laptop) to scroll through the timeline
- Upgrade the mini map timeline; inspo:
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);
}
}
}
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)