碰撞检测系统

时间:2012-06-17 20:40:44

标签: c#-4.0 xna

我正在努力制作一款简单的平台游戏。玩家是一个正方形,所有平台都是正方形。我是XNA的初学者,但我有适度的C#4.0体验。

我的代码存在的问题是,当我的角色穿过平台的底部时,即使我将其设置为不应该这样,他仍会继续经历。

事先我想问一下是否有人可以帮助我,因为我无法解决这个问题。

以下是不同的代码片段如何协同工作:

  • 在平台结构中加载图像并存储枚举,其中可以包含以下三个值中的一个:可通过(可以通过),无法通过(完全固定)和平台(可以通过底部并停在顶部)< / LI>
  • 需要修复的碰撞检测方法(它检查交叉点,检查该特定平台的枚举,然后确定它是否可以通过并返回包含以下内容的数组:{isabove,isbelow,isleft,是平台的)
    • 如果玩家位于平台顶部但是当他们触及底部时没有任何反应
    • ,则返回true
  • 我的玩家垂直运动处理引力和垂直运动,它可能是罪魁祸首,但我无法分辨。碰撞检查在开始的更新循环中运行,然后运行垂直运动方法

以下是碰撞的代码:

    public bool[] environmentCollisionDetect(Charachter thing, ScreenObjects sreenobjectlist, bool[] platformstatus)
    {
        //Defaults the collision to false
        platformstatus[0] = false;  //Above platform
        platformstatus[1] = false;  //Below Platform
        platformstatus[2] = false;  //Left
        platformstatus[3] = false;  //Right

        //Store the player in boxA
        boxA.Height = thing.image.Height;
        boxA.Width = thing.image.Width;
        boxA.X = (int)thing.position.X;
        boxA.Y = (int)thing.position.Y;

        //Find a collision
        foreach (Platform platform in screenobjectlist)
        {
            //Makes sure the platform cannot be passed through
            if (platform.platformCollisionProperty != platformCollision.passable)
            {
                //Store the platform's rectangle
                boxB = platform.destinationrectangle;
                boxB.Height = platform.image.Height;
                boxB.Width = platform.image.Width;
                boxB.X = (int)platform.destinationrectangle.X;
                boxB.Y = (int)platform.destinationrectangle.Y;

                //Collision Check
                if (boxA.Intersects(boxB))
                {
                    switch (platform.platformCollisionProperty)
                    {
                        //Platform is Solid
                        case platformCollision.impassible:

                            //Player is below it
                            if (boxA.Top > boxB.Bottom)
                            {
                                platformstatus[1] = true;
                            }

                            //Player is above it
                            if (boxA.Bottom > boxB.Top)
                            {
                                platformstatus[0] = true;
                            }
                            break;

                        //Platform can be passed through bottom
                        case platformCollision.platform:
                            if (boxA.Bottom > boxB.Top)
                            {
                                platformstatus[0] = true;
                            }
                            break;
                    }

                    break;
                }
            }
        }
      return platformstatus;
    }

这是垂直运动代码:

  • 激活跳转按钮时,isJumping bool设置为true
  • isinair bool仅在此循环中用于确定玩家是否仍然在空中滑行
  • 最后我被用作计数器,因为我无法使用计时器

    public void verticalMotionI(GameTime gametime)
    {
        //Resets the bools if not standing on platform
        if ((this.isJumping == true) && (this.platformstatus[0] == false))
        {
            this.i = 0;
            this.isJumping = false;
            this.isinair = false;
        }
    
        //Jumps if A button is activated and standing on a platform
        else if ((this.isJumping == true) && (this.platformstatus[0] == true))
        {
            //Set up bools to jump
            this.isJumping = false;
            this.isinair = true;
    
            //Overwrites the start time
            this.starttime = currentime;
    
            //Move up
            this.position.Y -= this.playermovementspeed * 1.5f;
    
            //Increase counter
            this.i++;
        }
    
        //Pulls stops moving player if jumptimer had elapsed
        else if ((this.isinair == true) && (i == this.jumptime))
        {
            this.isinair = false;
    
            //Apply gravity
            Gravity.forceofGravity(this);
        }
    
        //Stops the jump if bottom of a platform is hit
        else if ((this.isinair == true) && (this.platformstatus[1] == true))
        {
            //Reset bools
            this.isinair = false;
    
            //reset I
            this.i = 0;
    
            //Apply gravity
            Gravity.forceofGravity(this);
        }
    
        //Continues the jump if in air
        else if ((this.isinair == true) && (this.platformstatus[1] == false))
        {
            //Move up
            this.position.Y -= this.playermovementspeed * 1.5f;
    
            //Increase counter
            this.i++;
        }
    
        //Apply Gravity
        else if ((this.isinair == false) && (this.platformstatus[0] == false))
        {
            //reset I
            this.i = 0;
    
            Gravity.forceofGravity(this);
        }
    }
    

2 个答案:

答案 0 :(得分:0)

如果Gravity做了我的假设,看起来你没有明确设置玩家在撞击平台时的位置,我看到的是你的切换你的isInAir标志,并应用重力...出于测试目的和解决你的问题,试试像这样的伪代码:

if(dude is jumping & dude collides with platform){
   set the top of dudes head to be at position under the platform;
}
希望这可以提供帮助。 :)

不要击败死马或屁股,但你正在重新发明轮子。看看那里的一些物理引擎。我一直在玩Farseer 3+,这太棒了。在第一次弄清楚World Body Fixture模式时会有一个轻微的学习曲线,但是一旦你有了顿悟,那么在你的身体/固定装置上设置一些属性并启动OnCollision方法将是蛋糕。

Farseer是一个面向.NET的Box2D物理引擎端口,它是开源的,一旦你完成学习曲线,它就太棒了。

快速查看this farseer doc,你可能会喜欢你所看到的。 :) 即使你不爱它,它也是开源的,可以给你一些关于如何*咳嗽*复制*实现一些功能的想法。

如果你想要的只是一个简单的跳跃,对象状态和交互功能,你就不需要实现引擎的所有有趣的复杂性,这些功能都很好地包含在Farseer中。

答案 1 :(得分:0)

if (boxA.Top > boxB.Bottom) - 如果boxA.Intersects(boxB),这种情况永远不会成立。您的意思是if (boxA.Top < boxB.Bottom && boxA.Top > boxB.Center.Y)吗?

将我的评论探索重新发布作为未来参考的答案。由于我有答案的空间而不是评论,我也可以解释一些事情。

显然,Rectangle.Intersects(Rectangle)只有在某种程度上重叠时才会成立。诀窍在于,在解释时,我们需要记住屏幕上的Y坐标实际上是从上到下移动。 Y = 0位于屏幕顶部,Y =位于屏幕顶部。如果您不熟悉2D游戏编程,这可能看起来倒退,但这只是图形适配器的工作方式。

因此,通过说boxA的顶部是&gt;在boxB的底部,你真正说的是boxA的顶部位于屏幕上boxB的底部之下,由于我们已经知道它们重叠,因此永远不会是真的。我转过条件并添加了一个额外的逻辑点,以提供所需的功能。 boxA.Top > boxB.Center.Y表示您的boxA特别与位于框B之间相交。如果我把它保留为boxA.Top < boxB.Bottom,如果boxA从上面 boxB掉落,则条件也是如此,我认为你不认为我们必须区分平台和实体涉及到磁贴下方的播放器的逻辑块,因此我们必须在代码中进行区分。当然,您的评论也是//player is below it

最后,一句调试建议:如果您发现某些行为未发生,请在指示该行为的行(在本例中为platformstatus[1] = true)放置一个断点。如果你从未打过那个断点,你就知道为什么它没有发生。现在只需在封闭的条件上放置一个断点。当它到达该断点时,手动查看值,将它们与预期值进行比较,并查看是否使用了适当的逻辑。每个人有时会在条件错误中出错,这是我个人的第一个弱点之一。

相关问题