123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197 |
- #[macro_use] extern crate specs_derive;
- 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)
- }
- }
- #[derive(Component, Debug)]
- #[storage(VecStorage)]
- struct Sprite {
- u: u8,
- v: u8,
- }
- 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();
- }
- }
- }
- }
- }
- 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)?;
- self.sprites.clear();
- g::present(ctx);
- Ok(())
- }
- }
- 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>();
- world_from_file(&mut world, &Path::new("assets/main.tmx"));
- // Make a Context and an EventLoop.
- 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 {
- world,
- sprites,
- };
- event::run(&mut ctx, &mut my_game)
- }
|