《碰撞问题》在防止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 → 完美对齐
总结
在右侧和底部边界处理中减去精灵宽度/高度的根本原因是:
- 精灵使用左上角作为定位基准点
- 右侧边界约束的是精灵的右边界
- 底部边界约束的是精灵的下边界
- 通过
位置 = 边界值 - 精灵尺寸的转换:- 使精灵的右边界对齐屏幕右边界
- 使精灵的下边界对齐屏幕下边界
这种处理方式确保了精灵始终完整显示在屏幕内,且不会部分出现在屏幕外,是2D游戏开发中处理边界碰撞的标准方法。
浙公网安备 33010602011771号