Save / Load levels
This commit is contained in:
+7
-5
@@ -17,7 +17,7 @@ fn main() {
|
||||
|
||||
let mut running = true;
|
||||
|
||||
let mut map = Map::from_str(include_str!("../../assets/levels/level2.txt")).unwrap();
|
||||
let mut map = Map::load("./assets/levels/level2.lvl").unwrap();
|
||||
|
||||
loop {
|
||||
let top_panel_size = Vector2::new(renderer.window().size().x as f32, 50.0);
|
||||
@@ -42,10 +42,12 @@ fn main() {
|
||||
let x = ((x - left_panel_size.x as i32) / 16) as usize;
|
||||
let y = ((y - top_panel_size.y as i32) / 16) as usize;
|
||||
|
||||
if map.tile(y, x) == CollisionTile::empty() {
|
||||
map.set_tile(y, x, CollisionTile::full());
|
||||
} else {
|
||||
map.set_tile(y, x, CollisionTile::empty());
|
||||
if let Some(tile) = map.tile(y, x) {
|
||||
if tile == CollisionTile::empty() {
|
||||
map.set_tile(y, x, CollisionTile::full());
|
||||
} else {
|
||||
map.set_tile(y, x, CollisionTile::empty());
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
+22
-15
@@ -7,6 +7,7 @@ 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::scene::Scene;
|
||||
|
||||
fn parse_resolution(res: &str) -> Result<(u32, u32), String> {
|
||||
@@ -32,20 +33,25 @@ 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("fullscreen")
|
||||
.short("f")
|
||||
.long("fullscreen")
|
||||
.takes_value(false),
|
||||
).get_matches();
|
||||
.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))
|
||||
.get_matches();
|
||||
|
||||
let resolution = parse_resolution(matches.value_of("resolution").unwrap()).unwrap();
|
||||
let fullscreen = matches.is_present("fullscreen");
|
||||
@@ -62,7 +68,8 @@ fn main() {
|
||||
let mut character = Character::with_controls(controls);
|
||||
character.set_position((10.0, 0.0));
|
||||
|
||||
let mut scene = Scene::new();
|
||||
let map = Map::load(matches.value_of("map").unwrap()).unwrap();
|
||||
let mut scene = Scene::from_map(map);
|
||||
scene.add(character);
|
||||
|
||||
let mut renderer = Renderer::new(resolution.0, resolution.1, fullscreen);
|
||||
|
||||
+40
-5
@@ -1,6 +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 sfml::graphics::{FloatRect, IntRect};
|
||||
use sfml::system::Vector2;
|
||||
|
||||
use crate::{Error, Result};
|
||||
use crate::engine::math::{clamp, Matrix};
|
||||
use crate::engine::renderer::Drawable;
|
||||
use crate::engine::texture::Texture;
|
||||
@@ -37,7 +46,7 @@ impl CollisionAxis {
|
||||
}
|
||||
|
||||
/// This struct represents the different sides from which a collision can occur.
|
||||
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
|
||||
#[derive(Debug, Copy, Clone, PartialEq, Eq, Serialize, Deserialize)]
|
||||
pub struct CollisionTile {
|
||||
/// If the character comes from the top, it will collide if this bool is true.
|
||||
pub from_top: bool,
|
||||
@@ -75,7 +84,7 @@ impl CollisionTile {
|
||||
}
|
||||
|
||||
/// This struct represents a renderable tile linking to its part in the tileset texture.
|
||||
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
|
||||
#[derive(Debug, Copy, Clone, PartialEq, Eq, Serialize, Deserialize)]
|
||||
pub enum GraphicTile {
|
||||
/// There is nothing to draw.
|
||||
Hidden,
|
||||
@@ -273,6 +282,7 @@ impl Drawable for PositionedTile {
|
||||
}
|
||||
|
||||
/// The map represents the tiles contained in a level.
|
||||
#[derive(Serialize, Deserialize)]
|
||||
pub struct Map {
|
||||
/// The entrace point of the character in the map.
|
||||
entrance: (usize, usize),
|
||||
@@ -294,8 +304,33 @@ impl Map {
|
||||
Map::from_collision_tiles(tiles)
|
||||
}
|
||||
|
||||
/// Encodes the map into a binary format.
|
||||
pub fn encode(&self) -> Result<Vec<u8>> {
|
||||
serialize(&self).map_err(Error::Encoding)
|
||||
}
|
||||
|
||||
/// Decodes a map from bytes.
|
||||
pub fn decode(content: &[u8]) -> Result<Map> {
|
||||
deserialize(content).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).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_err(Error::Decoding)?)
|
||||
}
|
||||
|
||||
/// Creates a map from a txt file.
|
||||
pub fn from_str(text: &str) -> Result<Map, ()> {
|
||||
pub fn from_str(text: &str) -> Result<Map> {
|
||||
let split = text.split('\n').collect::<Vec<_>>();
|
||||
|
||||
// First two usize are the size of the map
|
||||
@@ -356,8 +391,8 @@ impl Map {
|
||||
}
|
||||
|
||||
/// Returns a tile of the map.
|
||||
pub fn tile(&self, i: usize, j: usize) -> CollisionTile {
|
||||
self.tiles[(i, j)].0
|
||||
pub fn tile(&self, i: usize, j: usize) -> Option<CollisionTile> {
|
||||
self.tiles.get((i, j)).map(|x| x.0)
|
||||
}
|
||||
|
||||
/// Changes a tile of the map.
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
use std::time::Duration;
|
||||
|
||||
use std::ops::{Index, IndexMut};
|
||||
|
||||
use serde::{Serialize, Deserialize};
|
||||
|
||||
/// Clamp a number between two boundaries.
|
||||
pub fn clamp(number: f32, min: f32, max: f32) -> f32 {
|
||||
if number < min {
|
||||
@@ -26,6 +27,7 @@ pub fn duration_as_f32(duration: &Duration) -> f32 {
|
||||
}
|
||||
|
||||
/// A generic matrix type, useful for levels.
|
||||
#[derive(Serialize, Deserialize)]
|
||||
pub struct Matrix<T> {
|
||||
/// The number of rows of the matrix.
|
||||
rows: usize,
|
||||
|
||||
@@ -17,11 +17,11 @@ pub struct Scene {
|
||||
}
|
||||
|
||||
impl Scene {
|
||||
/// Creates an empty scene.
|
||||
pub fn new() -> Scene {
|
||||
/// Creates a scene from a map level.
|
||||
pub fn from_map(map: Map) -> Scene {
|
||||
Scene {
|
||||
characters: vec![],
|
||||
map: Map::from_str(include_str!("../../../assets/levels/level2.txt")).unwrap(),
|
||||
map,
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+32
@@ -2,5 +2,37 @@
|
||||
|
||||
//! This crates contains the (future) rusty game.
|
||||
|
||||
use std::{io, fmt, result};
|
||||
|
||||
/// This module contains all the tools needed for the game.
|
||||
pub mod engine;
|
||||
|
||||
/// This is the error type of this library.
|
||||
#[derive(Debug)]
|
||||
pub enum Error {
|
||||
/// An error occured while trying to save a file.
|
||||
Save(io::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 {
|
||||
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
|
||||
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),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// This is the result type of this library.
|
||||
type Result<T> = result::Result<T, Error>;
|
||||
|
||||
Reference in New Issue
Block a user