Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Gamepad Support

Nightshade provides cross-platform gamepad support through the gilrs library.

Enabling Gamepad

Gamepad requires the gamepad feature:

[dependencies]
nightshade = { git = "...", features = ["engine", "gamepad"] }

Gamepad Resource

The gamepad state lives in world.resources.input.gamepad, which wraps the gilrs library:

#![allow(unused)]
fn main() {
pub struct Gamepad {
    pub gilrs: Option<gilrs::Gilrs>,
    pub gamepad: Option<gilrs::GamepadId>,
    pub events: Vec<gilrs::Event>,
}
}

The engine automatically initializes gilrs and tracks the active gamepad.

Querying the Active Gamepad

Use query_active_gamepad to get a gilrs gamepad handle for polling input:

#![allow(unused)]
fn main() {
use nightshade::ecs::input::queries::query_active_gamepad;

fn run_systems(&mut self, world: &mut World) {
    if let Some(gamepad) = query_active_gamepad(world) {
        let left_x = gamepad.value(gilrs::Axis::LeftStickX);
        let left_y = gamepad.value(gilrs::Axis::LeftStickY);

        if gamepad.is_pressed(gilrs::Button::South) {
            self.jump();
        }
    }
}
}

Button Input

Button States

#![allow(unused)]
fn main() {
use nightshade::ecs::input::queries::query_active_gamepad;

fn run_systems(&mut self, world: &mut World) {
    if let Some(gamepad) = query_active_gamepad(world) {
        if gamepad.is_pressed(gilrs::Button::South) {
            jump();
        }

        if gamepad.is_pressed(gilrs::Button::West) {
            attack();
        }
    }
}
}

Button Mapping

gilrs::ButtonXboxPlayStationNintendo
SouthACrossB
EastBCircleA
WestXSquareY
NorthYTriangleX
LeftTriggerLBL1L
RightTriggerRBR1R
SelectViewShare-
StartMenuOptions+
DPadUp/Down/Left/RightD-PadD-PadD-Pad

Analog Sticks

#![allow(unused)]
fn main() {
if let Some(gamepad) = query_active_gamepad(world) {
    let move_x = gamepad.value(gilrs::Axis::LeftStickX);
    let move_y = gamepad.value(gilrs::Axis::LeftStickY);

    let look_x = gamepad.value(gilrs::Axis::RightStickX);
    let look_y = gamepad.value(gilrs::Axis::RightStickY);
}
}

Axis values range from -1.0 to 1.0.

Triggers

#![allow(unused)]
fn main() {
if let Some(gamepad) = query_active_gamepad(world) {
    let left = gamepad.value(gilrs::Axis::LeftZ);
    let right = gamepad.value(gilrs::Axis::RightZ);

    let acceleration = right * max_acceleration;
}
}

Event-Based Input

Handle gamepad events in the State trait using raw gilrs events:

#![allow(unused)]
fn main() {
fn on_gamepad_event(&mut self, world: &mut World, event: gilrs::Event) {
    if let gilrs::EventType::ButtonPressed(button, _) = event.event {
        match button {
            gilrs::Button::Start => self.paused = !self.paused,
            gilrs::Button::South => self.player_jump(),
            _ => {}
        }
    }
}
}

Combining Keyboard and Gamepad

#![allow(unused)]
fn main() {
use nightshade::ecs::input::queries::query_active_gamepad;

struct PlayerInput {
    movement: Vec2,
    jump: bool,
    attack: bool,
}

fn gather_input(world: &mut World) -> PlayerInput {
    let mut input = PlayerInput {
        movement: Vec2::zeros(),
        jump: false,
        attack: false,
    };

    let keyboard = &world.resources.input.keyboard;
    if keyboard.is_key_pressed(KeyCode::KeyW) { input.movement.y -= 1.0; }
    if keyboard.is_key_pressed(KeyCode::KeyS) { input.movement.y += 1.0; }
    if keyboard.is_key_pressed(KeyCode::KeyA) { input.movement.x -= 1.0; }
    if keyboard.is_key_pressed(KeyCode::KeyD) { input.movement.x += 1.0; }
    input.jump |= keyboard.is_key_pressed(KeyCode::Space);

    if let Some(gamepad) = query_active_gamepad(world) {
        let stick_x = gamepad.value(gilrs::Axis::LeftStickX);
        let stick_y = gamepad.value(gilrs::Axis::LeftStickY);

        if stick_x.abs() > 0.15 || stick_y.abs() > 0.15 {
            input.movement = Vec2::new(stick_x, stick_y);
        }

        input.jump |= gamepad.is_pressed(gilrs::Button::South);
        input.attack |= gamepad.is_pressed(gilrs::Button::West);
    }

    input
}
}