Raylib 2D与Go开发:如何在碰撞结束时执行动作?
解决Raylib+Go马里奥克隆中玩家离开碰撞体后不下落的问题
问题根源
你当前的代码只在检测到与管道的Y轴碰撞时把playerGrounded设为true,但完全没处理「脱离所有管道碰撞」的场景——这就导致玩家离开管道后,程序还误以为玩家站在地面上,不会触发下落逻辑。
修复方案
核心思路
- 每帧先默认玩家不在地面,只有碰撞到支撑物(管道/地面)时才标记为
grounded - 补充地面碰撞逻辑,防止玩家无限下落
- 优化Y轴碰撞的判断逻辑,区分「踩在管道上」和「从其他方向撞管道」的不同情况
修改后的完整代码
func drawColliders() { // 每帧初始化:默认玩家不在地面,只有碰撞到支撑物才改为true playerGrounded = false for _, current_Pipe := range pipes { rl.DrawRectangle(current_Pipe.posX, current_Pipe.posY, current_Pipe.width, current_Pipe.height, current_Pipe.Color) pipeRec := rl.NewRectangle(float32(current_Pipe.posX), float32(current_Pipe.posY), float32(current_Pipe.width), float32(current_Pipe.height)) if rl.CheckCollisionRecs(playerDest, pipeRec) { isColliding = true // X轴碰撞偏移计算 var dx float32 if playerDest.X < pipeRec.X { dx = pipeRec.X - playerDest.Width } else { dx = pipeRec.X + pipeRec.Width } // Y轴碰撞偏移计算(修正原代码的公式错误) var dy float32 if playerDest.Y < pipeRec.Y { dy = pipeRec.Y - (playerDest.Y + playerDest.Height) } else { dy = pipeRec.Y + pipeRec.Height - playerDest.Y } // 计算轴碰撞时间,判断优先处理哪个轴 var xAxisTimeToCollide float32 = float32(math.Abs(float64((pipeRec.X - playerDest.X) / velocityX))) var yAxisTimeToCollide float32 = float32(math.Abs(float64((pipeRec.Y - playerDest.Y) / velocityY))) if xAxisTimeToCollide < yAxisTimeToCollide { // 处理X轴碰撞:把玩家推离管道 playerDest.X = dx } else { // 处理Y轴碰撞:区分踩管道和撞管道底部 if playerDest.Y + playerDest.Height <= pipeRec.Y + 5 { // 加小阈值避免误判 // 玩家从上方踩下来,标记为地面 playerGrounded = true playerJumping = false velocityY = 0 playerDest.Y = pipeRec.Y - playerDest.Height } else { // 玩家从下方/侧面撞管道,直接顶开 velocityY = 0 playerDest.Y = pipeRec.Y + pipeRec.Height } } } } // 处理地面碰撞(替换成你游戏中实际的地面Y坐标) const groundY float32 = 400 if playerDest.Y + playerDest.Height >= groundY { playerGrounded = true playerJumping = false velocityY = 0 playerDest.Y = groundY - playerDest.Height } // 下落逻辑:不在地面且未跳跃时,施加重力 if !playerGrounded && !playerJumping { velocityY += 0.5 // 重力值可根据手感调整 } // 应用速度更新玩家位置 playerDest.X += velocityX playerDest.Y += velocityY }
关键修改说明
- 初始化
playerGrounded = false:每帧重置状态,确保只有碰撞到支撑物时才标记为地面 - 修正Y轴碰撞计算:原代码的
dy公式存在错误,导致碰撞偏移计算不准确 - 区分Y轴碰撞场景:玩家踩管道时标记为地面,撞管道底部时直接顶开,符合马里奥的物理逻辑
- 补充地面碰撞:防止玩家无限下落出屏幕
- 独立下落逻辑:明确判断「不在地面且未跳跃」时触发重力下落
内容的提问来源于stack exchange,提问作者C-delb
相关产品推荐
相关产品推荐

