pub struct WfcModule<TBitSet>where
TBitSet: BitSearch + BitEmpty + BitSet + BitIntersection + BitUnion + BitTestNone + Hash + Eq + Copy + BitIntersection<Output = TBitSet> + BitUnion<Output = TBitSet>,{
pub north_neighbours: TBitSet,
pub south_neighbours: TBitSet,
pub east_neighbours: TBitSet,
pub west_neighbours: TBitSet,
}Expand description
A building block of WFC, which lets user to set adjacency rules for tiles
Each neighbours bitset are expected to hold indices of neighbour modules which will be hold in a &WfcModule used by WfcContext
Fields§
§north_neighbours: TBitSetNorth neighbouring modules
south_neighbours: TBitSetSouth neighbouring modules
east_neighbours: TBitSetEast neighbouring modules
west_neighbours: TBitSetWest neighbouring modules
Implementations§
Source§impl<TBitSet> WfcModule<TBitSet>where
TBitSet: BitSearch + BitEmpty + BitSet + BitIntersection + BitUnion + BitTestNone + Hash + Eq + Copy + BitIntersection<Output = TBitSet> + BitUnion<Output = TBitSet>,
impl<TBitSet> WfcModule<TBitSet>where
TBitSet: BitSearch + BitEmpty + BitSet + BitIntersection + BitUnion + BitTestNone + Hash + Eq + Copy + BitIntersection<Output = TBitSet> + BitUnion<Output = TBitSet>,
Sourcepub fn new() -> Self
pub fn new() -> Self
A constructor of a module with all neighbouring sets empty
Examples found in repository?
examples/wang_corner_carpet.rs (line 116)
69 pub async fn new(w: usize, h: usize) -> Self {
70 let InternalGlContext {
71 quad_context: ctx, ..
72 } = unsafe { get_internal_gl() };
73
74 let texture_bytes = load_file("assets/wang_4_corner.png").await.unwrap();
75
76 let img = image::load_from_memory(&texture_bytes[..])
77 .unwrap_or_else(|e| panic!("{}", e))
78 .to_rgba8();
79
80 let img_w = img.width();
81 let img_h = img.height();
82
83 let texture = Texture2D::from_miniquad_texture(
84 miniquad::Texture::from_data_and_format(
85 ctx,
86 &img.into_raw(),
87 TextureParams {
88 format: TextureFormat::RGBA8,
89 wrap: TextureWrap::Clamp,
90 filter: FilterMode::Nearest,
91 width: img_w,
92 height: img_h
93 }
94 )
95 );
96
97 let tiles = (0..=255)
98 .map(|idx| {
99 let width = 32;
100 let height = 32;
101 (
102 idx as u8,
103 SubRect {
104 x: (idx % 16) * width,
105 y: (idx / 16) * height,
106 width,
107 height
108 }
109 )
110 })
111 .collect::<Vec<_>>();
112
113 let modules = tiles
114 .iter()
115 .map(|tile| {
116 let mut module: WfcModule<CustomBitSet> = WfcModule::new();
117 for i in 0..tiles.len() {
118 let other_tile = &tiles[i];
119 if get_north_west(tile.0) == get_south_west(other_tile.0) &&
120 get_north_east(tile.0) == get_south_east(other_tile.0) {
121 module.add_north_neighbour(i);
122 }
123 if get_south_west(tile.0) == get_north_west(other_tile.0) &&
124 get_south_east(tile.0) == get_north_east(other_tile.0) {
125 module.add_south_neighbour(i);
126 }
127 if get_north_west(tile.0) == get_north_east(other_tile.0) &&
128 get_south_west(tile.0) == get_south_east(other_tile.0) {
129 module.add_west_neighbour(i);
130 }
131 if get_north_east(tile.0) == get_north_west(other_tile.0) &&
132 get_south_east(tile.0) == get_south_west(other_tile.0) {
133 module.add_east_neighbour(i);
134 }
135 }
136 module
137 })
138 .collect::<Vec<_>>();
139
140 Self {
141 w,
142 h,
143 tile_width: 32,
144 tile_height: 32,
145 tiles,
146 modules,
147 texture,
148 map_data: vec![0; w*h]
149 }
150 }More examples
examples/dungeon.rs (line 318)
144 pub async fn new(w: usize, h: usize) -> Self {
145 let InternalGlContext {
146 quad_context: ctx, ..
147 } = unsafe { get_internal_gl() };
148
149 let dungeon_bytes = load_file("assets/dungeon_tiles.png").await.unwrap();
150
151 let img = image::load_from_memory(&dungeon_bytes[..])
152 .unwrap_or_else(|e| panic!("{}", e))
153 .to_rgba8();
154
155 let img_w = img.width();
156 let img_h = img.height();
157
158 let texture = Texture2D::from_miniquad_texture(
159 miniquad::Texture::from_data_and_format(
160 ctx,
161 &img.into_raw(),
162 TextureParams {
163 format: TextureFormat::RGBA8,
164 wrap: TextureWrap::Clamp,
165 filter: FilterMode::Nearest,
166 width: img_w,
167 height: img_h
168 }
169 )
170 );
171
172 let tiles_bytes = load_file("assets/dungeon_tiles.ron").await.unwrap();
173 let dungeon_tiles: DungeonTiles = from_reader(&tiles_bytes[..]).unwrap();
174
175 let mut tiles = Vec::new();
176 for (kind_code, subrects) in dungeon_tiles.wang_4_corner_tiles.iter() {
177 tiles.push(Tile {
178 kind: TileKind::Wang4Corner(*kind_code),
179 subrects: subrects.clone(),
180 neighbours_east: Vec::new(),
181 neighbours_west: Vec::new(),
182 neighbours_north: Vec::new(),
183 neighbours_south: Vec::new()
184 });
185 }
186 // We need to be sure that zero tile is always a "void" tile, so we doing an extra sort step
187 tiles.sort_by(|lhs, rhs| {
188 match (lhs.kind, rhs.kind) {
189 (TileKind::Wang4Corner(kind_lhs), TileKind::Wang4Corner(kind_rhs)) => kind_lhs.cmp(&kind_rhs),
190 _ => Ordering::Equal
191 }
192 });
193
194 for i in 0..tiles.len() {
195 let current_kind = tiles[i].kind;
196 for j in 0..tiles.len() {
197 let candidate_kind = tiles[j].kind;
198 let (matches_north, matches_south, matches_east, matches_west) = {
199 match (current_kind, candidate_kind) {
200 (TileKind::Wang4Corner(current), TileKind::Wang4Corner(candidate)) => {
201 (
202 get_north_east(current) == get_south_east(candidate) &&
203 get_north_west(current) == get_south_west(candidate),
204
205 get_south_east(current) == get_north_east(candidate) &&
206 get_south_west(current) == get_north_west(candidate),
207
208 get_north_east(current) == get_north_west(candidate) &&
209 get_south_east(current) == get_south_west(candidate),
210
211 get_north_west(current) == get_north_east(candidate) &&
212 get_south_west(current) == get_south_east(candidate),
213 )
214 },
215 _ => continue
216 }
217 };
218 if matches_east {
219 tiles[i].neighbours_east.push(candidate_kind);
220 }
221 if matches_west {
222 tiles[i].neighbours_west.push(candidate_kind);
223 }
224 if matches_north {
225 tiles[i].neighbours_north.push(candidate_kind);
226 }
227 if matches_south {
228 tiles[i].neighbours_south.push(candidate_kind);
229 }
230 }
231 }
232
233 //Add bridges:
234 {
235 let bridge_tiles_offset = tiles.len();
236 tiles.extend_from_slice(&dungeon_tiles.extra_tiles[..]);
237
238 let mut bridge_match_queue_south = VecDeque::new();
239 let mut bridge_match_queue_north = VecDeque::new();
240 let mut bridge_match_queue_east = VecDeque::new();
241 let mut bridge_match_queue_west = VecDeque::new();
242
243 for bridge_tile in &tiles[bridge_tiles_offset..] {
244 for south_neighbour in bridge_tile.neighbours_south.iter() {
245 if let TileKind::Wang4Corner(kind) = south_neighbour {
246 for i in 0..bridge_tiles_offset {
247 match tiles[i].kind {
248 TileKind::Wang4Corner(kind_inner) if kind_inner == *kind => {
249 bridge_match_queue_south.push_back((bridge_tile.kind, i))
250 },
251 _ => ()
252 };
253 }
254 }
255 }
256 for north_neighbour in bridge_tile.neighbours_north.iter() {
257 if let TileKind::Wang4Corner(kind) = north_neighbour {
258 for i in 0..bridge_tiles_offset {
259 match tiles[i].kind {
260 TileKind::Wang4Corner(kind_inner) if kind_inner == *kind => {
261 bridge_match_queue_north.push_back((bridge_tile.kind, i))
262 },
263 _ => ()
264 };
265 }
266 }
267 }
268 for east_neighbour in bridge_tile.neighbours_east.iter() {
269 if let TileKind::Wang4Corner(kind) = east_neighbour {
270 for i in 0..bridge_tiles_offset {
271 match tiles[i].kind {
272 TileKind::Wang4Corner(kind_inner) if kind_inner == *kind => {
273 bridge_match_queue_east.push_back((bridge_tile.kind, i))
274 },
275 _ => ()
276 };
277 }
278 }
279 }
280 for west_neighbour in bridge_tile.neighbours_west.iter() {
281 if let TileKind::Wang4Corner(kind) = west_neighbour {
282 for i in 0..bridge_tiles_offset {
283 match tiles[i].kind {
284 TileKind::Wang4Corner(kind_inner) if kind_inner == *kind => {
285 bridge_match_queue_west.push_back((bridge_tile.kind, i))
286 },
287 _ => ()
288 };
289 }
290 }
291 }
292 }
293
294 while !bridge_match_queue_south.is_empty() {
295 let next_match = bridge_match_queue_south.pop_front().unwrap();
296 tiles[next_match.1].neighbours_north.push(next_match.0);
297 }
298
299 while !bridge_match_queue_north.is_empty() {
300 let next_match = bridge_match_queue_north.pop_front().unwrap();
301 tiles[next_match.1].neighbours_south.push(next_match.0);
302 }
303
304 while !bridge_match_queue_east.is_empty() {
305 let next_match = bridge_match_queue_east.pop_front().unwrap();
306 tiles[next_match.1].neighbours_west.push(next_match.0);
307 }
308
309 while !bridge_match_queue_west.is_empty() {
310 let next_match = bridge_match_queue_west.pop_front().unwrap();
311 tiles[next_match.1].neighbours_east.push(next_match.0);
312 }
313 }
314
315 let modules = tiles
316 .iter()
317 .map(|tile| {
318 let mut module: WfcModule<CustomBitSet> = WfcModule::new();
319 for i in 0..tiles.len() {
320 if tile.neighbours_north.contains(&tiles[i].kind) {
321 module.add_north_neighbour(i);
322 }
323 if tile.neighbours_south.contains(&tiles[i].kind) {
324 module.add_south_neighbour(i);
325 }
326 if tile.neighbours_west.contains(&tiles[i].kind) {
327 module.add_west_neighbour(i);
328 }
329 if tile.neighbours_east.contains(&tiles[i].kind) {
330 module.add_east_neighbour(i);
331 }
332 }
333 module
334 })
335 .collect::<Vec<_>>();
336
337 Self {
338 w,
339 h,
340 tile_width: dungeon_tiles.tile_width,
341 tile_height: dungeon_tiles.tile_height,
342 tiles,
343 modules,
344 texture,
345 map_data: vec![(0, 0); w*h]
346 }
347 }examples/summer_garden.rs (line 330)
183 pub async fn new(w: usize, h: usize, draw_scale: f32) -> Self {
184 let InternalGlContext {
185 quad_context: ctx, ..
186 } = unsafe { get_internal_gl() };
187
188 let texture_bytes = load_file("assets/reduced_wang_scheme.png").await.unwrap();
189
190 let img = image::load_from_memory(&texture_bytes[..])
191 .unwrap_or_else(|e| panic!("{}", e))
192 .to_rgba8();
193
194 let img_w = img.width();
195 let img_h = img.height();
196
197 let texture = Texture2D::from_miniquad_texture(
198 miniquad::Texture::from_data_and_format(
199 ctx,
200 &img.into_raw(),
201 TextureParams {
202 format: TextureFormat::RGBA8,
203 wrap: TextureWrap::Clamp,
204 filter: FilterMode::Nearest,
205 width: img_w,
206 height: img_h
207 }
208 )
209 );
210
211 let atlas_bytes = load_file("assets/reduced_wang_scheme.ron").await.unwrap();
212 let atlas: SummerGardenAtlas = from_reader(&atlas_bytes[..]).unwrap();
213
214 let mut tile_sides = Vec::new();
215 let mut neighbour_strategies = Vec::new();
216 let mut tiles = Vec::new();
217
218 {
219 for tile_cfg in atlas.terrain_tile_configs.iter() {
220 for pattern in &[
221 &atlas.reduced_wang_patterns[..],
222 &atlas.extended_set_1_patterns_north_west[..],
223 &atlas.extended_set_1_patterns_north_east[..],
224 &atlas.extended_set_1_patterns_south_west[..],
225 &atlas.extended_set_1_patterns_south_east[..],
226 &atlas.extended_set_2_patterns_north_west[..],
227 &atlas.extended_set_2_patterns_north_east[..],
228 &atlas.extended_set_2_patterns_south_west[..],
229 &atlas.extended_set_2_patterns_south_east[..],
230 ] {
231 tile_sides.extend(
232 pattern.iter().map(
233 |pattern| {
234 TileSides {
235 north_west: match pattern.north_west {
236 TileKind::Inner => { tile_cfg.inner_type }
237 TileKind::Outer => { tile_cfg.outer_type }
238 },
239 north_east: match pattern.north_east {
240 TileKind::Inner => { tile_cfg.inner_type }
241 TileKind::Outer => { tile_cfg.outer_type }
242 },
243 south_west: match pattern.south_west {
244 TileKind::Inner => { tile_cfg.inner_type }
245 TileKind::Outer => { tile_cfg.outer_type }
246 },
247 south_east: match pattern.south_east {
248 TileKind::Inner => { tile_cfg.inner_type }
249 TileKind::Outer => { tile_cfg.outer_type }
250 }
251 }
252 }
253 )
254 );
255 }
256 for j in 0..4 {
257 for i in 0..4 {
258 tiles.push(SubRect{
259 x: i * 32 + tile_cfg.x_offset,
260 y: j * 32 + tile_cfg.y_offset,
261 width: 32,
262 height: 32
263 })
264 }
265 }
266 for jj in 0..2 {
267 for ii in 0..2 {
268 for j in 0..2 {
269 for i in 0..2 {
270 tiles.push(SubRect{
271 x: (i + ii * 2) * 32 + tile_cfg.x_offset + 256,
272 y: (j + jj * 2) * 32 + tile_cfg.y_offset,
273 width: 32,
274 height: 32
275 })
276 }
277 }
278 }
279 }
280 for jj in 0..2 {
281 for ii in 0..2 {
282 for j in 0..2 {
283 for i in 0..2 {
284 tiles.push(SubRect{
285 x: (i + ii * 2) * 32 + tile_cfg.x_offset,
286 y: (j + jj * 2) * 32 + tile_cfg.y_offset + 256,
287 width: 32,
288 height: 32
289 })
290 }
291 }
292 }
293 }
294 neighbour_strategies.extend_from_slice(&atlas.reduced_wang_neighbour_strategy[..]);
295 for _ in 0..8 {
296 neighbour_strategies.extend_from_slice(&atlas.neighbour_strategy_2_x_2[..]);
297 }
298 }
299 tile_sides.extend_from_slice(&atlas.vertical_bridge_sides[..]);
300 tile_sides.extend_from_slice(&atlas.horizontal_bridge_sides[..]);
301 for j in 0..3 {
302 for i in 0..3 {
303 tiles.push(SubRect{
304 x: i * 32 + 256,
305 y: j * 32 + 256,
306 width: 32,
307 height: 32
308 })
309 }
310 }
311 for j in 0..3 {
312 for i in 0..3 {
313 tiles.push(SubRect{
314 x: i * 32 + 256 + 96,
315 y: j * 32 + 256,
316 width: 32,
317 height: 32
318 })
319 }
320 }
321 neighbour_strategies.extend_from_slice(&atlas.neighbour_strategy_3_x_3[..]);
322 neighbour_strategies.extend_from_slice(&atlas.neighbour_strategy_3_x_3[..]);
323
324 assert_eq!(tile_sides.len(), neighbour_strategies.len());
325 }
326
327 let mut modules = Vec::new();
328 for i in 0..tile_sides.len() {
329 let current_sides = tile_sides[i];
330 let mut module: WfcModule<CustomBitSet> = WfcModule::new();
331 match neighbour_strategies[i].north {
332 NeighbourKind::WangCorners => {
333 for j in 0..tile_sides.len() {
334 if neighbour_strategies[j].south != NeighbourKind::WangCorners {
335 continue;
336 }
337 if tile_sides[j].south_west == current_sides.north_west &&
338 tile_sides[j].south_east == current_sides.north_east {
339 module.add_north_neighbour(j);
340 }
341 }
342 }
343 NeighbourKind::RelOffset(offset) => {
344 let new_offset = (i as i32 + offset) as usize;
345 module.add_north_neighbour(new_offset);
346 }
347 }
348 match neighbour_strategies[i].south {
349 NeighbourKind::WangCorners => {
350 for j in 0..tile_sides.len() {
351 if neighbour_strategies[j].north != NeighbourKind::WangCorners {
352 continue;
353 }
354 if tile_sides[j].north_west == current_sides.south_west &&
355 tile_sides[j].north_east == current_sides.south_east {
356 module.add_south_neighbour(j);
357 }
358 }
359 }
360 NeighbourKind::RelOffset(offset) => {
361 let new_offset = (i as i32 + offset) as usize;
362 module.add_south_neighbour(new_offset);
363 }
364 }
365 match neighbour_strategies[i].east {
366 NeighbourKind::WangCorners => {
367 for j in 0..tile_sides.len() {
368 if neighbour_strategies[j].west != NeighbourKind::WangCorners {
369 continue;
370 }
371 if tile_sides[j].north_west == current_sides.north_east &&
372 tile_sides[j].south_west == current_sides.south_east {
373 module.add_east_neighbour(j);
374 }
375 }
376 }
377 NeighbourKind::RelOffset(offset) => {
378 let new_offset = (i as i32 + offset) as usize;
379 module.add_east_neighbour(new_offset);
380 }
381 }
382 match neighbour_strategies[i].west {
383 NeighbourKind::WangCorners => {
384 for j in 0..tile_sides.len() {
385 if neighbour_strategies[j].east != NeighbourKind::WangCorners {
386 continue;
387 }
388 if tile_sides[j].north_east == current_sides.north_west &&
389 tile_sides[j].south_east == current_sides.south_west {
390 module.add_west_neighbour(j);
391 }
392 }
393 }
394 NeighbourKind::RelOffset(offset) => {
395 let new_offset = (i as i32 + offset) as usize;
396 module.add_west_neighbour(new_offset);
397 }
398 }
399 modules.push(module);
400 }
401
402 Self {
403 w,
404 h,
405 draw_scale,
406 atlas,
407 tile_width: 32,
408 tile_height: 32,
409 tiles,
410 modules,
411 texture,
412 map_data: vec![0; w*h],
413 cell_tree_data: vec![TreeType::None; w*h],
414 corner_tree_data: vec![TreeType::None; (w+1)*(h+1)]
415 }
416 }Sourcepub fn add_north_neighbour(&mut self, idx: usize)
pub fn add_north_neighbour(&mut self, idx: usize)
A function which adds a neighbour on a north side
Examples found in repository?
examples/wang_corner_carpet.rs (line 121)
69 pub async fn new(w: usize, h: usize) -> Self {
70 let InternalGlContext {
71 quad_context: ctx, ..
72 } = unsafe { get_internal_gl() };
73
74 let texture_bytes = load_file("assets/wang_4_corner.png").await.unwrap();
75
76 let img = image::load_from_memory(&texture_bytes[..])
77 .unwrap_or_else(|e| panic!("{}", e))
78 .to_rgba8();
79
80 let img_w = img.width();
81 let img_h = img.height();
82
83 let texture = Texture2D::from_miniquad_texture(
84 miniquad::Texture::from_data_and_format(
85 ctx,
86 &img.into_raw(),
87 TextureParams {
88 format: TextureFormat::RGBA8,
89 wrap: TextureWrap::Clamp,
90 filter: FilterMode::Nearest,
91 width: img_w,
92 height: img_h
93 }
94 )
95 );
96
97 let tiles = (0..=255)
98 .map(|idx| {
99 let width = 32;
100 let height = 32;
101 (
102 idx as u8,
103 SubRect {
104 x: (idx % 16) * width,
105 y: (idx / 16) * height,
106 width,
107 height
108 }
109 )
110 })
111 .collect::<Vec<_>>();
112
113 let modules = tiles
114 .iter()
115 .map(|tile| {
116 let mut module: WfcModule<CustomBitSet> = WfcModule::new();
117 for i in 0..tiles.len() {
118 let other_tile = &tiles[i];
119 if get_north_west(tile.0) == get_south_west(other_tile.0) &&
120 get_north_east(tile.0) == get_south_east(other_tile.0) {
121 module.add_north_neighbour(i);
122 }
123 if get_south_west(tile.0) == get_north_west(other_tile.0) &&
124 get_south_east(tile.0) == get_north_east(other_tile.0) {
125 module.add_south_neighbour(i);
126 }
127 if get_north_west(tile.0) == get_north_east(other_tile.0) &&
128 get_south_west(tile.0) == get_south_east(other_tile.0) {
129 module.add_west_neighbour(i);
130 }
131 if get_north_east(tile.0) == get_north_west(other_tile.0) &&
132 get_south_east(tile.0) == get_south_west(other_tile.0) {
133 module.add_east_neighbour(i);
134 }
135 }
136 module
137 })
138 .collect::<Vec<_>>();
139
140 Self {
141 w,
142 h,
143 tile_width: 32,
144 tile_height: 32,
145 tiles,
146 modules,
147 texture,
148 map_data: vec![0; w*h]
149 }
150 }More examples
examples/dungeon.rs (line 321)
144 pub async fn new(w: usize, h: usize) -> Self {
145 let InternalGlContext {
146 quad_context: ctx, ..
147 } = unsafe { get_internal_gl() };
148
149 let dungeon_bytes = load_file("assets/dungeon_tiles.png").await.unwrap();
150
151 let img = image::load_from_memory(&dungeon_bytes[..])
152 .unwrap_or_else(|e| panic!("{}", e))
153 .to_rgba8();
154
155 let img_w = img.width();
156 let img_h = img.height();
157
158 let texture = Texture2D::from_miniquad_texture(
159 miniquad::Texture::from_data_and_format(
160 ctx,
161 &img.into_raw(),
162 TextureParams {
163 format: TextureFormat::RGBA8,
164 wrap: TextureWrap::Clamp,
165 filter: FilterMode::Nearest,
166 width: img_w,
167 height: img_h
168 }
169 )
170 );
171
172 let tiles_bytes = load_file("assets/dungeon_tiles.ron").await.unwrap();
173 let dungeon_tiles: DungeonTiles = from_reader(&tiles_bytes[..]).unwrap();
174
175 let mut tiles = Vec::new();
176 for (kind_code, subrects) in dungeon_tiles.wang_4_corner_tiles.iter() {
177 tiles.push(Tile {
178 kind: TileKind::Wang4Corner(*kind_code),
179 subrects: subrects.clone(),
180 neighbours_east: Vec::new(),
181 neighbours_west: Vec::new(),
182 neighbours_north: Vec::new(),
183 neighbours_south: Vec::new()
184 });
185 }
186 // We need to be sure that zero tile is always a "void" tile, so we doing an extra sort step
187 tiles.sort_by(|lhs, rhs| {
188 match (lhs.kind, rhs.kind) {
189 (TileKind::Wang4Corner(kind_lhs), TileKind::Wang4Corner(kind_rhs)) => kind_lhs.cmp(&kind_rhs),
190 _ => Ordering::Equal
191 }
192 });
193
194 for i in 0..tiles.len() {
195 let current_kind = tiles[i].kind;
196 for j in 0..tiles.len() {
197 let candidate_kind = tiles[j].kind;
198 let (matches_north, matches_south, matches_east, matches_west) = {
199 match (current_kind, candidate_kind) {
200 (TileKind::Wang4Corner(current), TileKind::Wang4Corner(candidate)) => {
201 (
202 get_north_east(current) == get_south_east(candidate) &&
203 get_north_west(current) == get_south_west(candidate),
204
205 get_south_east(current) == get_north_east(candidate) &&
206 get_south_west(current) == get_north_west(candidate),
207
208 get_north_east(current) == get_north_west(candidate) &&
209 get_south_east(current) == get_south_west(candidate),
210
211 get_north_west(current) == get_north_east(candidate) &&
212 get_south_west(current) == get_south_east(candidate),
213 )
214 },
215 _ => continue
216 }
217 };
218 if matches_east {
219 tiles[i].neighbours_east.push(candidate_kind);
220 }
221 if matches_west {
222 tiles[i].neighbours_west.push(candidate_kind);
223 }
224 if matches_north {
225 tiles[i].neighbours_north.push(candidate_kind);
226 }
227 if matches_south {
228 tiles[i].neighbours_south.push(candidate_kind);
229 }
230 }
231 }
232
233 //Add bridges:
234 {
235 let bridge_tiles_offset = tiles.len();
236 tiles.extend_from_slice(&dungeon_tiles.extra_tiles[..]);
237
238 let mut bridge_match_queue_south = VecDeque::new();
239 let mut bridge_match_queue_north = VecDeque::new();
240 let mut bridge_match_queue_east = VecDeque::new();
241 let mut bridge_match_queue_west = VecDeque::new();
242
243 for bridge_tile in &tiles[bridge_tiles_offset..] {
244 for south_neighbour in bridge_tile.neighbours_south.iter() {
245 if let TileKind::Wang4Corner(kind) = south_neighbour {
246 for i in 0..bridge_tiles_offset {
247 match tiles[i].kind {
248 TileKind::Wang4Corner(kind_inner) if kind_inner == *kind => {
249 bridge_match_queue_south.push_back((bridge_tile.kind, i))
250 },
251 _ => ()
252 };
253 }
254 }
255 }
256 for north_neighbour in bridge_tile.neighbours_north.iter() {
257 if let TileKind::Wang4Corner(kind) = north_neighbour {
258 for i in 0..bridge_tiles_offset {
259 match tiles[i].kind {
260 TileKind::Wang4Corner(kind_inner) if kind_inner == *kind => {
261 bridge_match_queue_north.push_back((bridge_tile.kind, i))
262 },
263 _ => ()
264 };
265 }
266 }
267 }
268 for east_neighbour in bridge_tile.neighbours_east.iter() {
269 if let TileKind::Wang4Corner(kind) = east_neighbour {
270 for i in 0..bridge_tiles_offset {
271 match tiles[i].kind {
272 TileKind::Wang4Corner(kind_inner) if kind_inner == *kind => {
273 bridge_match_queue_east.push_back((bridge_tile.kind, i))
274 },
275 _ => ()
276 };
277 }
278 }
279 }
280 for west_neighbour in bridge_tile.neighbours_west.iter() {
281 if let TileKind::Wang4Corner(kind) = west_neighbour {
282 for i in 0..bridge_tiles_offset {
283 match tiles[i].kind {
284 TileKind::Wang4Corner(kind_inner) if kind_inner == *kind => {
285 bridge_match_queue_west.push_back((bridge_tile.kind, i))
286 },
287 _ => ()
288 };
289 }
290 }
291 }
292 }
293
294 while !bridge_match_queue_south.is_empty() {
295 let next_match = bridge_match_queue_south.pop_front().unwrap();
296 tiles[next_match.1].neighbours_north.push(next_match.0);
297 }
298
299 while !bridge_match_queue_north.is_empty() {
300 let next_match = bridge_match_queue_north.pop_front().unwrap();
301 tiles[next_match.1].neighbours_south.push(next_match.0);
302 }
303
304 while !bridge_match_queue_east.is_empty() {
305 let next_match = bridge_match_queue_east.pop_front().unwrap();
306 tiles[next_match.1].neighbours_west.push(next_match.0);
307 }
308
309 while !bridge_match_queue_west.is_empty() {
310 let next_match = bridge_match_queue_west.pop_front().unwrap();
311 tiles[next_match.1].neighbours_east.push(next_match.0);
312 }
313 }
314
315 let modules = tiles
316 .iter()
317 .map(|tile| {
318 let mut module: WfcModule<CustomBitSet> = WfcModule::new();
319 for i in 0..tiles.len() {
320 if tile.neighbours_north.contains(&tiles[i].kind) {
321 module.add_north_neighbour(i);
322 }
323 if tile.neighbours_south.contains(&tiles[i].kind) {
324 module.add_south_neighbour(i);
325 }
326 if tile.neighbours_west.contains(&tiles[i].kind) {
327 module.add_west_neighbour(i);
328 }
329 if tile.neighbours_east.contains(&tiles[i].kind) {
330 module.add_east_neighbour(i);
331 }
332 }
333 module
334 })
335 .collect::<Vec<_>>();
336
337 Self {
338 w,
339 h,
340 tile_width: dungeon_tiles.tile_width,
341 tile_height: dungeon_tiles.tile_height,
342 tiles,
343 modules,
344 texture,
345 map_data: vec![(0, 0); w*h]
346 }
347 }examples/summer_garden.rs (line 339)
183 pub async fn new(w: usize, h: usize, draw_scale: f32) -> Self {
184 let InternalGlContext {
185 quad_context: ctx, ..
186 } = unsafe { get_internal_gl() };
187
188 let texture_bytes = load_file("assets/reduced_wang_scheme.png").await.unwrap();
189
190 let img = image::load_from_memory(&texture_bytes[..])
191 .unwrap_or_else(|e| panic!("{}", e))
192 .to_rgba8();
193
194 let img_w = img.width();
195 let img_h = img.height();
196
197 let texture = Texture2D::from_miniquad_texture(
198 miniquad::Texture::from_data_and_format(
199 ctx,
200 &img.into_raw(),
201 TextureParams {
202 format: TextureFormat::RGBA8,
203 wrap: TextureWrap::Clamp,
204 filter: FilterMode::Nearest,
205 width: img_w,
206 height: img_h
207 }
208 )
209 );
210
211 let atlas_bytes = load_file("assets/reduced_wang_scheme.ron").await.unwrap();
212 let atlas: SummerGardenAtlas = from_reader(&atlas_bytes[..]).unwrap();
213
214 let mut tile_sides = Vec::new();
215 let mut neighbour_strategies = Vec::new();
216 let mut tiles = Vec::new();
217
218 {
219 for tile_cfg in atlas.terrain_tile_configs.iter() {
220 for pattern in &[
221 &atlas.reduced_wang_patterns[..],
222 &atlas.extended_set_1_patterns_north_west[..],
223 &atlas.extended_set_1_patterns_north_east[..],
224 &atlas.extended_set_1_patterns_south_west[..],
225 &atlas.extended_set_1_patterns_south_east[..],
226 &atlas.extended_set_2_patterns_north_west[..],
227 &atlas.extended_set_2_patterns_north_east[..],
228 &atlas.extended_set_2_patterns_south_west[..],
229 &atlas.extended_set_2_patterns_south_east[..],
230 ] {
231 tile_sides.extend(
232 pattern.iter().map(
233 |pattern| {
234 TileSides {
235 north_west: match pattern.north_west {
236 TileKind::Inner => { tile_cfg.inner_type }
237 TileKind::Outer => { tile_cfg.outer_type }
238 },
239 north_east: match pattern.north_east {
240 TileKind::Inner => { tile_cfg.inner_type }
241 TileKind::Outer => { tile_cfg.outer_type }
242 },
243 south_west: match pattern.south_west {
244 TileKind::Inner => { tile_cfg.inner_type }
245 TileKind::Outer => { tile_cfg.outer_type }
246 },
247 south_east: match pattern.south_east {
248 TileKind::Inner => { tile_cfg.inner_type }
249 TileKind::Outer => { tile_cfg.outer_type }
250 }
251 }
252 }
253 )
254 );
255 }
256 for j in 0..4 {
257 for i in 0..4 {
258 tiles.push(SubRect{
259 x: i * 32 + tile_cfg.x_offset,
260 y: j * 32 + tile_cfg.y_offset,
261 width: 32,
262 height: 32
263 })
264 }
265 }
266 for jj in 0..2 {
267 for ii in 0..2 {
268 for j in 0..2 {
269 for i in 0..2 {
270 tiles.push(SubRect{
271 x: (i + ii * 2) * 32 + tile_cfg.x_offset + 256,
272 y: (j + jj * 2) * 32 + tile_cfg.y_offset,
273 width: 32,
274 height: 32
275 })
276 }
277 }
278 }
279 }
280 for jj in 0..2 {
281 for ii in 0..2 {
282 for j in 0..2 {
283 for i in 0..2 {
284 tiles.push(SubRect{
285 x: (i + ii * 2) * 32 + tile_cfg.x_offset,
286 y: (j + jj * 2) * 32 + tile_cfg.y_offset + 256,
287 width: 32,
288 height: 32
289 })
290 }
291 }
292 }
293 }
294 neighbour_strategies.extend_from_slice(&atlas.reduced_wang_neighbour_strategy[..]);
295 for _ in 0..8 {
296 neighbour_strategies.extend_from_slice(&atlas.neighbour_strategy_2_x_2[..]);
297 }
298 }
299 tile_sides.extend_from_slice(&atlas.vertical_bridge_sides[..]);
300 tile_sides.extend_from_slice(&atlas.horizontal_bridge_sides[..]);
301 for j in 0..3 {
302 for i in 0..3 {
303 tiles.push(SubRect{
304 x: i * 32 + 256,
305 y: j * 32 + 256,
306 width: 32,
307 height: 32
308 })
309 }
310 }
311 for j in 0..3 {
312 for i in 0..3 {
313 tiles.push(SubRect{
314 x: i * 32 + 256 + 96,
315 y: j * 32 + 256,
316 width: 32,
317 height: 32
318 })
319 }
320 }
321 neighbour_strategies.extend_from_slice(&atlas.neighbour_strategy_3_x_3[..]);
322 neighbour_strategies.extend_from_slice(&atlas.neighbour_strategy_3_x_3[..]);
323
324 assert_eq!(tile_sides.len(), neighbour_strategies.len());
325 }
326
327 let mut modules = Vec::new();
328 for i in 0..tile_sides.len() {
329 let current_sides = tile_sides[i];
330 let mut module: WfcModule<CustomBitSet> = WfcModule::new();
331 match neighbour_strategies[i].north {
332 NeighbourKind::WangCorners => {
333 for j in 0..tile_sides.len() {
334 if neighbour_strategies[j].south != NeighbourKind::WangCorners {
335 continue;
336 }
337 if tile_sides[j].south_west == current_sides.north_west &&
338 tile_sides[j].south_east == current_sides.north_east {
339 module.add_north_neighbour(j);
340 }
341 }
342 }
343 NeighbourKind::RelOffset(offset) => {
344 let new_offset = (i as i32 + offset) as usize;
345 module.add_north_neighbour(new_offset);
346 }
347 }
348 match neighbour_strategies[i].south {
349 NeighbourKind::WangCorners => {
350 for j in 0..tile_sides.len() {
351 if neighbour_strategies[j].north != NeighbourKind::WangCorners {
352 continue;
353 }
354 if tile_sides[j].north_west == current_sides.south_west &&
355 tile_sides[j].north_east == current_sides.south_east {
356 module.add_south_neighbour(j);
357 }
358 }
359 }
360 NeighbourKind::RelOffset(offset) => {
361 let new_offset = (i as i32 + offset) as usize;
362 module.add_south_neighbour(new_offset);
363 }
364 }
365 match neighbour_strategies[i].east {
366 NeighbourKind::WangCorners => {
367 for j in 0..tile_sides.len() {
368 if neighbour_strategies[j].west != NeighbourKind::WangCorners {
369 continue;
370 }
371 if tile_sides[j].north_west == current_sides.north_east &&
372 tile_sides[j].south_west == current_sides.south_east {
373 module.add_east_neighbour(j);
374 }
375 }
376 }
377 NeighbourKind::RelOffset(offset) => {
378 let new_offset = (i as i32 + offset) as usize;
379 module.add_east_neighbour(new_offset);
380 }
381 }
382 match neighbour_strategies[i].west {
383 NeighbourKind::WangCorners => {
384 for j in 0..tile_sides.len() {
385 if neighbour_strategies[j].east != NeighbourKind::WangCorners {
386 continue;
387 }
388 if tile_sides[j].north_east == current_sides.north_west &&
389 tile_sides[j].south_east == current_sides.south_west {
390 module.add_west_neighbour(j);
391 }
392 }
393 }
394 NeighbourKind::RelOffset(offset) => {
395 let new_offset = (i as i32 + offset) as usize;
396 module.add_west_neighbour(new_offset);
397 }
398 }
399 modules.push(module);
400 }
401
402 Self {
403 w,
404 h,
405 draw_scale,
406 atlas,
407 tile_width: 32,
408 tile_height: 32,
409 tiles,
410 modules,
411 texture,
412 map_data: vec![0; w*h],
413 cell_tree_data: vec![TreeType::None; w*h],
414 corner_tree_data: vec![TreeType::None; (w+1)*(h+1)]
415 }
416 }Sourcepub fn add_south_neighbour(&mut self, idx: usize)
pub fn add_south_neighbour(&mut self, idx: usize)
A function which adds a neighbour on a south side
Examples found in repository?
examples/wang_corner_carpet.rs (line 125)
69 pub async fn new(w: usize, h: usize) -> Self {
70 let InternalGlContext {
71 quad_context: ctx, ..
72 } = unsafe { get_internal_gl() };
73
74 let texture_bytes = load_file("assets/wang_4_corner.png").await.unwrap();
75
76 let img = image::load_from_memory(&texture_bytes[..])
77 .unwrap_or_else(|e| panic!("{}", e))
78 .to_rgba8();
79
80 let img_w = img.width();
81 let img_h = img.height();
82
83 let texture = Texture2D::from_miniquad_texture(
84 miniquad::Texture::from_data_and_format(
85 ctx,
86 &img.into_raw(),
87 TextureParams {
88 format: TextureFormat::RGBA8,
89 wrap: TextureWrap::Clamp,
90 filter: FilterMode::Nearest,
91 width: img_w,
92 height: img_h
93 }
94 )
95 );
96
97 let tiles = (0..=255)
98 .map(|idx| {
99 let width = 32;
100 let height = 32;
101 (
102 idx as u8,
103 SubRect {
104 x: (idx % 16) * width,
105 y: (idx / 16) * height,
106 width,
107 height
108 }
109 )
110 })
111 .collect::<Vec<_>>();
112
113 let modules = tiles
114 .iter()
115 .map(|tile| {
116 let mut module: WfcModule<CustomBitSet> = WfcModule::new();
117 for i in 0..tiles.len() {
118 let other_tile = &tiles[i];
119 if get_north_west(tile.0) == get_south_west(other_tile.0) &&
120 get_north_east(tile.0) == get_south_east(other_tile.0) {
121 module.add_north_neighbour(i);
122 }
123 if get_south_west(tile.0) == get_north_west(other_tile.0) &&
124 get_south_east(tile.0) == get_north_east(other_tile.0) {
125 module.add_south_neighbour(i);
126 }
127 if get_north_west(tile.0) == get_north_east(other_tile.0) &&
128 get_south_west(tile.0) == get_south_east(other_tile.0) {
129 module.add_west_neighbour(i);
130 }
131 if get_north_east(tile.0) == get_north_west(other_tile.0) &&
132 get_south_east(tile.0) == get_south_west(other_tile.0) {
133 module.add_east_neighbour(i);
134 }
135 }
136 module
137 })
138 .collect::<Vec<_>>();
139
140 Self {
141 w,
142 h,
143 tile_width: 32,
144 tile_height: 32,
145 tiles,
146 modules,
147 texture,
148 map_data: vec![0; w*h]
149 }
150 }More examples
examples/dungeon.rs (line 324)
144 pub async fn new(w: usize, h: usize) -> Self {
145 let InternalGlContext {
146 quad_context: ctx, ..
147 } = unsafe { get_internal_gl() };
148
149 let dungeon_bytes = load_file("assets/dungeon_tiles.png").await.unwrap();
150
151 let img = image::load_from_memory(&dungeon_bytes[..])
152 .unwrap_or_else(|e| panic!("{}", e))
153 .to_rgba8();
154
155 let img_w = img.width();
156 let img_h = img.height();
157
158 let texture = Texture2D::from_miniquad_texture(
159 miniquad::Texture::from_data_and_format(
160 ctx,
161 &img.into_raw(),
162 TextureParams {
163 format: TextureFormat::RGBA8,
164 wrap: TextureWrap::Clamp,
165 filter: FilterMode::Nearest,
166 width: img_w,
167 height: img_h
168 }
169 )
170 );
171
172 let tiles_bytes = load_file("assets/dungeon_tiles.ron").await.unwrap();
173 let dungeon_tiles: DungeonTiles = from_reader(&tiles_bytes[..]).unwrap();
174
175 let mut tiles = Vec::new();
176 for (kind_code, subrects) in dungeon_tiles.wang_4_corner_tiles.iter() {
177 tiles.push(Tile {
178 kind: TileKind::Wang4Corner(*kind_code),
179 subrects: subrects.clone(),
180 neighbours_east: Vec::new(),
181 neighbours_west: Vec::new(),
182 neighbours_north: Vec::new(),
183 neighbours_south: Vec::new()
184 });
185 }
186 // We need to be sure that zero tile is always a "void" tile, so we doing an extra sort step
187 tiles.sort_by(|lhs, rhs| {
188 match (lhs.kind, rhs.kind) {
189 (TileKind::Wang4Corner(kind_lhs), TileKind::Wang4Corner(kind_rhs)) => kind_lhs.cmp(&kind_rhs),
190 _ => Ordering::Equal
191 }
192 });
193
194 for i in 0..tiles.len() {
195 let current_kind = tiles[i].kind;
196 for j in 0..tiles.len() {
197 let candidate_kind = tiles[j].kind;
198 let (matches_north, matches_south, matches_east, matches_west) = {
199 match (current_kind, candidate_kind) {
200 (TileKind::Wang4Corner(current), TileKind::Wang4Corner(candidate)) => {
201 (
202 get_north_east(current) == get_south_east(candidate) &&
203 get_north_west(current) == get_south_west(candidate),
204
205 get_south_east(current) == get_north_east(candidate) &&
206 get_south_west(current) == get_north_west(candidate),
207
208 get_north_east(current) == get_north_west(candidate) &&
209 get_south_east(current) == get_south_west(candidate),
210
211 get_north_west(current) == get_north_east(candidate) &&
212 get_south_west(current) == get_south_east(candidate),
213 )
214 },
215 _ => continue
216 }
217 };
218 if matches_east {
219 tiles[i].neighbours_east.push(candidate_kind);
220 }
221 if matches_west {
222 tiles[i].neighbours_west.push(candidate_kind);
223 }
224 if matches_north {
225 tiles[i].neighbours_north.push(candidate_kind);
226 }
227 if matches_south {
228 tiles[i].neighbours_south.push(candidate_kind);
229 }
230 }
231 }
232
233 //Add bridges:
234 {
235 let bridge_tiles_offset = tiles.len();
236 tiles.extend_from_slice(&dungeon_tiles.extra_tiles[..]);
237
238 let mut bridge_match_queue_south = VecDeque::new();
239 let mut bridge_match_queue_north = VecDeque::new();
240 let mut bridge_match_queue_east = VecDeque::new();
241 let mut bridge_match_queue_west = VecDeque::new();
242
243 for bridge_tile in &tiles[bridge_tiles_offset..] {
244 for south_neighbour in bridge_tile.neighbours_south.iter() {
245 if let TileKind::Wang4Corner(kind) = south_neighbour {
246 for i in 0..bridge_tiles_offset {
247 match tiles[i].kind {
248 TileKind::Wang4Corner(kind_inner) if kind_inner == *kind => {
249 bridge_match_queue_south.push_back((bridge_tile.kind, i))
250 },
251 _ => ()
252 };
253 }
254 }
255 }
256 for north_neighbour in bridge_tile.neighbours_north.iter() {
257 if let TileKind::Wang4Corner(kind) = north_neighbour {
258 for i in 0..bridge_tiles_offset {
259 match tiles[i].kind {
260 TileKind::Wang4Corner(kind_inner) if kind_inner == *kind => {
261 bridge_match_queue_north.push_back((bridge_tile.kind, i))
262 },
263 _ => ()
264 };
265 }
266 }
267 }
268 for east_neighbour in bridge_tile.neighbours_east.iter() {
269 if let TileKind::Wang4Corner(kind) = east_neighbour {
270 for i in 0..bridge_tiles_offset {
271 match tiles[i].kind {
272 TileKind::Wang4Corner(kind_inner) if kind_inner == *kind => {
273 bridge_match_queue_east.push_back((bridge_tile.kind, i))
274 },
275 _ => ()
276 };
277 }
278 }
279 }
280 for west_neighbour in bridge_tile.neighbours_west.iter() {
281 if let TileKind::Wang4Corner(kind) = west_neighbour {
282 for i in 0..bridge_tiles_offset {
283 match tiles[i].kind {
284 TileKind::Wang4Corner(kind_inner) if kind_inner == *kind => {
285 bridge_match_queue_west.push_back((bridge_tile.kind, i))
286 },
287 _ => ()
288 };
289 }
290 }
291 }
292 }
293
294 while !bridge_match_queue_south.is_empty() {
295 let next_match = bridge_match_queue_south.pop_front().unwrap();
296 tiles[next_match.1].neighbours_north.push(next_match.0);
297 }
298
299 while !bridge_match_queue_north.is_empty() {
300 let next_match = bridge_match_queue_north.pop_front().unwrap();
301 tiles[next_match.1].neighbours_south.push(next_match.0);
302 }
303
304 while !bridge_match_queue_east.is_empty() {
305 let next_match = bridge_match_queue_east.pop_front().unwrap();
306 tiles[next_match.1].neighbours_west.push(next_match.0);
307 }
308
309 while !bridge_match_queue_west.is_empty() {
310 let next_match = bridge_match_queue_west.pop_front().unwrap();
311 tiles[next_match.1].neighbours_east.push(next_match.0);
312 }
313 }
314
315 let modules = tiles
316 .iter()
317 .map(|tile| {
318 let mut module: WfcModule<CustomBitSet> = WfcModule::new();
319 for i in 0..tiles.len() {
320 if tile.neighbours_north.contains(&tiles[i].kind) {
321 module.add_north_neighbour(i);
322 }
323 if tile.neighbours_south.contains(&tiles[i].kind) {
324 module.add_south_neighbour(i);
325 }
326 if tile.neighbours_west.contains(&tiles[i].kind) {
327 module.add_west_neighbour(i);
328 }
329 if tile.neighbours_east.contains(&tiles[i].kind) {
330 module.add_east_neighbour(i);
331 }
332 }
333 module
334 })
335 .collect::<Vec<_>>();
336
337 Self {
338 w,
339 h,
340 tile_width: dungeon_tiles.tile_width,
341 tile_height: dungeon_tiles.tile_height,
342 tiles,
343 modules,
344 texture,
345 map_data: vec![(0, 0); w*h]
346 }
347 }examples/summer_garden.rs (line 356)
183 pub async fn new(w: usize, h: usize, draw_scale: f32) -> Self {
184 let InternalGlContext {
185 quad_context: ctx, ..
186 } = unsafe { get_internal_gl() };
187
188 let texture_bytes = load_file("assets/reduced_wang_scheme.png").await.unwrap();
189
190 let img = image::load_from_memory(&texture_bytes[..])
191 .unwrap_or_else(|e| panic!("{}", e))
192 .to_rgba8();
193
194 let img_w = img.width();
195 let img_h = img.height();
196
197 let texture = Texture2D::from_miniquad_texture(
198 miniquad::Texture::from_data_and_format(
199 ctx,
200 &img.into_raw(),
201 TextureParams {
202 format: TextureFormat::RGBA8,
203 wrap: TextureWrap::Clamp,
204 filter: FilterMode::Nearest,
205 width: img_w,
206 height: img_h
207 }
208 )
209 );
210
211 let atlas_bytes = load_file("assets/reduced_wang_scheme.ron").await.unwrap();
212 let atlas: SummerGardenAtlas = from_reader(&atlas_bytes[..]).unwrap();
213
214 let mut tile_sides = Vec::new();
215 let mut neighbour_strategies = Vec::new();
216 let mut tiles = Vec::new();
217
218 {
219 for tile_cfg in atlas.terrain_tile_configs.iter() {
220 for pattern in &[
221 &atlas.reduced_wang_patterns[..],
222 &atlas.extended_set_1_patterns_north_west[..],
223 &atlas.extended_set_1_patterns_north_east[..],
224 &atlas.extended_set_1_patterns_south_west[..],
225 &atlas.extended_set_1_patterns_south_east[..],
226 &atlas.extended_set_2_patterns_north_west[..],
227 &atlas.extended_set_2_patterns_north_east[..],
228 &atlas.extended_set_2_patterns_south_west[..],
229 &atlas.extended_set_2_patterns_south_east[..],
230 ] {
231 tile_sides.extend(
232 pattern.iter().map(
233 |pattern| {
234 TileSides {
235 north_west: match pattern.north_west {
236 TileKind::Inner => { tile_cfg.inner_type }
237 TileKind::Outer => { tile_cfg.outer_type }
238 },
239 north_east: match pattern.north_east {
240 TileKind::Inner => { tile_cfg.inner_type }
241 TileKind::Outer => { tile_cfg.outer_type }
242 },
243 south_west: match pattern.south_west {
244 TileKind::Inner => { tile_cfg.inner_type }
245 TileKind::Outer => { tile_cfg.outer_type }
246 },
247 south_east: match pattern.south_east {
248 TileKind::Inner => { tile_cfg.inner_type }
249 TileKind::Outer => { tile_cfg.outer_type }
250 }
251 }
252 }
253 )
254 );
255 }
256 for j in 0..4 {
257 for i in 0..4 {
258 tiles.push(SubRect{
259 x: i * 32 + tile_cfg.x_offset,
260 y: j * 32 + tile_cfg.y_offset,
261 width: 32,
262 height: 32
263 })
264 }
265 }
266 for jj in 0..2 {
267 for ii in 0..2 {
268 for j in 0..2 {
269 for i in 0..2 {
270 tiles.push(SubRect{
271 x: (i + ii * 2) * 32 + tile_cfg.x_offset + 256,
272 y: (j + jj * 2) * 32 + tile_cfg.y_offset,
273 width: 32,
274 height: 32
275 })
276 }
277 }
278 }
279 }
280 for jj in 0..2 {
281 for ii in 0..2 {
282 for j in 0..2 {
283 for i in 0..2 {
284 tiles.push(SubRect{
285 x: (i + ii * 2) * 32 + tile_cfg.x_offset,
286 y: (j + jj * 2) * 32 + tile_cfg.y_offset + 256,
287 width: 32,
288 height: 32
289 })
290 }
291 }
292 }
293 }
294 neighbour_strategies.extend_from_slice(&atlas.reduced_wang_neighbour_strategy[..]);
295 for _ in 0..8 {
296 neighbour_strategies.extend_from_slice(&atlas.neighbour_strategy_2_x_2[..]);
297 }
298 }
299 tile_sides.extend_from_slice(&atlas.vertical_bridge_sides[..]);
300 tile_sides.extend_from_slice(&atlas.horizontal_bridge_sides[..]);
301 for j in 0..3 {
302 for i in 0..3 {
303 tiles.push(SubRect{
304 x: i * 32 + 256,
305 y: j * 32 + 256,
306 width: 32,
307 height: 32
308 })
309 }
310 }
311 for j in 0..3 {
312 for i in 0..3 {
313 tiles.push(SubRect{
314 x: i * 32 + 256 + 96,
315 y: j * 32 + 256,
316 width: 32,
317 height: 32
318 })
319 }
320 }
321 neighbour_strategies.extend_from_slice(&atlas.neighbour_strategy_3_x_3[..]);
322 neighbour_strategies.extend_from_slice(&atlas.neighbour_strategy_3_x_3[..]);
323
324 assert_eq!(tile_sides.len(), neighbour_strategies.len());
325 }
326
327 let mut modules = Vec::new();
328 for i in 0..tile_sides.len() {
329 let current_sides = tile_sides[i];
330 let mut module: WfcModule<CustomBitSet> = WfcModule::new();
331 match neighbour_strategies[i].north {
332 NeighbourKind::WangCorners => {
333 for j in 0..tile_sides.len() {
334 if neighbour_strategies[j].south != NeighbourKind::WangCorners {
335 continue;
336 }
337 if tile_sides[j].south_west == current_sides.north_west &&
338 tile_sides[j].south_east == current_sides.north_east {
339 module.add_north_neighbour(j);
340 }
341 }
342 }
343 NeighbourKind::RelOffset(offset) => {
344 let new_offset = (i as i32 + offset) as usize;
345 module.add_north_neighbour(new_offset);
346 }
347 }
348 match neighbour_strategies[i].south {
349 NeighbourKind::WangCorners => {
350 for j in 0..tile_sides.len() {
351 if neighbour_strategies[j].north != NeighbourKind::WangCorners {
352 continue;
353 }
354 if tile_sides[j].north_west == current_sides.south_west &&
355 tile_sides[j].north_east == current_sides.south_east {
356 module.add_south_neighbour(j);
357 }
358 }
359 }
360 NeighbourKind::RelOffset(offset) => {
361 let new_offset = (i as i32 + offset) as usize;
362 module.add_south_neighbour(new_offset);
363 }
364 }
365 match neighbour_strategies[i].east {
366 NeighbourKind::WangCorners => {
367 for j in 0..tile_sides.len() {
368 if neighbour_strategies[j].west != NeighbourKind::WangCorners {
369 continue;
370 }
371 if tile_sides[j].north_west == current_sides.north_east &&
372 tile_sides[j].south_west == current_sides.south_east {
373 module.add_east_neighbour(j);
374 }
375 }
376 }
377 NeighbourKind::RelOffset(offset) => {
378 let new_offset = (i as i32 + offset) as usize;
379 module.add_east_neighbour(new_offset);
380 }
381 }
382 match neighbour_strategies[i].west {
383 NeighbourKind::WangCorners => {
384 for j in 0..tile_sides.len() {
385 if neighbour_strategies[j].east != NeighbourKind::WangCorners {
386 continue;
387 }
388 if tile_sides[j].north_east == current_sides.north_west &&
389 tile_sides[j].south_east == current_sides.south_west {
390 module.add_west_neighbour(j);
391 }
392 }
393 }
394 NeighbourKind::RelOffset(offset) => {
395 let new_offset = (i as i32 + offset) as usize;
396 module.add_west_neighbour(new_offset);
397 }
398 }
399 modules.push(module);
400 }
401
402 Self {
403 w,
404 h,
405 draw_scale,
406 atlas,
407 tile_width: 32,
408 tile_height: 32,
409 tiles,
410 modules,
411 texture,
412 map_data: vec![0; w*h],
413 cell_tree_data: vec![TreeType::None; w*h],
414 corner_tree_data: vec![TreeType::None; (w+1)*(h+1)]
415 }
416 }Sourcepub fn add_east_neighbour(&mut self, idx: usize)
pub fn add_east_neighbour(&mut self, idx: usize)
A function which adds a neighbour on an east side
Examples found in repository?
examples/wang_corner_carpet.rs (line 133)
69 pub async fn new(w: usize, h: usize) -> Self {
70 let InternalGlContext {
71 quad_context: ctx, ..
72 } = unsafe { get_internal_gl() };
73
74 let texture_bytes = load_file("assets/wang_4_corner.png").await.unwrap();
75
76 let img = image::load_from_memory(&texture_bytes[..])
77 .unwrap_or_else(|e| panic!("{}", e))
78 .to_rgba8();
79
80 let img_w = img.width();
81 let img_h = img.height();
82
83 let texture = Texture2D::from_miniquad_texture(
84 miniquad::Texture::from_data_and_format(
85 ctx,
86 &img.into_raw(),
87 TextureParams {
88 format: TextureFormat::RGBA8,
89 wrap: TextureWrap::Clamp,
90 filter: FilterMode::Nearest,
91 width: img_w,
92 height: img_h
93 }
94 )
95 );
96
97 let tiles = (0..=255)
98 .map(|idx| {
99 let width = 32;
100 let height = 32;
101 (
102 idx as u8,
103 SubRect {
104 x: (idx % 16) * width,
105 y: (idx / 16) * height,
106 width,
107 height
108 }
109 )
110 })
111 .collect::<Vec<_>>();
112
113 let modules = tiles
114 .iter()
115 .map(|tile| {
116 let mut module: WfcModule<CustomBitSet> = WfcModule::new();
117 for i in 0..tiles.len() {
118 let other_tile = &tiles[i];
119 if get_north_west(tile.0) == get_south_west(other_tile.0) &&
120 get_north_east(tile.0) == get_south_east(other_tile.0) {
121 module.add_north_neighbour(i);
122 }
123 if get_south_west(tile.0) == get_north_west(other_tile.0) &&
124 get_south_east(tile.0) == get_north_east(other_tile.0) {
125 module.add_south_neighbour(i);
126 }
127 if get_north_west(tile.0) == get_north_east(other_tile.0) &&
128 get_south_west(tile.0) == get_south_east(other_tile.0) {
129 module.add_west_neighbour(i);
130 }
131 if get_north_east(tile.0) == get_north_west(other_tile.0) &&
132 get_south_east(tile.0) == get_south_west(other_tile.0) {
133 module.add_east_neighbour(i);
134 }
135 }
136 module
137 })
138 .collect::<Vec<_>>();
139
140 Self {
141 w,
142 h,
143 tile_width: 32,
144 tile_height: 32,
145 tiles,
146 modules,
147 texture,
148 map_data: vec![0; w*h]
149 }
150 }More examples
examples/dungeon.rs (line 330)
144 pub async fn new(w: usize, h: usize) -> Self {
145 let InternalGlContext {
146 quad_context: ctx, ..
147 } = unsafe { get_internal_gl() };
148
149 let dungeon_bytes = load_file("assets/dungeon_tiles.png").await.unwrap();
150
151 let img = image::load_from_memory(&dungeon_bytes[..])
152 .unwrap_or_else(|e| panic!("{}", e))
153 .to_rgba8();
154
155 let img_w = img.width();
156 let img_h = img.height();
157
158 let texture = Texture2D::from_miniquad_texture(
159 miniquad::Texture::from_data_and_format(
160 ctx,
161 &img.into_raw(),
162 TextureParams {
163 format: TextureFormat::RGBA8,
164 wrap: TextureWrap::Clamp,
165 filter: FilterMode::Nearest,
166 width: img_w,
167 height: img_h
168 }
169 )
170 );
171
172 let tiles_bytes = load_file("assets/dungeon_tiles.ron").await.unwrap();
173 let dungeon_tiles: DungeonTiles = from_reader(&tiles_bytes[..]).unwrap();
174
175 let mut tiles = Vec::new();
176 for (kind_code, subrects) in dungeon_tiles.wang_4_corner_tiles.iter() {
177 tiles.push(Tile {
178 kind: TileKind::Wang4Corner(*kind_code),
179 subrects: subrects.clone(),
180 neighbours_east: Vec::new(),
181 neighbours_west: Vec::new(),
182 neighbours_north: Vec::new(),
183 neighbours_south: Vec::new()
184 });
185 }
186 // We need to be sure that zero tile is always a "void" tile, so we doing an extra sort step
187 tiles.sort_by(|lhs, rhs| {
188 match (lhs.kind, rhs.kind) {
189 (TileKind::Wang4Corner(kind_lhs), TileKind::Wang4Corner(kind_rhs)) => kind_lhs.cmp(&kind_rhs),
190 _ => Ordering::Equal
191 }
192 });
193
194 for i in 0..tiles.len() {
195 let current_kind = tiles[i].kind;
196 for j in 0..tiles.len() {
197 let candidate_kind = tiles[j].kind;
198 let (matches_north, matches_south, matches_east, matches_west) = {
199 match (current_kind, candidate_kind) {
200 (TileKind::Wang4Corner(current), TileKind::Wang4Corner(candidate)) => {
201 (
202 get_north_east(current) == get_south_east(candidate) &&
203 get_north_west(current) == get_south_west(candidate),
204
205 get_south_east(current) == get_north_east(candidate) &&
206 get_south_west(current) == get_north_west(candidate),
207
208 get_north_east(current) == get_north_west(candidate) &&
209 get_south_east(current) == get_south_west(candidate),
210
211 get_north_west(current) == get_north_east(candidate) &&
212 get_south_west(current) == get_south_east(candidate),
213 )
214 },
215 _ => continue
216 }
217 };
218 if matches_east {
219 tiles[i].neighbours_east.push(candidate_kind);
220 }
221 if matches_west {
222 tiles[i].neighbours_west.push(candidate_kind);
223 }
224 if matches_north {
225 tiles[i].neighbours_north.push(candidate_kind);
226 }
227 if matches_south {
228 tiles[i].neighbours_south.push(candidate_kind);
229 }
230 }
231 }
232
233 //Add bridges:
234 {
235 let bridge_tiles_offset = tiles.len();
236 tiles.extend_from_slice(&dungeon_tiles.extra_tiles[..]);
237
238 let mut bridge_match_queue_south = VecDeque::new();
239 let mut bridge_match_queue_north = VecDeque::new();
240 let mut bridge_match_queue_east = VecDeque::new();
241 let mut bridge_match_queue_west = VecDeque::new();
242
243 for bridge_tile in &tiles[bridge_tiles_offset..] {
244 for south_neighbour in bridge_tile.neighbours_south.iter() {
245 if let TileKind::Wang4Corner(kind) = south_neighbour {
246 for i in 0..bridge_tiles_offset {
247 match tiles[i].kind {
248 TileKind::Wang4Corner(kind_inner) if kind_inner == *kind => {
249 bridge_match_queue_south.push_back((bridge_tile.kind, i))
250 },
251 _ => ()
252 };
253 }
254 }
255 }
256 for north_neighbour in bridge_tile.neighbours_north.iter() {
257 if let TileKind::Wang4Corner(kind) = north_neighbour {
258 for i in 0..bridge_tiles_offset {
259 match tiles[i].kind {
260 TileKind::Wang4Corner(kind_inner) if kind_inner == *kind => {
261 bridge_match_queue_north.push_back((bridge_tile.kind, i))
262 },
263 _ => ()
264 };
265 }
266 }
267 }
268 for east_neighbour in bridge_tile.neighbours_east.iter() {
269 if let TileKind::Wang4Corner(kind) = east_neighbour {
270 for i in 0..bridge_tiles_offset {
271 match tiles[i].kind {
272 TileKind::Wang4Corner(kind_inner) if kind_inner == *kind => {
273 bridge_match_queue_east.push_back((bridge_tile.kind, i))
274 },
275 _ => ()
276 };
277 }
278 }
279 }
280 for west_neighbour in bridge_tile.neighbours_west.iter() {
281 if let TileKind::Wang4Corner(kind) = west_neighbour {
282 for i in 0..bridge_tiles_offset {
283 match tiles[i].kind {
284 TileKind::Wang4Corner(kind_inner) if kind_inner == *kind => {
285 bridge_match_queue_west.push_back((bridge_tile.kind, i))
286 },
287 _ => ()
288 };
289 }
290 }
291 }
292 }
293
294 while !bridge_match_queue_south.is_empty() {
295 let next_match = bridge_match_queue_south.pop_front().unwrap();
296 tiles[next_match.1].neighbours_north.push(next_match.0);
297 }
298
299 while !bridge_match_queue_north.is_empty() {
300 let next_match = bridge_match_queue_north.pop_front().unwrap();
301 tiles[next_match.1].neighbours_south.push(next_match.0);
302 }
303
304 while !bridge_match_queue_east.is_empty() {
305 let next_match = bridge_match_queue_east.pop_front().unwrap();
306 tiles[next_match.1].neighbours_west.push(next_match.0);
307 }
308
309 while !bridge_match_queue_west.is_empty() {
310 let next_match = bridge_match_queue_west.pop_front().unwrap();
311 tiles[next_match.1].neighbours_east.push(next_match.0);
312 }
313 }
314
315 let modules = tiles
316 .iter()
317 .map(|tile| {
318 let mut module: WfcModule<CustomBitSet> = WfcModule::new();
319 for i in 0..tiles.len() {
320 if tile.neighbours_north.contains(&tiles[i].kind) {
321 module.add_north_neighbour(i);
322 }
323 if tile.neighbours_south.contains(&tiles[i].kind) {
324 module.add_south_neighbour(i);
325 }
326 if tile.neighbours_west.contains(&tiles[i].kind) {
327 module.add_west_neighbour(i);
328 }
329 if tile.neighbours_east.contains(&tiles[i].kind) {
330 module.add_east_neighbour(i);
331 }
332 }
333 module
334 })
335 .collect::<Vec<_>>();
336
337 Self {
338 w,
339 h,
340 tile_width: dungeon_tiles.tile_width,
341 tile_height: dungeon_tiles.tile_height,
342 tiles,
343 modules,
344 texture,
345 map_data: vec![(0, 0); w*h]
346 }
347 }examples/summer_garden.rs (line 373)
183 pub async fn new(w: usize, h: usize, draw_scale: f32) -> Self {
184 let InternalGlContext {
185 quad_context: ctx, ..
186 } = unsafe { get_internal_gl() };
187
188 let texture_bytes = load_file("assets/reduced_wang_scheme.png").await.unwrap();
189
190 let img = image::load_from_memory(&texture_bytes[..])
191 .unwrap_or_else(|e| panic!("{}", e))
192 .to_rgba8();
193
194 let img_w = img.width();
195 let img_h = img.height();
196
197 let texture = Texture2D::from_miniquad_texture(
198 miniquad::Texture::from_data_and_format(
199 ctx,
200 &img.into_raw(),
201 TextureParams {
202 format: TextureFormat::RGBA8,
203 wrap: TextureWrap::Clamp,
204 filter: FilterMode::Nearest,
205 width: img_w,
206 height: img_h
207 }
208 )
209 );
210
211 let atlas_bytes = load_file("assets/reduced_wang_scheme.ron").await.unwrap();
212 let atlas: SummerGardenAtlas = from_reader(&atlas_bytes[..]).unwrap();
213
214 let mut tile_sides = Vec::new();
215 let mut neighbour_strategies = Vec::new();
216 let mut tiles = Vec::new();
217
218 {
219 for tile_cfg in atlas.terrain_tile_configs.iter() {
220 for pattern in &[
221 &atlas.reduced_wang_patterns[..],
222 &atlas.extended_set_1_patterns_north_west[..],
223 &atlas.extended_set_1_patterns_north_east[..],
224 &atlas.extended_set_1_patterns_south_west[..],
225 &atlas.extended_set_1_patterns_south_east[..],
226 &atlas.extended_set_2_patterns_north_west[..],
227 &atlas.extended_set_2_patterns_north_east[..],
228 &atlas.extended_set_2_patterns_south_west[..],
229 &atlas.extended_set_2_patterns_south_east[..],
230 ] {
231 tile_sides.extend(
232 pattern.iter().map(
233 |pattern| {
234 TileSides {
235 north_west: match pattern.north_west {
236 TileKind::Inner => { tile_cfg.inner_type }
237 TileKind::Outer => { tile_cfg.outer_type }
238 },
239 north_east: match pattern.north_east {
240 TileKind::Inner => { tile_cfg.inner_type }
241 TileKind::Outer => { tile_cfg.outer_type }
242 },
243 south_west: match pattern.south_west {
244 TileKind::Inner => { tile_cfg.inner_type }
245 TileKind::Outer => { tile_cfg.outer_type }
246 },
247 south_east: match pattern.south_east {
248 TileKind::Inner => { tile_cfg.inner_type }
249 TileKind::Outer => { tile_cfg.outer_type }
250 }
251 }
252 }
253 )
254 );
255 }
256 for j in 0..4 {
257 for i in 0..4 {
258 tiles.push(SubRect{
259 x: i * 32 + tile_cfg.x_offset,
260 y: j * 32 + tile_cfg.y_offset,
261 width: 32,
262 height: 32
263 })
264 }
265 }
266 for jj in 0..2 {
267 for ii in 0..2 {
268 for j in 0..2 {
269 for i in 0..2 {
270 tiles.push(SubRect{
271 x: (i + ii * 2) * 32 + tile_cfg.x_offset + 256,
272 y: (j + jj * 2) * 32 + tile_cfg.y_offset,
273 width: 32,
274 height: 32
275 })
276 }
277 }
278 }
279 }
280 for jj in 0..2 {
281 for ii in 0..2 {
282 for j in 0..2 {
283 for i in 0..2 {
284 tiles.push(SubRect{
285 x: (i + ii * 2) * 32 + tile_cfg.x_offset,
286 y: (j + jj * 2) * 32 + tile_cfg.y_offset + 256,
287 width: 32,
288 height: 32
289 })
290 }
291 }
292 }
293 }
294 neighbour_strategies.extend_from_slice(&atlas.reduced_wang_neighbour_strategy[..]);
295 for _ in 0..8 {
296 neighbour_strategies.extend_from_slice(&atlas.neighbour_strategy_2_x_2[..]);
297 }
298 }
299 tile_sides.extend_from_slice(&atlas.vertical_bridge_sides[..]);
300 tile_sides.extend_from_slice(&atlas.horizontal_bridge_sides[..]);
301 for j in 0..3 {
302 for i in 0..3 {
303 tiles.push(SubRect{
304 x: i * 32 + 256,
305 y: j * 32 + 256,
306 width: 32,
307 height: 32
308 })
309 }
310 }
311 for j in 0..3 {
312 for i in 0..3 {
313 tiles.push(SubRect{
314 x: i * 32 + 256 + 96,
315 y: j * 32 + 256,
316 width: 32,
317 height: 32
318 })
319 }
320 }
321 neighbour_strategies.extend_from_slice(&atlas.neighbour_strategy_3_x_3[..]);
322 neighbour_strategies.extend_from_slice(&atlas.neighbour_strategy_3_x_3[..]);
323
324 assert_eq!(tile_sides.len(), neighbour_strategies.len());
325 }
326
327 let mut modules = Vec::new();
328 for i in 0..tile_sides.len() {
329 let current_sides = tile_sides[i];
330 let mut module: WfcModule<CustomBitSet> = WfcModule::new();
331 match neighbour_strategies[i].north {
332 NeighbourKind::WangCorners => {
333 for j in 0..tile_sides.len() {
334 if neighbour_strategies[j].south != NeighbourKind::WangCorners {
335 continue;
336 }
337 if tile_sides[j].south_west == current_sides.north_west &&
338 tile_sides[j].south_east == current_sides.north_east {
339 module.add_north_neighbour(j);
340 }
341 }
342 }
343 NeighbourKind::RelOffset(offset) => {
344 let new_offset = (i as i32 + offset) as usize;
345 module.add_north_neighbour(new_offset);
346 }
347 }
348 match neighbour_strategies[i].south {
349 NeighbourKind::WangCorners => {
350 for j in 0..tile_sides.len() {
351 if neighbour_strategies[j].north != NeighbourKind::WangCorners {
352 continue;
353 }
354 if tile_sides[j].north_west == current_sides.south_west &&
355 tile_sides[j].north_east == current_sides.south_east {
356 module.add_south_neighbour(j);
357 }
358 }
359 }
360 NeighbourKind::RelOffset(offset) => {
361 let new_offset = (i as i32 + offset) as usize;
362 module.add_south_neighbour(new_offset);
363 }
364 }
365 match neighbour_strategies[i].east {
366 NeighbourKind::WangCorners => {
367 for j in 0..tile_sides.len() {
368 if neighbour_strategies[j].west != NeighbourKind::WangCorners {
369 continue;
370 }
371 if tile_sides[j].north_west == current_sides.north_east &&
372 tile_sides[j].south_west == current_sides.south_east {
373 module.add_east_neighbour(j);
374 }
375 }
376 }
377 NeighbourKind::RelOffset(offset) => {
378 let new_offset = (i as i32 + offset) as usize;
379 module.add_east_neighbour(new_offset);
380 }
381 }
382 match neighbour_strategies[i].west {
383 NeighbourKind::WangCorners => {
384 for j in 0..tile_sides.len() {
385 if neighbour_strategies[j].east != NeighbourKind::WangCorners {
386 continue;
387 }
388 if tile_sides[j].north_east == current_sides.north_west &&
389 tile_sides[j].south_east == current_sides.south_west {
390 module.add_west_neighbour(j);
391 }
392 }
393 }
394 NeighbourKind::RelOffset(offset) => {
395 let new_offset = (i as i32 + offset) as usize;
396 module.add_west_neighbour(new_offset);
397 }
398 }
399 modules.push(module);
400 }
401
402 Self {
403 w,
404 h,
405 draw_scale,
406 atlas,
407 tile_width: 32,
408 tile_height: 32,
409 tiles,
410 modules,
411 texture,
412 map_data: vec![0; w*h],
413 cell_tree_data: vec![TreeType::None; w*h],
414 corner_tree_data: vec![TreeType::None; (w+1)*(h+1)]
415 }
416 }Sourcepub fn add_west_neighbour(&mut self, idx: usize)
pub fn add_west_neighbour(&mut self, idx: usize)
A function which adds a neighbour on a west side
Examples found in repository?
examples/wang_corner_carpet.rs (line 129)
69 pub async fn new(w: usize, h: usize) -> Self {
70 let InternalGlContext {
71 quad_context: ctx, ..
72 } = unsafe { get_internal_gl() };
73
74 let texture_bytes = load_file("assets/wang_4_corner.png").await.unwrap();
75
76 let img = image::load_from_memory(&texture_bytes[..])
77 .unwrap_or_else(|e| panic!("{}", e))
78 .to_rgba8();
79
80 let img_w = img.width();
81 let img_h = img.height();
82
83 let texture = Texture2D::from_miniquad_texture(
84 miniquad::Texture::from_data_and_format(
85 ctx,
86 &img.into_raw(),
87 TextureParams {
88 format: TextureFormat::RGBA8,
89 wrap: TextureWrap::Clamp,
90 filter: FilterMode::Nearest,
91 width: img_w,
92 height: img_h
93 }
94 )
95 );
96
97 let tiles = (0..=255)
98 .map(|idx| {
99 let width = 32;
100 let height = 32;
101 (
102 idx as u8,
103 SubRect {
104 x: (idx % 16) * width,
105 y: (idx / 16) * height,
106 width,
107 height
108 }
109 )
110 })
111 .collect::<Vec<_>>();
112
113 let modules = tiles
114 .iter()
115 .map(|tile| {
116 let mut module: WfcModule<CustomBitSet> = WfcModule::new();
117 for i in 0..tiles.len() {
118 let other_tile = &tiles[i];
119 if get_north_west(tile.0) == get_south_west(other_tile.0) &&
120 get_north_east(tile.0) == get_south_east(other_tile.0) {
121 module.add_north_neighbour(i);
122 }
123 if get_south_west(tile.0) == get_north_west(other_tile.0) &&
124 get_south_east(tile.0) == get_north_east(other_tile.0) {
125 module.add_south_neighbour(i);
126 }
127 if get_north_west(tile.0) == get_north_east(other_tile.0) &&
128 get_south_west(tile.0) == get_south_east(other_tile.0) {
129 module.add_west_neighbour(i);
130 }
131 if get_north_east(tile.0) == get_north_west(other_tile.0) &&
132 get_south_east(tile.0) == get_south_west(other_tile.0) {
133 module.add_east_neighbour(i);
134 }
135 }
136 module
137 })
138 .collect::<Vec<_>>();
139
140 Self {
141 w,
142 h,
143 tile_width: 32,
144 tile_height: 32,
145 tiles,
146 modules,
147 texture,
148 map_data: vec![0; w*h]
149 }
150 }More examples
examples/dungeon.rs (line 327)
144 pub async fn new(w: usize, h: usize) -> Self {
145 let InternalGlContext {
146 quad_context: ctx, ..
147 } = unsafe { get_internal_gl() };
148
149 let dungeon_bytes = load_file("assets/dungeon_tiles.png").await.unwrap();
150
151 let img = image::load_from_memory(&dungeon_bytes[..])
152 .unwrap_or_else(|e| panic!("{}", e))
153 .to_rgba8();
154
155 let img_w = img.width();
156 let img_h = img.height();
157
158 let texture = Texture2D::from_miniquad_texture(
159 miniquad::Texture::from_data_and_format(
160 ctx,
161 &img.into_raw(),
162 TextureParams {
163 format: TextureFormat::RGBA8,
164 wrap: TextureWrap::Clamp,
165 filter: FilterMode::Nearest,
166 width: img_w,
167 height: img_h
168 }
169 )
170 );
171
172 let tiles_bytes = load_file("assets/dungeon_tiles.ron").await.unwrap();
173 let dungeon_tiles: DungeonTiles = from_reader(&tiles_bytes[..]).unwrap();
174
175 let mut tiles = Vec::new();
176 for (kind_code, subrects) in dungeon_tiles.wang_4_corner_tiles.iter() {
177 tiles.push(Tile {
178 kind: TileKind::Wang4Corner(*kind_code),
179 subrects: subrects.clone(),
180 neighbours_east: Vec::new(),
181 neighbours_west: Vec::new(),
182 neighbours_north: Vec::new(),
183 neighbours_south: Vec::new()
184 });
185 }
186 // We need to be sure that zero tile is always a "void" tile, so we doing an extra sort step
187 tiles.sort_by(|lhs, rhs| {
188 match (lhs.kind, rhs.kind) {
189 (TileKind::Wang4Corner(kind_lhs), TileKind::Wang4Corner(kind_rhs)) => kind_lhs.cmp(&kind_rhs),
190 _ => Ordering::Equal
191 }
192 });
193
194 for i in 0..tiles.len() {
195 let current_kind = tiles[i].kind;
196 for j in 0..tiles.len() {
197 let candidate_kind = tiles[j].kind;
198 let (matches_north, matches_south, matches_east, matches_west) = {
199 match (current_kind, candidate_kind) {
200 (TileKind::Wang4Corner(current), TileKind::Wang4Corner(candidate)) => {
201 (
202 get_north_east(current) == get_south_east(candidate) &&
203 get_north_west(current) == get_south_west(candidate),
204
205 get_south_east(current) == get_north_east(candidate) &&
206 get_south_west(current) == get_north_west(candidate),
207
208 get_north_east(current) == get_north_west(candidate) &&
209 get_south_east(current) == get_south_west(candidate),
210
211 get_north_west(current) == get_north_east(candidate) &&
212 get_south_west(current) == get_south_east(candidate),
213 )
214 },
215 _ => continue
216 }
217 };
218 if matches_east {
219 tiles[i].neighbours_east.push(candidate_kind);
220 }
221 if matches_west {
222 tiles[i].neighbours_west.push(candidate_kind);
223 }
224 if matches_north {
225 tiles[i].neighbours_north.push(candidate_kind);
226 }
227 if matches_south {
228 tiles[i].neighbours_south.push(candidate_kind);
229 }
230 }
231 }
232
233 //Add bridges:
234 {
235 let bridge_tiles_offset = tiles.len();
236 tiles.extend_from_slice(&dungeon_tiles.extra_tiles[..]);
237
238 let mut bridge_match_queue_south = VecDeque::new();
239 let mut bridge_match_queue_north = VecDeque::new();
240 let mut bridge_match_queue_east = VecDeque::new();
241 let mut bridge_match_queue_west = VecDeque::new();
242
243 for bridge_tile in &tiles[bridge_tiles_offset..] {
244 for south_neighbour in bridge_tile.neighbours_south.iter() {
245 if let TileKind::Wang4Corner(kind) = south_neighbour {
246 for i in 0..bridge_tiles_offset {
247 match tiles[i].kind {
248 TileKind::Wang4Corner(kind_inner) if kind_inner == *kind => {
249 bridge_match_queue_south.push_back((bridge_tile.kind, i))
250 },
251 _ => ()
252 };
253 }
254 }
255 }
256 for north_neighbour in bridge_tile.neighbours_north.iter() {
257 if let TileKind::Wang4Corner(kind) = north_neighbour {
258 for i in 0..bridge_tiles_offset {
259 match tiles[i].kind {
260 TileKind::Wang4Corner(kind_inner) if kind_inner == *kind => {
261 bridge_match_queue_north.push_back((bridge_tile.kind, i))
262 },
263 _ => ()
264 };
265 }
266 }
267 }
268 for east_neighbour in bridge_tile.neighbours_east.iter() {
269 if let TileKind::Wang4Corner(kind) = east_neighbour {
270 for i in 0..bridge_tiles_offset {
271 match tiles[i].kind {
272 TileKind::Wang4Corner(kind_inner) if kind_inner == *kind => {
273 bridge_match_queue_east.push_back((bridge_tile.kind, i))
274 },
275 _ => ()
276 };
277 }
278 }
279 }
280 for west_neighbour in bridge_tile.neighbours_west.iter() {
281 if let TileKind::Wang4Corner(kind) = west_neighbour {
282 for i in 0..bridge_tiles_offset {
283 match tiles[i].kind {
284 TileKind::Wang4Corner(kind_inner) if kind_inner == *kind => {
285 bridge_match_queue_west.push_back((bridge_tile.kind, i))
286 },
287 _ => ()
288 };
289 }
290 }
291 }
292 }
293
294 while !bridge_match_queue_south.is_empty() {
295 let next_match = bridge_match_queue_south.pop_front().unwrap();
296 tiles[next_match.1].neighbours_north.push(next_match.0);
297 }
298
299 while !bridge_match_queue_north.is_empty() {
300 let next_match = bridge_match_queue_north.pop_front().unwrap();
301 tiles[next_match.1].neighbours_south.push(next_match.0);
302 }
303
304 while !bridge_match_queue_east.is_empty() {
305 let next_match = bridge_match_queue_east.pop_front().unwrap();
306 tiles[next_match.1].neighbours_west.push(next_match.0);
307 }
308
309 while !bridge_match_queue_west.is_empty() {
310 let next_match = bridge_match_queue_west.pop_front().unwrap();
311 tiles[next_match.1].neighbours_east.push(next_match.0);
312 }
313 }
314
315 let modules = tiles
316 .iter()
317 .map(|tile| {
318 let mut module: WfcModule<CustomBitSet> = WfcModule::new();
319 for i in 0..tiles.len() {
320 if tile.neighbours_north.contains(&tiles[i].kind) {
321 module.add_north_neighbour(i);
322 }
323 if tile.neighbours_south.contains(&tiles[i].kind) {
324 module.add_south_neighbour(i);
325 }
326 if tile.neighbours_west.contains(&tiles[i].kind) {
327 module.add_west_neighbour(i);
328 }
329 if tile.neighbours_east.contains(&tiles[i].kind) {
330 module.add_east_neighbour(i);
331 }
332 }
333 module
334 })
335 .collect::<Vec<_>>();
336
337 Self {
338 w,
339 h,
340 tile_width: dungeon_tiles.tile_width,
341 tile_height: dungeon_tiles.tile_height,
342 tiles,
343 modules,
344 texture,
345 map_data: vec![(0, 0); w*h]
346 }
347 }examples/summer_garden.rs (line 390)
183 pub async fn new(w: usize, h: usize, draw_scale: f32) -> Self {
184 let InternalGlContext {
185 quad_context: ctx, ..
186 } = unsafe { get_internal_gl() };
187
188 let texture_bytes = load_file("assets/reduced_wang_scheme.png").await.unwrap();
189
190 let img = image::load_from_memory(&texture_bytes[..])
191 .unwrap_or_else(|e| panic!("{}", e))
192 .to_rgba8();
193
194 let img_w = img.width();
195 let img_h = img.height();
196
197 let texture = Texture2D::from_miniquad_texture(
198 miniquad::Texture::from_data_and_format(
199 ctx,
200 &img.into_raw(),
201 TextureParams {
202 format: TextureFormat::RGBA8,
203 wrap: TextureWrap::Clamp,
204 filter: FilterMode::Nearest,
205 width: img_w,
206 height: img_h
207 }
208 )
209 );
210
211 let atlas_bytes = load_file("assets/reduced_wang_scheme.ron").await.unwrap();
212 let atlas: SummerGardenAtlas = from_reader(&atlas_bytes[..]).unwrap();
213
214 let mut tile_sides = Vec::new();
215 let mut neighbour_strategies = Vec::new();
216 let mut tiles = Vec::new();
217
218 {
219 for tile_cfg in atlas.terrain_tile_configs.iter() {
220 for pattern in &[
221 &atlas.reduced_wang_patterns[..],
222 &atlas.extended_set_1_patterns_north_west[..],
223 &atlas.extended_set_1_patterns_north_east[..],
224 &atlas.extended_set_1_patterns_south_west[..],
225 &atlas.extended_set_1_patterns_south_east[..],
226 &atlas.extended_set_2_patterns_north_west[..],
227 &atlas.extended_set_2_patterns_north_east[..],
228 &atlas.extended_set_2_patterns_south_west[..],
229 &atlas.extended_set_2_patterns_south_east[..],
230 ] {
231 tile_sides.extend(
232 pattern.iter().map(
233 |pattern| {
234 TileSides {
235 north_west: match pattern.north_west {
236 TileKind::Inner => { tile_cfg.inner_type }
237 TileKind::Outer => { tile_cfg.outer_type }
238 },
239 north_east: match pattern.north_east {
240 TileKind::Inner => { tile_cfg.inner_type }
241 TileKind::Outer => { tile_cfg.outer_type }
242 },
243 south_west: match pattern.south_west {
244 TileKind::Inner => { tile_cfg.inner_type }
245 TileKind::Outer => { tile_cfg.outer_type }
246 },
247 south_east: match pattern.south_east {
248 TileKind::Inner => { tile_cfg.inner_type }
249 TileKind::Outer => { tile_cfg.outer_type }
250 }
251 }
252 }
253 )
254 );
255 }
256 for j in 0..4 {
257 for i in 0..4 {
258 tiles.push(SubRect{
259 x: i * 32 + tile_cfg.x_offset,
260 y: j * 32 + tile_cfg.y_offset,
261 width: 32,
262 height: 32
263 })
264 }
265 }
266 for jj in 0..2 {
267 for ii in 0..2 {
268 for j in 0..2 {
269 for i in 0..2 {
270 tiles.push(SubRect{
271 x: (i + ii * 2) * 32 + tile_cfg.x_offset + 256,
272 y: (j + jj * 2) * 32 + tile_cfg.y_offset,
273 width: 32,
274 height: 32
275 })
276 }
277 }
278 }
279 }
280 for jj in 0..2 {
281 for ii in 0..2 {
282 for j in 0..2 {
283 for i in 0..2 {
284 tiles.push(SubRect{
285 x: (i + ii * 2) * 32 + tile_cfg.x_offset,
286 y: (j + jj * 2) * 32 + tile_cfg.y_offset + 256,
287 width: 32,
288 height: 32
289 })
290 }
291 }
292 }
293 }
294 neighbour_strategies.extend_from_slice(&atlas.reduced_wang_neighbour_strategy[..]);
295 for _ in 0..8 {
296 neighbour_strategies.extend_from_slice(&atlas.neighbour_strategy_2_x_2[..]);
297 }
298 }
299 tile_sides.extend_from_slice(&atlas.vertical_bridge_sides[..]);
300 tile_sides.extend_from_slice(&atlas.horizontal_bridge_sides[..]);
301 for j in 0..3 {
302 for i in 0..3 {
303 tiles.push(SubRect{
304 x: i * 32 + 256,
305 y: j * 32 + 256,
306 width: 32,
307 height: 32
308 })
309 }
310 }
311 for j in 0..3 {
312 for i in 0..3 {
313 tiles.push(SubRect{
314 x: i * 32 + 256 + 96,
315 y: j * 32 + 256,
316 width: 32,
317 height: 32
318 })
319 }
320 }
321 neighbour_strategies.extend_from_slice(&atlas.neighbour_strategy_3_x_3[..]);
322 neighbour_strategies.extend_from_slice(&atlas.neighbour_strategy_3_x_3[..]);
323
324 assert_eq!(tile_sides.len(), neighbour_strategies.len());
325 }
326
327 let mut modules = Vec::new();
328 for i in 0..tile_sides.len() {
329 let current_sides = tile_sides[i];
330 let mut module: WfcModule<CustomBitSet> = WfcModule::new();
331 match neighbour_strategies[i].north {
332 NeighbourKind::WangCorners => {
333 for j in 0..tile_sides.len() {
334 if neighbour_strategies[j].south != NeighbourKind::WangCorners {
335 continue;
336 }
337 if tile_sides[j].south_west == current_sides.north_west &&
338 tile_sides[j].south_east == current_sides.north_east {
339 module.add_north_neighbour(j);
340 }
341 }
342 }
343 NeighbourKind::RelOffset(offset) => {
344 let new_offset = (i as i32 + offset) as usize;
345 module.add_north_neighbour(new_offset);
346 }
347 }
348 match neighbour_strategies[i].south {
349 NeighbourKind::WangCorners => {
350 for j in 0..tile_sides.len() {
351 if neighbour_strategies[j].north != NeighbourKind::WangCorners {
352 continue;
353 }
354 if tile_sides[j].north_west == current_sides.south_west &&
355 tile_sides[j].north_east == current_sides.south_east {
356 module.add_south_neighbour(j);
357 }
358 }
359 }
360 NeighbourKind::RelOffset(offset) => {
361 let new_offset = (i as i32 + offset) as usize;
362 module.add_south_neighbour(new_offset);
363 }
364 }
365 match neighbour_strategies[i].east {
366 NeighbourKind::WangCorners => {
367 for j in 0..tile_sides.len() {
368 if neighbour_strategies[j].west != NeighbourKind::WangCorners {
369 continue;
370 }
371 if tile_sides[j].north_west == current_sides.north_east &&
372 tile_sides[j].south_west == current_sides.south_east {
373 module.add_east_neighbour(j);
374 }
375 }
376 }
377 NeighbourKind::RelOffset(offset) => {
378 let new_offset = (i as i32 + offset) as usize;
379 module.add_east_neighbour(new_offset);
380 }
381 }
382 match neighbour_strategies[i].west {
383 NeighbourKind::WangCorners => {
384 for j in 0..tile_sides.len() {
385 if neighbour_strategies[j].east != NeighbourKind::WangCorners {
386 continue;
387 }
388 if tile_sides[j].north_east == current_sides.north_west &&
389 tile_sides[j].south_east == current_sides.south_west {
390 module.add_west_neighbour(j);
391 }
392 }
393 }
394 NeighbourKind::RelOffset(offset) => {
395 let new_offset = (i as i32 + offset) as usize;
396 module.add_west_neighbour(new_offset);
397 }
398 }
399 modules.push(module);
400 }
401
402 Self {
403 w,
404 h,
405 draw_scale,
406 atlas,
407 tile_width: 32,
408 tile_height: 32,
409 tiles,
410 modules,
411 texture,
412 map_data: vec![0; w*h],
413 cell_tree_data: vec![TreeType::None; w*h],
414 corner_tree_data: vec![TreeType::None; (w+1)*(h+1)]
415 }
416 }Trait Implementations§
Source§impl<TBitSet> Clone for WfcModule<TBitSet>where
TBitSet: BitSearch + BitEmpty + BitSet + BitIntersection + BitUnion + BitTestNone + Hash + Eq + Copy + BitIntersection<Output = TBitSet> + BitUnion<Output = TBitSet> + Clone,
impl<TBitSet> Clone for WfcModule<TBitSet>where
TBitSet: BitSearch + BitEmpty + BitSet + BitIntersection + BitUnion + BitTestNone + Hash + Eq + Copy + BitIntersection<Output = TBitSet> + BitUnion<Output = TBitSet> + Clone,
impl<TBitSet> Copy for WfcModule<TBitSet>where
TBitSet: BitSearch + BitEmpty + BitSet + BitIntersection + BitUnion + BitTestNone + Hash + Eq + Copy + BitIntersection<Output = TBitSet> + BitUnion<Output = TBitSet> + Copy,
Auto Trait Implementations§
impl<TBitSet> Freeze for WfcModule<TBitSet>where
TBitSet: Freeze,
impl<TBitSet> RefUnwindSafe for WfcModule<TBitSet>where
TBitSet: RefUnwindSafe,
impl<TBitSet> Send for WfcModule<TBitSet>where
TBitSet: Send,
impl<TBitSet> Sync for WfcModule<TBitSet>where
TBitSet: Sync,
impl<TBitSet> Unpin for WfcModule<TBitSet>where
TBitSet: Unpin,
impl<TBitSet> UnwindSafe for WfcModule<TBitSet>where
TBitSet: UnwindSafe,
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Mutably borrows from an owned value. Read more