@@ -16,10 +16,12 @@ use spooky_core::systems::setup::TextureAssets;
16
16
/// Render the maze tile map, coins, and the player ghost into the off‑screen framebuffer,
17
17
/// then flush it to the physical display.
18
18
///
19
- /// Drawing order is:
19
+ /// The camera is simulated by calculating an offset so that the player (whose world
20
+ /// coordinates are in PlayerPosition) is always centered on the display.
21
+ /// The drawing order is:
20
22
/// 1. Maze tile map (background)
21
- /// 2. Coins (drawn so that they’re centered on the tile )
22
- /// 3. (Other elements, such as the player, might be drawn separately )
23
+ /// 2. Coins (drawn using the tile’s top‑left as anchor )
24
+ /// 3. The player ghost (drawn using the tile’s top‑left as anchor )
23
25
pub fn render_system (
24
26
mut display_res : NonSendMut < crate :: DisplayResource > ,
25
27
mut fb_res : ResMut < crate :: FrameBufferResource > ,
@@ -35,11 +37,16 @@ pub fn render_system(
35
37
let tile_w = maze. tile_width as i32 ;
36
38
let tile_h = maze. tile_height as i32 ;
37
39
40
+ // Compute the camera offset so that the player is centered.
41
+ // For example, if the display is 320x240 then the center is (160,120).
42
+ let display_center_x = ( crate :: LCD_H_RES as i32 ) / 2 ;
43
+ let display_center_y = ( crate :: LCD_V_RES as i32 ) / 2 ;
44
+ let offset_x = player_pos. x as i32 - display_center_x;
45
+ let offset_y = player_pos. y as i32 - display_center_y;
46
+
38
47
// --- Render the maze tile map (background) ---
39
48
for ty in 0 ..maze. height as i32 {
40
49
for tx in 0 ..maze. width as i32 {
41
- // Since our maze data is stored bottom‑up, we can use the current (tx, ty)
42
- // directly if valid_coordinates are computed that way.
43
50
let tile_index = ( ty * maze. width as i32 + tx) as usize ;
44
51
let bmp_opt = match maze. data [ tile_index] {
45
52
1 => texture_assets. wall . as_ref ( ) ,
@@ -49,10 +56,13 @@ pub fn render_system(
49
56
} ;
50
57
51
58
if let Some ( bmp) = bmp_opt {
52
- // Compute the top‑left pixel coordinate of this tile.
53
- let x = left + tx * tile_w;
54
- let y = bottom + ty * tile_h;
55
- let pos = Point :: new ( x, y) ;
59
+ // Compute the tile's world coordinate (top‑left of the tile)
60
+ let world_x = left + tx * tile_w;
61
+ let world_y = bottom + ty * tile_h;
62
+ // Compute the screen coordinate by subtracting the camera offset.
63
+ let screen_x = world_x - offset_x;
64
+ let screen_y = world_y - offset_y;
65
+ let pos = Point :: new ( screen_x, screen_y) ;
56
66
Image :: new ( bmp, pos)
57
67
. draw ( & mut fb_res. frame_buf )
58
68
. unwrap ( ) ;
@@ -64,17 +74,27 @@ pub fn render_system(
64
74
for coin in & maze. coins {
65
75
if coin. x != -1 && coin. y != -1 {
66
76
if let Some ( bmp) = texture_assets. coin . as_ref ( ) {
67
- // The valid coordinate is the center of the tile.
68
- // Subtract half the tile dimensions so the coin is centered.
69
- let pos = Point :: new ( coin. x - tile_w / 2 , coin. y - tile_h / 2 ) ;
77
+ // Use the coin's coordinate as the top‑left corner.
78
+ let screen_x = coin. x - offset_x;
79
+ let screen_y = coin. y - offset_y;
80
+ let pos = Point :: new ( screen_x, screen_y) ;
70
81
Image :: new ( bmp, pos)
71
82
. draw ( & mut fb_res. frame_buf )
72
83
. unwrap ( ) ;
73
84
}
74
85
}
75
86
}
76
87
77
- // (You can add additional drawing for the player ghost here if needed.)
88
+ // --- Render the player ghost ---
89
+ if let Some ( bmp) = texture_assets. ghost . as_ref ( ) {
90
+ // Use the player position as the top‑left coordinate.
91
+ let screen_x = player_pos. x as i32 - offset_x;
92
+ let screen_y = player_pos. y as i32 - offset_y;
93
+ let pos = Point :: new ( screen_x, screen_y) ;
94
+ Image :: new ( bmp, pos)
95
+ . draw ( & mut fb_res. frame_buf )
96
+ . unwrap ( ) ;
97
+ }
78
98
79
99
// Flush the completed framebuffer to the physical display.
80
100
let area = Rectangle :: new ( Point :: zero ( ) , fb_res. frame_buf . size ( ) ) ;
0 commit comments