1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
use collision::center_point;
use context::Window;
use sdl2::rect::Rect;
fn calc_viewport_point(center_coord: f64, window_coord: f64, map_coord: f64) -> f64 {
let half = window_coord / 2.0;
((center_coord - half).max(0.0))
.min((map_coord - window_coord).min((center_coord - half).abs()))
}
#[derive(Clone)]
pub struct Viewport {
pub x: i32,
pub y: i32,
pub window_dimensions: (i32, i32),
pub map_dimensions: (i32, i32),
}
impl Viewport {
pub fn new(window: &Window, map_dimensions: (i32, i32)) -> Viewport {
Viewport {
x: 0,
y: 0,
window_dimensions: (window.width as i32, window.height as i32),
map_dimensions: map_dimensions,
}
}
pub fn set_position(&mut self, new_center: (i32, i32)) {
let new_x = calc_viewport_point(new_center.0 as f64,
self.window_dimensions.0 as f64,
self.map_dimensions.0 as f64);
let new_y = calc_viewport_point(new_center.1 as f64,
self.window_dimensions.1 as f64,
self.map_dimensions.1 as f64);
self.x = new_x as i32;
self.y = new_y as i32;
}
pub fn in_viewport(&self, point: (i32, i32)) -> bool {
let margin = 32;
let (v_min_x, v_max_x) = (self.x - margin, self.x + self.window_dimensions.0);
let (v_min_y, v_max_y) = (self.y - margin, self.y + self.window_dimensions.1);
point.0 >= v_min_x && point.0 <= v_max_x && point.1 >= v_min_y && point.1 <= v_max_y
}
pub fn relative_point(&self, map_point: (i32, i32)) -> (i32, i32) {
(map_point.0 - self.x, map_point.1 - self.y)
}
pub fn constrain_to_viewport(&self, rect: &Rect) -> Option<Rect> {
let rect_points = [(rect.x(), rect.y()),
(rect.x() + (rect.width() as i32), rect.y()),
(rect.x(), rect.y() + (rect.height() as i32)),
(rect.x() + (rect.width() as i32), rect.y() + (rect.height() as i32))];
let mut in_viewport = false;
for point in rect_points.iter() {
if self.in_viewport(*point) {
in_viewport = true;
break;
}
}
if in_viewport {
let center = center_point(rect);
let (x, y) = self.relative_point((center.0 as i32, center.1 as i32));
Some(Rect::new_unwrap(x, y, rect.width(), rect.height()))
} else {
None
}
}
}