Finish chapter 1
This commit is contained in:
parent
9afe446f13
commit
6ca2dbc3f6
11
Cargo.toml
Normal file
11
Cargo.toml
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
[package]
|
||||||
|
name = "rust-sokoban"
|
||||||
|
version = "0.1.0"
|
||||||
|
authors = ["Timothy Warren <twarren@nabancard.com>"]
|
||||||
|
edition = "2018"
|
||||||
|
|
||||||
|
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
ggez = "0.5.1"
|
||||||
|
specs = { version="0.15.0", features=["specs-derive"] }
|
BIN
resources/images/box.png
Normal file
BIN
resources/images/box.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 197 B |
BIN
resources/images/box_spot.png
Normal file
BIN
resources/images/box_spot.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 162 B |
BIN
resources/images/floor.png
Normal file
BIN
resources/images/floor.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 131 B |
BIN
resources/images/player.png
Normal file
BIN
resources/images/player.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 264 B |
BIN
resources/images/wall.png
Normal file
BIN
resources/images/wall.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 167 B |
212
src/main.rs
Normal file
212
src/main.rs
Normal file
@ -0,0 +1,212 @@
|
|||||||
|
use ggez::graphics;
|
||||||
|
use ggez::graphics::DrawParam;
|
||||||
|
use ggez::graphics::Image;
|
||||||
|
use ggez::nalgebra as na;
|
||||||
|
use ggez::{conf, event, Context, GameResult};
|
||||||
|
use specs::{
|
||||||
|
join::Join, Builder, Component, ReadStorage, RunNow, System, VecStorage, World, WorldExt,
|
||||||
|
};
|
||||||
|
|
||||||
|
use std::path;
|
||||||
|
|
||||||
|
const TILE_WIDTH: f32 = 32.0;
|
||||||
|
|
||||||
|
// Components
|
||||||
|
#[derive(Debug, Component, Clone, Copy)]
|
||||||
|
#[storage(VecStorage)]
|
||||||
|
pub struct Position {
|
||||||
|
x: u8,
|
||||||
|
y: u8,
|
||||||
|
z: u8,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Component)]
|
||||||
|
#[storage(VecStorage)]
|
||||||
|
pub struct Renderable {
|
||||||
|
path: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Component)]
|
||||||
|
#[storage(VecStorage)]
|
||||||
|
pub struct Wall {}
|
||||||
|
|
||||||
|
#[derive(Component)]
|
||||||
|
#[storage(VecStorage)]
|
||||||
|
pub struct Player {}
|
||||||
|
|
||||||
|
#[derive(Component)]
|
||||||
|
#[storage(VecStorage)]
|
||||||
|
pub struct Box {}
|
||||||
|
|
||||||
|
#[derive(Component)]
|
||||||
|
#[storage(VecStorage)]
|
||||||
|
pub struct BoxSpot {}
|
||||||
|
|
||||||
|
// Systems
|
||||||
|
pub struct RenderingSystem<'a> {
|
||||||
|
context: &'a mut Context,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> System<'a> for RenderingSystem<'a> {
|
||||||
|
type SystemData = (ReadStorage<'a, Position>, ReadStorage<'a, Renderable>);
|
||||||
|
|
||||||
|
fn run(&mut self, data: Self::SystemData) {
|
||||||
|
let (positions, renderables) = data;
|
||||||
|
|
||||||
|
// Clear the screen/set the background
|
||||||
|
graphics::clear(self.context, graphics::Color::new(0.95, 0.95, 0.95, 1.0));
|
||||||
|
|
||||||
|
// Get all the renderables with their positions and sort by the position z
|
||||||
|
// This will allow us to have entities layered visually.
|
||||||
|
let mut rendering_data = (&positions, &renderables).join().collect::<Vec<_>>();
|
||||||
|
rendering_data.sort_by(|&a, &b| a.0.z.partial_cmp(&b.0.z).expect("expected comparison"));
|
||||||
|
|
||||||
|
// Iterate through all paris of positions & renderables, load the image
|
||||||
|
// and draw it at the specified position.
|
||||||
|
for (position, renderable) in rendering_data.iter() {
|
||||||
|
// Load the image
|
||||||
|
let image = Image::new(self.context, renderable.path.clone()).expect("expected image");
|
||||||
|
let x = position.x as f32 * TILE_WIDTH;
|
||||||
|
let y = position.y as f32 * TILE_WIDTH;
|
||||||
|
|
||||||
|
// draw
|
||||||
|
let draw_params = DrawParam::new().dest(na::Point2::new(x, y));
|
||||||
|
graphics::draw(self.context, &image, draw_params).expect("expected render");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Finally, present the context, this will actually display everything
|
||||||
|
// on the screen.
|
||||||
|
graphics::present(self.context).expect("expected to present");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// All the game state
|
||||||
|
struct Game {
|
||||||
|
world: World,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl event::EventHandler for Game {
|
||||||
|
fn update(&mut self, _context: &mut Context) -> GameResult {
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn draw(&mut self, context: &mut Context) -> GameResult {
|
||||||
|
// Render gaem entities
|
||||||
|
{
|
||||||
|
let mut rs = RenderingSystem { context };
|
||||||
|
rs.run_now(&self.world);
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn register_components(world: &mut World) {
|
||||||
|
world.register::<Position>();
|
||||||
|
world.register::<Renderable>();
|
||||||
|
world.register::<Player>();
|
||||||
|
world.register::<Wall>();
|
||||||
|
world.register::<Box>();
|
||||||
|
world.register::<BoxSpot>();
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn create_wall(world: &mut World, position: Position) {
|
||||||
|
world
|
||||||
|
.create_entity()
|
||||||
|
.with(Position { z: 10, ..position })
|
||||||
|
.with(Renderable {
|
||||||
|
path: "/images/wall.png".to_string(),
|
||||||
|
})
|
||||||
|
.with(Wall {})
|
||||||
|
.build();
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn create_floor(world: &mut World, position: Position) {
|
||||||
|
world
|
||||||
|
.create_entity()
|
||||||
|
.with(Position { z: 5, ..position })
|
||||||
|
.with(Renderable {
|
||||||
|
path: "/images/floor.png".to_string(),
|
||||||
|
})
|
||||||
|
.build();
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn create_box(world: &mut World, position: Position) {
|
||||||
|
world
|
||||||
|
.create_entity()
|
||||||
|
.with(Position { z: 10, ..position })
|
||||||
|
.with(Renderable {
|
||||||
|
path: "/images/box.png".to_string(),
|
||||||
|
})
|
||||||
|
.build();
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn create_box_spot(world: &mut World, position: Position) {
|
||||||
|
world
|
||||||
|
.create_entity()
|
||||||
|
.with(Position { z: 9, ..position })
|
||||||
|
.with(Renderable {
|
||||||
|
path: "/images/box_spot.png".to_string(),
|
||||||
|
})
|
||||||
|
.with(BoxSpot {})
|
||||||
|
.build();
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn create_player(world: &mut World, position: Position) {
|
||||||
|
world
|
||||||
|
.create_entity()
|
||||||
|
.with(Position { z: 10, ..position })
|
||||||
|
.with(Renderable {
|
||||||
|
path: "/images/player.png".to_string(),
|
||||||
|
})
|
||||||
|
.with(Player {})
|
||||||
|
.build();
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn initialize_level(world: &mut World) {
|
||||||
|
create_player(
|
||||||
|
world,
|
||||||
|
Position {
|
||||||
|
x: 0,
|
||||||
|
y: 0,
|
||||||
|
z: 0, // we will get the z from the factory functions
|
||||||
|
},
|
||||||
|
);
|
||||||
|
create_wall(
|
||||||
|
world,
|
||||||
|
Position {
|
||||||
|
x: 1,
|
||||||
|
y: 0,
|
||||||
|
z: 0, // we will get the z from the factory functions
|
||||||
|
},
|
||||||
|
);
|
||||||
|
create_box(
|
||||||
|
world,
|
||||||
|
Position {
|
||||||
|
x: 2,
|
||||||
|
y: 0,
|
||||||
|
z: 0, // we will get the z from the factory functions
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
pub fn main() -> GameResult {
|
||||||
|
let mut world = World::new();
|
||||||
|
register_components(&mut world);
|
||||||
|
initialize_level(&mut world);
|
||||||
|
|
||||||
|
// Create a game context and event loop
|
||||||
|
let context_builder = ggez::ContextBuilder::new("rust_sokoban", "Timothy J. Warren")
|
||||||
|
.window_setup(conf::WindowSetup::default().title("Rust Sokoban!"))
|
||||||
|
.window_mode(conf::WindowMode::default().dimensions(800.0, 600.0))
|
||||||
|
.add_resource_path(path::PathBuf::from("./resources"));
|
||||||
|
|
||||||
|
let (context, event_loop) = &mut context_builder.build()?;
|
||||||
|
|
||||||
|
// Create the game state
|
||||||
|
let game = &mut Game { world };
|
||||||
|
|
||||||
|
// Run the main event loop
|
||||||
|
event::run(context, event_loop, game)
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user