Module dotrix::systems[][src]

Systems implement logic of your game. A system take a set of crate::services as parameters and implements a feature. For example, here is a system that moves camera by X axis if Right mouse button is pressed:

use dotrix_core::{
    Dotrix,
    input::{ ActionMapper, Button, State as InputState, Mapper }, 
    ecs::{ Const, Mut, System },
    services::{ Camera, Frame, Input }, 
};

// camera moving system
pub fn camera_move_x(mut camera: Mut<Camera>, input: Const<Input>, frame: Const<Frame>) {
    let time_delta = frame.delta().as_secs_f32();

    if input.button_state(Button::MouseRight) == Some(InputState::Hold) {
        camera.target.x += 1.0 * time_delta;
    }
}

fn main() {
    Dotrix::application("My Game")
        // add system to yout application
        .with_system(System::from(camera_move_x))
        // services should also be there
        .with_service(Camera::default())
        .with_service(Frame::default())
        .with_service(Input::new(Box::new(Mapper::<Action>::new())))
        .run();
}

// Mapping is required for the Input service
#[derive(PartialEq, Eq, Clone, Copy, Hash)]
enum Action {}

impl ActionMapper<Action> for Input {
    fn action_mapped(&self, action: Action) -> Option<&Button> {
        let mapper = self.mapper::<Mapper<Action>>();
        mapper.get_button(action)
    }
}

crate::ecs::Mut and crate::ecs::Const are just the accessors for services to keep Rust mutability controls. The set of services that system takes as arguments is up to developer. It can be effortlessly extended at any time. The order of crate::services in arguments list does not matter.

What is also important to mention here, is that all services used in systems must be added to your game using the application builder.

Systems with context

Sometimes it is usefull to preserve some data between system executions. It can be done using a crate::Service, but it has sense only when the data has to be shared between different systems. Otherwise it is better to use the crate::ecs::Context.

System can have only one context and if it does, the context must be always passed as a first argument. Another requirement is that crate::ecs::Context structure must implement the Default trait.

Example

use dotrix_core::{
    ecs::Context,
};

#[derive(Default)]
struct Counter {
    value: usize,
}

fn count_up(mut counter: Context<Counter>) {
    counter.value += 1;
    println!("The `counter_up` system has been called {} times", counter.value);
}

System run levels

Developer can affect the execution of systems by assigning them specific run levels. If crate::ecs::RunLevel is not set explicitly, the RunLevel::Standard will be used.

use dotrix_core::{
    Dotrix,
    services::Assets,
    ecs::{ Mut, System, RunLevel },
};

fn init_game(mut assets: Mut<Assets>) {
    println!("Starting my super game");
    assets.import("/path/to/my/asset.png");
}

fn main() {
    Dotrix::application("My Game")
        .with_system(System::from(init_game).with(RunLevel::Startup))
        .with_service(Assets::new())
        .run();
}

Functions

camera_control

System controlling camera with mouse

overlay_update

System feeding overlays with inputs

skeletal_animation

System handling skeletal animation

world_renderer

System to render models, skyboxes, wire frames and overlays