0

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

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

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

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

  • 在平台结构中加载图像并存储一个枚举,它可以保存三个值之一:可通过(可以通过)、不可通过(完全实心)和平台(可以通过底部并停在顶部)
  • 需要修复的碰撞检测方法(它检查交叉点,检查该特定平台的枚举,然后确定它是否可以通过并返回一个数组,其中包含:{isabove, isbelow, isleft, isright}该平台)
    • 如果玩家在平台顶部,它确实返回 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);
        }
    }
    
4

2 回答 2

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 模式时有一个轻微的学习曲线,但是一旦你有了顿悟,就可以在你的 body/fixture 上设置一些属性并启动 OnCollision 方法。

Farseer 是 .NET 的 Box2D 物理引擎端口,它是开源的,一旦你完成了学习曲线,它就会令人惊叹。

快速浏览一下这个farseer doc,你可能会喜欢你所看到的。:) 即使您不喜欢它,它也是开源的,并且可以为您提供一些关于如何*咳嗽*复制* 以您自己的方式实现某些功能的想法。

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

于 2012-06-19T17:21:49.880 回答
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 的顶部 > boxB 的底部,您实际上是在说 boxA 的顶部在屏幕上 boxB 的底部下方,这永远不会是真的,因为我们已经知道它们重叠。我转过条件并添加了一个额外的逻辑点,以提供所需的功能。boxA.Top > boxB.Center.Y表示您的 boxA在 boxB下方专门相交。如果我将其保留为 just ,则如果 boxA 从 boxB上方boxA.Top < boxB.Bottom掉落,则条件也为真,考虑到我们必须区分平台和实体块以实现涉及瓷砖下方玩家的逻辑,我认为您不希望这样做,所以我们必须在代码中做出这种区分。另外,当然,您的评论说。//player is below it

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

于 2012-06-20T13:12:22.847 回答