Raylib沙盒游戏屏幕边界碰撞检测不准问题求解
问题根源
你代码的三个异常全部来自逻辑设计错误,核心问题如下:
- 边界空隙:边界判断只检测方块左上角坐标,没有计入方块自身的宽高尺寸;且越界后执行坐标取反是反弹逻辑,不是停止逻辑,固定步长下落会让方块越过边界后才触发判断,反弹后自然和边界留空隙。
- 方块闪烁:你把位置更新逻辑写在了绘制函数
DrawMat()里,每帧先绘制方块再修改坐标,加上越界后坐标反复跳变,必然出现闪烁;同时没有用帧时间(deltaTime)适配帧率,不同刷新率下移动速度不稳定,会加重跳变感。另外你的主循环漏写了EndDrawing(),也会导致渲染异常。 - X轴不对齐:X轴越界后直接坐标取反的逻辑会让方块左右来回反弹,根本不会静止,自然无法对齐。
- 额外冗余问题:你定义的
SpeedX/SpeedY/Gravity等物理参数完全没有被使用,下落位移直接写死加9.81,不符合物理运动计算逻辑。
修复方案
核心调整原则:物理更新和绘制逻辑拆分,边界判断计入方块尺寸,越界后直接钳制坐标并标记停止,用帧时间保证运动速度和帧率无关。
1. 重写Mat结构体
把更新和绘制逻辑拆开,新增停止状态标记:
struct Mat { Vector2 pos; Vector2 size; Color color; float fallSpeed; bool isStopped; // 仅负责物理状态更新,不做绘制 void Update(float deltaTime) { if (isStopped) return; // 按帧时间计算下落位移,保证不同帧率下速度一致 pos.y += fallSpeed * deltaTime; // 底部边界检测:计入方块高度,触底后直接贴边并标记停止 float screenH = GetScreenHeight(); if (pos.y + size.y >= screenH) { pos.y = screenH - size.y; isStopped = true; } // 左右边界钳制,防止方块超出屏幕 float screenW = GetScreenWidth(); pos.x = Clamp(pos.x, 0, screenW - size.x); } // 仅负责绘制,不修改任何状态 void Draw() { DrawRectangleV(pos, size, color); } };
2. 修正主循环逻辑
调整执行顺序为「处理输入→更新物理→统一绘制」,补上缺失的渲染接口调用:
int main() { InitWindow(800, 600, "Sandbox Simulator"); SetWindowState(FLAG_VSYNC_HINT); Mat Sand; Sand.size = {5, 5}; Sand.color = YELLOW; Sand.fallSpeed = 300.0f; // 下落速度可自行调整 Sand.isStopped = false; int Numof = 0; std::vector<Mat> positions = {}; while (!WindowShouldClose()) { float deltaTime = GetFrameTime(); // 输入处理 if (IsKeyPressed(KEY_ONE)) { Numof = 1; } if (Numof == 1 && IsMouseButtonPressed(MOUSE_BUTTON_LEFT)) { Sand.pos = GetMousePosition(); Sand.isStopped = false; // 新生成的方块为运动状态 positions.push_back(Sand); } // 批量更新所有方块物理状态 for (size_t i = 0; i < positions.size(); i++) { positions[i].Update(deltaTime); } // 统一绘制 BeginDrawing(); ClearBackground(BLACK); for (size_t i = 0; i < positions.size(); i++) { positions[i].Draw(); } EndDrawing(); // 必须补上,否则会出现渲染异常 } CloseWindow(); return 0; }
修复效果
- 方块触底时会完全贴齐屏幕下边缘,不存在空隙
- 物理更新和绘制顺序正确,帧率适配后运动平滑,无闪烁问题
- 方块下落过程X坐标保持点击时的数值不变,停止后同列方块完全对齐

内容的提问来源于stack exchange,提问作者GreenDev
相关产品推荐
相关产品推荐

