summaryrefslogtreecommitdiffstats
path: root/src/graphics.rs
blob: 947992a4333bc3965bdebe318d236d89106dd5f5 (plain)
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
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
use std::collections::HashMap;
use sfml::window::{
	ContextSettings,
	Event,
	Style,
};

use sfml::graphics::{
	RenderWindow,
	RenderTarget,
	Texture,
	Image,
	Color,
	Rect,
};


#[derive(RustEmbed)]
#[folder = "res"]
pub struct Assets;


pub fn start() -> RenderWindow {
	let default_window_size = (1280, 720);
	let default_framerate = 80;

	let context_settings = ContextSettings {
		antialiasing_level: 0,
		..Default::default()
	};

	let mut window = RenderWindow::new(
		default_window_size,
		"Subconscious",
		Style::CLOSE,
		&context_settings
	);

	window.set_framerate_limit(default_framerate);
	window.set_vertical_sync_enabled(true);

	return window;
}

pub fn render(window: &mut RenderWindow, state: &crate::game::State) {

	// background
	let bgcolor = match state.map.background_colour {
		Some(color) => Color::rgb(color.red, color.green, color.blue),
		None => Color::BLACK,
	};

	window.clear(&bgcolor);

	// render map

	// loaded textures
	// TODO: cache outside of this function 
	let mut tilesets: HashMap<u32, Image> = HashMap::new();
	let mut textures: HashMap<u32, Texture> = HashMap::new();

	// for each tile 
	for y in 0 .. state.map.height {
		for x in 0 .. state.map.width {
			// for each layer
			for layer in &state.map.layers {
				let tmx_tile = layer.tiles[y as usize][x as usize];

				let tmx_tileset = match state.map.get_tileset_by_gid(tmx_tile) {
					Some(tileset) => tileset,
					None => continue
				};

				// load tileset if not loaded yet
				// TODO: load in a separate thread?
				if !tilesets.contains_key(&tmx_tileset.first_gid) {
					// TODO: replace with iter or error message
					assert_eq!(tmx_tileset.images.len(), 1);
					
					(|| {
						// load tileset image
						let tmx_image = &tmx_tileset.images[0];

						let asset = match Assets::get(&tmx_image.source) {
							Some(asset) => asset,
							None => return,
						};

						let image = match Image::from_memory(asset.as_ref()) {
							Some(image) => image,
							None => return,
						};

						// load tiles (textures)
						let tileset_width = tmx_image.width as u32 / tmx_tileset.tile_width;
						let tileset_height = tmx_image.height as u32 / tmx_tileset.tile_height;

						for ty in 0 .. tileset_height {
							for tx in 0 .. tileset_width {
								let texture = match Texture::from_image_with_rect(
									&image, &Rect::new(
										(tx * tmx_tileset.tile_width) as i32,
										(ty * tmx_tileset.tile_height) as i32,
										tmx_tileset.tile_width as i32,
										tmx_tileset.tile_height as i32
									)
								) {
									Some(texture) => texture,
									None => continue,
								};
								// save tile texture
								textures.insert(tmx_tile, texture);
							}
						}

						// save tileset image
						tilesets.insert(tmx_tileset.first_gid, image);
					})();
				}

				// 
			}
		}
	}

	window.display();
}

pub fn update(window: &mut RenderWindow) {
	while let Some(ev) = window.poll_event() {
		match ev {
			Event::Closed => window.close(),
			_ => {},
		}
	}
}