This repository has been archived by the owner on Jan 2, 2022. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 1
/
build.rs
107 lines (82 loc) · 3.34 KB
/
build.rs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
use std::collections::HashMap;
use std::env;
use std::fs::File;
use std::io::{BufWriter, Write};
use std::path::Path;
use quote::quote;
fn main() {
let out_dir = env::var("OUT_DIR").expect("OUT_DIR environment variable must be specified");
let playground_filename = "map/map.tmx";
println!("cargo:rerun-if-changed={}", playground_filename);
let map = tiled::parse_file(Path::new(playground_filename)).unwrap();
let width = map.width;
let height = map.height;
let cloud_layer = &map.layers[0];
let cloud_tiles = extract_tiles(&cloud_layer.tiles);
let background_layer = &map.layers[1];
let background_tiles = extract_tiles(&background_layer.tiles);
let foreground_layer = &map.layers[2];
let foreground_tiles = extract_tiles(&foreground_layer.tiles);
let (slimes_x, slimes_y) = get_spawn_locations(&map.object_groups[0], "Slime Spawn");
let (bats_x, bats_y) = get_spawn_locations(&map.object_groups[0], "Bat Spawn");
let (emus_x, emus_y) = get_spawn_locations(&map.object_groups[0], "Emu Spawn");
let mut tile_types = HashMap::new();
for tile in map.tilesets[0].tiles.iter() {
if let Some("Collision") = tile.tile_type.as_deref() {
tile_types.insert(tile.id, 1u8);
}
}
let tile_types =
(0..map.tilesets[0].tilecount.unwrap()).map(|id| tile_types.get(&(id + 1)).unwrap_or(&0));
let output = quote! {
pub const CLOUD_MAP: &[u16] = &[#(#cloud_tiles),*];
pub const BACKGROUND_MAP: &[u16] = &[#(#background_tiles),*];
pub const FOREGROUND_MAP: &[u16] = &[#(#foreground_tiles),*];
pub const WIDTH: u32 = #width;
pub const HEIGHT: u32 = #height;
pub const SLIME_SPAWNS_X: &[u16] = &[#(#slimes_x),*];
pub const SLIME_SPAWNS_Y: &[u16] = &[#(#slimes_y),*];
pub const BAT_SPAWNS_X: &[u16] = &[#(#bats_x),*];
pub const BAT_SPAWNS_Y: &[u16] = &[#(#bats_y),*];
pub const EMU_SPAWNS_X: &[u16] = &[#(#emus_x),*];
pub const EMU_SPAWNS_Y: &[u16] = &[#(#emus_y),*];
pub const TILE_TYPES: &[u8] = &[#(#tile_types),*];
};
let output_file = File::create(format!("{}/tilemap.rs", out_dir))
.expect("failed to open tilemap.rs file for writing");
let mut writer = BufWriter::new(output_file);
write!(&mut writer, "{}", output).unwrap();
}
fn extract_tiles<'a>(layer: &'a tiled::LayerData) -> impl Iterator<Item = u16> + 'a {
match layer {
tiled::LayerData::Finite(tiles) => {
tiles.iter().flat_map(|row| row.iter().map(|tile| tile.gid))
}
_ => unimplemented!("cannot use infinite layer"),
}
.map(|tileid| get_map_id(tileid))
}
fn get_map_id(tileid: u32) -> u16 {
match tileid {
0 => 0,
i => i as u16 - 1,
}
}
fn get_spawn_locations<'a>(
object_group: &'a tiled::ObjectGroup,
enemy_type: &str,
) -> (
impl Iterator<Item = u16> + 'a,
impl Iterator<Item = u16> + 'a,
) {
let mut spawns = object_group
.objects
.iter()
.filter(|object| &object.obj_type == enemy_type)
.map(|object| (object.x as u16, object.y as u16))
.collect::<Vec<_>>();
spawns.sort_by(|a, b| a.0.cmp(&b.0));
let xs = spawns.iter().map(|pos| pos.0).collect::<Vec<_>>();
let ys = spawns.iter().map(|pos| pos.1).collect::<Vec<_>>();
return (xs.into_iter(), ys.into_iter());
}