Skip to content

Instantly share code, notes, and snippets.

@ElectricCoffee
Last active May 15, 2019 11:05
Show Gist options
  • Save ElectricCoffee/aad0ed88a0162e35bf28d7c4303b8ea1 to your computer and use it in GitHub Desktop.
Save ElectricCoffee/aad0ed88a0162e35bf28d7c4303b8ea1 to your computer and use it in GitHub Desktop.
use specs::prelude::*;
use specs_derive::*;
#[derive(Component)]
#[storage(VecStorage)]
struct Position {
x: i32,
y: i32,
}
struct Color(u8, u8, u8);
#[derive(Component)]
#[storage(VecStorage)]
struct Drawable {
char: char,
background_color: Color,
foreground_color: Color,
}
#[derive(Component)]
#[storage(VecStorage)]
struct Health {
max_health: i32,
current_health: i32,
}
#[derive(Component)]
#[storage(VecStorage)]
struct Name {
name: String,
}
struct Draw;
impl<'a> System<'a> for Draw {
type SystemData = (ReadStorage<'a, Position>, ReadStorage<'a, Drawable>, ReadStorage<'a, Health>);
fn run(&mut self, (pos, drawable, health): Self::SystemData) {
use specs::Join;
for (pos, drawable, health) in (&pos, &drawable, &health).join() {
println!("{} at ({}, {}) {}/{}", drawable.char, pos.x, pos.y, health.current_health, health.max_health);
}
}
}
struct UpdatePos;
impl<'a> System<'a> for UpdatePos {
type SystemData = WriteStorage<'a, Position>;
fn run(&mut self, mut pos: Self::SystemData) {
use specs::Join;
for pos in (&mut pos).join() {
pos.x += 1;
pos.y += 1;
}
}
}
struct UpdateHealth;
impl<'a> System<'a> for UpdateHealth {
type SystemData = WriteStorage<'a, Health>;
fn run(&mut self, mut health: Self::SystemData) {
use specs::Join;
for health in (&mut health).join() {
health.current_health -= 1;
}
}
}
struct Hello;
impl<'a> System<'a> for Hello {
type SystemData = (Write<'a, States>, Write<'a, i32>);
fn run(&mut self, (mut state, mut number): Self::SystemData) {
println!("Hello from {:?} the integer is currently {}", *state, *number);
*number += 2;
if *state == States::Main {
*state = States::Game;
} else {
*state = States::Main;
}
}
}
fn create_player(world: &mut World, char: char, pos: Position) {
world.create_entity()
.with(pos)
.with(Health { max_health: 100, current_health: 100 })
.with(Drawable { char, foreground_color: Color(0xff, 0xff, 0xff), background_color: Color(0, 0, 0)})
.build();
}
#[derive(Debug, PartialEq, Clone, Copy)]
enum States {
Main,
Game,
}
impl Default for States {
fn default() -> States {
States::Main
}
}
fn main() {
let mut world = World::new();
let mut game_dispatcher = DispatcherBuilder::new()
.with(Hello, "hello", &[])
.with(UpdatePos, "update_pos", &[])
.with(UpdateHealth, "update_health", &[])
.with_thread_local(Draw)
.build();
game_dispatcher.setup(&mut world.res); // ...and comment out this line to make it work
let mut main_dispatcher = DispatcherBuilder::new()
.with(Hello, "hello", &[])
.build();
main_dispatcher.setup(&mut world.res);
create_player(&mut world, '@', Position { x: 0, y: 0 });
create_player(&mut world, 'T', Position { x: 0, y: 5 });
for _ in 0 .. 10 {
let state = *world.read_resource::<States>();
match state {
States::Main => main_dispatcher.dispatch(&world.res),
States::Game => game_dispatcher.dispatch(&world.res),
}
world.maintain();
}
}
@ElectricCoffee
Copy link
Author

The output from running the program should be

Hello from Main the integer is currently 0
Hello from Game the integer is currently 2
@ at (1, 1) 99/100
T at (1, 6) 99/100
Hello from Main the integer is currently 4
Hello from Game the integer is currently 6
@ at (2, 2) 98/100
T at (2, 7) 98/100
Hello from Main the integer is currently 8
Hello from Game the integer is currently 10
@ at (3, 3) 97/100
T at (3, 8) 97/100
Hello from Main the integer is currently 12
Hello from Game the integer is currently 14
@ at (4, 4) 96/100
T at (4, 9) 96/100
Hello from Main the integer is currently 16
Hello from Game the integer is currently 18
@ at (5, 5) 95/100
T at (5, 10) 95/100

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment