119 lines
4.2 KiB
C#
119 lines
4.2 KiB
C#
using Godot;
|
||
|
||
namespace Milimoe.GodotGame
|
||
{
|
||
public partial class CameraFight : Camera2D
|
||
{
|
||
[Export]
|
||
public float MoveSpeed = 200f;
|
||
|
||
[Export]
|
||
public TileMapLayer BattleTileLayer;
|
||
|
||
public override void _Ready()
|
||
{
|
||
// 默认关闭处理,只有进入战斗信号触发后才开启
|
||
SetPhysicsProcess(false);
|
||
}
|
||
|
||
public override void _PhysicsProcess(double delta)
|
||
{
|
||
// 这里的控制逻辑和角色类似,但作用于摄像机
|
||
Vector2 inputDir = Input.GetVector("move_left", "move_right", "move_up", "move_down");
|
||
|
||
if (inputDir != Vector2.Zero)
|
||
{
|
||
Vector2 targetPos = GlobalPosition + inputDir * MoveSpeed * (float)delta;
|
||
|
||
// 获取带缩放的屏幕尺寸
|
||
Vector2 viewSize = GetViewportRect().Size / Zoom;
|
||
Vector2 halfView = viewSize / 2;
|
||
|
||
// --- 核心修复逻辑 ---
|
||
|
||
// 1. 处理 X 轴
|
||
float minX = LimitLeft + halfView.X;
|
||
float maxX = LimitRight - halfView.X;
|
||
|
||
if (minX <= maxX)
|
||
{
|
||
// 如果地图够大,正常限位
|
||
targetPos.X = Mathf.Clamp(targetPos.X, minX, maxX);
|
||
}
|
||
else
|
||
{
|
||
// 如果地图比屏幕窄,强行居中,防止报错
|
||
targetPos.X = (LimitLeft + LimitRight) / 2f;
|
||
}
|
||
|
||
// 2. 处理 Y 轴
|
||
float minY = LimitTop + halfView.Y;
|
||
float maxY = LimitBottom - halfView.Y;
|
||
|
||
if (minY <= maxY)
|
||
{
|
||
targetPos.Y = Mathf.Clamp(targetPos.Y, minY, maxY);
|
||
}
|
||
else
|
||
{
|
||
// 如果地图比屏幕短,强行居中
|
||
targetPos.Y = (LimitTop + LimitBottom) / 2f;
|
||
}
|
||
|
||
GlobalPosition = targetPos;
|
||
}
|
||
|
||
// (可选) 按下某个键退出战斗模式
|
||
if (Input.IsActionJustPressed("ui_cancel"))
|
||
{
|
||
ExitBattleMode();
|
||
}
|
||
}
|
||
|
||
public void ExitBattleMode()
|
||
{
|
||
AudioStreamPlayer FightMusic = GetParent().GetNode<AudioStreamPlayer>("FightMusic");
|
||
FightMusic.Stop();
|
||
AudioStreamPlayer MapMusic = GetParent().GetNode<AudioStreamPlayer>("MapMusic");
|
||
if (MapMusic.StreamPaused)
|
||
{
|
||
MapMusic.StreamPaused = false;
|
||
}
|
||
SetPhysicsProcess(false);
|
||
GameConstant.Pause = false;
|
||
// 切换回角色的摄像机(假设角色下有个 Camera2D)
|
||
GetParent().GetNode<Camera2D>("Player/Camera2D").MakeCurrent();
|
||
Enabled = false;
|
||
}
|
||
|
||
public void UpdateLimitsFromTileMap()
|
||
{
|
||
if (BattleTileLayer is null) return;
|
||
|
||
// 1. 定义你的格子坐标
|
||
Vector2I cellTopLeft = new(88, 4);
|
||
Vector2I cellBottomRight = new(115, 15);
|
||
|
||
// 2. 获取 Tile 的大小 (通常是 16x16 或 32x32)
|
||
Vector2I tileSize = BattleTileLayer.TileSet.TileSize;
|
||
|
||
// 3. 计算像素坐标
|
||
// MapToLocal 返回的是格子的中心点,所以我们要减去/加上半个 Tile 大小来对齐边缘
|
||
Vector2 topLeftPixel = BattleTileLayer.MapToLocal(cellTopLeft) - (Vector2)tileSize / 2;
|
||
Vector2 bottomRightPixel = BattleTileLayer.MapToLocal(cellBottomRight) + (Vector2)tileSize / 2;
|
||
|
||
// 4. 如果你的 TileMapLayer 本身有位移或缩放,需要转为全局坐标
|
||
Vector2 globalTopLeft = BattleTileLayer.ToGlobal(topLeftPixel);
|
||
Vector2 globalBottomRight = BattleTileLayer.ToGlobal(bottomRightPixel);
|
||
|
||
// 5. 设置摄像机界限
|
||
LimitLeft = (int)globalTopLeft.X;
|
||
LimitTop = (int)globalTopLeft.Y;
|
||
LimitRight = (int)globalBottomRight.X;
|
||
LimitBottom = (int)globalBottomRight.Y;
|
||
|
||
GD.Print($"摄像机界限已设置:左{LimitLeft}, 上{LimitTop}, 右{LimitRight}, 下{LimitBottom}");
|
||
}
|
||
}
|
||
}
|