首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >碰撞检测系统

碰撞检测系统
EN

Stack Overflow用户
提问于 2012-06-17 20:40:44
回答 2查看 243关注 0票数 0

我试着做一个简单的平台游戏。玩家是正方形的,所有的平台都是正方形的。我是一个初学者在XNA,但我有温和的C# 4.0经验。

我的代码的问题是,当我的角色通过一个平台的底部时,他会继续通过,即使我设置了它,所以他不应该这样做。

在此之前,我想问一下,是否有人能帮助我,因为我不能解决这个问题。

下面是不同代码块是如何协同工作的:

  • 在平台结构中,图像被加载并存储一个枚举,它可以保存三个值中的一个:可通过(可以通过)、无法通过(完全固态)和平台(可以通过底部并在顶部停止)。
  • 一种需要固定的碰撞检测方法(它检查交叉点,检查该特定平台的枚举,然后确定它是否可以通过,并返回一个数组,其中包含:{ it,isleft,isright} ) 。
    • 如果玩家在平台的顶部,它会返回真,但是当他们到达底部时不会发生任何事情。

  • 我的玩家的垂直运动,它处理重力和垂直运动,它可能是罪魁祸首,但我不知道。碰撞检查在更新循环的开头运行,然后运行垂直运动方法。

以下是碰撞的代码:

代码语言:javascript
复制
    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仅在此循环中使用,以确定玩家是否仍在空中滑行。
  • 最后,我被用作柜台,因为我无法让计时器工作 公共无效verticalMotionI(GameTime游戏时间){//重置如果不站在平台上的bools ((this.isJumping == true) & (this.platformstatus == false)) { this.i = 0;this.isJumping = false;this.isinair = false;}//跳转如果一个按钮被激活并站在一个平台上,如果((this.isJumping == true) & (this.platformstatus == true)) {//设置bools以跳this.isJumping = false;this.isinair = true;//覆盖启动时间this.starttime = currentime;//向上移动.//增加计数器this.i++;}//如果jumptimer已过,则停止移动播放器,如果((this.isinair == true) & (i == this.jumptime)) { this.isinair = false;//应用重力Gravity.forceofGravity(this);}//如果平台底部被击中,//停止跳转,如果((this.isinair == true) & (this.platformstatus1 == true)) { //Reset bools this.isinair = false;//reset I this I= 0;//应用重力Gravity.forceofGravity(this);}//继续跳转如果在空中,如果((this.isinair == true) & (this.platformstatus1 == false)) {//向上移动这个位置。Y -= this.playermovementspeed * 1.5f;//增加计数器this.i++;}//应用重力,否则如果((this.isinair == false) & (this.platformstatus == false)) {//重置I-I= 0;Gravity.forceofGravity(this);}}
EN

回答 2

Stack Overflow用户

发布于 2012-06-19 17:21:49

如果重力做了我假设的事情,它看上去不像你在平台上显式地设置播放器的位置,我看到的是你切换你的isInAir标志,并应用重力.为了进行测试并解决您的问题,请尝试类似于以下伪代码:

代码语言:javascript
复制
if(dude is jumping & dude collides with platform){
   set the top of dudes head to be at position under the platform;
}

希望这能帮上忙。:)

不是为了打败一匹死马,也不是做一只驴,而是你在重新发明轮子。看看外面的一些物理引擎。我一直在和法西埃3+玩,这太棒了。当你第一次计算出世界身体夹具模式时,会有一条轻微的学习曲线,但是一旦你有了顿悟,就可以在你的身体/固定装置上设置一些属性,并启动OnCollision方法。

Farseer是Box2D物理引擎到.NET的端口,它是开源的,一旦你完成了学习曲线,它就会很神奇。

快速查看一下这个法西尔医生,您可能会喜欢您所看到的。即使你不喜欢它,它也是开源的,它可以给你一些关于如何*咳嗽*复制*用你自己的扭曲实现一些功能的想法。

如果您只需要一个简单的跳转、对象状态和交互功能,那么您就不需要实现引擎的所有有趣的复杂功能,这些功能都很好地封装在Farseer中。

票数 0
EN

Stack Overflow用户

发布于 2012-06-20 13:12:22

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下面特别相交。如果我只把它作为boxA.Top < boxB.Bottom,那么如果boxA是从boxB上掉下来的话,条件也是正确的,我认为您不想这样做,因为我们必须区分平台和实体块,以便在代码中对涉及玩家的逻辑进行区分。当然,你的评论中还提到了//player is below it

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

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/11074630

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档