问题描述
我已经解析了电子游戏《反恐精英》中有关手榴弹投掷的一些数据.样本数据表明,我在投掷手榴弹的位置,投掷手榴弹的位置以及投掷手榴弹的时间上都有自己的位置.
I have parsed some data on grenade throws from the videogame Counter Strike. The sample data beloew reveals that I have positions on where the grenade is thrown from and where the grenade detonates and when the grenade is thrown.
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"))
然后使用ggplot2可以绘制手榴弹的静态轨迹,如下所示
And using ggplot2 I can plot the static trajectories of the grenades like shown here
但是我想给手榴弹轨迹设置动画,并按照round_throw_time
规定的顺序开始每个轨迹的动画,并从玩家位置移动到引爆位置.到目前为止,我已经尝试过:
But I would like to animate the grenade trajectories and iniate the animation of each trajectory in the order that round_throw_time
prescribes it and moving from player position to detonate position.So far I have attempted this:
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)
但是在添加轨迹线以及如何重置动画而不是仅仅回到原点时,我有点迷茫.
But I'm kinda lost when it comes to adding the trajectory lines and how to reset the animation instead of the point just moving back to their origin.
任何提示将不胜感激!
我绘制到的图像可以在这里下载 http://simpleradar.com/downloads/infernoV2.zip
The image I plot onto can be downloaded herehttp://simpleradar.com/downloads/infernoV2.zip
推荐答案
首先,这很棒.
我注释掉了问题中未定义的部分.我添加了wrap = F
来使动画在最后重置(而不是后退),并添加了shadow_wake
来捕捉轨迹.
I commented out the pieces that weren't defined in the question. I added wrap = F
to make the animation reset (rather than rewind) at the end, and shadow_wake
to capture the trajectory.
# 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)
如果我们给每个帧一个参考玩家位置的信息,我们也可以将轨迹添加为一个片段:
We could also add the trajectory as a segment, if we give each frame a reference to the player position:
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)
类似于第二个,但是我添加了每个轨迹的距离,行进时间和开始时间.我在这里假设爆炸是结束时间,并且要追溯到弹道开始的时候.
Similar to 2nd, but I add each trajectory's distance, travel time, and start time. I assume here that the detonation is the end time, and work back to when the trajectory started.
(我第一次尝试使用transition_time
,但是在出现第一条轨迹后,如果没有错误行为,就无法使其正常工作.)
(I first tried transition_time
, but couldn't get it to work without buggy behavior after the first trajectory.)
# 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)
) %>%
### EDIT - added below to make timing explicit and fix code which
# was broken in current version of gganimate @ 2019-11-15
# Thanks @Deep North for tip.
group_by(plot_group) %>%
mutate(event_time_per_grp = event_time - first(event_time)) %>%
ungroup() %>%
mutate(event_time_cuml = cumsum(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(event_time_cuml) ### EDIT, see above
这篇关于gganimate根据时间为多个路径设置动画的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!