#[macro_use] extern crate itertools; use ggez::{Context, ContextBuilder, GameResult}; use ggez::event::{self, EventHandler}; use ggez::graphics; use std::path::Path; #[allow(dead_code)] mod consts { pub const SPEED: u32 = 2; pub const TILE_SIZE: u32 = 24; pub const HALF_TILE: u32 = TILE_SIZE / 2; pub const QUARTER_TILE: u32 = TILE_SIZE / 4; pub const BOARD_WIDTH: usize = 16; pub const BOARD_HEIGHT: usize = 12; pub const SCALE: u32 = 3; pub const TILED_TRUE: tiled::PropertyValue = tiled::PropertyValue::BoolValue(true); } #[derive(Debug)] struct Board { tiles: Vec>, entities: Vec>, decoration: Vec>, } impl Board { fn from_file(path: &Path) -> Board { let tiled::Map { tilesets, layers, .. } = tiled::parse_file(path).unwrap(); let read_layer = |idx: usize| { layers[idx].tiles.iter() .flat_map(|row| row) .map(|&n| if n > 0 { Some(Tile::from_tileset(n, &tilesets[0])) } else { None }) .collect() }; let tiles = read_layer(0); let entities = read_layer(1); let decoration = read_layer(2); Board { tiles, entities, decoration, } } fn draw() { } } #[derive(Debug, Clone)] struct Tile { action: Action, sprite: (u8, u8), pass: bool, } impl Tile { fn from_tileset(n: u32, tileset: &tiled::Tileset) -> Tile { let x = (n - 1) % 32; let y = (n - x - 1) / 32; let pass = tileset.tiles[n as usize].properties.get("pass").eq( &Some(&consts::TILED_TRUE)); Tile { action: Action::NoAction, sprite: (x as u8, y as u8), pass: pass, } } fn draw(&self, (y, x): (usize, usize)) -> graphics::DrawParam { let (tx, ty) = self.sprite; graphics::DrawParam { src: graphics::Rect { x: (1.0 / 32.0) * tx as f32, y: (1.0 / 32.0) * ty as f32, w: 1.0 / 32.0, h: 1.0 / 32.0, }, dest: ggez::nalgebra::Point2::new( x as f32 * 24.0, y as f32 * 24.0), ..Default::default() } } } #[derive(Debug, Clone)] enum Action { NoAction, } struct MyGame { board: Board, sprites: graphics::spritebatch::SpriteBatch, } impl EventHandler for MyGame { fn update(&mut self, _ctx: &mut Context) -> GameResult<()> { Ok(()) } fn draw(&mut self, ctx: &mut Context) -> GameResult<()> { use ggez::graphics as g; use ggez::nalgebra as n; g::set_background_color(ctx, g::BLACK); g::clear(ctx); for layer in [ &self.board.tiles, &self.board.entities, &self.board.decoration ].iter() { for (pt, t) in iproduct!((0..consts::BOARD_HEIGHT), (0..consts::BOARD_WIDTH)).zip( layer.iter()) { if let Some(t) = t { self.sprites.add(t.draw(pt)); } } } g::draw(ctx, &self.sprites, n::Point2::new(0.0, 0.0), 0.0)?; self.sprites.clear(); g::present(ctx); Ok(()) } } fn main() -> Result<(), ggez::error::GameError> { // Make a Context and an EventLoop. let board = Board::from_file(&Path::new("assets/main.tmx")); let mut ctx = ContextBuilder::new("game", "me") .add_resource_path({ let base = std::env::var("CARGO_MANIFEST_DIR").unwrap(); let mut path = std::path::PathBuf::from(base); path.push("assets"); path }) .build()?; let image = graphics::Image::new(&mut ctx, "/spritesheet.png")?; let sprites = graphics::spritebatch::SpriteBatch::new(image); let mut my_game = MyGame { board, sprites, }; event::run(&mut ctx, &mut my_game) }