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

Raylib 2D与Go开发:如何在碰撞结束时执行动作?

解决Raylib+Go马里奥克隆中玩家离开碰撞体后不下落的问题

问题根源

你当前的代码只在检测到与管道的Y轴碰撞时把playerGrounded设为true,但完全没处理「脱离所有管道碰撞」的场景——这就导致玩家离开管道后,程序还误以为玩家站在地面上,不会触发下落逻辑。

修复方案

核心思路

  1. 每帧先默认玩家不在地面,只有碰撞到支撑物(管道/地面)时才标记为grounded
  2. 补充地面碰撞逻辑,防止玩家无限下落
  3. 优化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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.19 13:30:40