《碰撞问题》在防止player 出屏幕范围的时候 为什么>屏幕下面 和 右面 都要减掉 宽高?

if (slimeBounds.Left < screenBounds.Left)
{
_slimePosition.X = screenBounds.Left;
}
else if (slimeBounds.Right > screenBounds.Right)
{
_slimePosition.X = screenBounds.Right - _slime.Width;
}

if (slimeBounds.Top < screenBounds.Top)
{
_slimePosition.Y = screenBounds.Top;
}
else if (slimeBounds.Bottom > screenBounds.Bottom)
{
_slimePosition.Y = screenBounds.Bottom - _slime.Height;
}
在防止player 出这个范围的时候 为什么>屏幕下面 和 右面 都要减掉 宽高?

您的问题非常到位!这段代码是处理玩家(史莱姆)边界碰撞的核心逻辑,需要详细解释为什么在右侧和底部边界处理中要减去宽度和高度。让我一步步拆解:

核心概念:精灵定位原理

在XNA/MonoGame中,精灵绘制位置由Vector2 position参数决定,这个位置表示精灵左上角的坐标。

边界检测逻辑详解

1. 左侧边界处理 (X轴最小值)

if (slimeBounds.Left < screenBounds.Left)  // 0
{
    _slimePosition.X = screenBounds.Left;  // 0
}
  • 问题:史莱姆左侧超出屏幕左边界
  • 解决方案:将史莱姆左上角X坐标设置为0
  • 结果:精灵左侧与屏幕左侧对齐
  • 不需要减宽度:因为定位点是左上角,设置X=0自然让精灵左边界对齐

2. 右侧边界处理 (X轴最大值)

else if (slimeBounds.Right > screenBounds.Right)  // 屏幕宽度
{
    _slimePosition.X = screenBounds.Right - _slime.Width;
}
  • 问题:史莱姆右侧超出屏幕右边界
  • 关键点screenBounds.Right = 屏幕宽度(如1280px)
  • 错误做法:如果直接设置X = screenBounds.Right
    • 精灵左上角会出现在1280px位置
    • 精灵实际占据区域:1280px 到 (1280 + 精灵宽度)px → 完全在屏幕外
  • 正确做法
    • 计算:X = 屏幕宽度 - 精灵宽度
    • 示例:1280 - 64 = 1216px
  • 结果
    • 精灵左上角在1216px
    • 精灵右侧:1216 + 64 = 1280px → 正好对齐屏幕右边界

3. 顶部边界处理 (Y轴最小值)

if (slimeBounds.Top < screenBounds.Top)  // 0
{
    _slimePosition.Y = screenBounds.Top;  // 0
}
  • 同左侧原理:设置Y=0使精灵顶部对齐屏幕上边界

4. 底部边界处理 (Y轴最大值)

else if (slimeBounds.Bottom > screenBounds.Bottom)  // 屏幕高度
{
    _slimePosition.Y = screenBounds.Bottom - _slime.Height;
}
  • 问题:史莱姆底部超出屏幕下边界
  • 关键点screenBounds.Bottom = 屏幕高度(如720px)
  • 正确计算
    • Y = 屏幕高度 - 精灵高度
    • 示例:720 - 64 = 656px
  • 结果
    • 精灵左上角Y=656px
    • 精灵底部:656 + 64 = 720px → 正好对齐屏幕底部

视觉化示例

假设:

  • 屏幕尺寸:1280×720
  • 史莱姆尺寸:64×64
  • 史莱姆即将超出右边界的位置:
    当前位置:X=1260 (左上角)
    实际右边界:1260+64=1324 > 1280 → 超出
    

调整后:

新位置:X = 1280 - 64 = 1216
精灵区域:1216 到 1280 → 完美贴合

为什么不对称处理?

边界 设置方法 原因
左侧/顶部 直接设为0 因为0位置就是边界起始点
右侧/底部 屏幕尺寸 - 精灵尺寸 因为边界值是结束点,需考虑精灵尺寸

物理引擎类比

可以想象精灵是一个有体积的物体:

  • 左侧碰撞:物体左表面接触边界 → 定位点=边界位置
  • 右侧碰撞:物体右表面接触边界 → 定位点=边界位置 - 物体宽度

实际代码验证

// 假设精灵宽高均为100
_slime.Width = 100;
_slime.Height = 100;

// 屏幕尺寸
int screenWidth = 800;
int screenHeight = 600;

// 测试右侧碰撞
_slimePosition.X = 750; // 精灵右侧=750+100=850 > 800
if(slimeBounds.Right > screenWidth)
{
    _slimePosition.X = screenWidth - _slime.Width; // 800-100=700
}
// 现在精灵:左侧=700, 右侧=700+100=800 → 完美对齐

// 测试底部碰撞
_slimePosition.Y = 550; // 精灵底部=550+100=650 > 600
if(slimeBounds.Bottom > screenHeight)
{
    _slimePosition.Y = screenHeight - _slime.Height; // 600-100=500
}
// 现在精灵:顶部=500, 底部=500+100=600 → 完美对齐

总结

在右侧和底部边界处理中减去精灵宽度/高度的根本原因是:

  1. 精灵使用左上角作为定位基准点
  2. 右侧边界约束的是精灵的右边界
  3. 底部边界约束的是精灵的下边界
  4. 通过位置 = 边界值 - 精灵尺寸的转换:
    • 使精灵的右边界对齐屏幕右边界
    • 使精灵的下边界对齐屏幕下边界

这种处理方式确保了精灵始终完整显示在屏幕内,且不会部分出现在屏幕外,是2D游戏开发中处理边界碰撞的标准方法。

posted on 2025-07-29 20:05  C#我喜欢  阅读(16)  评论(1)    收藏  举报

导航