Raylib开发2D游戏:玩家碰地面无法移动的问题求助
核心问题定位
你当前的逻辑存在两个致命设计错误,直接导致贴地时输入完全失效:
- 执行顺序完全颠倒:碰撞检测发生在
plr矩形赋值之前,相当于用上一帧的旧碰撞盒判定当前帧的位置,检测结果完全不准。 - 碰撞回退粒度太粗:只要检测到任意碰撞(包括重力导致的y方向轻微下沉),就把整个newPos(包含左右按键带来的x方向合法位移)全部回退到oldPos。只要玩家站在地面上,重力每帧都会把y方向往下拉一点,这一帧必然触发碰撞——你按左右键产生的x位移,直接跟着y的下沉量一起被回退抹掉,自然完全动不了。
- 存在初始化缺陷:
oldPos从未被赋值,程序启动初期会存在坐标野值。
修复方案
放弃“碰撞就整体回退上一帧位置”的粗粒度逻辑,改成分轴独立处理碰撞:每帧先记录当前位置,分别计算x、y方向的位移,分别检测两个方向是否碰撞,哪个方向碰了就只回退哪个方向的位移,不影响另一个方向的合法移动。
核心修复代码片段:
// 将原重力宏改为可变变量,支持落地时临时关闭 float gravity = 3.0f; // 主循环核心逻辑 while(!WindowShouldClose()) { // 1. 记录当前帧初始位置作为回退基准 pl.oldPos = pl.newPos; // 2. 计算x方向的输入位移 float moveX = 0; if (IsKeyDown(KEY_RIGHT)) moveX += plSpeed; if (IsKeyDown(KEY_LEFT)) moveX -= plSpeed; // 3. 计算y方向的位移(上跳输入+重力) if (IsKeyDown(KEY_UP)) pl.newPos.y -= plSpeed; pl.newPos.y += gravity; // 4. 提前给碰撞盒赋值当前的候选位置,避免用过期数据检测 plr.width = 30; plr.height = 30; plr.x = pl.newPos.x; plr.y = pl.newPos.y; // 5. 单独处理y方向碰撞(地面接触) if (CheckCollisionRecs(plr, floor)) { // 只修正y坐标:贴在地面上边缘,不产生重叠 pl.newPos.y = floor.y - plr.height; plr.y = pl.newPos.y; gravity = 0; // 落地后关闭重力,避免每帧持续下沉触发碰撞 } else { gravity = 3.0f; // 在空中恢复重力 } // 6. 单独处理x方向位移碰撞 pl.newPos.x += moveX; plr.x = pl.newPos.x; if (CheckCollisionRecs(plr, floor)) { // 只回退x方向的位移,不影响y方向的贴地状态 pl.newPos.x -= moveX; plr.x = pl.newPos.x; } // 原有绘制逻辑保持不变 BeginDrawing(); ClearBackground(RAYWHITE); DrawRectangleRec(floor, GREEN); DrawRectangleRec(plr, pl.color); EndDrawing(); }
这套逻辑下,玩家站在地面时,y方向的位置会被校准到刚好贴住地面,x方向的左右输入只会被单独检测是否碰到障碍物,不会被重力导致的y方向碰撞连带回退,可正常响应移动输入。
内容的提问来源于stack exchange,提问作者arydev
相关产品推荐
相关产品推荐

