1use std::cell::RefCell;
6
7use box2d_rust::body::create_body;
8use box2d_rust::geometry::make_offset_box;
9use box2d_rust::math_functions::{offset_pos, to_pos, Vec2, ROT_IDENTITY};
10use box2d_rust::shape::create_polygon_shape;
11use box2d_rust::types::{default_body_def, default_shape_def};
12use box2d_rust::world::World;
13
14use crate::human::{create_human, destroy_human, Human};
15
16use super::BENCHMARK_DEBUG;
17
18const RAIN_ROW_COUNT: i32 = if BENCHMARK_DEBUG { 3 } else { 5 };
20const RAIN_COLUMN_COUNT: i32 = if BENCHMARK_DEBUG { 10 } else { 40 };
21const RAIN_GROUP_SIZE: i32 = if BENCHMARK_DEBUG { 2 } else { 5 };
22
23struct RainData {
25 groups: Vec<Vec<Human>>,
26 grid_size: f32,
27 grid_count: i32,
28 column_count: i32,
29 column_index: i32,
30}
31
32impl RainData {
33 fn new() -> Self {
34 RainData {
35 groups: Vec::new(),
36 grid_size: 0.0,
37 grid_count: 0,
38 column_count: 0,
39 column_index: 0,
40 }
41 }
42
43 fn reset(&mut self) {
45 let group_count = (RAIN_ROW_COUNT * RAIN_COLUMN_COUNT) as usize;
46 self.groups = (0..group_count)
47 .map(|_| vec![Human::default(); RAIN_GROUP_SIZE as usize])
48 .collect();
49 self.grid_size = 0.0;
50 self.grid_count = 0;
51 self.column_count = 0;
52 self.column_index = 0;
53 }
54}
55
56thread_local! {
57 static RAIN_DATA: RefCell<RainData> = RefCell::new(RainData::new());
58}
59
60pub fn create_rain(world: &mut World) {
62 RAIN_DATA.with(|rd| rd.borrow_mut().reset());
63
64 let grid_size = 0.5;
65 let grid_count = if BENCHMARK_DEBUG { 200 } else { 500 };
66 RAIN_DATA.with(|rd| {
67 let mut rd = rd.borrow_mut();
68 rd.grid_size = grid_size;
69 rd.grid_count = grid_count;
70 });
71
72 {
73 let body_def = default_body_def();
74 let ground_id = create_body(world, &body_def);
75
76 let shape_def = default_shape_def();
77 let mut y = 0.0;
78 let width = grid_size;
79 let height = grid_size;
80
81 for _ in 0..RAIN_ROW_COUNT {
82 let mut x = -0.5 * grid_count as f32 * grid_size;
83 for _ in 0..=grid_count {
84 let box_shape =
85 make_offset_box(0.5 * width, 0.5 * height, Vec2 { x, y }, ROT_IDENTITY);
86 create_polygon_shape(world, ground_id, &shape_def, &box_shape);
87
88 x += grid_size;
89 }
90
91 y += 45.0;
92 }
93 }
94
95 RAIN_DATA.with(|rd| {
96 let mut rd = rd.borrow_mut();
97 rd.column_count = 0;
98 rd.column_index = 0;
99 });
100}
101
102fn create_group(world: &mut World, row_index: i32, column_index: i32) {
104 debug_assert!(row_index < RAIN_ROW_COUNT && column_index < RAIN_COLUMN_COUNT);
105
106 RAIN_DATA.with(|rd| {
107 let mut rd = rd.borrow_mut();
108
109 let group_index = (row_index * RAIN_COLUMN_COUNT + column_index) as usize;
110
111 let span = rd.grid_count as f32 * rd.grid_size;
112 let group_distance = 1.0 * span / RAIN_COLUMN_COUNT as f32;
113
114 let mut position = to_pos(Vec2 {
115 x: -0.5 * span + group_distance * (column_index as f32 + 0.5),
116 y: 40.0 + 45.0 * row_index as f32,
117 });
118
119 let scale = 1.0;
120 let joint_friction = 0.05;
121 let joint_hertz = 5.0;
122 let joint_damping = 0.5;
123
124 for i in 0..RAIN_GROUP_SIZE {
125 create_human(
126 &mut rd.groups[group_index][i as usize],
127 world,
128 position,
129 scale,
130 joint_friction,
131 joint_hertz,
132 joint_damping,
133 i + 1,
134 0,
135 false,
136 );
137 position = offset_pos(position, Vec2 { x: 0.5, y: 0.0 });
138 }
139 });
140}
141
142fn destroy_group(world: &mut World, row_index: i32, column_index: i32) {
144 debug_assert!(row_index < RAIN_ROW_COUNT && column_index < RAIN_COLUMN_COUNT);
145
146 RAIN_DATA.with(|rd| {
147 let mut rd = rd.borrow_mut();
148 let group_index = (row_index * RAIN_COLUMN_COUNT + column_index) as usize;
149
150 for i in 0..RAIN_GROUP_SIZE {
151 destroy_human(world, &mut rd.groups[group_index][i as usize]);
152 }
153 });
154}
155
156pub fn step_rain(world: &mut World, step_count: i32) -> f32 {
158 let delay: i32 = if BENCHMARK_DEBUG { 0x1F } else { 0x7 };
159
160 if (step_count & delay) == 0 {
161 let column_count = RAIN_DATA.with(|rd| rd.borrow().column_count);
162
163 if column_count < RAIN_COLUMN_COUNT {
164 for i in 0..RAIN_ROW_COUNT {
165 create_group(world, i, column_count);
166 }
167
168 RAIN_DATA.with(|rd| rd.borrow_mut().column_count += 1);
169 } else {
170 let column_index = RAIN_DATA.with(|rd| rd.borrow().column_index);
171
172 for i in 0..RAIN_ROW_COUNT {
173 destroy_group(world, i, column_index);
174 create_group(world, i, column_index);
175 }
176
177 RAIN_DATA.with(|rd| {
178 let mut rd = rd.borrow_mut();
179 rd.column_index = (rd.column_index + 1) % RAIN_COLUMN_COUNT;
180 });
181 }
182 }
183
184 0.0
185}