|  | @@ -4,177 +4,76 @@ use ggez::{Context, ContextBuilder, GameResult};
 | 
	
		
			
				|  |  |  use ggez::event::{self, EventHandler};
 | 
	
		
			
				|  |  |  use ggez::graphics;
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -use std::path::Path;
 | 
	
		
			
				|  |  | -use specs::{Component, RunNow, System, NullStorage, VecStorage};
 | 
	
		
			
				|  |  | -use specs::world::Builder;
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -#[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(Component, Debug)]
 | 
	
		
			
				|  |  | -#[storage(VecStorage)]
 | 
	
		
			
				|  |  | -struct Position {
 | 
	
		
			
				|  |  | -    x: f32,
 | 
	
		
			
				|  |  | -    y: f32,
 | 
	
		
			
				|  |  | -}
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -impl Position {
 | 
	
		
			
				|  |  | -    fn to_point(&self) -> ggez::nalgebra::Point2<f32> {
 | 
	
		
			
				|  |  | -        ggez::nalgebra::Point2::new(self.x, self.y)
 | 
	
		
			
				|  |  | -    }
 | 
	
		
			
				|  |  | -}
 | 
	
		
			
				|  |  | +use specs::RunNow;
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -#[derive(Component, Debug)]
 | 
	
		
			
				|  |  | -#[storage(VecStorage)]
 | 
	
		
			
				|  |  | -struct Sprite {
 | 
	
		
			
				|  |  | -    u: u8,
 | 
	
		
			
				|  |  | -    v: u8,
 | 
	
		
			
				|  |  | -}
 | 
	
		
			
				|  |  | +use sdl2::keyboard as sdl;
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -impl Sprite {
 | 
	
		
			
				|  |  | -    fn to_rect(&self) -> graphics::Rect {
 | 
	
		
			
				|  |  | -        graphics::Rect {
 | 
	
		
			
				|  |  | -            x: (1.0 / 32.0) * self.u as f32,
 | 
	
		
			
				|  |  | -            y: (1.0 / 32.0) * self.v as f32,
 | 
	
		
			
				|  |  | -            w: 1.0 / 32.0,
 | 
	
		
			
				|  |  | -            h: 1.0 / 32.0,
 | 
	
		
			
				|  |  | -        }
 | 
	
		
			
				|  |  | -    }
 | 
	
		
			
				|  |  | -}
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -#[derive(Debug, Copy, Clone)]
 | 
	
		
			
				|  |  | -enum DrawLayer {
 | 
	
		
			
				|  |  | -    Background,
 | 
	
		
			
				|  |  | -    Foreground,
 | 
	
		
			
				|  |  | -    Decoration,
 | 
	
		
			
				|  |  | -}
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -static DRAW_LAYERS: [DrawLayer;3] = [
 | 
	
		
			
				|  |  | -    DrawLayer::Background,
 | 
	
		
			
				|  |  | -    DrawLayer::Foreground,
 | 
	
		
			
				|  |  | -    DrawLayer::Decoration,
 | 
	
		
			
				|  |  | -];
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -#[derive(Component, Default, Debug)]
 | 
	
		
			
				|  |  | -#[storage(NullStorage)]
 | 
	
		
			
				|  |  | -struct Background;
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -#[derive(Component, Default, Debug)]
 | 
	
		
			
				|  |  | -#[storage(NullStorage)]
 | 
	
		
			
				|  |  | -struct Foreground;
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -#[derive(Component, Default, Debug)]
 | 
	
		
			
				|  |  | -#[storage(NullStorage)]
 | 
	
		
			
				|  |  | -struct Decoration;
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -fn world_from_file(w: &mut specs::World, path: &Path) {
 | 
	
		
			
				|  |  | -    let tiled::Map {
 | 
	
		
			
				|  |  | -        layers,
 | 
	
		
			
				|  |  | -        ..
 | 
	
		
			
				|  |  | -    } = tiled::parse_file(path).unwrap();
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -    for (phase, layer) in DRAW_LAYERS.iter().zip(layers) {
 | 
	
		
			
				|  |  | -        for (row, y) in layer.tiles.iter().zip(0..) {
 | 
	
		
			
				|  |  | -            for (&n, x) in row.iter().zip(0..) {
 | 
	
		
			
				|  |  | -                if n != 0 {
 | 
	
		
			
				|  |  | -                    let x = x as f32 * 24.0;
 | 
	
		
			
				|  |  | -                    let y = y as f32 * 24.0;
 | 
	
		
			
				|  |  | -                    let u = ((n - 1) % 32) as u8;
 | 
	
		
			
				|  |  | -                    let v = ((n - u as u32 - 1) / 32) as u8;
 | 
	
		
			
				|  |  | -                    let mut e = w.create_entity()
 | 
	
		
			
				|  |  | -                        .with(Position { x, y })
 | 
	
		
			
				|  |  | -                        .with(Sprite { u, v });
 | 
	
		
			
				|  |  | -                    e = match phase {
 | 
	
		
			
				|  |  | -                        DrawLayer::Background => e.with(Background),
 | 
	
		
			
				|  |  | -                        DrawLayer::Foreground => e.with(Foreground),
 | 
	
		
			
				|  |  | -                        DrawLayer::Decoration => e.with(Decoration),
 | 
	
		
			
				|  |  | -                    };
 | 
	
		
			
				|  |  | -                    e.build();
 | 
	
		
			
				|  |  | -            }
 | 
	
		
			
				|  |  | -        }
 | 
	
		
			
				|  |  | -    }
 | 
	
		
			
				|  |  | -    }
 | 
	
		
			
				|  |  | -}
 | 
	
		
			
				|  |  | +pub mod consts;
 | 
	
		
			
				|  |  | +pub mod components;
 | 
	
		
			
				|  |  | +pub mod res;
 | 
	
		
			
				|  |  | +pub mod sys;
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  struct MyGame {
 | 
	
		
			
				|  |  |      world: specs::World,
 | 
	
		
			
				|  |  |      sprites: graphics::spritebatch::SpriteBatch,
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -struct Draw<'t, Phase> {
 | 
	
		
			
				|  |  | -    ctx: &'t mut Context,
 | 
	
		
			
				|  |  | -    sprites: &'t mut graphics::spritebatch::SpriteBatch,
 | 
	
		
			
				|  |  | -    _phase: Phase,
 | 
	
		
			
				|  |  | -}
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -impl<'a, 't, Phase: Component> System<'a> for Draw<'t, Phase> {
 | 
	
		
			
				|  |  | -    type SystemData = (
 | 
	
		
			
				|  |  | -        specs::ReadStorage<'a, Position>,
 | 
	
		
			
				|  |  | -        specs::ReadStorage<'a, Sprite>,
 | 
	
		
			
				|  |  | -        specs::ReadStorage<'a, Phase>,
 | 
	
		
			
				|  |  | -    );
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -    fn run(&mut self, (positions, sprites, phase): Self::SystemData) {
 | 
	
		
			
				|  |  | -        use specs::Join;
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -        for (pos, spr, _) in (&positions, &sprites, &phase).join() {
 | 
	
		
			
				|  |  | -            let param = graphics::DrawParam {
 | 
	
		
			
				|  |  | -                src: spr.to_rect(),
 | 
	
		
			
				|  |  | -                dest: pos.to_point(),
 | 
	
		
			
				|  |  | -                ..Default::default()
 | 
	
		
			
				|  |  | -            };
 | 
	
		
			
				|  |  | -            self.sprites.add(param);
 | 
	
		
			
				|  |  | -            graphics::draw(
 | 
	
		
			
				|  |  | -                self.ctx,
 | 
	
		
			
				|  |  | -                self.sprites,
 | 
	
		
			
				|  |  | -                ggez::nalgebra::Point2::new(0.0, 0.0),
 | 
	
		
			
				|  |  | -                0.0).unwrap();
 | 
	
		
			
				|  |  | -            self.sprites.clear();
 | 
	
		
			
				|  |  | -        }
 | 
	
		
			
				|  |  | -    }
 | 
	
		
			
				|  |  | -}
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  |  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);
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -        Draw { ctx, sprites: &mut self.sprites, _phase: Background }.run_now(&self.world.res);
 | 
	
		
			
				|  |  | -        Draw { ctx, sprites: &mut self.sprites, _phase: Foreground }.run_now(&self.world.res);
 | 
	
		
			
				|  |  | -        Draw { ctx, sprites: &mut self.sprites, _phase: Decoration }.run_now(&self.world.res);
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -        g::draw(ctx, &self.sprites, n::Point2::new(0.0, 0.0), 0.0)?;
 | 
	
		
			
				|  |  | +        ggez::graphics::set_background_color(ctx, ggez::graphics::BLACK);
 | 
	
		
			
				|  |  | +        ggez::graphics::clear(ctx);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        sys::Draw {
 | 
	
		
			
				|  |  | +            ctx,
 | 
	
		
			
				|  |  | +            sprites: &mut self.sprites,
 | 
	
		
			
				|  |  | +            _phase: components::Background,
 | 
	
		
			
				|  |  | +        }.run_now(&self.world.res);
 | 
	
		
			
				|  |  | +        sys::Draw {
 | 
	
		
			
				|  |  | +            ctx,
 | 
	
		
			
				|  |  | +            sprites: &mut self.sprites,
 | 
	
		
			
				|  |  | +            _phase: components::Foreground,
 | 
	
		
			
				|  |  | +        }.run_now(&self.world.res);
 | 
	
		
			
				|  |  | +        sys::Draw {
 | 
	
		
			
				|  |  | +            ctx,
 | 
	
		
			
				|  |  | +            sprites: &mut self.sprites,
 | 
	
		
			
				|  |  | +            _phase: components::Decoration,
 | 
	
		
			
				|  |  | +        }.run_now(&self.world.res);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        ggez::graphics::draw(
 | 
	
		
			
				|  |  | +            ctx,
 | 
	
		
			
				|  |  | +            &self.sprites,
 | 
	
		
			
				|  |  | +            ggez::nalgebra::Point2::new(0.0, 0.0),
 | 
	
		
			
				|  |  | +            0.0
 | 
	
		
			
				|  |  | +        )?;
 | 
	
		
			
				|  |  |          self.sprites.clear();
 | 
	
		
			
				|  |  | -        g::present(ctx);
 | 
	
		
			
				|  |  | +        ggez::graphics::present(ctx);
 | 
	
		
			
				|  |  |          Ok(())
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    fn key_down_event(
 | 
	
		
			
				|  |  | +        &mut self,
 | 
	
		
			
				|  |  | +        ctx: &mut Context,
 | 
	
		
			
				|  |  | +        keycode: sdl::Keycode,
 | 
	
		
			
				|  |  | +        _keymod: sdl::Mod,
 | 
	
		
			
				|  |  | +        _repeat: bool,
 | 
	
		
			
				|  |  | +    ) {
 | 
	
		
			
				|  |  | +        if keycode == sdl::Keycode::Escape {
 | 
	
		
			
				|  |  | +            ctx.quit().expect("Should never fail");
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  | +        sys::Move { keycode }.run_now(&self.world.res);
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  fn main() -> Result<(), ggez::error::GameError> {
 | 
	
		
			
				|  |  |      let mut world = specs::World::new();
 | 
	
		
			
				|  |  | -    world.register::<Position>();
 | 
	
		
			
				|  |  | -    world.register::<Sprite>();
 | 
	
		
			
				|  |  | -    world.register::<Background>();
 | 
	
		
			
				|  |  | -    world.register::<Foreground>();
 | 
	
		
			
				|  |  | -    world.register::<Decoration>();
 | 
	
		
			
				|  |  | +    components::register(&mut world);
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -    world_from_file(&mut world, &Path::new("assets/main.tmx"));
 | 
	
		
			
				|  |  | +    res::world_from_file(&mut world, "assets/main.tmx");
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |      // Make a Context and an EventLoop.
 | 
	
		
			
				|  |  |      let mut ctx = ContextBuilder::new("game", "me")
 | 
	
	
		
			
				|  | @@ -184,9 +83,15 @@ fn main() -> Result<(), ggez::error::GameError> {
 | 
	
		
			
				|  |  |              path.push("assets");
 | 
	
		
			
				|  |  |              path
 | 
	
		
			
				|  |  |          })
 | 
	
		
			
				|  |  | +        .window_mode(ggez::conf::WindowMode {
 | 
	
		
			
				|  |  | +            width: consts::WINDOW_WIDTH,
 | 
	
		
			
				|  |  | +            height: consts::WINDOW_HEIGHT,
 | 
	
		
			
				|  |  | +            ..Default::default()
 | 
	
		
			
				|  |  | +        })
 | 
	
		
			
				|  |  |          .build()?;
 | 
	
		
			
				|  |  |      let image = graphics::Image::new(&mut ctx, "/spritesheet.png")?;
 | 
	
		
			
				|  |  | -    let sprites = graphics::spritebatch::SpriteBatch::new(image);
 | 
	
		
			
				|  |  | +    let mut sprites = graphics::spritebatch::SpriteBatch::new(image);
 | 
	
		
			
				|  |  | +    sprites.set_filter(ggez::graphics::FilterMode::Nearest);
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |      let mut my_game = MyGame {
 | 
	
		
			
				|  |  |          world,
 |