-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathflubber.R
92 lines (70 loc) · 1.82 KB
/
flubber.R
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
#' Flubber (1997)
source("util.R")
library(ggplot2)
library(dplyr)
library(purrrlyr)
PATH = 'img/animation/flubber_{i}.png' # path to save the images
M = 0.11
DECAY = 1.2
MAX_SPEED = 55
N_BALLS = 10
#' Returns a random ball
random_ball = function() {
x = runif(min = -5, max = 5, n = 1)
v_x = rnorm(mean = 0, sd = 2.5, n = 1)
a_x = 0
y = runif(min = 10, max = 20, n = 1)
v_y = rnorm(mean = 0, sd = 2, n = 1)
a_y = -8
color = random_color()
data.frame(x, v_x, a_x, y, v_y, a_y, color)
}
#' Creates next frame for projectiles
update_balls_df = function(balls) {
if (is_valid_dataframe(balls)) {
purrrlyr::by_row(balls, update_ball_row, .collate = "rows", .labels = F) %>%
select(-.row)
}
}
#' Updates a single row of the dataframe
#'
#' TODO: generalize this function to
update_ball_row = function(row) {
new = update_projectiles(row)
# bounce off of y walls
if (new$y < 0 || new$y > 50) {
new$y = round(new$y) # set to 0 to avoid clipping
new$v_y = DECAY * -1 * new$v_y
}
# max speed
if (new$v_y > MAX_SPEED) {
new$v_y = MAX_SPEED
} else if (new$v_y < -MAX_SPEED) {
new$v_y = -MAX_SPEED
}
# bounce off of x walls
if (new$x <= -5 || new$x >= 5) {
new$x = round(new$x)
new$v_x = -1 * new$v_x
}
new
}
balls = data.frame()
for (i in 1:N_BALLS) {
new_ball = random_ball()
balls = bind_rows(balls, new_ball)
}
color_anchor = data.frame(y = c(0, 50)) # we need two invisible points at min_y and max_y to "anchor" the color scale
for (i in 0:300) {
plt =
balls %>% bind_rows(color_anchor) %>%
ggplot() +
geom_point(aes(x, y, color = color), size = 2) +
theme_physics()
# write plot
fpath = glue::glue(PATH, i=i)
ggsave(filename = fpath, plot = plt, width = 1.5, height = 1.5)
message(fpath)
print(balls)
balls = update_balls_df(balls)
}