@@ -0,0 +1 @@ | |||||
/target |
@@ -0,0 +1,13 @@ | |||||
[package] | |||||
name = "unnamed" | |||||
version = "0.1.0" | |||||
authors = ["isabelle"] | |||||
edition = "2018" | |||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html | |||||
[dependencies] | |||||
ggez = "0.5.1" | |||||
thiserror = "1.0.20" | |||||
serde = { version = "1.0.114", features = ["derive"] } | |||||
toml = "0.5.6" |
@@ -0,0 +1,6 @@ | |||||
[window_mode] | |||||
width = 1024 | |||||
height = 768 | |||||
[window_setup] | |||||
title = "unnamed" | |||||
resizable = false |
@@ -0,0 +1,3 @@ | |||||
[nothing] | |||||
path = "img/tiles/nothing.png" | |||||
blocking = true |
@@ -0,0 +1,53 @@ | |||||
mod util; | |||||
mod world; | |||||
use ggez::{ | |||||
event::{self, EventHandler}, | |||||
graphics, Context, ContextBuilder, GameResult, | |||||
}; | |||||
use world::World; | |||||
pub type Result<T> = std::result::Result<T, Error>; | |||||
#[derive(Debug, thiserror::Error)] | |||||
pub enum Error { | |||||
#[error(transparent)] | |||||
Stdio(#[from] std::io::Error), | |||||
#[error(transparent)] | |||||
Toml(#[from] toml::de::Error), | |||||
} | |||||
struct MainState { | |||||
world: World, | |||||
} | |||||
impl MainState { | |||||
pub fn new(_ctx: &mut Context) -> MainState { | |||||
MainState { | |||||
world: World::new(20, 20, 3), | |||||
} | |||||
} | |||||
} | |||||
impl EventHandler for MainState { | |||||
fn update(&mut self, _ctx: &mut Context) -> GameResult<()> { | |||||
Ok(()) | |||||
} | |||||
fn draw(&mut self, ctx: &mut Context) -> GameResult<()> { | |||||
graphics::clear(ctx, graphics::WHITE); | |||||
graphics::present(ctx) | |||||
} | |||||
} | |||||
fn main() { | |||||
let (mut ctx, mut event_loop) = ContextBuilder::new("unnamed", "Isabelle L.") | |||||
.build() | |||||
.expect("failed to start context"); | |||||
let mut state = MainState::new(&mut ctx); | |||||
if let Err(err) = event::run(&mut ctx, &mut event_loop, &mut state) { | |||||
eprintln!("an error occured: {:?}", err); | |||||
} | |||||
} |
@@ -0,0 +1,69 @@ | |||||
use std::convert::From; | |||||
pub struct CartesianVector(usize, usize); | |||||
pub struct IsometricVector(usize, usize); | |||||
pub struct Vector3d(usize, usize, usize); | |||||
impl Vector3d { | |||||
pub fn x(&self) -> usize { | |||||
self.0 | |||||
} | |||||
pub fn y(&self) -> usize { | |||||
self.1 | |||||
} | |||||
pub fn z(&self) -> usize { | |||||
self.2 | |||||
} | |||||
} | |||||
impl From<(usize, usize, usize)> for Vector3d { | |||||
fn from(tuple: (usize, usize, usize)) -> Vector3d { | |||||
Vector3d(tuple.0, tuple.1, tuple.2) | |||||
} | |||||
} | |||||
impl CartesianVector { | |||||
pub fn x(&self) -> usize { | |||||
self.0 | |||||
} | |||||
pub fn y(&self) -> usize { | |||||
self.1 | |||||
} | |||||
} | |||||
impl IsometricVector { | |||||
pub fn x(&self) -> usize { | |||||
self.0 | |||||
} | |||||
pub fn y(&self) -> usize { | |||||
self.1 | |||||
} | |||||
} | |||||
impl From<(usize, usize)> for CartesianVector { | |||||
fn from(tuple: (usize, usize)) -> CartesianVector { | |||||
CartesianVector(tuple.0, tuple.1) | |||||
} | |||||
} | |||||
impl From<IsometricVector> for CartesianVector { | |||||
fn from(iso: IsometricVector) -> CartesianVector { | |||||
CartesianVector((2 * iso.y() + iso.x()) / 2, (2 * iso.y() - iso.x()) / 2) | |||||
} | |||||
} | |||||
impl From<CartesianVector> for IsometricVector { | |||||
fn from(cart: CartesianVector) -> IsometricVector { | |||||
IsometricVector(cart.x() - cart.y(), (cart.x() + cart.y()) / 2) | |||||
} | |||||
} | |||||
impl From<(usize, usize)> for IsometricVector { | |||||
fn from(tuple: (usize, usize)) -> IsometricVector { | |||||
IsometricVector(tuple.0, tuple.1) | |||||
} | |||||
} |
@@ -0,0 +1,23 @@ | |||||
mod tile; | |||||
use crate::util::Vector3d; | |||||
use std::collections::HashMap; | |||||
use tile::*; | |||||
pub struct World { | |||||
width: usize, | |||||
height: usize, | |||||
depth: usize, | |||||
data: HashMap<Vector3d, Tile>, | |||||
} | |||||
impl World { | |||||
pub fn new(width: usize, height: usize, depth: usize) -> World { | |||||
World { | |||||
width, | |||||
height, | |||||
depth, | |||||
data: HashMap::new(), | |||||
} | |||||
} | |||||
} |
@@ -0,0 +1,48 @@ | |||||
use crate::Result; | |||||
use ggez::graphics::Image; | |||||
use ggez::Context; | |||||
use serde::Deserialize; | |||||
use std::collections::HashMap; | |||||
use std::path::PathBuf; | |||||
use std::rc::Rc; | |||||
pub struct TileBuilder { | |||||
textures: HashMap<String, MasterTile>, | |||||
} | |||||
impl TileBuilder { | |||||
pub fn new(ctx: &mut Context, tiles_config: PathBuf) -> Result<TileBuilder> { | |||||
let raw_data = std::fs::read_to_string(tiles_config)?; | |||||
let raw_map: HashMap<String, RawTile> = toml::from_str(&raw_data)?; | |||||
let mut textures: HashMap<String, MasterTile> = HashMap::new(); | |||||
raw_map.iter().for_each(|(kind, raw_tile)| { | |||||
let tile = MasterTile { | |||||
texture: Image::new(ctx, &raw_tile.path).expect("failed to load image"), | |||||
kind: kind.to_owned(), | |||||
blocking: raw_tile.blocking, | |||||
}; | |||||
textures.insert(kind.to_owned(), tile); | |||||
}); | |||||
Ok(TileBuilder { textures: textures }) | |||||
} | |||||
} | |||||
pub struct Tile { | |||||
texture: Rc<Image>, | |||||
kind: String, | |||||
blocking: bool, | |||||
} | |||||
struct MasterTile { | |||||
texture: Image, | |||||
kind: String, | |||||
blocking: bool, | |||||
} | |||||
#[derive(Deserialize)] | |||||
struct RawTile { | |||||
path: PathBuf, | |||||
blocking: bool, | |||||
} |