feat(地图系统): 实现角色移动约束和地图切换功能
添加地图移动区域检测和角色移动约束逻辑 引入地图切换请求队列机制,支持延迟处理角色传送 在CharacterObject中实现地图边界检测和位置约束应用
This commit is contained in:
@@ -1,5 +1,8 @@
|
||||
#include "character/CharacterObject.h"
|
||||
#include "map/GameMap.h"
|
||||
#include "world/GameWorld.h"
|
||||
#include <SDL2/SDL.h>
|
||||
#include <cmath>
|
||||
#include <frostbite2D/core/application.h>
|
||||
#include <sstream>
|
||||
#include <utility>
|
||||
@@ -34,6 +37,15 @@ const char* NonEmptyOrPlaceholder(const std::string& value, const char* placehol
|
||||
return value.empty() ? placeholder : value.c_str();
|
||||
}
|
||||
|
||||
Vec3 ToWorldVector(const CharacterWorldPosition& position) {
|
||||
return Vec3(static_cast<float>(position.x), static_cast<float>(position.y),
|
||||
static_cast<float>(position.z));
|
||||
}
|
||||
|
||||
int32 RoundWorldCoordinate(float value) {
|
||||
return static_cast<int32>(std::lround(value));
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
bool CharacterObject::Construction(int jobId) {
|
||||
@@ -147,6 +159,53 @@ void CharacterObject::SyncActorPositionFromWorld() {
|
||||
SetZOrder(worldPosition.y);
|
||||
}
|
||||
|
||||
GameMap* CharacterObject::FindOwningMap() const {
|
||||
Actor* node = GetParent();
|
||||
while (node) {
|
||||
if (auto* map = dynamic_cast<GameMap*>(node)) {
|
||||
return map;
|
||||
}
|
||||
node = node->GetParent();
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void CharacterObject::ApplyMapMovementConstraints(
|
||||
const CharacterWorldPosition& previousPosition) {
|
||||
GameMap* map = FindOwningMap();
|
||||
if (!map) {
|
||||
return;
|
||||
}
|
||||
|
||||
Vec3 previousWorldPos = ToWorldVector(previousPosition);
|
||||
Vec3 worldOffset(static_cast<float>(motor_.position.x - previousPosition.x),
|
||||
static_cast<float>(motor_.position.y - previousPosition.y),
|
||||
static_cast<float>(motor_.position.z - previousPosition.z));
|
||||
Vec3 resolvedWorldPos = map->CheckIsItMovable(previousWorldPos, worldOffset);
|
||||
motor_.position.x = RoundWorldCoordinate(resolvedWorldPos.x);
|
||||
motor_.position.y = RoundWorldCoordinate(resolvedWorldPos.y);
|
||||
motor_.position.z = RoundWorldCoordinate(resolvedWorldPos.z);
|
||||
}
|
||||
|
||||
void CharacterObject::QueueMapTransitionIfNeeded() {
|
||||
GameMap* map = FindOwningMap();
|
||||
if (!map) {
|
||||
return;
|
||||
}
|
||||
|
||||
GameMap::MapMoveArea target;
|
||||
if (!map->TryGetMoveAreaTarget(ToWorldVector(motor_.position), target)) {
|
||||
return;
|
||||
}
|
||||
|
||||
GameWorld* world = GameWorld::GetWorld();
|
||||
if (!world) {
|
||||
return;
|
||||
}
|
||||
|
||||
world->RequestMoveCharacter(RefPtr<Actor>(this), target.town, target.area);
|
||||
}
|
||||
|
||||
void CharacterObject::PushCommand(const CharacterCommand& command) {
|
||||
commandBuffer_.Submit(command);
|
||||
}
|
||||
@@ -244,7 +303,10 @@ void CharacterObject::OnUpdate(float deltaTime) {
|
||||
inputRouter_.EmitCommands(commandBuffer_);
|
||||
currentIntent_ = commandBuffer_.BuildIntent();
|
||||
stateMachine_.Update(*this, commandBuffer_, currentIntent_, deltaTime);
|
||||
CharacterWorldPosition previousPosition = motor_.position;
|
||||
motor_.Update(deltaTime);
|
||||
ApplyMapMovementConstraints(previousPosition);
|
||||
QueueMapTransitionIfNeeded();
|
||||
SyncActorPositionFromWorld();
|
||||
SetFacing(motor_.facing);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user