From 7867100ea1bc26950b3d0b1c035baf37e7856cac Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Franti=C5=A1ek=20Boh=C3=A1=C4=8Dek?=
 <fandabohacek@gmail.com>
Date: Tue, 20 Dec 2022 19:53:46 +0100
Subject: [PATCH] feat: add guess and number increment animations

---
 src/animation.rs  | 94 ++++++++++++++++++++++++++++++++++++++++++++---
 src/entrypoint.rs | 36 ++++++++++++++++--
 2 files changed, 121 insertions(+), 9 deletions(-)

diff --git a/src/animation.rs b/src/animation.rs
index 7d2db4e..026e743 100644
--- a/src/animation.rs
+++ b/src/animation.rs
@@ -1,6 +1,16 @@
 use super::filled_seven_segment;
 use super::led_matrix;
 
+const WIN_ANIMATION_MAX_LED_OUTER_STEP: u8 = 5; // max led_step
+const WIN_ANIMATION_MAX_LED_STEP: u8 = 4; // add led_step
+const WIN_ANIMATION_MAX_LED_INNER_STEP: u16 = 2500; // 10000; // add led_quarter
+
+const HELO_ANIMATION_MAX_INNER_STEP: u16 = 5000; // 20000;
+const HELO_ANIMATION_MAX_OUTER_STEP: u16 = 5;
+
+const GUESS_ANIMATION_MAX_STEP: u16 = 3000;
+const DIGIT_INCREMENT_ANIMATION_MAX_STEP: u16 = 1000;
+
 #[derive(PartialEq, Eq)]
 pub enum AnimationState {
     Running,
@@ -27,12 +37,86 @@ pub struct WinAnimation {
     pub hidden: bool
 }
 
-const WIN_ANIMATION_MAX_LED_OUTER_STEP: u8 = 5; // max led_step
-const WIN_ANIMATION_MAX_LED_STEP: u8 = 4; // add led_step
-const WIN_ANIMATION_MAX_LED_INNER_STEP: u16 = 2500; // 10000; // add led_quarter
+pub struct GuessAnimation {
+    pub step: u16
+}
 
-const HELO_ANIMATION_MAX_INNER_STEP: u16 = 5000; // 20000;
-const HELO_ANIMATION_MAX_OUTER_STEP: u16 = 5;
+pub struct DigitIncrementAnimation {
+    pub digit_index: usize,
+    pub step: u16
+}
+
+impl DigitIncrementAnimation {
+    pub fn create(digit_index: usize) -> DigitIncrementAnimation {
+        DigitIncrementAnimation {
+            step: 0,
+            digit_index
+        }
+    }
+
+    pub fn reset(&mut self, digit_index: usize) {
+        self.digit_index = digit_index;
+        self.step = 0;
+    }
+}
+
+impl Animation for DigitIncrementAnimation {
+    fn step(&mut self, seven_segment: &mut filled_seven_segment::FilledSevenSegment, _: &mut led_matrix::LEDMatrix) -> AnimationState {
+        if !self.running() {
+            return AnimationState::End;
+        }
+
+        if self.step == 0 {
+            seven_segment.hide_digit(self.digit_index);
+        }
+        self.step += 1;
+
+        AnimationState::Running
+    }
+
+    fn cleanup(&mut self, seven_segment: &mut filled_seven_segment::FilledSevenSegment, _: &mut led_matrix::LEDMatrix) {
+        seven_segment.show_digit(self.digit_index);
+    }
+
+    fn running(&self) -> bool {
+        self.step < DIGIT_INCREMENT_ANIMATION_MAX_STEP
+    }
+}
+
+impl GuessAnimation {
+    pub fn create() -> GuessAnimation {
+        GuessAnimation {
+            step: 0
+        }
+    }
+
+    pub fn reset(&mut self) {
+        self.step = 0;
+    }
+}
+
+impl Animation for GuessAnimation {
+    fn step(&mut self, seven_segment: &mut filled_seven_segment::FilledSevenSegment, _: &mut led_matrix::LEDMatrix) -> AnimationState {
+        if !self.running() {
+            return AnimationState::End;
+        }
+
+        if self.step == 0 {
+            seven_segment.hide_all_digits();
+        }
+        self.step += 1;
+
+        AnimationState::Running
+    }
+
+    fn cleanup(&mut self, seven_segment: &mut filled_seven_segment::FilledSevenSegment, _: &mut led_matrix::LEDMatrix) {
+        seven_segment.show_all_digits();
+    }
+
+    fn running(&self) -> bool {
+        self.step < GUESS_ANIMATION_MAX_STEP
+    }
+}
 
 impl WinAnimation {
     pub fn create(number: u16) -> WinAnimation {
diff --git a/src/entrypoint.rs b/src/entrypoint.rs
index 70620ba..5d05633 100644
--- a/src/entrypoint.rs
+++ b/src/entrypoint.rs
@@ -29,6 +29,15 @@ static mut WIN_ANIMATION: animation::WinAnimation = animation::WinAnimation {
     hidden: true,
 };
 
+static mut GUESS_ANIMATION: animation::GuessAnimation = animation::GuessAnimation {
+    step: 0,
+};
+
+static mut DIGIT_INC_ANIMATION: animation::DigitIncrementAnimation = animation::DigitIncrementAnimation {
+    step: 0,
+    digit_index: 0,
+};
+
 #[atmega_hal::entry]
 fn main() -> ! {
     // PERIPHERALS
@@ -88,7 +97,9 @@ fn main() -> ! {
     unsafe {
         HELLO_ANIMATION = animation::HelloAnimation::create();
         WIN_ANIMATION = animation::WinAnimation::create(0);
-        game.animation = Some(&mut HELLO_ANIMATION);
+        GUESS_ANIMATION = animation::GuessAnimation::create();
+        DIGIT_INC_ANIMATION = animation::DigitIncrementAnimation::create(0);
+        game.set_animation(&mut HELLO_ANIMATION);
     }
 
     let mut step: u64 = 0;
@@ -159,6 +170,10 @@ impl Game {
                     }
 
                     self.update_led_matrix();
+                    unsafe {
+                        self.set_animation(&mut GUESS_ANIMATION);
+                        GUESS_ANIMATION.reset();
+                    }
                 }
 
                 let mut btns_pressed: [bool; DIGITS] = [false; DIGITS];
@@ -169,13 +184,26 @@ impl Game {
 
                 for (i, pressed) in btns_pressed.iter().enumerate() {
                     if *pressed {
-                        self.increase_digit(DIGITS - 1 - i);
+                        let digit_index = DIGITS - 1 - i;
+                        self.increase_digit(digit_index);
+                        unsafe {
+                            self.set_animation(&mut DIGIT_INC_ANIMATION);
+                            DIGIT_INC_ANIMATION.reset(digit_index);
+                        }
                     }
                 }
             }
         }
     }
 
+    pub fn set_animation(&mut self, animation: &'static mut dyn animation::Animation) {
+        if let Some(current_animation) = &mut self.animation {
+            current_animation.cleanup(&mut self.seven_segment, &mut self.led_matrix);
+        }
+
+        self.animation = Some(animation);
+    }
+
     fn get_digit(number: u16, digit_index: usize) -> u8 {
         let mut digit = number;
         for _ in 0..digit_index {
@@ -205,7 +233,7 @@ impl Game {
 
             for j in 0..DIGITS {
                 if i != j &&
-                    current_digits[j] != guessing_digits[i] &&
+                    current_digits[j] != guessing_digits[j] &&
                     current_digits[i] == guessing_digits[j]
                 {
                     self.led_matrix.set(
@@ -238,8 +266,8 @@ impl Game {
 
     fn end_current_game(&mut self) {
         unsafe {
+            self.set_animation(&mut WIN_ANIMATION);
             WIN_ANIMATION.reset(self.guessing_number.unwrap());
-            self.animation = Some(&mut WIN_ANIMATION);
         }
         self.cleanup_current_game();
         self.state = GameState::Won;
-- 
2.48.1