Files
DNF_DEV/source_game/Actor/Map/GameMapCamera.cpp

127 lines
3.7 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#include "GameMapCamera.h"
#include "EngineCore/Game.h"
#include "Actor/Map/GameMap.h"
#include "Actor/Object/BaseObject.h"
#include <algorithm>
GameMapCamera::GameMapCamera()
{
}
GameMapCamera::~GameMapCamera()
{
}
void GameMapCamera::SetFromActor(BaseObject *actor)
{
this->_FromActor = actor;
_FromActor->_AffCamera = this;
}
void GameMapCamera::Update(float deltaTime)
{
SyncPosByFromParent(deltaTime);
}
void GameMapCamera::SyncPos(float deltaTime)
{
}
void GameMapCamera::SetPos(int x, int y, int z)
{
// this->X = x;
// this->Y = y;
// this->Z = z;
}
void GameMapCamera::AddPos(int x, int y, int z)
{
// this->X += x;
// this->Y += y;
// this->Z += z;
}
void GameMapCamera::SyncPosByFromParent(float deltaTime)
{
if (this->_FromActor == nullptr)
{
return;
}
int targetX = _FromActor->Position.x;
int targetY = _FromActor->Position.y;
if (_isSmoothMoving)
{
// 平滑移动计算
VecPos targetPosition(targetX, targetY);
_currentPosition = SmoothDamp(_currentPosition, targetPosition, _velocity, _smoothTime, _maxSpeed, deltaTime);
}
else
{
_currentPosition.x = targetX;
_currentPosition.y = targetY;
}
}
VecPos GameMapCamera::SmoothDamp(const VecPos &current, const VecPos &target, VecPos &currentVelocity, float smoothTime, int maxSpeed, float deltaTime)
{
// 平滑时间为0时直接返回目标位置并重置速度
if (smoothTime <= 0.f)
{
currentVelocity = VecPos(0, 0);
return target;
}
// 临界阻尼系数计算(避免过冲的核心参数)
const float omega = 2.0f / smoothTime;
const float x = omega * deltaTime;
const float expTerm = 1.0f / (1.0f + x + 0.48f * x * x + 0.235f * x * x * x);
// 计算当前位置与目标的差值
VecPos delta = target - current;
// 计算目标速度(基于阻尼公式和当前差值)
// 注意:这里先通过浮点计算保持精度,最后转换为整数
const float tx = delta.x * (omega * omega * deltaTime) - currentVelocity.x * (1.0f + 0.48f * x) * x;
const float ty = delta.y * (omega * omega * deltaTime) - currentVelocity.y * (1.0f + 0.48f * x) * x;
VecPos targetVelocity(static_cast<int>(tx), static_cast<int>(ty));
// 应用速度衰减(指数平滑)
currentVelocity += targetVelocity;
currentVelocity = VecPos(
static_cast<int>(currentVelocity.x * expTerm),
static_cast<int>(currentVelocity.y * expTerm));
// 限制最大速度如果设置了maxSpeed
if (maxSpeed > 0)
{
// 计算当前速度的模长(浮点精度)
const float speedSq = static_cast<float>(currentVelocity.x * currentVelocity.x + currentVelocity.y * currentVelocity.y);
const float maxSpeedSq = static_cast<float>(maxSpeed * maxSpeed);
if (speedSq > maxSpeedSq)
{
// 速度超限,按比例缩放至最大速度
const float scale = maxSpeed / sqrtf(speedSq);
currentVelocity = VecPos(
static_cast<int>(currentVelocity.x * scale),
static_cast<int>(currentVelocity.y * scale));
}
}
// 计算新位置(当前位置 + 速度 * 时间)
VecPos newPos = current + VecPos(
static_cast<int>(currentVelocity.x * deltaTime),
static_cast<int>(currentVelocity.y * deltaTime));
// 检测过冲:如果新位置已越过目标,直接锁定目标并重置速度
// 点积 > 0 表示方向相反(已超过目标)
const int dot = delta.x * (newPos.x - target.x) + delta.y * (newPos.y - target.y);
if (dot > 0)
{
newPos = target;
currentVelocity = VecPos(0, 0);
}
return newPos;
}