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
25namespace {
26
27const float CAMERA_PAN_SPEED = 5.0;
28
29} // namespace
30
31namespace worldmap {
32
33Camera::Camera() :
34 m_camera_offset(),
35 m_pan_pos(),
36 m_panning(false)
37{
38}
39
40void
41Camera::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
73void
74Camera::pan()
75{
76 m_panning = true;
77 m_pan_pos = get_camera_pos_for_tux();
78 clamp_camera_position(m_pan_pos);
79}
80
81Vector
82Camera::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
94void
95Camera::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