Raylib C++平台游戏碰撞问题:仅地面顶部碰撞生效
Raylib C++平台游戏碰撞检测问题修复
问题根源
你的代码存在几个核心问题导致碰撞仅在玩家站在地面顶部生效:
- 玩家碰撞矩形计算存在笔误:
GetRectangle()中的y - h / x是错误逻辑,会导致碰撞区域偏移 - 碰撞响应逻辑过于粗暴,仅处理了玩家站在地面顶部的场景,未考虑其他方向的碰撞
- 移动与重力未结合
deltaTime,帧率变化会导致游戏速度不稳定
修复后的完整代码
#include "raylib.h" #include <stdio.h> #include <math.h> struct square { float x, y; float w, h; float gravity; float velocity; float speed; // 修复矩形计算:以玩家中心为原点生成正确的碰撞矩形 Rectangle GetRectangle() { return Rectangle{ x - w / 2, y - h / 2, w, h }; } void drawsquare() { DrawRectangleRec(GetRectangle(), RED); } }; struct obby { float x, y; float w, h; Rectangle GetRectangle() { return Rectangle{ x, y, w, h }; } void drawobby() { DrawRectangleRec(GetRectangle(), BROWN); } }; int currentLevel = 1; int main(void) { InitWindow(1100, 700, "Basic Platformer"); SetWindowState(FLAG_VSYNC_HINT); SetTargetFPS(60); square player; player.x = 100; player.y = 400; player.w = 80; player.h = 80; player.gravity = 0.0f; player.velocity = 300.0f; // 调整为适配deltaTime的数值 player.speed = 200.0f; obby floor1; floor1.x = 50; floor1.y = 575; floor1.w = 160; floor1.h = 30; while (!WindowShouldClose()) { float deltaTime = GetFrameTime(); // 重力更新(结合deltaTime保证帧率无关) player.gravity += player.velocity * deltaTime; player.y += player.gravity * deltaTime; // 水平移动(分离A/D按键判断,避免互锁) if (IsKeyDown(KEY_A)) { player.x -= player.speed * deltaTime; } if (IsKeyDown(KEY_D)) { player.x += player.speed * deltaTime; currentLevel = 2; } // 跳跃触发 if (IsKeyPressed(KEY_W)) { player.gravity = -250.0f; } // 碰撞检测与多方向响应 Rectangle playerRec = player.GetRectangle(); Rectangle floorRec = floor1.GetRectangle(); if (CheckCollisionRecs(playerRec, floorRec)) { // 计算四个方向的碰撞重叠量 float overlapTop = floorRec.y - (playerRec.y + playerRec.height); float overlapBottom = (floorRec.y + floorRec.height) - playerRec.y; float overlapLeft = floorRec.x - (playerRec.x + playerRec.width); float overlapRight = (floorRec.x + floorRec.width) - playerRec.x; // 找到最小重叠的方向,确定碰撞面 float minOverlap = fminf(fminf(fabsf(overlapTop), fabsf(overlapBottom)), fminf(fabsf(overlapLeft), fabsf(overlapRight))); if (minOverlap == fabsf(overlapTop)) { // 玩家从上方碰撞地面(站在地面) player.y = floorRec.y - playerRec.height; player.gravity = 0.0f; } else if (minOverlap == fabsf(overlapBottom)) { // 玩家从下方碰撞地面(比如跳穿场景) player.y = floorRec.y + floorRec.height; player.gravity = 0.0f; } else if (minOverlap == fabsf(overlapLeft)) { // 玩家从左侧碰撞地面 player.x = floorRec.x - playerRec.width; } else if (minOverlap == fabsf(overlapRight)) { // 玩家从右侧碰撞地面 player.x = floorRec.x + floorRec.width; } } BeginDrawing(); ClearBackground(GRAY); // 关卡渲染(保留你的预留逻辑) if (currentLevel == 1) { floor1.drawobby(); } player.drawsquare(); EndDrawing(); } CloseWindow(); return 0; }
关键修复说明
- 修正碰撞矩形计算:将
y - h / x改为y - h / 2,确保玩家碰撞区域以自身中心为原点正确生成,这是碰撞检测异常的核心原因 - 帧率无关运动:所有移动、重力计算都乘以
deltaTime,保证游戏在不同帧率下运行速度一致 - 多方向碰撞响应:通过计算四个方向的碰撞重叠量,精准判断碰撞面,支持顶部、底部、左侧、右侧的碰撞处理
- 优化碰撞位置修正:根据实际重叠量调整玩家位置,避免粗暴赋值导致的穿模或位置异常
内容的提问来源于stack exchange,提问作者ayden
相关产品推荐
相关产品推荐

