You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Raylib(C语言)矩形碰撞检测问题:玩家触碰物体后瞬移

Raylib矩形碰撞瞬移问题解决与多方案实现

问题根源

你的代码在碰撞后同时对x、y两个方向进行强制位置修正,没有区分玩家的移动方向和碰撞的重叠轴向,导致玩家被直接"弹"到目标矩形的另一侧,出现瞬移现象。要实现"碰撞时停止当前方向移动"的效果,核心是只在发生碰撞的移动轴上回退位置,而非同时修改两个轴。


方案一:预移动检测(最直观的入门方案)

思路:先记录玩家移动前的位置,执行移动后检测碰撞,若碰撞则回退到移动前的位置。这种方式能保证玩家不会进入障碍物内部,且逻辑简单易懂。

修改后的代码:

#include "raylib.h"

int main() {
    const int screenWidth = 800;
    const int screenHeight = 450;

    InitWindow(screenWidth, screenHeight, "Rectangle Collision Example");
    SetTargetFPS(60);

    Rectangle rec1 = { 100, 200, 50, 50 };
    Rectangle rec2 = { 400, 200, 50, 50 };
    Rectangle prevRec1; // 记录移动前的位置

    while (!WindowShouldClose()) {
        // 保存移动前的位置
        prevRec1 = rec1;

        // 处理玩家移动
        if (IsKeyDown(KEY_LEFT)) rec1.x -= 2;
        if (IsKeyDown(KEY_RIGHT)) rec1.x += 2;
        if (IsKeyDown(KEY_UP)) rec1.y -= 2;
        if (IsKeyDown(KEY_DOWN)) rec1.y += 2;

        // 碰撞检测:如果碰撞,回退到移动前的位置
        if (CheckCollisionRecs(rec1, rec2)) {
            rec1 = prevRec1;
        }

        BeginDrawing();
        ClearBackground(RAYWHITE);
        DrawRectangleRec(rec1, BLUE);
        DrawRectangleRec(rec2, RED);
        EndDrawing();
    }

    CloseWindow();
    return 0;
}

优点:逻辑简单,容易扩展到多障碍物场景;缺点:如果玩家同时按两个方向键(比如斜向移动),只要碰到障碍物就会完全停止移动,无法实现"沿无碰撞方向继续移动"的效果。


方案二:轴向分离修正(支持斜向移动的精准碰撞)

思路:分别检测x轴和y轴的移动是否会导致碰撞,只回退发生碰撞的轴向位置。这样玩家斜向移动时,碰到障碍物可以沿无碰撞的轴继续移动。

修改后的代码:

#include "raylib.h"

int main() {
    const int screenWidth = 800;
    const int screenHeight = 450;

    InitWindow(screenWidth, screenHeight, "Rectangle Collision Example");
    SetTargetFPS(60);

    Rectangle rec1 = { 100, 200, 50, 50 };
    Rectangle rec2 = { 400, 200, 50, 50 };
    float moveSpeed = 2.0f;

    while (!WindowShouldClose()) {
        // 先处理X轴移动
        if (IsKeyDown(KEY_LEFT)) rec1.x -= moveSpeed;
        if (IsKeyDown(KEY_RIGHT)) rec1.x += moveSpeed;

        // 检测X轴碰撞,碰撞则回退
        if (CheckCollisionRecs(rec1, rec2)) {
            if (IsKeyDown(KEY_LEFT)) rec1.x += moveSpeed;
            if (IsKeyDown(KEY_RIGHT)) rec1.x -= moveSpeed;
        }

        // 再处理Y轴移动
        if (IsKeyDown(KEY_UP)) rec1.y -= moveSpeed;
        if (IsKeyDown(KEY_DOWN)) rec1.y += moveSpeed;

        // 检测Y轴碰撞,碰撞则回退
        if (CheckCollisionRecs(rec1, rec2)) {
            if (IsKeyDown(KEY_UP)) rec1.y += moveSpeed;
            if (IsKeyDown(KEY_DOWN)) rec1.y -= moveSpeed;
        }

        BeginDrawing();
        ClearBackground(RAYWHITE);
        DrawRectangleRec(rec1, BLUE);
        DrawRectangleRec(rec2, RED);
        EndDrawing();
    }

    CloseWindow();
    return 0;
}

优点:支持斜向移动时的部分碰撞响应,玩家体验更自然;缺点:需要分轴处理,多障碍物场景下需要循环检测每个障碍物。


方案三:重叠量计算(专业碰撞响应方案)

思路:利用Raylib的GetCollisionRec函数获取两个矩形的重叠区域,根据重叠区域的宽高判断碰撞的主要轴向,然后将玩家矩形推离障碍物,只修正重叠量最小的轴向(避免同时修改x/y导致瞬移)。

修改后的代码:

#include "raylib.h"

int main() {
    const int screenWidth = 800;
    const int screenHeight = 450;

    InitWindow(screenWidth, screenHeight, "Rectangle Collision Example");
    SetTargetFPS(60);

    Rectangle rec1 = { 100, 200, 50, 50 };
    Rectangle rec2 = { 400, 200, 50, 50 };
    float moveSpeed = 2.0f;

    while (!WindowShouldClose()) {
        // 处理玩家移动
        if (IsKeyDown(KEY_LEFT)) rec1.x -= moveSpeed;
        if (IsKeyDown(KEY_RIGHT)) rec1.x += moveSpeed;
        if (IsKeyDown(KEY_UP)) rec1.y -= moveSpeed;
        if (IsKeyDown(KEY_DOWN)) rec1.y += moveSpeed;

        // 检测碰撞并计算重叠区域
        if (CheckCollisionRecs(rec1, rec2)) {
            Rectangle overlap = GetCollisionRec(rec1, rec2);

            // 判断哪个轴向的重叠量更小,优先修正该轴
            if (overlap.width < overlap.height) {
                // X轴重叠更小,修正X位置
                if (rec1.x < rec2.x) {
                    rec1.x = rec2.x - rec1.width;
                } else {
                    rec1.x = rec2.x + rec2.width;
                }
            } else {
                // Y轴重叠更小,修正Y位置
                if (rec1.y < rec2.y) {
                    rec1.y = rec2.y - rec1.height;
                } else {
                    rec1.y = rec2.y + rec2.height;
                }
            }
        }

        BeginDrawing();
        ClearBackground(RAYWHITE);
        DrawRectangleRec(rec1, BLUE);
        DrawRectangleRec(rec2, RED);
        EndDrawing();
    }

    CloseWindow();
    return 0;
}

优点:精准处理碰撞方向,适合复杂场景下的碰撞响应;缺点:逻辑相对复杂,需要理解重叠区域的计算逻辑。


内容的提问来源于stack exchange,提问作者Proyash Ck

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.24 15:02:42