euv-engine 0.28.21

A high-performance 2D game engine built on the euv framework, featuring ECS, fixed-timestep game loop, canvas rendering, physics, collision detection, sprite animation, and audio.
Documentation
use super::*;

fn state() -> InputState {
    InputState::default()
}

#[test]
fn a_fresh_input_state_reports_nothing() {
    let input: InputState = state();
    assert!(
        !input.is_key_pressed("KeyA"),
        "nothing is pressed on the first frame"
    );
    assert!(!input.is_key_held("KeyA"), "nothing is held either");
    assert!(!input.is_key_released("KeyA"), "and nothing was released");
}

#[test]
fn a_fresh_input_state_has_no_mouse_buttons() {
    let input: InputState = state();
    assert!(
        !input.is_mouse_button_pressed(MouseButton::Left),
        "no button starts pressed"
    );
    assert!(
        !input.is_mouse_button_held(MouseButton::Left),
        "and none starts held"
    );
}

#[test]
fn a_newly_pressed_key_is_both_pressed_and_held() {
    let mut input: InputState = state();
    input.press_key(String::from("KeyA"));
    assert!(
        input.is_key_pressed("KeyA"),
        "the first frame is the press edge"
    );
    assert!(input.is_key_held("KeyA"), "and the key is down");
    assert!(!input.is_key_released("KeyA"), "a press is not a release");
}

#[test]
fn a_key_pressed_again_while_held_keeps_the_same_single_edge() {
    let mut input: InputState = state();
    input.press_key(String::from("KeyA"));
    input.press_key(String::from("KeyA"));
    assert!(
        input.is_key_pressed("KeyA"),
        "the edge from the first press is still in force for this frame"
    );
    assert!(input.is_key_held("KeyA"), "and the key is down");
    input.end_frame();
    assert!(
        !input.is_key_pressed("KeyA"),
        "the second press must not have queued a second edge for the next frame"
    );
}

#[test]
fn releasing_a_key_reports_the_release_edge_and_clears_held() {
    let mut input: InputState = state();
    input.press_key(String::from("KeyA"));
    input.release_key(String::from("KeyA"));
    assert!(
        input.is_key_released("KeyA"),
        "the release is an edge of its own"
    );
    assert!(!input.is_key_held("KeyA"), "and the key is no longer down");
}

#[test]
fn a_released_key_reports_both_edges_in_the_same_frame() {
    let mut input: InputState = state();
    input.press_key(String::from("KeyA"));
    input.release_key(String::from("KeyA"));
    assert!(
        input.is_key_pressed("KeyA") && input.is_key_released("KeyA"),
        "a key tapped and let go inside one frame shows both edges"
    );
}

#[test]
fn releasing_a_key_that_was_never_held_still_reports_a_release() {
    let mut input: InputState = state();
    input.release_key(String::from("KeyZ"));
    assert!(
        input.is_key_released("KeyZ"),
        "a release is reported even without a press"
    );
    assert!(!input.is_key_held("KeyZ"), "but the key is not held");
}

#[test]
fn keys_are_tracked_independently() {
    let mut input: InputState = state();
    input.press_key(String::from("KeyA"));
    input.press_key(String::from("KeyB"));
    input.release_key(String::from("KeyA"));
    assert!(!input.is_key_held("KeyA"), "the released key comes up");
    assert!(input.is_key_held("KeyB"), "while the other stays down");
    assert!(
        input.is_key_released("KeyA"),
        "and only the released one is an edge"
    );
    assert!(!input.is_key_released("KeyB"), "the held one is not");
}

#[test]
fn end_frame_clears_the_key_edges_but_keeps_what_is_held() {
    let mut input: InputState = state();
    input.press_key(String::from("KeyA"));
    input.press_key(String::from("KeyB"));
    input.release_key(String::from("KeyB"));
    input.end_frame();
    assert!(
        !input.is_key_pressed("KeyA"),
        "press edges do not survive a frame"
    );
    assert!(
        !input.is_key_released("KeyB"),
        "release edges do not either"
    );
    assert!(
        input.is_key_held("KeyA"),
        "but a key still physically down must stay held"
    );
    assert!(
        !input.is_key_held("KeyB"),
        "while a released one does not come back"
    );
}

#[test]
fn a_press_after_a_release_and_a_frame_boundary_is_a_fresh_edge() {
    let mut input: InputState = state();
    input.press_key(String::from("KeyA"));
    input.end_frame();
    input.release_key(String::from("KeyA"));
    input.end_frame();
    input.press_key(String::from("KeyA"));
    assert!(
        input.is_key_pressed("KeyA"),
        "once the key is genuinely up, pressing it again is a real press"
    );
}

#[test]
fn a_key_still_down_across_frames_never_re_arms_its_edge() {
    let mut input: InputState = state();
    input.press_key(String::from("KeyA"));
    for _ in 0..5 {
        input.end_frame();
        input.press_key(String::from("KeyA"));
    }
    assert!(
        !input.is_key_pressed("KeyA"),
        "a key held down for many frames must not fire an edge every frame"
    );
}

#[test]
fn a_pressed_mouse_button_is_both_pressed_and_held() {
    let mut input: InputState = state();
    input.press_mouse_button(MouseButton::Left, Vector2D::new(10.0, 20.0));
    assert!(
        input.is_mouse_button_pressed(MouseButton::Left),
        "the first frame is the press edge"
    );
    assert!(
        input.is_mouse_button_held(MouseButton::Left),
        "and the button is down"
    );
}

#[test]
fn a_mouse_button_pressed_again_while_held_keeps_the_same_single_edge() {
    let mut input: InputState = state();
    input.press_mouse_button(MouseButton::Left, Vector2D::zero());
    input.press_mouse_button(MouseButton::Left, Vector2D::zero());
    assert!(
        input.is_mouse_button_pressed(MouseButton::Left),
        "the edge from the first press still stands for this frame"
    );
    assert!(
        input.is_mouse_button_held(MouseButton::Left),
        "and the button is down"
    );
    input.end_frame();
    assert!(
        !input.is_mouse_button_pressed(MouseButton::Left),
        "a repeat must not queue a second edge"
    );
}

#[test]
fn releasing_a_mouse_button_clears_held_but_the_press_edge_survives_the_frame() {
    let mut input: InputState = state();
    input.press_mouse_button(MouseButton::Left, Vector2D::zero());
    input.release_mouse_button(MouseButton::Left);
    assert!(
        !input.is_mouse_button_held(MouseButton::Left),
        "the button comes up at once"
    );
    assert!(
        input.is_mouse_button_pressed(MouseButton::Left),
        "the press edge is still in force for the rest of the frame"
    );
    input.end_frame();
    assert!(
        !input.is_mouse_button_pressed(MouseButton::Left),
        "and then it clears"
    );
}

#[test]
fn mouse_buttons_are_tracked_independently() {
    let mut input: InputState = state();
    input.press_mouse_button(MouseButton::Left, Vector2D::zero());
    input.press_mouse_button(MouseButton::Right, Vector2D::zero());
    input.release_mouse_button(MouseButton::Left);
    assert!(
        !input.is_mouse_button_held(MouseButton::Left),
        "the released one is up"
    );
    assert!(
        input.is_mouse_button_held(MouseButton::Right),
        "the other stays down"
    );
}

#[test]
fn a_press_records_where_the_mouse_was() {
    let mut input: InputState = state();
    input.press_mouse_button(MouseButton::Left, Vector2D::new(42.0, 24.0));
    let observed: Vector2D = input.get_mouse_position();
    assert_eq!(
        observed,
        Vector2D::new(42.0, 24.0),
        "the press position becomes the current mouse position"
    );
}

#[test]
fn moving_the_mouse_updates_the_position() {
    let mut input: InputState = state();
    input.update_mouse_position(Vector2D::new(5.0, 6.0));
    let observed: Vector2D = input.get_mouse_position();
    assert_eq!(
        observed,
        Vector2D::new(5.0, 6.0),
        "the new position is recorded"
    );
}

#[test]
fn end_frame_resets_the_mouse_delta() {
    let mut input: InputState = state();
    input.update_mouse_position(Vector2D::new(10.0, 10.0));
    input.update_mouse_position(Vector2D::new(20.0, 10.0));
    input.end_frame();
    let observed: Vector2D = input.get_mouse_delta();
    assert_eq!(
        observed,
        Vector2D::zero(),
        "the delta is a per-frame quantity"
    );
}

#[test]
fn end_frame_clears_the_mouse_button_edges() {
    let mut input: InputState = state();
    input.press_mouse_button(MouseButton::Left, Vector2D::zero());
    input.end_frame();
    assert!(
        !input.is_mouse_button_pressed(MouseButton::Left),
        "a button edge does not survive the frame it happened in"
    );
    assert!(
        input.is_mouse_button_held(MouseButton::Left),
        "while a still-down button remains held"
    );
}

#[test]
fn there_is_no_primary_touch_before_any_touch_starts() {
    let input: InputState = state();
    assert_eq!(
        input.primary_touch_position(),
        None,
        "a finger has to land before there is a position to report"
    );
}

#[test]
fn a_started_touch_reports_its_position() {
    let mut input: InputState = state();
    input.start_touch(0, Vector2D::new(100.0, 200.0));
    let observed: Option<Vector2D> = input.primary_touch_position();
    assert_eq!(
        observed,
        Some(Vector2D::new(100.0, 200.0)),
        "the position comes back"
    );
}

#[test]
fn the_lowest_identifier_is_the_primary_touch() {
    let mut input: InputState = state();
    input.start_touch(2, Vector2D::new(0.0, 0.0));
    input.start_touch(0, Vector2D::new(7.0, 8.0));
    input.start_touch(1, Vector2D::new(3.0, 4.0));
    let observed: Option<Vector2D> = input.primary_touch_position();
    assert_eq!(
        observed,
        Some(Vector2D::new(7.0, 8.0)),
        "identifier order decides which finger is primary, not insertion order"
    );
}

#[test]
fn a_moved_touch_keeps_its_identity() {
    let mut input: InputState = state();
    input.start_touch(0, Vector2D::new(1.0, 1.0));
    input.update_touch(0, Vector2D::new(9.0, 9.0));
    let observed: Option<Vector2D> = input.primary_touch_position();
    assert_eq!(
        observed,
        Some(Vector2D::new(9.0, 9.0)),
        "a moving finger keeps its identifier, so it stays primary"
    );
}

#[test]
fn ending_the_primary_touch_promotes_the_next_one() {
    let mut input: InputState = state();
    input.start_touch(0, Vector2D::new(1.0, 1.0));
    input.start_touch(1, Vector2D::new(5.0, 5.0));
    input.end_touch(0);
    let observed: Option<Vector2D> = input.primary_touch_position();
    assert_eq!(
        observed,
        Some(Vector2D::new(5.0, 5.0)),
        "once the lowest identifier lifts, the next one is primary"
    );
}

#[test]
fn ending_every_touch_leaves_no_primary() {
    let mut input: InputState = state();
    input.start_touch(0, Vector2D::new(1.0, 1.0));
    input.end_touch(0);
    let observed: Option<Vector2D> = input.primary_touch_position();
    assert_eq!(observed, None, "no fingers means no primary touch");
}

#[test]
fn ending_a_touch_that_never_started_is_harmless() {
    let mut input: InputState = state();
    input.end_touch(9);
    let observed: Option<Vector2D> = input.primary_touch_position();
    assert_eq!(observed, None, "lifting an unknown finger changes nothing");
}

#[test]
fn end_frame_clears_the_touch_edges() {
    let mut input: InputState = state();
    input.start_touch(0, Vector2D::zero());
    input.end_frame();
    input.start_touch(0, Vector2D::zero());
    input.end_frame();
    let observed: Option<Vector2D> = input.primary_touch_position();
    assert_eq!(
        observed,
        Some(Vector2D::zero()),
        "a touch that is still down survives the frame boundary"
    );
}

#[test]
fn the_default_mouse_button_is_the_left_one() {
    let observed: MouseButton = MouseButton::default();
    assert_eq!(observed, MouseButton::Left, "button zero is the default");
}