pico_engine_core/
lib.rs

1#![no_std]
2// ============================================================================
3// ENGINE MODULE
4// ============================================================================
5// Provides the game loop architecture and timing control.
6// This module ensures consistent frame timing and game state management.
7
8#![allow(unused)]
9
10pub mod _game;
11pub use pico_engine_hardware::{Hardware, Display, Timer, Input, InputState};
12pub use _game::Game;
13
14/// Game engine that runs the game loop
15pub struct Engine<H: Hardware> {
16    hardware: H,
17}
18
19impl<H: Hardware> Engine<H> {
20    /// Create a new game engine
21    pub fn new(hardware: H) -> Self {
22        Engine { hardware }
23    }
24
25    /// Run the game loop with the provided game implementation
26    pub fn run<G: Game>(&mut self, game: &mut G) -> ! {
27        // Initialize the game
28        game.init(self.hardware.display().get_screen_width() as u16, self.hardware.display().get_screen_height() as u16);
29
30        const FRAME_TIME_MS: u32 = 33; // ~30 FPS
31
32        // Main game loop
33        let mut delta_time = FRAME_TIME_MS;
34        let mut fps = 60u32;
35        
36        loop {
37            // Record frame start time
38            let frame_start = self.hardware.timer().get_counter();
39
40            // Update game state
41            self.hardware.input().update();
42            let should_continue = game.update(self.hardware.input().current_state(), delta_time);
43            if !should_continue {
44                // Game requested exit - in embedded systems we just halt
45                // In a real console, you might return to a menu or reset
46                panic!("Game exited");
47            }
48
49            // Render the frame
50            game.render(self.hardware.display(), delta_time);
51
52            /// Wait for next frame
53            let current_time = self.hardware.timer().get_counter();
54            let elapsed = (current_time - frame_start) / 1000; // Convert micros to millis
55            if elapsed < FRAME_TIME_MS as u64 {
56                self.hardware
57                    .timer()
58                    .delay_ms((FRAME_TIME_MS as u64 - elapsed) as u32);
59            }
60            let end_time = self.hardware.timer().get_counter();
61            delta_time = ((end_time - frame_start) / 1000) as u32;
62
63            
64            // Note: If frame takes longer than 17ms, we skip delay and continue
65            // This prevents timing drift while maintaining responsiveness
66        }
67    }
68}