|
@@ -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,
|