mirror of
https://github.com/libretro/scummvm.git
synced 2025-02-12 22:51:11 +00:00
118 lines
3.8 KiB
C++
118 lines
3.8 KiB
C++
/* ScummVM - Graphic Adventure Engine
|
|
*
|
|
* ScummVM is the legal property of its developers, whose names
|
|
* are too numerous to list here. Please refer to the COPYRIGHT
|
|
* file distributed with this source distribution.
|
|
*
|
|
* This program is free software: you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License as published by
|
|
* the Free Software Foundation, either version 3 of the License, or
|
|
* (at your option) any later version.
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
*
|
|
*/
|
|
|
|
#include "twp/twp.h"
|
|
#include "twp/object.h"
|
|
#include "twp/room.h"
|
|
|
|
namespace Twp {
|
|
|
|
void Camera::clamp(const Math::Vector2d &at) {
|
|
if (_room) {
|
|
Math::Vector2d roomSize = _room->_roomSize;
|
|
Math::Vector2d screenSize = _room->getScreenSize();
|
|
// fix assertion when screen size is greater than room height
|
|
if (screenSize.getY() > roomSize.getY()) {
|
|
screenSize.setY(roomSize.getY());
|
|
}
|
|
|
|
_pos.setX(CLIP(at.getX(), screenSize.getX() / 2.f + _bounds.left(), screenSize.getX() / 2 + _bounds.right()));
|
|
_pos.setY(CLIP(at.getY(), _bounds.bottom(), _bounds.top() - screenSize.getY() / 2));
|
|
_pos.setX(CLIP(_pos.getX(), screenSize.getX() / 2.f, MAX(roomSize.getX() - screenSize.getX() / 2.f, 0.f)));
|
|
_pos.setY(CLIP(_pos.getY(), screenSize.getY() / 2, MAX(roomSize.getY() - screenSize.getY() / 2, 0.f)));
|
|
}
|
|
}
|
|
|
|
void Camera::setAtCore(const Math::Vector2d &at) {
|
|
Math::Vector2d screenSize = _room->getScreenSize();
|
|
_pos = at;
|
|
clamp(_pos);
|
|
g_twp->getGfx().cameraPos(_pos - screenSize / 2.f);
|
|
}
|
|
|
|
void Camera::setAt(const Math::Vector2d &at) {
|
|
setAtCore(at);
|
|
_target = _pos;
|
|
_time = 0;
|
|
_moving = false;
|
|
}
|
|
|
|
void Camera::panTo(const Math::Vector2d &target, float time, InterpolationKind interpolation) {
|
|
if (!_moving) {
|
|
_moving = true;
|
|
_init = _pos;
|
|
_elapsed = 0.f;
|
|
}
|
|
_function = easing(interpolation);
|
|
_target = target;
|
|
_time = time;
|
|
}
|
|
|
|
void Camera::update(Common::SharedPtr<Room> room, Common::SharedPtr<Object> follow, float elapsed) {
|
|
_room = room;
|
|
_elapsed += elapsed;
|
|
bool isMoving = _elapsed < _time;
|
|
|
|
if (_moving && !isMoving) {
|
|
_moving = false;
|
|
_time = 0.f;
|
|
setAt(_target);
|
|
}
|
|
|
|
if (isMoving) {
|
|
float t = _elapsed / _time;
|
|
Math::Vector2d d = _target - _init;
|
|
Math::Vector2d pos = _init + (d * _function.func(t));
|
|
setAtCore(pos);
|
|
return;
|
|
}
|
|
|
|
if (follow && follow->_node->isVisible() && follow->_room == room) {
|
|
Math::Vector2d screen = room->getScreenSize();
|
|
Math::Vector2d pos = follow->_node->getPos();
|
|
Math::Vector2d margin(screen.getX() / 6.f, screen.getY() / 6.f);
|
|
Math::Vector2d cameraPos = getAt();
|
|
|
|
Math::Vector2d d = pos - cameraPos;
|
|
Math::Vector2d delta = d * elapsed;
|
|
bool sameActor = _follow == follow;
|
|
|
|
float x, y;
|
|
if (sameActor && (pos.getX() > (cameraPos.getX() + margin.getX())))
|
|
x = pos.getX() - margin.getX();
|
|
else if (sameActor && (pos.getX() < (cameraPos.getX() - margin.getX())))
|
|
x = pos.getX() + margin.getX();
|
|
else
|
|
x = cameraPos.getX() + (d.getX() > 0 ? MIN(delta.getX(), d.getX()) : MAX(delta.getX(), d.getX()));
|
|
if (sameActor && (pos.getY() > (cameraPos.getY() + margin.getY())))
|
|
y = pos.getY() - margin.getY();
|
|
else if (sameActor && (pos.getY() < (cameraPos.getY() - margin.getY())))
|
|
y = pos.getY() + margin.getY();
|
|
else
|
|
y = cameraPos.getY() + (d.getY() > 0 ? MIN(delta.getY(), d.getY()) : MAX(delta.getY(), d.getY()));
|
|
setAtCore(Math::Vector2d(x, y));
|
|
if (!sameActor && (fabs(pos.getX() - x) < 1.f) && (fabs(pos.getY() - y) < 1.f))
|
|
_follow = follow;
|
|
}
|
|
}
|
|
|
|
} // namespace Twp
|