terrr 0.1.0

a linux horror game
use crossterm::event::{Event, KeyCode, KeyEvent};
use ratatui::style::{Color, Style};
use std::time::{Duration, Instant};
use rand::Rng;

/// Represents a menu item in the game
pub struct MenuItem {
    pub label: String,
    pub action: MenuAction,
    pub highlighted: bool,
    pub glitch_intensity: f32,
    last_glitch: Instant,
}

impl MenuItem {
    pub fn new(label: &str, action: MenuAction) -> Self {
        Self {
            label: label.to_string(),
            action,
            highlighted: false,
            glitch_intensity: 0.0,
            last_glitch: Instant::now(),
        }
    }
    
    pub fn update(&mut self) {
        // Randomly apply glitch effects to menu items
        if self.last_glitch.elapsed() > Duration::from_millis(500) {
            let mut rng = rand::thread_rng();
            if rng.gen::<f32>() < self.glitch_intensity {
                // Apply subtle glitch effect
                self.last_glitch = Instant::now();
            }
        }
    }
    
    pub fn select(&mut self) {
        self.highlighted = true;
        self.glitch_intensity = 0.1; // Increase glitch when selected
    }
    
    pub fn deselect(&mut self) {
        self.highlighted = false;
        self.glitch_intensity = 0.0;
    }
    
    pub fn get_style(&self) -> Style {
        if self.highlighted {
            Style::default().fg(Color::Red)
        } else {
            Style::default().fg(Color::White)
        }
    }
}

/// Represents actions that can be performed from the menu
#[derive(Clone)]
pub enum MenuAction {
    StartGame,
    ShowRules,
    ShowAbout,
    Quit,
}

/// Main menu of the game
pub struct MainMenu {
    pub items: Vec<MenuItem>,
    pub selected: usize,
    pub last_update: Instant,
}

impl MainMenu {
    pub fn new() -> Self {
        let mut menu = Self {
            items: vec![
                MenuItem::new("PLAY", MenuAction::StartGame),
                MenuItem::new("RULES", MenuAction::ShowRules),
                MenuItem::new("ABOUT", MenuAction::ShowAbout),
                MenuItem::new("QUIT", MenuAction::Quit),
            ],
            selected: 0,
            last_update: Instant::now(),
        };
        
        // Set the first item as selected by default
        menu.items[0].select();
        
        menu
    }
    
    pub fn update(&mut self) {
        // Update all menu items
        for item in &mut self.items {
            item.update();
        }
    }
    
    pub fn handle_input(&mut self, event: Event) -> Option<MenuAction> {
        match event {
            Event::Key(KeyEvent { code, .. }) => match code {
                KeyCode::Up => self.select_prev(),
                KeyCode::Down => self.select_next(),
                KeyCode::Enter => return Some(self.items[self.selected].action.clone()),
                _ => {}
            },
            _ => {}
        }
        None
    }
    
    fn select_next(&mut self) {
        self.items[self.selected].deselect();
        self.selected = (self.selected + 1) % self.items.len();
        self.items[self.selected].select();
    }
    
    fn select_prev(&mut self) {
        self.items[self.selected].deselect();
        self.selected = if self.selected == 0 {
            self.items.len() - 1
        } else {
            self.selected - 1
        };
        self.items[self.selected].select();
    }
}