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}