0.1.0-0-pre.10
This commit is contained in:
@@ -1,17 +1,18 @@
|
||||
// file: crates/games/game-reflex-poc/src/state.rs
|
||||
// version: 3
|
||||
// version: 4
|
||||
|
||||
/// Minimal deterministic state used to validate the first game boundary.
|
||||
#[derive(Clone, Copy, Debug, Default, Eq, PartialEq)]
|
||||
/// Deterministic playable state for the Reflex POC.
|
||||
#[derive(Clone, Copy, Debug, PartialEq)]
|
||||
pub struct ReflexState {
|
||||
score: u64,
|
||||
target: engine_v1_common::NormalizedRect,
|
||||
}
|
||||
|
||||
impl ReflexState {
|
||||
/// Creates a fresh Reflex state.
|
||||
#[must_use]
|
||||
pub const fn new() -> Self {
|
||||
return Self { score: 0 };
|
||||
pub fn new() -> Self {
|
||||
return Self { score: 0, target: target_for_index(0) };
|
||||
}
|
||||
|
||||
/// Returns the current score.
|
||||
@@ -20,19 +21,58 @@ impl ReflexState {
|
||||
return self.score;
|
||||
}
|
||||
|
||||
/// Registers one successful reflex action.
|
||||
pub const fn register_success(&mut self) {
|
||||
/// Returns the current normalized target rectangle.
|
||||
#[must_use]
|
||||
pub const fn target(self) -> engine_v1_common::NormalizedRect {
|
||||
return self.target;
|
||||
}
|
||||
|
||||
/// Registers one successful reflex action and relocates the target.
|
||||
pub fn register_success(&mut self) {
|
||||
self.score = self.score.saturating_add(1);
|
||||
self.target = target_for_index(self.score);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for ReflexState {
|
||||
fn default() -> Self {
|
||||
return Self::new();
|
||||
}
|
||||
}
|
||||
|
||||
impl engine_v1_common::EngineGame for ReflexState {
|
||||
fn update(&mut self, _frame: engine_v1_common::EngineFrame, input: engine_v1_common::InputState) {
|
||||
if input.is_active(engine_v1_common::GameAction::Primary) {
|
||||
if !input.is_active(engine_v1_common::GameAction::Primary) {
|
||||
return;
|
||||
}
|
||||
let pointer = input.pointer();
|
||||
if !pointer.active() {
|
||||
return;
|
||||
}
|
||||
if self.target.contains(pointer.x(), pointer.y()) {
|
||||
self.register_success();
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
fn scene(&self) -> engine_v1_common::EngineScene {
|
||||
let target = engine_v1_common::RenderRect::new(self.target, engine_v1_common::RenderColor::rgb(255, 196, 64));
|
||||
return engine_v1_common::EngineScene::empty(engine_v1_common::RenderColor::rgb(18, 18, 24)).with_rect(target);
|
||||
}
|
||||
}
|
||||
|
||||
fn target_for_index(index: u64) -> engine_v1_common::NormalizedRect {
|
||||
return match index % 8 {
|
||||
0 => engine_v1_common::NormalizedRect::new(0.12, 0.12, 0.24, 0.14),
|
||||
1 => engine_v1_common::NormalizedRect::new(0.62, 0.16, 0.24, 0.14),
|
||||
2 => engine_v1_common::NormalizedRect::new(0.34, 0.34, 0.24, 0.14),
|
||||
3 => engine_v1_common::NormalizedRect::new(0.08, 0.52, 0.24, 0.14),
|
||||
4 => engine_v1_common::NormalizedRect::new(0.66, 0.54, 0.24, 0.14),
|
||||
5 => engine_v1_common::NormalizedRect::new(0.38, 0.72, 0.24, 0.14),
|
||||
6 => engine_v1_common::NormalizedRect::new(0.14, 0.78, 0.24, 0.14),
|
||||
_ => engine_v1_common::NormalizedRect::new(0.62, 0.76, 0.24, 0.14),
|
||||
};
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
|
||||
@@ -1,20 +1,24 @@
|
||||
// file: crates/games/game-reflex-poc/unit_tests/state.rs
|
||||
// version: 1
|
||||
// version: 2
|
||||
|
||||
#[test]
|
||||
fn success_increments_score() {
|
||||
game_logging_lib::with_test_tracing("success_increments_score", || {
|
||||
fn success_increments_score_and_moves_target() {
|
||||
game_logging_lib::with_test_tracing("success_increments_score_and_moves_target", || {
|
||||
let mut state = crate::ReflexState::new();
|
||||
let initial_target = state.target();
|
||||
state.register_success();
|
||||
assert_eq!(state.score(), 1);
|
||||
assert_ne!(state.target(), initial_target);
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn engine_update_maps_primary_action_to_success() {
|
||||
game_logging_lib::with_test_tracing("engine_update_maps_primary_action_to_success", || {
|
||||
fn primary_pointer_inside_target_scores_once() {
|
||||
game_logging_lib::with_test_tracing("primary_pointer_inside_target_scores_once", || {
|
||||
let mut state = crate::ReflexState::new();
|
||||
let input = engine_v1_common::InputState::none().with_action(engine_v1_common::GameAction::Primary, true);
|
||||
let target = state.target();
|
||||
let pointer = engine_v1_common::PointerState::normalized(true, target.x() + target.width() / 2.0, target.y() + target.height() / 2.0);
|
||||
let input = engine_v1_common::InputState::none().with_pointer(pointer).with_action(engine_v1_common::GameAction::Primary, true);
|
||||
engine_v1_common::EngineGame::update(
|
||||
&mut state,
|
||||
engine_v1_common::EngineFrame::new(0, std::time::Duration::from_millis(16), std::time::Duration::ZERO),
|
||||
@@ -23,3 +27,28 @@ fn engine_update_maps_primary_action_to_success() {
|
||||
assert_eq!(state.score(), 1);
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn primary_pointer_outside_target_does_not_score() {
|
||||
game_logging_lib::with_test_tracing("primary_pointer_outside_target_does_not_score", || {
|
||||
let mut state = crate::ReflexState::new();
|
||||
let pointer = engine_v1_common::PointerState::normalized(true, 0.95, 0.95);
|
||||
let input = engine_v1_common::InputState::none().with_pointer(pointer).with_action(engine_v1_common::GameAction::Primary, true);
|
||||
engine_v1_common::EngineGame::update(
|
||||
&mut state,
|
||||
engine_v1_common::EngineFrame::new(0, std::time::Duration::from_millis(16), std::time::Duration::ZERO),
|
||||
input,
|
||||
);
|
||||
assert_eq!(state.score(), 0);
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn scene_contains_current_target() {
|
||||
game_logging_lib::with_test_tracing("scene_contains_current_target", || {
|
||||
let state = crate::ReflexState::new();
|
||||
let scene = engine_v1_common::EngineGame::scene(&state);
|
||||
let first = scene.rectangles()[0];
|
||||
assert_eq!(first, Some(engine_v1_common::RenderRect::new(state.target(), engine_v1_common::RenderColor::rgb(255, 196, 64))));
|
||||
});
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user