Bringing back things together
This commit is contained in:
		
							parent
							
								
									1ae9635fe8
								
							
						
					
					
						commit
						11ac199dd1
					
				
							
								
								
									
										33
									
								
								Cargo.lock
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										33
									
								
								Cargo.lock
									
									
									
										generated
									
									
									
								
							| @ -44,16 +44,6 @@ name = "autocfg" | ||||
| version = "0.1.2" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| 
 | ||||
| [[package]] | ||||
| name = "bincode" | ||||
| version = "1.1.2" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| dependencies = [ | ||||
|  "autocfg 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", | ||||
|  "byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", | ||||
|  "serde 1.0.89 (registry+https://github.com/rust-lang/crates.io-index)", | ||||
| ] | ||||
| 
 | ||||
| [[package]] | ||||
| name = "bitflags" | ||||
| version = "1.0.4" | ||||
| @ -554,11 +544,9 @@ dependencies = [ | ||||
| name = "rusty" | ||||
| version = "0.1.0" | ||||
| dependencies = [ | ||||
|  "bincode 1.1.2 (registry+https://github.com/rust-lang/crates.io-index)", | ||||
|  "clap 2.32.0 (registry+https://github.com/rust-lang/crates.io-index)", | ||||
|  "image 0.21.0 (registry+https://github.com/rust-lang/crates.io-index)", | ||||
|  "imageproc 0.18.0 (registry+https://github.com/rust-lang/crates.io-index)", | ||||
|  "serde 1.0.89 (registry+https://github.com/rust-lang/crates.io-index)", | ||||
|  "sfml 0.14.0 (registry+https://github.com/rust-lang/crates.io-index)", | ||||
| ] | ||||
| 
 | ||||
| @ -577,24 +565,6 @@ name = "scopeguard" | ||||
| version = "0.3.3" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| 
 | ||||
| [[package]] | ||||
| name = "serde" | ||||
| version = "1.0.89" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| dependencies = [ | ||||
|  "serde_derive 1.0.89 (registry+https://github.com/rust-lang/crates.io-index)", | ||||
| ] | ||||
| 
 | ||||
| [[package]] | ||||
| name = "serde_derive" | ||||
| version = "1.0.89" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| dependencies = [ | ||||
|  "proc-macro2 0.4.27 (registry+https://github.com/rust-lang/crates.io-index)", | ||||
|  "quote 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)", | ||||
|  "syn 0.15.29 (registry+https://github.com/rust-lang/crates.io-index)", | ||||
| ] | ||||
| 
 | ||||
| [[package]] | ||||
| name = "sfml" | ||||
| version = "0.14.0" | ||||
| @ -705,7 +675,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| "checksum arrayvec 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)" = "92c7fb76bc8826a8b33b4ee5bb07a247a81e76764ab4d55e8f73e3a4d8808c71" | ||||
| "checksum atty 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "9a7d5b8723950951411ee34d271d99dddcc2035a16ab25310ea2c8cfd4369652" | ||||
| "checksum autocfg 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "a6d640bee2da49f60a4068a7fae53acde8982514ab7bae8b8cea9e88cbcfd799" | ||||
| "checksum bincode 1.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "3efe0b4c8eaeed8600549c29f538a6a11bf422858d0ed435b1d70ec4ab101190" | ||||
| "checksum bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "228047a76f468627ca71776ecdebd732a3423081fcf5125585bcd7c49886ce12" | ||||
| "checksum byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "a019b10a2a7cdeb292db131fc8113e57ea2a908f6e7894b0c3c671893b65dbeb" | ||||
| "checksum cfg-if 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "11d43355396e872eefb45ce6342e4374ed7bc2b3a502d1b28e36d6e23c05d1f4" | ||||
| @ -767,8 +736,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| "checksum safe-transmute 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)" = "9604873ffe1980bc1f179103704a65c8aca141c248d9e52b7af95ff10578166e" | ||||
| "checksum scoped_threadpool 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)" = "1d51f5df5af43ab3f1360b429fa5e0152ac5ce8c0bd6485cae490332e96846a8" | ||||
| "checksum scopeguard 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "94258f53601af11e6a49f722422f6e3425c52b06245a5cf9bc09908b174f5e27" | ||||
| "checksum serde 1.0.89 (registry+https://github.com/rust-lang/crates.io-index)" = "92514fb95f900c9b5126e32d020f5c6d40564c27a5ea6d1d7d9f157a96623560" | ||||
| "checksum serde_derive 1.0.89 (registry+https://github.com/rust-lang/crates.io-index)" = "bb6eabf4b5914e88e24eea240bb7c9f9a2cbc1bbbe8d961d381975ec3c6b806c" | ||||
| "checksum sfml 0.14.0 (registry+https://github.com/rust-lang/crates.io-index)" = "47b06f9db4d3f8b936d232d92bfbd6335060ae51ddcf1be2e79361aeb5c8fef1" | ||||
| "checksum sfml-build 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ff35ae173aff95bc967d1b4f0e131a8aec384c317fd057738da4b0f71c8cf841" | ||||
| "checksum stb_truetype 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "69b7df505db8e81d54ff8be4693421e5b543e08214bd8d99eb761fcb4d5668ba" | ||||
|  | ||||
| @ -7,8 +7,6 @@ edition = "2018" | ||||
| [dependencies] | ||||
| clap = "2.32.0" | ||||
| sfml = "0.14.0" | ||||
| serde = { version = "1.0.89", features = ["derive"] } | ||||
| bincode = "1.1.2" | ||||
| 
 | ||||
| [build-dependencies] | ||||
| image = { version = "0.21.0" } | ||||
| @ -18,6 +16,3 @@ imageproc = "0.18.0" | ||||
| name = "rusty-maker" | ||||
| path = "src/app/game.rs" | ||||
| 
 | ||||
| [[bin]] | ||||
| name = "rusty-editor" | ||||
| path = "src/app/editor/main.rs" | ||||
|  | ||||
										
											Binary file not shown.
										
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										
											BIN
										
									
								
								assets/textures/rusty-walking.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								assets/textures/rusty-walking.png
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							| After Width: | Height: | Size: 1008 B | 
							
								
								
									
										
											BIN
										
									
								
								assets/textures/rusty.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								assets/textures/rusty.png
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							| After Width: | Height: | Size: 2.0 KiB | 
							
								
								
									
										49
									
								
								build.rs
									
									
									
									
									
								
							
							
						
						
									
										49
									
								
								build.rs
									
									
									
									
									
								
							| @ -1,13 +1,13 @@ | ||||
| use std::fs::create_dir_all; | ||||
| 
 | ||||
| use image::{RgbaImage, GenericImage}; | ||||
| use image::imageops::{rotate90, rotate180, rotate270}; | ||||
| use image::imageops::{rotate180, rotate270, rotate90}; | ||||
| use image::{GenericImage, RgbaImage}; | ||||
| 
 | ||||
| fn superpose(image: &RgbaImage, superposition: &RgbaImage) -> RgbaImage { | ||||
|     let mut clone = image.clone(); | ||||
| 
 | ||||
|     for i in 0 .. image.width() { | ||||
|         for j in 0 .. image.height() { | ||||
|     for i in 0..image.width() { | ||||
|         for j in 0..image.height() { | ||||
|             let new_pixel = superposition.get_pixel(i, j); | ||||
|             if new_pixel[3] > 0 { | ||||
|                 *clone.get_pixel_mut(i, j) = *new_pixel; | ||||
| @ -23,9 +23,9 @@ fn main() { | ||||
|     let mut texture = image::open("assets/textures/grass.png").unwrap().to_rgba(); | ||||
|     let background = texture.sub_image(0, 0, 32, 32).to_image(); | ||||
|     let border = texture.sub_image(32, 0, 32, 32).to_image(); | ||||
|     let corner_horiz = texture.sub_image(32 * 2 , 0, 32, 32).to_image(); | ||||
|     let corner_vert =    texture.sub_image(32 * 3, 0, 32, 32).to_image(); | ||||
|     let corner_inside =  texture.sub_image(32 * 4, 0, 32, 32).to_image(); | ||||
|     let corner_horiz = texture.sub_image(32 * 2, 0, 32, 32).to_image(); | ||||
|     let corner_vert = texture.sub_image(32 * 3, 0, 32, 32).to_image(); | ||||
|     let corner_inside = texture.sub_image(32 * 4, 0, 32, 32).to_image(); | ||||
|     let corner_outside = texture.sub_image(32 * 5, 0, 32, 32).to_image(); | ||||
|     let mut background_color = texture.sub_image(32 * 6, 0, 32, 32); | ||||
|     let background_color = background_color.get_pixel_mut(0, 0); | ||||
| @ -68,7 +68,13 @@ fn main() { | ||||
|     let image_29 = superpose(&image_1, &image_28); | ||||
|     vec.push(&image_29); | ||||
| 
 | ||||
|     let image_31 = superpose(&superpose(&border, &superpose(&rotate90(&border), &rotate90(&corner_inside))), &corner_horiz); | ||||
|     let image_31 = superpose( | ||||
|         &superpose( | ||||
|             &border, | ||||
|             &superpose(&rotate90(&border), &rotate90(&corner_inside)), | ||||
|         ), | ||||
|         &corner_horiz, | ||||
|     ); | ||||
|     let image_31 = superpose(&image_31, &rotate180(&corner_vert)); | ||||
|     vec.push(&image_31); | ||||
| 
 | ||||
| @ -132,8 +138,17 @@ fn main() { | ||||
|     let image_125 = superpose(&image_1, &image_124); | ||||
|     vec.push(&image_125); | ||||
| 
 | ||||
|     let image_127 = superpose(&superpose(&border, &superpose(&rotate90(&border), &rotate90(&corner_inside))), &corner_horiz); | ||||
|     let image_127 = superpose(&superpose(&image_127, &rotate180(&corner_inside)), &rotate180(&border)); | ||||
|     let image_127 = superpose( | ||||
|         &superpose( | ||||
|             &border, | ||||
|             &superpose(&rotate90(&border), &rotate90(&corner_inside)), | ||||
|         ), | ||||
|         &corner_horiz, | ||||
|     ); | ||||
|     let image_127 = superpose( | ||||
|         &superpose(&image_127, &rotate180(&corner_inside)), | ||||
|         &rotate180(&border), | ||||
|     ); | ||||
|     let image_127 = superpose(&image_127, &rotate270(&corner_vert)); | ||||
|     vec.push(&image_127); | ||||
| 
 | ||||
| @ -173,7 +188,13 @@ fn main() { | ||||
|     let image_253 = rotate180(&image_223); | ||||
|     vec.push(&image_253); | ||||
| 
 | ||||
|     let image_255 = superpose(&border, &superpose(&rotate90(&border), &superpose(&rotate180(&border), &rotate270(&border)))); | ||||
|     let image_255 = superpose( | ||||
|         &border, | ||||
|         &superpose( | ||||
|             &rotate90(&border), | ||||
|             &superpose(&rotate180(&border), &rotate270(&border)), | ||||
|         ), | ||||
|     ); | ||||
|     let image_255 = superpose(&image_255, &corner_inside); | ||||
|     let image_255 = superpose(&image_255, &rotate90(&corner_inside)); | ||||
|     let image_255 = superpose(&image_255, &rotate180(&corner_inside)); | ||||
| @ -182,8 +203,8 @@ fn main() { | ||||
| 
 | ||||
|     let mut output = RgbaImage::new(32 * 47, 32); | ||||
|     for (index, image) in vec.into_iter().enumerate() { | ||||
|         for y in 0 .. image.width() { | ||||
|             for x in 0 .. image.height() { | ||||
|         for y in 0..image.width() { | ||||
|             for x in 0..image.height() { | ||||
|                 let new_pixel = image.get_pixel(x, y); | ||||
|                 if new_pixel != background_color { | ||||
|                     *output.get_pixel_mut(x + 32 * index as u32, y) = *background.get_pixel(x, y); | ||||
| @ -197,5 +218,3 @@ fn main() { | ||||
| 
 | ||||
|     output.save("assets/textures-generated/grass.png").unwrap(); | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
|  | ||||
| @ -1,11 +0,0 @@ | ||||
| use clap::{App, crate_version}; | ||||
| 
 | ||||
| use rusty::app::editor::Editor; | ||||
| 
 | ||||
| fn main() { | ||||
|     let _ = App::new("Rusty Editor") | ||||
|         .version(crate_version!()) | ||||
|         .get_matches(); | ||||
| 
 | ||||
|     Editor::new().run(); | ||||
| } | ||||
| @ -1,230 +0,0 @@ | ||||
| use sfml::system::Vector2; | ||||
| use sfml::window::{Event, Key, mouse::Button as MouseButton}; | ||||
| use sfml::graphics::{Color, RectangleShape, RenderTarget, Transformable, Shape}; | ||||
| 
 | ||||
| use crate::engine::renderer::Renderer; | ||||
| use crate::engine::map::{CollisionTile, Map}; | ||||
| use crate::engine::texture::SPRITE_SIZE_I32; | ||||
| use crate::engine::font::Font; | ||||
| use crate::Result; | ||||
| 
 | ||||
| /// An action caused by a button.
 | ||||
| #[derive(Copy, Clone)] | ||||
| pub enum Action { | ||||
|     /// Saves the level.
 | ||||
|     Save, | ||||
| } | ||||
| 
 | ||||
| /// A button that can be clicked.
 | ||||
| pub struct Button { | ||||
|     /// The label of the button.
 | ||||
|     pub label: String, | ||||
| 
 | ||||
|     /// The position of the button.
 | ||||
|     pub position: Vector2<f32>, | ||||
| 
 | ||||
|     /// The size of the button.
 | ||||
|     pub size: Vector2<f32>, | ||||
| 
 | ||||
|     /// The action of the button.
 | ||||
|     action: Action, | ||||
| } | ||||
| 
 | ||||
| impl Button { | ||||
|     /// Creates a new button.
 | ||||
|     pub fn new(label: &str, action: Action, x: f32, y: f32, w: f32, h: f32) -> Button { | ||||
|         Button { | ||||
|             action, | ||||
|             label: label.to_owned(), | ||||
|             position: Vector2::new(x, y), | ||||
|             size: Vector2::new(w, h), | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     /// Returns the shape of the button.
 | ||||
|     pub fn shape(&self) -> RectangleShape { | ||||
|         let mut shape = RectangleShape::new(); | ||||
|         shape.set_position(self.position + 0.1 * self.size); | ||||
|         shape.set_size(self.size - 0.2 * self.size); | ||||
|         shape.set_fill_color(&Color::rgb(255, 255, 255)); | ||||
|         shape | ||||
|     } | ||||
| 
 | ||||
|     /// Draws the button on the renderer.
 | ||||
|     pub fn render_on(&self, renderer: &mut Renderer) { | ||||
|         renderer.window_mut().draw(&self.shape()); | ||||
|         renderer.draw_text( | ||||
|             &self.label, | ||||
|             Font::Sansation, | ||||
|             self.size.y as u32 / 2, | ||||
|             &Color::rgb(0, 0, 0) | ||||
|         ); | ||||
|     } | ||||
| 
 | ||||
|     /// Returns true if the coordinates fall inside the shape of the button.
 | ||||
|     pub fn contains(&self, x: f32, y: f32) -> bool { | ||||
|         let shape = self.shape(); | ||||
|         x > shape.position().x && x < shape.position().x + shape.size().x && | ||||
|         y > shape.position().y && y < shape.position().y + shape.size().y | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| /// Represents a level editor.
 | ||||
| pub struct Editor { | ||||
|     /// The renderer used by the editor.
 | ||||
|     renderer: Renderer, | ||||
| 
 | ||||
|     /// The map being currently edited.
 | ||||
|     map: Map, | ||||
| 
 | ||||
|     /// Indicates whether the editor is running or not.
 | ||||
|     running: bool, | ||||
| 
 | ||||
|     /// The size of the left panel.
 | ||||
|     left_panel_size: Vector2<f32>, | ||||
| 
 | ||||
|     /// The size of the top panel.
 | ||||
|     top_panel_size: Vector2<f32>, | ||||
| 
 | ||||
|     /// The buttons of the menu bar.
 | ||||
|     menu_bar: Vec<Button>, | ||||
| } | ||||
| 
 | ||||
| impl Editor { | ||||
|     /// Creates a new editor.
 | ||||
|     pub fn new() -> Editor { | ||||
|         let renderer = Renderer::new(800, 600, false); | ||||
|         let menu_bar = vec![ | ||||
|             Button::new("Save", Action::Save, 0.0, 0.0, 50.0, 50.0), | ||||
|         ]; | ||||
| 
 | ||||
|         Editor { | ||||
|             map: Map::new(50, 50), | ||||
|             running: true, | ||||
|             top_panel_size: Vector2::new(renderer.window().size().x as f32, 50.0), | ||||
|             left_panel_size: Vector2::new(100.0, renderer.window().size().y as f32 - 50.0), | ||||
|             renderer, | ||||
|             menu_bar, | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     /// Runs the main loop of the editor.
 | ||||
|     pub fn run(&mut self) { | ||||
|         while self.running { | ||||
|             while let Some(event) = self.renderer.poll_event() { | ||||
|                 self.manage_event(event); | ||||
|             } | ||||
| 
 | ||||
|             self.render(); | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     /// Manages the event occuring on the display.
 | ||||
|     pub fn manage_event(&mut self, event: Event) { | ||||
| 
 | ||||
|         match event { | ||||
|             // Quit the game if window is closed
 | ||||
|             Event::Closed => self.running = false, | ||||
| 
 | ||||
|             // Quit the game if escape is pressed
 | ||||
|             Event::KeyPressed { | ||||
|                 code: Key::Escape, .. | ||||
|             } => self.running = false, | ||||
| 
 | ||||
|             // A click on the screen
 | ||||
|             Event::MouseButtonPressed { | ||||
|                 button: MouseButton::Left, x, y, | ||||
|             } => { | ||||
|                 if x as f32 >= self.left_panel_size.x && y as f32 >= self.top_panel_size.y { | ||||
|                     let x = ((x - self.left_panel_size.x as i32) / SPRITE_SIZE_I32) as usize; | ||||
|                     let y = ((y - self.top_panel_size.y as i32) / SPRITE_SIZE_I32) as usize; | ||||
| 
 | ||||
|                     if let Some(tile) = self.map.collision_tile(y, x) { | ||||
|                         if tile.is_empty() { | ||||
|                             self.map.set_tile(y, x, CollisionTile::full()); | ||||
|                         } else { | ||||
|                             self.map.set_tile(y, x, CollisionTile::empty()); | ||||
|                         } | ||||
|                     } | ||||
|                 } | ||||
| 
 | ||||
|                 let mut actions = vec![]; | ||||
|                 for button in &self.menu_bar { | ||||
|                     if button.contains(x as f32, y as f32) { | ||||
|                         actions.push(button.action); | ||||
|                     } | ||||
|                 } | ||||
| 
 | ||||
|                 for action in actions { | ||||
|                     if let Err(e) = self.apply_action(action) { | ||||
|                         eprintln!("warning: {}", e); | ||||
|                     } | ||||
|                 } | ||||
|             }, | ||||
| 
 | ||||
|             _ => (), | ||||
|         } | ||||
| 
 | ||||
|     } | ||||
| 
 | ||||
|     /// Performs the rendering on the screen.
 | ||||
|     pub fn render(&mut self) { | ||||
| 
 | ||||
|         self.renderer.clear(); | ||||
| 
 | ||||
|         // Show the top panel
 | ||||
|         let mut top_panel = RectangleShape::with_size(self.top_panel_size); | ||||
|         top_panel.set_fill_color(&Color::rgb(255, 0, 0)); | ||||
|         self.renderer.window_mut().draw(&top_panel); | ||||
| 
 | ||||
|         for button in &self.menu_bar { | ||||
|             button.render_on(&mut self.renderer); | ||||
|         } | ||||
| 
 | ||||
|         // Show the left panel
 | ||||
|         let mut left_panel = RectangleShape::with_size(self.left_panel_size); | ||||
|         left_panel.set_position((0.0, self.top_panel_size.y)); | ||||
|         left_panel.set_fill_color(&Color::rgb(0, 255, 0)); | ||||
|         self.renderer.window_mut().draw(&left_panel); | ||||
| 
 | ||||
|         // Show the map
 | ||||
|         for i in 0 .. self.map.rows() { | ||||
|             for j in 0 .. self.map.cols() { | ||||
|                 let tile = self.map.at(i, j); | ||||
|                 if tile.graphic.is_visible() { | ||||
|                     self.renderer.translate_and_draw( | ||||
|                         &tile, | ||||
|                         (self.left_panel_size.x, self.top_panel_size.y) | ||||
|                     ); | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|         // Draw the border of the map
 | ||||
|         let mut border = RectangleShape::new(); | ||||
|         border.set_size((( | ||||
|             self.map.cols() * SPRITE_SIZE_I32 as usize) as f32, | ||||
|             (self.map.rows() * SPRITE_SIZE_I32 as usize) as f32 | ||||
|         )); | ||||
|         border.set_position((self.left_panel_size.x, self.top_panel_size.y)); | ||||
|         border.set_fill_color(&Color::rgba(0, 0, 0, 0)); | ||||
|         border.set_outline_color(&Color::rgb(0, 0, 0)); | ||||
|         border.set_outline_thickness(2.0); | ||||
|         self.renderer.window_mut().draw(&border); | ||||
| 
 | ||||
|         // Display and manage the frame rate
 | ||||
|         self.renderer.display(); | ||||
|     } | ||||
| 
 | ||||
|     /// Saves the level.
 | ||||
|     pub fn export(&self) -> Result<()> { | ||||
|         self.map.save("level.lvl") | ||||
|     } | ||||
| 
 | ||||
|     /// Applies the corresponding action.
 | ||||
|     pub fn apply_action(&mut self, action: Action) -> Result<()> { | ||||
|         match action { | ||||
|             Action::Save => self.export() | ||||
|         } | ||||
|     } | ||||
| } | ||||
| @ -1,13 +1,13 @@ | ||||
| use std::time::Instant; | ||||
| 
 | ||||
| use clap::{App, Arg, crate_version}; | ||||
| use clap::{crate_version, App, Arg}; | ||||
| 
 | ||||
| use sfml::window::{joystick, Event, Key}; | ||||
| 
 | ||||
| use rusty::engine::character::Character; | ||||
| use rusty::engine::controls::Controls; | ||||
| use rusty::engine::renderer::Renderer; | ||||
| use rusty::engine::map::Map; | ||||
| use rusty::engine::renderer::Renderer; | ||||
| use rusty::engine::scene::{Scene, State}; | ||||
| 
 | ||||
| fn parse_resolution(res: &str) -> Result<(u32, u32), String> { | ||||
| @ -33,24 +33,30 @@ fn parse_resolution(res: &str) -> Result<(u32, u32), String> { | ||||
| fn main() { | ||||
|     let matches = App::new("Rusty Maker") | ||||
|         .version(crate_version!()) | ||||
|         .arg(Arg::with_name("resolution") | ||||
|             .short("r") | ||||
|             .long("resolution") | ||||
|             .value_name("WIDTHxHEIGHT") | ||||
|             .takes_value(true) | ||||
|             .default_value("800x450") | ||||
|             .validator(|x| parse_resolution(&x).map(|_| ()))) | ||||
|         .arg(Arg::with_name("map") | ||||
|              .short("m") | ||||
|              .long("map") | ||||
|              .value_name("MAP") | ||||
|              .takes_value(true) | ||||
|              .default_value("assets/levels/level2.lvl") | ||||
|              .validator(|x| Map::load(x).map(|_| ()).map_err(|x| format!("{}", x)))) | ||||
|         .arg(Arg::with_name("fullscreen") | ||||
|             .short("f") | ||||
|             .long("fullscreen") | ||||
|             .takes_value(false)) | ||||
|         .arg( | ||||
|             Arg::with_name("resolution") | ||||
|                 .short("r") | ||||
|                 .long("resolution") | ||||
|                 .value_name("WIDTHxHEIGHT") | ||||
|                 .takes_value(true) | ||||
|                 .default_value("800x450") | ||||
|                 .validator(|x| parse_resolution(&x).map(|_| ())), | ||||
|         ) | ||||
|         .arg( | ||||
|             Arg::with_name("map") | ||||
|                 .short("m") | ||||
|                 .long("map") | ||||
|                 .value_name("MAP") | ||||
|                 .takes_value(true) | ||||
|                 .default_value("assets/levels/level2.lvl") | ||||
|                 .validator(|x| Map::from_file(x).map(|_| ()).map_err(|x| format!("{}", x))), | ||||
|         ) | ||||
|         .arg( | ||||
|             Arg::with_name("fullscreen") | ||||
|                 .short("f") | ||||
|                 .long("fullscreen") | ||||
|                 .takes_value(false), | ||||
|         ) | ||||
|         .get_matches(); | ||||
| 
 | ||||
|     let resolution = parse_resolution(matches.value_of("resolution").unwrap()).unwrap(); | ||||
| @ -68,7 +74,7 @@ fn main() { | ||||
|     let mut character = Character::with_controls(controls); | ||||
|     character.set_position((10.0, 0.0)); | ||||
| 
 | ||||
|     let map = Map::load(matches.value_of("map").unwrap()).unwrap(); | ||||
|     let map = Map::from_file(matches.value_of("map").unwrap()).unwrap(); | ||||
|     let mut scene = Scene::from_map(map); | ||||
|     scene.add(character); | ||||
| 
 | ||||
|  | ||||
| @ -1,2 +0,0 @@ | ||||
| /// This module contains everything related to the level editor.
 | ||||
| pub mod editor; | ||||
| @ -5,10 +5,10 @@ use sfml::system::Vector2; | ||||
| use sfml::window::Event; | ||||
| 
 | ||||
| use crate::engine::controls::{Action, Controls}; | ||||
| use crate::engine::scene::Updatable; | ||||
| use crate::engine::math::{clamp, duration_as_f32, duration_as_frame}; | ||||
| use crate::engine::physics; | ||||
| use crate::engine::renderer::Drawable; | ||||
| use crate::engine::scene::Updatable; | ||||
| use crate::engine::texture::Texture; | ||||
| 
 | ||||
| /// The different sides a character can face.
 | ||||
| @ -50,8 +50,8 @@ impl Side { | ||||
|     /// Returns the offset in the texture.
 | ||||
|     pub fn offset(&self) -> i32 { | ||||
|         match *self { | ||||
|             Side::Left => 0, | ||||
|             Side::Right => 32, | ||||
|             Side::Left => 32, | ||||
|             Side::Right => 0, | ||||
|         } | ||||
|     } | ||||
| } | ||||
| @ -84,7 +84,10 @@ pub struct Character { | ||||
|     max_jump: usize, | ||||
| 
 | ||||
|     /// The timer of the character's animation.
 | ||||
|     animation_timer: Option<Instant>, | ||||
|     animation_timer: Instant, | ||||
| 
 | ||||
|     /// Whether the character is walking or not.
 | ||||
|     walking: bool, | ||||
| 
 | ||||
|     /// Indicates that the player has released the jump button.
 | ||||
|     can_jump: bool, | ||||
| @ -101,8 +104,9 @@ impl Character { | ||||
|             hp: 1, | ||||
|             jump_counter: 1, | ||||
|             max_jump: 1, | ||||
|             animation_timer: None, | ||||
|             animation_timer: Instant::now(), | ||||
|             can_jump: true, | ||||
|             walking: false, | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
| @ -153,7 +157,7 @@ impl Character { | ||||
| 
 | ||||
|     /// Returns the collision bounding box of the character.
 | ||||
|     pub fn bbox(&self) -> FloatRect { | ||||
|         FloatRect::new(self.position.x + 8.0, self.position.y + 16.0, 16.0, 16.0) | ||||
|         FloatRect::new(self.position.x + 8.0, self.position.y, 16.0, 32.0) | ||||
|     } | ||||
| 
 | ||||
|     /// Returns the number of hp of the character.
 | ||||
| @ -190,13 +194,16 @@ impl Updatable for Character { | ||||
|         } | ||||
| 
 | ||||
|         if let Some(side) = Side::from_force(force) { | ||||
|             self.side = side; | ||||
| 
 | ||||
|             if self.animation_timer.is_none() { | ||||
|                 self.animation_timer = Some(Instant::now()); | ||||
|             if !self.walking { | ||||
|                 self.animation_timer = Instant::now(); | ||||
|             } | ||||
|             self.walking = true; | ||||
|             self.side = side; | ||||
|         } else { | ||||
|             self.animation_timer = None; | ||||
|             if self.walking { | ||||
|                 self.animation_timer = Instant::now(); | ||||
|             } | ||||
|             self.walking = false; | ||||
|         } | ||||
| 
 | ||||
|         let duration = duration_as_f32(duration); | ||||
| @ -247,17 +254,13 @@ impl Updatable for Character { | ||||
| 
 | ||||
| impl Drawable for Character { | ||||
|     fn texture(&self) -> Texture { | ||||
|         Texture::Mario | ||||
|         Texture::Rusty | ||||
|     } | ||||
| 
 | ||||
|     fn texture_rect(&self) -> IntRect { | ||||
|         let frame = if let Some(started) = self.animation_timer { | ||||
|             1 - duration_as_frame(&Instant::now().duration_since(started), 2) | ||||
|         } else { | ||||
|             0 | ||||
|         }; | ||||
| 
 | ||||
|         IntRect::new(self.side.offset(), frame * 32, 32, 32) | ||||
|         let frame = duration_as_frame(&Instant::now().duration_since(self.animation_timer), 4); | ||||
|         let offset = if self.walking { 64 } else { 0 }; | ||||
|         IntRect::new(self.side.offset() + offset, frame * 32, 32, 32) | ||||
|     } | ||||
| 
 | ||||
|     fn position(&self) -> Vector2<f32> { | ||||
|  | ||||
| @ -67,7 +67,6 @@ make_fonts!( | ||||
| impl FontManager { | ||||
|     /// Creates a fonts from an array of bytes.
 | ||||
|     fn _make_font_from_bytes(bytes: Vec<u8>) -> SfFont { | ||||
|         SfFont::from_memory(&bytes) | ||||
|             .expect("Failed to create font") | ||||
|         SfFont::from_memory(&bytes).expect("Failed to create font") | ||||
|     } | ||||
| } | ||||
|  | ||||
| @ -1,19 +1,15 @@ | ||||
| use std::path::Path; | ||||
| use std::fs::File; | ||||
| use std::io::{BufWriter, BufReader}; | ||||
| 
 | ||||
| use serde::{Serialize, Deserialize}; | ||||
| 
 | ||||
| use bincode::{serialize, deserialize, serialize_into, deserialize_from}; | ||||
| use std::io::Read; | ||||
| use std::path::Path; | ||||
| 
 | ||||
| use sfml::graphics::{FloatRect, IntRect}; | ||||
| use sfml::system::Vector2; | ||||
| 
 | ||||
| use crate::{Error, Result}; | ||||
| use crate::engine::character::Damage; | ||||
| use crate::engine::math::{clamp, Matrix}; | ||||
| use crate::engine::renderer::Drawable; | ||||
| use crate::engine::texture::{Texture, byte_to_index, SPRITE_SIZE_F32, SPRITE_SIZE_I32}; | ||||
| use crate::engine::character::Damage; | ||||
| use crate::engine::texture::{byte_to_index, Texture, SPRITE_SIZE_F32, SPRITE_SIZE_I32}; | ||||
| use crate::{Error, Result}; | ||||
| 
 | ||||
| /// This enum represents if the collision happens on the X axis or the Y axis.
 | ||||
| #[derive(Copy, Clone)] | ||||
| @ -47,7 +43,7 @@ impl CollisionAxis { | ||||
| } | ||||
| 
 | ||||
| /// This struct represents the different sides from which a collision can occur.
 | ||||
| #[derive(Debug, Copy, Clone, PartialEq, Eq, Serialize, Deserialize)] | ||||
| #[derive(Debug, Copy, Clone, PartialEq, Eq)] | ||||
| pub struct CollisionTile { | ||||
|     /// If the character comes from the top, it will collide if this bool is true.
 | ||||
|     pub from_top: bool, | ||||
| @ -95,12 +91,10 @@ impl CollisionTile { | ||||
| } | ||||
| 
 | ||||
| /// This struct represents a renderable tile linking to its part in the tileset texture.
 | ||||
| #[derive(Debug, Copy, Clone, PartialEq, Eq, Serialize, Deserialize)] | ||||
| #[derive(Debug, Copy, Clone, PartialEq, Eq)] | ||||
| pub struct GraphicTile(Option<i32>); | ||||
| 
 | ||||
| impl GraphicTile { | ||||
| 
 | ||||
| 
 | ||||
|     /// Creates the correct graphic tile depending on the neighbours.
 | ||||
|     ///
 | ||||
|     /// A none will be considered solid.
 | ||||
| @ -119,7 +113,6 @@ impl GraphicTile { | ||||
| 
 | ||||
|     /// Creates the correct graphic tile depending on the neighbours.
 | ||||
|     pub fn from_neighbours(tiles: &[CollisionTile; 8]) -> GraphicTile { | ||||
| 
 | ||||
|         let mut byte = 0; | ||||
| 
 | ||||
|         if !tiles[7].is_full() || !tiles[0].is_full() || !tiles[1].is_full() { | ||||
| @ -130,11 +123,11 @@ impl GraphicTile { | ||||
|             byte += 2; | ||||
|         } | ||||
| 
 | ||||
|         if !tiles[1] .is_full() || !tiles[2].is_full() || !tiles[3].is_full() { | ||||
|         if !tiles[1].is_full() || !tiles[2].is_full() || !tiles[3].is_full() { | ||||
|             byte += 4; | ||||
|         } | ||||
| 
 | ||||
|         if !tiles[3] .is_full() { | ||||
|         if !tiles[3].is_full() { | ||||
|             byte += 8; | ||||
|         } | ||||
| 
 | ||||
| @ -150,7 +143,7 @@ impl GraphicTile { | ||||
|             byte += 64; | ||||
|         } | ||||
| 
 | ||||
|         if !tiles[7] .is_full() { | ||||
|         if !tiles[7].is_full() { | ||||
|             byte += 128; | ||||
|         } | ||||
| 
 | ||||
| @ -161,7 +154,7 @@ impl GraphicTile { | ||||
|     pub fn offset(self) -> (i32, i32) { | ||||
|         match self.0 { | ||||
|             None => (0, 0), | ||||
|             Some(v) => (32 * v, 0) | ||||
|             Some(v) => (32 * v, 0), | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
| @ -198,23 +191,6 @@ impl Drawable for PositionedTile { | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| /// The content of a map that needs to be saved.
 | ||||
| #[derive(Serialize, Deserialize)] | ||||
| struct SaveMap { | ||||
|     /// The entrance point of the character in the map.
 | ||||
|     entrance: (usize, usize), | ||||
| 
 | ||||
|     /// The collision tiles contained in the level.
 | ||||
|     collision_tiles: Matrix<CollisionTile>, | ||||
| } | ||||
| 
 | ||||
| impl SaveMap { | ||||
|     /// Creates a map from the save map.
 | ||||
|     fn to_map(self) -> Map { | ||||
|         Map::from_entrance_and_collision_tiles(self.entrance, self.collision_tiles) | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| /// The map represents the tiles contained in a level.
 | ||||
| #[derive(Clone)] | ||||
| pub struct Map { | ||||
| @ -241,39 +217,69 @@ impl Map { | ||||
|         Map::from_collision_tiles(tiles) | ||||
|     } | ||||
| 
 | ||||
|     /// Creates a SaveMap from a map
 | ||||
|     fn save_map(&self) -> SaveMap { | ||||
|         SaveMap { | ||||
|             entrance: self.entrance, | ||||
|             collision_tiles: self.collision_tiles.clone(), | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     /// Encodes the map into a binary format.
 | ||||
|     pub fn encode(&self) -> Result<Vec<u8>> { | ||||
|         serialize(&self.save_map()).map_err(Error::Encoding) | ||||
|     } | ||||
| 
 | ||||
|     /// Decodes a map from bytes.
 | ||||
|     pub fn decode(content: &[u8]) -> Result<Map> { | ||||
|         deserialize(content).map(SaveMap::to_map).map_err(Error::Decoding) | ||||
|     } | ||||
| 
 | ||||
|     /// Saves the map to a file.
 | ||||
|     pub fn save<P: AsRef<Path>>(&self, path: P) -> Result<()> { | ||||
|         let file = File::create(path.as_ref()).map_err(Error::Save)?; | ||||
|         let mut writer = BufWriter::new(file); | ||||
|         serialize_into(&mut writer, &self.save_map()).map_err(Error::Encoding)?; | ||||
|         Ok(()) | ||||
|     } | ||||
| 
 | ||||
|     /// Loads a map from a file.
 | ||||
|     pub fn load<P: AsRef<Path>>(path: P) -> Result<Map> { | ||||
|         let file = File::open(path.as_ref()).map_err(Error::Load)?; | ||||
|         let mut reader = BufReader::new(file); | ||||
|         Ok(deserialize_from(&mut reader).map(SaveMap::to_map).map_err(Error::Decoding)?) | ||||
|     pub fn from_file<P: AsRef<Path>>(path: P) -> Result<Map> { | ||||
|         let mut file = File::open(path.as_ref()).map_err(Error::Load)?; | ||||
|         let mut s = String::new(); | ||||
|         file.read_to_string(&mut s).map_err(Error::Load)?; | ||||
|         Map::from_str(&s) | ||||
|     } | ||||
| 
 | ||||
|     /// Loads a map from a string.
 | ||||
|     pub fn from_str(text: &str) -> Result<Map> { | ||||
|         let split = text.split('\n').collect::<Vec<_>>(); | ||||
| 
 | ||||
|         // First two usize are the size of the map
 | ||||
|         let size = split[0] | ||||
|             .split_whitespace() | ||||
|             .map(|x| x.parse::<usize>().unwrap()) | ||||
|             .collect::<Vec<_>>(); | ||||
| 
 | ||||
|         let mut tiles = Matrix::from_size(size[0], size[1], CollisionTile::empty()); | ||||
| 
 | ||||
|         for (row, line) in split.iter().skip(1).enumerate() { | ||||
|             for (col, tile) in line.split_whitespace().enumerate() { | ||||
|                 let num = tile.parse::<u8>().unwrap(); | ||||
|                 match num { | ||||
|                     0 => (), | ||||
|                     1 => tiles[(row, col)] = CollisionTile::full(), | ||||
|                     _ => panic!("Expecting 0 or 1 in level files"), | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|         Ok(Map::from_collision_tiles(tiles)) | ||||
|     } | ||||
| 
 | ||||
|     // /// Encodes the map into a binary format.
 | ||||
|     // pub fn encode(&self) -> Result<Vec<u8>> {
 | ||||
|     //     serialize(&self.save_map()).map_err(Error::Encoding)
 | ||||
|     // }
 | ||||
| 
 | ||||
|     // /// Decodes a map from bytes.
 | ||||
|     // pub fn decode(content: &[u8]) -> Result<Map> {
 | ||||
|     //     deserialize(content)
 | ||||
|     //         .map(SaveMap::to_map)
 | ||||
|     //         .map_err(Error::Decoding)
 | ||||
|     // }
 | ||||
| 
 | ||||
|     // /// Saves the map to a file.
 | ||||
|     // pub fn save<P: AsRef<Path>>(&self, path: P) -> Result<()> {
 | ||||
|     //     let file = File::create(path.as_ref()).map_err(Error::Save)?;
 | ||||
|     //     let mut writer = BufWriter::new(file);
 | ||||
|     //     serialize_into(&mut writer, &self.save_map()).map_err(Error::Encoding)?;
 | ||||
|     //     Ok(())
 | ||||
|     // }
 | ||||
| 
 | ||||
|     // /// Loads a map from a file.
 | ||||
|     // pub fn load<P: AsRef<Path>>(path: P) -> Result<Map> {
 | ||||
|     //     let file = File::open(path.as_ref()).map_err(Error::Load)?;
 | ||||
|     //     let mut reader = BufReader::new(file);
 | ||||
|     //     Ok(deserialize_from(&mut reader)
 | ||||
|     //         .map(SaveMap::to_map)
 | ||||
|     //         .map_err(Error::Decoding)?)
 | ||||
|     // }
 | ||||
| 
 | ||||
|     /// Creates a map from its entrance and collision tiles.
 | ||||
|     pub fn from_entrance_and_collision_tiles(e: (usize, usize), t: Matrix<CollisionTile>) -> Map { | ||||
|         let rows = t.rows(); | ||||
| @ -287,8 +293,8 @@ impl Map { | ||||
|             graphic_tiles, | ||||
|         }; | ||||
| 
 | ||||
|         for i in 0 .. rows { | ||||
|             for j in 0 .. cols { | ||||
|         for i in 0..rows { | ||||
|             for j in 0..cols { | ||||
|                 map.graphic_tiles[(i, j)] = map.graphic_tile(i, j); | ||||
|             } | ||||
|         } | ||||
| @ -305,14 +311,34 @@ impl Map { | ||||
|     /// Creates the neighbours of a tile.
 | ||||
|     pub fn neighbours(&self, i: usize, j: usize) -> [Option<CollisionTile>; 8] { | ||||
|         [ | ||||
|             if i > 0 && j > 0 { self.collision_tiles.get(i - 1, j - 1).cloned() } else { None }, | ||||
|             if i > 0          { self.collision_tiles.get(i - 1, j    ).cloned() } else { None }, | ||||
|             if i > 0          { self.collision_tiles.get(i - 1, j + 1).cloned() } else { None }, | ||||
|                                 self.collision_tiles.get(i    , j + 1).cloned(), | ||||
|                                 self.collision_tiles.get(i + 1, j + 1).cloned(), | ||||
|                                 self.collision_tiles.get(i + 1, j    ).cloned(), | ||||
|             if j > 0          { self.collision_tiles.get(i + 1, j - 1).cloned() } else { None }, | ||||
|             if j > 0          { self.collision_tiles.get(i    , j - 1).cloned() } else { None }, | ||||
|             if i > 0 && j > 0 { | ||||
|                 self.collision_tiles.get(i - 1, j - 1).cloned() | ||||
|             } else { | ||||
|                 None | ||||
|             }, | ||||
|             if i > 0 { | ||||
|                 self.collision_tiles.get(i - 1, j).cloned() | ||||
|             } else { | ||||
|                 None | ||||
|             }, | ||||
|             if i > 0 { | ||||
|                 self.collision_tiles.get(i - 1, j + 1).cloned() | ||||
|             } else { | ||||
|                 None | ||||
|             }, | ||||
|             self.collision_tiles.get(i, j + 1).cloned(), | ||||
|             self.collision_tiles.get(i + 1, j + 1).cloned(), | ||||
|             self.collision_tiles.get(i + 1, j).cloned(), | ||||
|             if j > 0 { | ||||
|                 self.collision_tiles.get(i + 1, j - 1).cloned() | ||||
|             } else { | ||||
|                 None | ||||
|             }, | ||||
|             if j > 0 { | ||||
|                 self.collision_tiles.get(i, j - 1).cloned() | ||||
|             } else { | ||||
|                 None | ||||
|             }, | ||||
|         ] | ||||
|     } | ||||
| 
 | ||||
| @ -337,8 +363,8 @@ impl Map { | ||||
| 
 | ||||
|         // Refresh the current graphic tile and their neighbours
 | ||||
|         use std::cmp::max; | ||||
|         for i in max(i, 1) - 1 ..= (i + 1) { | ||||
|             for j in max(j, 1) - 1 ..= (j + 1) { | ||||
|         for i in max(i, 1) - 1..=(i + 1) { | ||||
|             for j in max(j, 1) - 1..=(j + 1) { | ||||
|                 let new_tile = self.graphic_tile(i, j); | ||||
|                 if let Some(tile) = self.graphic_tiles.get_mut(i, j) { | ||||
|                     *tile = new_tile; | ||||
| @ -384,7 +410,6 @@ impl Map { | ||||
|         old: FloatRect, | ||||
|         new: FloatRect, | ||||
|     ) -> Option<(CollisionAxis, Vector2<f32>, Damage)> { | ||||
| 
 | ||||
|         let mut damage = Damage::None; | ||||
| 
 | ||||
|         let cols = self.collision_tiles.cols() - 1; | ||||
| @ -400,8 +425,8 @@ impl Map { | ||||
|         let mut collision_y = false; | ||||
|         let mut new = new; | ||||
| 
 | ||||
|         for col in min_col ..= max_col { | ||||
|             for row in min_row ..= max_row { | ||||
|         for col in min_col..=max_col { | ||||
|             for row in min_row..=max_row { | ||||
|                 let tile_left = col as f32 * SPRITE_SIZE_F32; | ||||
|                 let tile_top = row as f32 * SPRITE_SIZE_F32; | ||||
| 
 | ||||
|  | ||||
| @ -1,7 +1,5 @@ | ||||
| use std::time::Duration; | ||||
| use std::ops::{Index, IndexMut}; | ||||
| 
 | ||||
| use serde::{Serialize, Deserialize}; | ||||
| use std::time::Duration; | ||||
| 
 | ||||
| /// Clamp a number between two boundaries.
 | ||||
| pub fn clamp(number: f32, min: f32, max: f32) -> f32 { | ||||
| @ -18,7 +16,7 @@ pub fn clamp(number: f32, min: f32, max: f32) -> f32 { | ||||
| pub fn duration_as_frame(duration: &Duration, total: usize) -> i32 { | ||||
|     let secs = duration_as_f32(duration); | ||||
| 
 | ||||
|     (secs * 4.0) as i32 % total as i32 | ||||
|     (secs * 10.0) as i32 % total as i32 | ||||
| } | ||||
| 
 | ||||
| /// Converts a duration into its number of seconds.
 | ||||
| @ -27,7 +25,7 @@ pub fn duration_as_f32(duration: &Duration) -> f32 { | ||||
| } | ||||
| 
 | ||||
| /// A generic matrix type, useful for levels.
 | ||||
| #[derive(Serialize, Deserialize, Clone)] | ||||
| #[derive(Clone)] | ||||
| pub struct Matrix<T> { | ||||
|     /// The number of rows of the matrix.
 | ||||
|     rows: usize, | ||||
|  | ||||
| @ -1,14 +1,14 @@ | ||||
| use std::time::Instant; | ||||
| 
 | ||||
| use sfml::graphics::{Color, IntRect, RenderTarget, RenderWindow, Sprite, View, Text}; | ||||
| use sfml::graphics::{Color, IntRect, RenderTarget, RenderWindow, Sprite, Text, View}; | ||||
| 
 | ||||
| use sfml::window::{Event, Style}; | ||||
| 
 | ||||
| use sfml::system::Vector2; | ||||
| 
 | ||||
| use crate::engine::font::{Font, FontManager}; | ||||
| use crate::engine::scene::Scene; | ||||
| use crate::engine::texture::{Texture, TextureManager}; | ||||
| use crate::engine::font::{Font, FontManager}; | ||||
| 
 | ||||
| /// Our custom drawable trait.
 | ||||
| pub trait Drawable { | ||||
| @ -80,7 +80,11 @@ impl Renderer { | ||||
|     } | ||||
| 
 | ||||
|     /// Draws a drawable with a certain translation.
 | ||||
|     pub fn translate_and_draw<D: Drawable, V: Into<Vector2<f32>>>(&mut self, drawable: &D, translation: V) { | ||||
|     pub fn translate_and_draw<D: Drawable, V: Into<Vector2<f32>>>( | ||||
|         &mut self, | ||||
|         drawable: &D, | ||||
|         translation: V, | ||||
|     ) { | ||||
|         let texture = self.texture_manager.get(drawable.texture()); | ||||
|         let mut sprite = Sprite::with_texture(&texture); | ||||
|         sprite.set_texture_rect(&drawable.texture_rect()); | ||||
|  | ||||
| @ -4,9 +4,9 @@ use sfml::graphics::View; | ||||
| use sfml::system::Vector2; | ||||
| use sfml::window::Event; | ||||
| 
 | ||||
| use crate::engine::texture::SPRITE_SIZE_F32; | ||||
| use crate::engine::character::Character; | ||||
| use crate::engine::map::Map; | ||||
| use crate::engine::texture::SPRITE_SIZE_F32; | ||||
| 
 | ||||
| /// Contains everything needed to play.
 | ||||
| pub struct Scene { | ||||
| @ -86,14 +86,11 @@ impl Scene { | ||||
| 
 | ||||
|     /// Updates the whole scene.
 | ||||
|     pub fn update(&mut self, duration: &Duration) -> State { | ||||
| 
 | ||||
|         let mut state = State::Finished; | ||||
| 
 | ||||
|         for c in &mut self.characters { | ||||
| 
 | ||||
|             // Don't need to update if the character is dead
 | ||||
|             if c.is_alive() { | ||||
| 
 | ||||
|                 let old = c.bbox(); | ||||
| 
 | ||||
|                 // Compute the offset between position and bbox
 | ||||
| @ -112,7 +109,6 @@ impl Scene { | ||||
|                     } | ||||
| 
 | ||||
|                     c.take_damage(damage); | ||||
| 
 | ||||
|                 } else { | ||||
|                     c.fall_off(); | ||||
|                 } | ||||
| @ -121,7 +117,6 @@ impl Scene { | ||||
|                 if c.controls().is_some() { | ||||
|                     state = State::Running; | ||||
|                 } | ||||
| 
 | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|  | ||||
| @ -10,32 +10,32 @@ pub const SPRITE_SIZE_F32: f32 = 32.0; | ||||
| /// tileset.
 | ||||
| pub fn byte_to_index(byte: u8) -> i32 { | ||||
|     match byte { | ||||
|         0   => 0, | ||||
|         1   => 1, | ||||
|         4   => 2, | ||||
|         5   => 3, | ||||
|         7   => 4, | ||||
|         16  => 5, | ||||
|         17  => 6, | ||||
|         20  => 7, | ||||
|         21  => 8, | ||||
|         23  => 9, | ||||
|         28  => 10, | ||||
|         29  => 11, | ||||
|         31  => 12, | ||||
|         64  => 13, | ||||
|         65  => 14, | ||||
|         68  => 15, | ||||
|         69  => 16, | ||||
|         71  => 17, | ||||
|         80  => 18, | ||||
|         81  => 19, | ||||
|         84  => 20, | ||||
|         85  => 21, | ||||
|         87  => 22, | ||||
|         92  => 23, | ||||
|         93  => 24, | ||||
|         95  => 25, | ||||
|         0 => 0, | ||||
|         1 => 1, | ||||
|         4 => 2, | ||||
|         5 => 3, | ||||
|         7 => 4, | ||||
|         16 => 5, | ||||
|         17 => 6, | ||||
|         20 => 7, | ||||
|         21 => 8, | ||||
|         23 => 9, | ||||
|         28 => 10, | ||||
|         29 => 11, | ||||
|         31 => 12, | ||||
|         64 => 13, | ||||
|         65 => 14, | ||||
|         68 => 15, | ||||
|         69 => 16, | ||||
|         71 => 17, | ||||
|         80 => 18, | ||||
|         81 => 19, | ||||
|         84 => 20, | ||||
|         85 => 21, | ||||
|         87 => 22, | ||||
|         92 => 23, | ||||
|         93 => 24, | ||||
|         95 => 25, | ||||
|         112 => 26, | ||||
|         113 => 27, | ||||
|         116 => 28, | ||||
| @ -120,10 +120,10 @@ macro_rules! make_textures { | ||||
| } | ||||
| 
 | ||||
| make_textures!( | ||||
|     Mario, | ||||
|     mario, | ||||
|     make_mario_texture, | ||||
|     "../../../assets/textures/mario.png", | ||||
|     Rusty, | ||||
|     rusty, | ||||
|     make_rusty_texture, | ||||
|     "../../../assets/textures/rusty.png", | ||||
|     256, | ||||
|     256, | ||||
|     Overworld, | ||||
|  | ||||
							
								
								
									
										13
									
								
								src/lib.rs
									
									
									
									
									
								
							
							
						
						
									
										13
									
								
								src/lib.rs
									
									
									
									
									
								
							| @ -2,14 +2,11 @@ | ||||
| 
 | ||||
| //! This crates contains the (future) rusty game.
 | ||||
| 
 | ||||
| use std::{io, fmt, result}; | ||||
| use std::{fmt, io, result}; | ||||
| 
 | ||||
| /// This module contains all the tools needed for the game.
 | ||||
| pub mod engine; | ||||
| 
 | ||||
| /// This module contains all the applications of the game.
 | ||||
| pub mod app; | ||||
| 
 | ||||
| /// This is the error type of this library.
 | ||||
| #[derive(Debug)] | ||||
| pub enum Error { | ||||
| @ -18,12 +15,6 @@ pub enum Error { | ||||
| 
 | ||||
|     /// An error occured while trying to load a file.
 | ||||
|     Load(io::Error), | ||||
| 
 | ||||
|     /// An error occured while encoding a file.
 | ||||
|     Encoding(bincode::Error), | ||||
| 
 | ||||
|     /// An error occured while decoding a file.
 | ||||
|     Decoding(bincode::Error), | ||||
| } | ||||
| 
 | ||||
| impl fmt::Display for Error { | ||||
| @ -31,8 +22,6 @@ impl fmt::Display for Error { | ||||
|         match *self { | ||||
|             Error::Save(ref e) => write!(fmt, "couldn't save file: {}", e), | ||||
|             Error::Load(ref e) => write!(fmt, "couldn't load file: {}", e), | ||||
|             Error::Encoding(ref e) => write!(fmt, "couldn't encode file: {}", e), | ||||
|             Error::Decoding(ref e) => write!(fmt, "couldn't decode file: {}", e), | ||||
|         } | ||||
|     } | ||||
| } | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user