1 | // SuperTux |
---|---|
2 | // Copyright (C) 2018 Ingo Ruhnke <grumbel@gmail.com> |
3 | // |
4 | // This program is free software: you can redistribute it and/or modify |
5 | // it under the terms of the GNU General Public License as published by |
6 | // the Free Software Foundation, either version 3 of the License, or |
7 | // (at your option) any later version. |
8 | // |
9 | // This program is distributed in the hope that it will be useful, |
10 | // but WITHOUT ANY WARRANTY; without even the implied warranty of |
11 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
12 | // GNU General Public License for more details. |
13 | // |
14 | // You should have received a copy of the GNU General Public License |
15 | // along with this program. If not, see <http://www.gnu.org/licenses/>. |
16 | |
17 | #include "worldmap/camera.hpp" |
18 | |
19 | #include "supertux/globals.hpp" |
20 | #include "video/video_system.hpp" |
21 | #include "video/viewport.hpp" |
22 | #include "worldmap/tux.hpp" |
23 | #include "worldmap/worldmap.hpp" |
24 | |
25 | namespace { |
26 | |
27 | const float CAMERA_PAN_SPEED = 5.0; |
28 | |
29 | } // namespace |
30 | |
31 | namespace worldmap { |
32 | |
33 | Camera::Camera() : |
34 | m_camera_offset(), |
35 | m_pan_pos(), |
36 | m_panning(false) |
37 | { |
38 | } |
39 | |
40 | void |
41 | Camera::update(float dt_sec) |
42 | { |
43 | Vector requested_pos; |
44 | |
45 | // position "camera" |
46 | if (!m_panning) { |
47 | m_camera_offset = get_camera_pos_for_tux(); |
48 | } else { |
49 | Vector delta__ = m_pan_pos - m_camera_offset; |
50 | float mag = delta__.norm(); |
51 | if (mag > CAMERA_PAN_SPEED) { |
52 | delta__ *= CAMERA_PAN_SPEED/mag; |
53 | } |
54 | m_camera_offset += delta__; |
55 | if (m_camera_offset == m_pan_pos) { |
56 | m_panning = false; |
57 | } |
58 | } |
59 | |
60 | requested_pos = m_camera_offset; |
61 | clamp_camera_position(m_camera_offset); |
62 | |
63 | if (m_panning) { |
64 | if (requested_pos.x != m_camera_offset.x) { |
65 | m_pan_pos.x = m_camera_offset.x; |
66 | } |
67 | if (requested_pos.y != m_camera_offset.y) { |
68 | m_pan_pos.y = m_camera_offset.y; |
69 | } |
70 | } |
71 | } |
72 | |
73 | void |
74 | Camera::pan() |
75 | { |
76 | m_panning = true; |
77 | m_pan_pos = get_camera_pos_for_tux(); |
78 | clamp_camera_position(m_pan_pos); |
79 | } |
80 | |
81 | Vector |
82 | Camera::get_camera_pos_for_tux() const |
83 | { |
84 | auto& worldmap = *WorldMap::current(); |
85 | auto& tux = worldmap.get_singleton_by_type<Tux>(); |
86 | |
87 | Vector camera_offset_; |
88 | Vector tux_pos = tux.get_pos(); |
89 | camera_offset_.x = tux_pos.x - static_cast<float>(SCREEN_WIDTH) / 2.0f; |
90 | camera_offset_.y = tux_pos.y - static_cast<float>(SCREEN_HEIGHT) / 2.0f; |
91 | return camera_offset_; |
92 | } |
93 | |
94 | void |
95 | Camera::clamp_camera_position(Vector& c) const |
96 | { |
97 | auto& worldmap = *WorldMap::current(); |
98 | |
99 | if (c.x < 0) { |
100 | c.x = 0; |
101 | } |
102 | |
103 | if (c.y < 0) { |
104 | c.y = 0; |
105 | } |
106 | |
107 | if (c.x > worldmap.get_width() - static_cast<float>(SCREEN_WIDTH)) { |
108 | c.x = worldmap.get_width() - static_cast<float>(SCREEN_WIDTH); |
109 | } |
110 | |
111 | if (c.y > worldmap.get_height() - static_cast<float>(SCREEN_HEIGHT)) { |
112 | c.y = worldmap.get_height() - static_cast<float>(SCREEN_HEIGHT); |
113 | } |
114 | |
115 | if (worldmap.get_width() < static_cast<float>(SCREEN_WIDTH)) { |
116 | c.x = (worldmap.get_width() - static_cast<float>(SCREEN_WIDTH)) / 2.0f; |
117 | } |
118 | |
119 | if (worldmap.get_height() < static_cast<float>(SCREEN_HEIGHT)) { |
120 | c.y = (worldmap.get_height() - static_cast<float>(SCREEN_HEIGHT)) / 2.0f; |
121 | } |
122 | } |
123 | |
124 | } // namespace worldmap |
125 | |
126 | /* EOF */ |
127 |