2026-02-03 01:38:51 +08:00

119 lines
4.2 KiB
C#
Raw Permalink 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.

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}");
}
}
}