11use crate :: cell:: CellType ;
2+ use crate :: line:: LineFullIter ;
23use crate :: matrix:: MatrixIndex ;
34use crate :: world_data:: { FullIndex , VoxelWorld , World , WorldModified } ;
5+ use crate :: { CHUNK_HEIGHT_LAST , CHUNK_WIDTH_LAST } ;
46use bevy:: diagnostic:: FrameCount ;
57use bevy:: prelude:: { Local , Res , ResMut } ;
68use rand:: distr:: { Bernoulli , Uniform } ;
@@ -47,6 +49,17 @@ impl WorldRand {
4749 self . rng . sample ( self . gas )
4850 }
4951}
52+ #[ derive( Clone , Copy , Debug ) ]
53+ pub enum Direction {
54+ UpLeft ,
55+ Up ,
56+ UpRight ,
57+ Left ,
58+ Right ,
59+ DownLeft ,
60+ Down ,
61+ DownRight ,
62+ }
5063impl World {
5164 pub fn simulate ( & mut self , voxel_world : & mut VoxelWorld , frame : u8 ) {
5265 #[ cfg( not( feature = "wasm" ) ) ]
@@ -93,12 +106,24 @@ impl World {
93106 rand : & mut WorldRand ,
94107 frame : u8 ,
95108 ) {
96- for i in 0 ..=65535 {
97- let index = FullIndex {
98- chunk_index,
99- cell_index : MatrixIndex :: from ( i) ,
100- } ;
101- self . simulate_cell ( voxel_world, index, rand, frame) ;
109+ for y in 0 ..=CHUNK_HEIGHT_LAST {
110+ if y. is_multiple_of ( 2 ) ^ frame. is_multiple_of ( 2 ) {
111+ for x in ( 0 ..=CHUNK_WIDTH_LAST ) . rev ( ) {
112+ let index = FullIndex {
113+ chunk_index,
114+ cell_index : MatrixIndex { x, y } ,
115+ } ;
116+ self . simulate_cell ( voxel_world, index, rand, frame) ;
117+ }
118+ } else {
119+ for x in 0 ..=CHUNK_WIDTH_LAST {
120+ let index = FullIndex {
121+ chunk_index,
122+ cell_index : MatrixIndex { x, y } ,
123+ } ;
124+ self . simulate_cell ( voxel_world, index, rand, frame) ;
125+ }
126+ }
102127 }
103128 }
104129 pub fn simulate_cell (
@@ -117,50 +142,53 @@ impl World {
117142 cell. last_changed = frame;
118143 match cell. cell_type ( ) {
119144 CellType :: Liquid => {
145+ cell. gravity ( 64 ) ;
146+ if cell. velocity . is_zero ( ) {
147+ return ;
148+ }
120149 let check = if rand. half ( ) {
121150 [
122- index - ( 0 , 1 ) ,
123- index - ( 0 , 1 ) + ( 1 , 0 ) ,
124- index - ( 0 , 1 ) - ( 1 , 0 ) ,
125- index + ( 1 , 0 ) ,
126- index - ( 1 , 0 ) ,
151+ Direction :: Down ,
152+ Direction :: DownLeft ,
153+ Direction :: DownRight ,
154+ Direction :: Left ,
155+ Direction :: Right ,
127156 ]
128157 } else {
129158 [
130- index - ( 0 , 1 ) ,
131- index - ( 0 , 1 ) - ( 1 , 0 ) ,
132- index - ( 0 , 1 ) + ( 1 , 0 ) ,
133- index - ( 1 , 0 ) ,
134- index + ( 1 , 0 ) ,
159+ Direction :: Down ,
160+ Direction :: DownRight ,
161+ Direction :: DownLeft ,
162+ Direction :: Right ,
163+ Direction :: Left ,
135164 ]
136165 } ;
137166 self . swap_from_list ( voxel_world, index, & check) ;
138167 }
139168 CellType :: Granular => {
169+ cell. gravity ( 64 ) ;
170+ if cell. velocity . is_zero ( ) {
171+ return ;
172+ }
140173 let check = if rand. half ( ) {
141- [
142- index - ( 0 , 1 ) ,
143- index - ( 0 , 1 ) + ( 1 , 0 ) ,
144- index - ( 0 , 1 ) - ( 1 , 0 ) ,
145- ]
174+ [ Direction :: Down , Direction :: DownLeft , Direction :: DownRight ]
146175 } else {
147- [
148- index - ( 0 , 1 ) ,
149- index - ( 0 , 1 ) - ( 1 , 0 ) ,
150- index - ( 0 , 1 ) + ( 1 , 0 ) ,
151- ]
176+ [ Direction :: Down , Direction :: DownRight , Direction :: DownLeft ]
152177 } ;
153178 self . swap_from_list ( voxel_world, index, & check) ;
154179 }
155180 CellType :: Gas => {
181+ cell. gravity ( 64 ) ;
182+ if cell. velocity . is_zero ( ) {
183+ return ;
184+ }
156185 let check = [ match rand. gas ( ) {
157- 0 => index + ( 0 , 1 ) - ( 1 , 0 ) ,
158- 1 => index + ( 0 , 1 ) ,
159- 2 => index + ( 1 , 1 ) ,
160- 3 => index - ( 1 , 0 ) ,
161- 4 => index,
162- 5 => index + ( 1 , 0 ) ,
163- _ => unreachable ! ( ) ,
186+ 0 => Direction :: UpLeft ,
187+ 1 => Direction :: Up ,
188+ 2 => Direction :: UpRight ,
189+ 3 => Direction :: Left ,
190+ 4 => Direction :: Right ,
191+ _ => return ,
164192 } ] ;
165193 self . swap_from_list ( voxel_world, index, & check) ;
166194 }
@@ -171,10 +199,10 @@ impl World {
171199 & mut self ,
172200 voxel_world : & mut VoxelWorld ,
173201 index : FullIndex ,
174- check : & [ FullIndex ] ,
202+ check : & [ Direction ] ,
175203 ) {
176- for swap_index in check. iter ( ) . copied ( ) {
177- if self . try_swap ( voxel_world, index, swap_index ) {
204+ for direction in check. iter ( ) . copied ( ) {
205+ if self . try_swap ( voxel_world, index, direction ) {
178206 return ;
179207 }
180208 }
@@ -183,13 +211,47 @@ impl World {
183211 & mut self ,
184212 voxel_world : & mut VoxelWorld ,
185213 index : FullIndex ,
186- swap_index : FullIndex ,
214+ direction : Direction ,
187215 ) -> bool {
188- if let Some ( cell) = self . get ( index)
189- && let Some ( other) = self . get ( swap_index)
190- && cell. can_move ( other)
191- {
192- self . swap ( voxel_world, index, swap_index) ;
216+ if let Some ( cell) = self . get ( index) {
217+ let vel = cell. velocity . to_dir ( direction) ;
218+ let mut line = LineFullIter :: new_vel ( index, vel) ;
219+ line. next ( ) ;
220+ let mut last = index;
221+ let mut n = 0 ;
222+ for ( _, swap_index) in line {
223+ n += 1 ;
224+ if let Some ( new) = self . get ( swap_index) {
225+ if new. is_air ( ) {
226+ last = swap_index;
227+ } else if cell. can_move ( new) {
228+ if let Some ( cell) = self . get_mut ( index) {
229+ for _ in 0 ..n {
230+ cell. friction ( 16 , 16 ) ;
231+ }
232+ }
233+ if last == index {
234+ self . swap ( voxel_world, index, swap_index) ;
235+ } else {
236+ self . swap ( voxel_world, swap_index, last) ;
237+ self . swap ( voxel_world, index, swap_index) ;
238+ }
239+ return true ;
240+ } else if last == index {
241+ return false ;
242+ } else {
243+ break ;
244+ }
245+ } else {
246+ return false ;
247+ }
248+ }
249+ if let Some ( cell) = self . get_mut ( index) {
250+ for _ in 0 ..n {
251+ cell. friction ( 16 , 16 ) ;
252+ }
253+ }
254+ self . swap ( voxel_world, index, last) ;
193255 true
194256 } else {
195257 false
0 commit comments