dotzuki_engine/overworld/
map_transitions.rs1use crate::map::MapTrait;
2use crate::overworld::types::{Direction, MapData};
3use crate::tileset::TilesetTrait;
4
5#[derive(Debug, Clone, Copy, PartialEq, Eq)]
6pub struct ConnectionTransition<M: MapTrait> {
7 pub new_map: M,
8 pub new_x: u16,
9 pub new_y: u16,
10}
11
12#[derive(Debug, Clone, Copy, PartialEq, Eq)]
13pub struct WarpTransition<M: MapTrait> {
14 pub new_map: M,
15 pub dest_warp_id: u8,
16 pub is_last_map: bool,
17}
18
19pub trait MapTransitionProvider<M: MapTrait> {
25 fn resolve_map_id(&self, name: &str) -> Option<M>;
27
28 fn get_map_dimensions(&self, map: M) -> (u8, u8);
30}
31
32pub fn calculate_connection_transition<P, M, T, Mus>(
35 map_data: &MapData<M, T, Mus>,
36 provider: &P,
37 px: u16,
38 py: u16,
39 direction: Direction,
40) -> Option<ConnectionTransition<M>>
41where
42 M: MapTrait,
43 T: TilesetTrait,
44 P: MapTransitionProvider<M>,
45{
46 let conns = &map_data.connections;
47 let current_w = map_data.width as u16 * 2;
48 let current_h = map_data.height as u16 * 2;
49
50 match direction {
51 Direction::Up => {
52 if py != 0 {
53 return None;
54 }
55 let conn = conns.north.as_ref()?;
56 let (_, dest_h) = provider.get_map_dimensions(conn.target_map);
57 let new_y = (dest_h as u16) * 2 - 1;
58 let new_x = apply_offset(px, conn.offset);
59 Some(ConnectionTransition {
60 new_map: conn.target_map,
61 new_x,
62 new_y,
63 })
64 }
65 Direction::Down => {
66 if py != current_h - 1 {
67 return None;
68 }
69 let conn = conns.south.as_ref()?;
70 let new_y = 0;
71 let new_x = apply_offset(px, conn.offset);
72 Some(ConnectionTransition {
73 new_map: conn.target_map,
74 new_x,
75 new_y,
76 })
77 }
78 Direction::Left => {
79 if px != 0 {
80 return None;
81 }
82 let conn = conns.west.as_ref()?;
83 let (dest_w, _) = provider.get_map_dimensions(conn.target_map);
84 let new_x = (dest_w as u16) * 2 - 1;
85 let new_y = apply_offset(py, conn.offset);
86 Some(ConnectionTransition {
87 new_map: conn.target_map,
88 new_x,
89 new_y,
90 })
91 }
92 Direction::Right => {
93 if px != current_w - 1 {
94 return None;
95 }
96 let conn = conns.east.as_ref()?;
97 let new_x = 0;
98 let new_y = apply_offset(py, conn.offset);
99 Some(ConnectionTransition {
100 new_map: conn.target_map,
101 new_x,
102 new_y,
103 })
104 }
105 }
106}
107
108fn apply_offset(coord: u16, offset: i8) -> u16 {
109 let adjusted = coord as i32 - (offset as i32 * 2);
110 adjusted.max(0) as u16
111}
112
113pub fn check_warp_at<M: MapTrait, T: TilesetTrait, Mus>(
116 map_data: &MapData<M, T, Mus>,
117 px: u8,
118 py: u8,
119) -> Option<WarpTransition<M>> {
120 for warp in &map_data.warps {
121 if px == warp.x && py == warp.y {
122 return Some(WarpTransition {
123 new_map: warp.target_map,
124 dest_warp_id: warp.target_warp_id,
125 is_last_map: warp.is_last_map,
126 });
127 }
128 }
129 None
130}