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("FightMusic"); FightMusic.Stop(); AudioStreamPlayer MapMusic = GetParent().GetNode("MapMusic"); if (MapMusic.StreamPaused) { MapMusic.StreamPaused = false; } SetPhysicsProcess(false); GameConstant.Pause = false; // 切换回角色的摄像机(假设角色下有个 Camera2D) GetParent().GetNode("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}"); } } }