我已经解析了电子游戏《反恐精英》中有关手榴弹投掷的一些数据。样本数据显示,我在投掷手榴弹的位置,手榴弹的爆炸位置以及投掷手榴弹的时间上都有自己的位置。
df <- data.frame(pos_x = c(443.6699994744587,459.4566921116250, 443.5131582404877, 565.8823313012402, 725.3048665125078, 437.3428992800084, 475.7286794460795, 591.4138769182258),
pos_y = c(595.8564633895517, 469.8560006170301, 558.8543552036199, 390.5840189222542, 674.7983854380914, 688.0909476552858, 468.4987145207733, 264.6016042780749),
plot_group = c(1, 1, 2, 2, 3, 3, 4, 4),
round_throw_time = c(31.734375, 31.734375, 24.843750, 24.843750, 35.281250, 35.281250, 30.437500, 30.437500),
pos_type = c("Player position", "HE detonate", "Player position", "HE detonate", "Player position", "HE detonate", "Player position", "HE detonate"))
但是我想为手榴弹轨迹设置动画,并按照round_throw_time
规定的顺序开始每个轨迹的动画,并从玩家位置移动到引爆位置。
到目前为止,我已经尝试过:
ggplot(df, aes(pos_x, pos_y, group = plot_group)) +
annotation_custom(grid::rasterGrob(img, width = unit(1,"npc"), height =
unit(1,"npc")), 0, w, 0, -h) +
scale_x_continuous(expand = c(0,0),limits = c(0,w)) +
scale_y_reverse(expand = c(0,0),limits = c(h,0)) +
geom_point(color = "red") +
transition_states(states=pos_type, transition_length = 1, state_length = 1)
但是,当我添加轨迹线以及如何重置动画而不是仅仅回到原点时,我有点迷失。
任何提示将不胜感激!
我绘制的图像可以在这里下载 http://simpleradar.com/downloads/infernoV2.zip
答案 0 :(得分:4)
首先,这太棒了。
我注释掉了问题中未定义的部分。我添加了wrap = F
来使动画在最后重置(而不是后退),并添加了shadow_wake
来捕捉轨迹。
# The factors of pos_type are backwards (b/c alphabetical), so R thinks the detonation
# comes before the player position. Here we reverse that.
df$pos_type <- forcats::fct_rev(df$pos_type)
ggplot(df, aes(pos_x, pos_y, group = plot_group)) +
# annotation_custom(grid::rasterGrob(img, width = unit(1,"npc"), height =
# unit(1,"npc")), 0, w, 0, -h) +
scale_x_continuous(expand = c(0,0)) + # ,limits = c(0,w)) +
scale_y_reverse(expand = c(0,0)) + # ,limits = c(h,0)) +
geom_point(color = "red") +
transition_states(states=pos_type, transition_length = 1, state_length = 1, wrap = F) +
shadow_wake(wake_length = 1)
如果我们给每个帧一个参考玩家位置的信息,我们也可以将轨迹添加为一段:
df %>%
# Add reference to first coordinates for each plot_group
left_join(by = "plot_group",
df %>%
group_by(plot_group) %>%
filter(pos_type == "Player position") %>%
mutate(pos_x1 = pos_x, pos_y1 = pos_y) %>%
select(plot_group, pos_x1, pos_y1)
) %>%
ggplot(aes(pos_x, pos_y, group = plot_group)) +
# annotation_custom(grid::rasterGrob(img, width = unit(1,"npc"), height =
# unit(1,"npc")), 0, w, 0, -h) +
scale_x_continuous(expand = c(0,0)) + # ,limits = c(0,w)) +
scale_y_reverse(expand = c(0,0)) + # ,limits = c(h,0)) +
geom_point(color = "red") +
geom_segment(color = "gray70", aes(xend = pos_x1, yend = pos_y1)) +
transition_states(states=pos_type, transition_length = 1, state_length = 1, wrap = F)
类似于第二个,但是我添加了每个轨迹的距离,行进时间和开始时间。我在这里假设爆炸是结束时间,并且要追溯到弹道开始的时候。
(我第一次尝试使用transition_time
,但是在出现第一条轨迹后,如果没有错误行为,就无法使其正常工作。)
# trajectory speed
dist_per_time = 50
df2 <- df %>%
# Add reference to first coordinates for each plot_group
left_join(by = "plot_group",
df %>%
group_by(plot_group) %>%
filter(pos_type == "Player position") %>%
mutate(pos_x1 = pos_x, pos_y1 = pos_y) %>%
select(plot_group, pos_x1, pos_y1)
) %>%
left_join(by = c("plot_group", "pos_type"),
df %>%
group_by(plot_group) %>%
mutate(x_d = (range(pos_x)[1] - range(pos_x)[2]),
y_d = (range(pos_y)[1] - range(pos_y)[2]),
dist = sqrt(x_d^2 + y_d^2),
event_time = round_throw_time - if_else(pos_type == "Player position",
dist / dist_per_time,
0),
event_time = round(event_time, 1)) %>%
select(plot_group, pos_type, dist, event_time)
)
ggplot(df2, aes(pos_x, pos_y, group = plot_group)) +
# annotation_custom(grid::rasterGrob(img, width = unit(1,"npc"), height =
# unit(1,"npc")), 0, w, 0, -h) +
scale_x_continuous(expand = c(0,0)) + # ,limits = c(0,w)) +
scale_y_reverse(expand = c(0,0)) + # ,limits = c(h,0)) +
geom_point(color = "red") +
geom_segment(color = "gray70", aes(xend = pos_x1, yend = pos_y1)) +
transition_reveal(plot_group, event_time)