简体   繁体   English

Java矩形碰撞相交(并非始终有效)

[英]Java Rectangle Collision Intersection (Not always working)

I'm currently working on a tile collision system for an RPG style game and it mostly working except for some inconsistency with rectangle intersection. 我目前正在为RPG风格的游戏开发瓷砖碰撞系统,除了矩形交点有些不一致以外,它大部分都可以正常工作。

protected void tileCollision() 
{  
    AnimatedSprite player = findPlayer();
    for(int i = 0; i < _sprites.size(); i++) 
    {
        AnimatedSprite spr = _sprites.get(i);
        for(int j = 0; j < tileWithinRange.length; j++) 
        {
            Tile tile = tileWithinRange[j];
            if(tile != null) 
            {       
                if(tile.getBounds().intersects(player.getBounds())) 
                {
                    player.setCollided(true);
                    tileCollision(player, tile, -1, -1);
                } else 
                {
                    player.setCollided(false);
                }
            }
        }
    }   
}

When I first collide with a tile upon launching the game, it always returns true, but if I move along a column of tiles, I start getting false returns and then after a while I only get false returns. 当我在启动游戏时第一次与图块发生碰撞时,它总是返回true,但是如果我沿着一列图块移动,我会开始获得错误的回报,然后过一会儿我只会获得错误的回报。

Here is an image of the player intersecting with a tile 这是播放器与图块相交的图像

There is an obvious intersection here, yet in this scenario, the variable collided returned false. 这里有一个明显的交集,但是在这种情况下,碰撞的变量返回false。

What is going wrong that the intersection isn't always registering?` 十字路口不总是注册是怎么回事?

There is too little info here to really know what's happening, but something looks fishy here: 这里的信息太少,无法真正知道正在发生什么,但是这里有些东西看起来很可疑:

     if(tile.getBounds().intersects(player.getBounds())) 
     {
        player.setCollided(true);
        tileCollision(player, tile, -1, -1);
     } else 
     {
        player.setCollided(false);
     }

Since you are checking multiple tiles against the player in a loop, what if the player collides with the first tile, but doesn't collide with the second tile? 由于您要在一个循环中针对玩家检查多个图块,因此如果播放器与第一个图块发生碰撞但不与第二个图块发生碰撞该怎么办? You'd end up calling player.setCollided(false); 您最终将调用player.setCollided(false); even though he collided with a former tile, overwriting that true collision state with a false one. 即使他与以前的瓷砖碰撞,也用false瓷砖覆盖了true碰撞状态。 That might explain the behavior you're getting where you're getting only false returns after a while (perhaps because of the order in which you are checking the tiles makes it so you keep overwriting true states with false states). 这可能解释了您得到的行为,过了一会儿您只会得到错误的返回(也许是因为检查图块的顺序使它返回,所以您始终用错误的状态覆盖真实的状态)。

I'm not sure if that's desirable or not to have these kinds of side effects, but it is a bit confusing at the very least to have this kind of collision state first being turned on and then overwritten with off within the same loop. 我不确定是否需要这种副作用,但是至少要使这种碰撞状态先打开然后在同一循环中被覆盖,至少有点令人困惑。 If that's undesirable behavior, perhaps what you're after needs you to break out of the loop if a collision occurs. 如果这是不受欢迎的行为,那么如果发生冲突,也许您要追求的是脱离循环。 Or perhaps what you want is something more like this: 也许您想要的是更多这样的东西:

    player.setCollided(false);
    for(int j = 0; j < tileWithinRange.length; j++) 
    {
        Tile tile = tileWithinRange[j];
        if(tile != null && tile.getBounds().intersects(player.getBounds())) 
        {
            player.setCollided(true);
            tileCollision(player, tile, -1, -1);
        }
    }
}

Or maybe your bounds/intersection function is genuinely malfunctioning -- it's too hard to tell with so little code/info (we don't know how these are implemented). 也许您的bounds / intersection函数确实有问题-很难用这么少的代码/信息来分辨(我们不知道这些是如何实现的)。

It's good to be able to isolate your code and learn how to construct test cases to test out individual functions in little pieces independently. 能够隔离您的代码并学习如何构造测试用例来独立地测试各个功能是一件好事。 You want to eliminate suspects through a process of elimination with a testing procedure that allows you to figure out, "Okay, this part works perfectly in every case, let's move on to the next thing." 您想通过一个消除过程的消除过程来消除可疑对象,该过程允许您弄清楚,“好吧,这部分在每种情况下都可以正常工作,让我们继续下一步。” Otherwise it becomes a guessing game trying to figure out what went wrong. 否则,它会变成一个猜谜游戏,试图找出问题所在。 One of the easiest ways to lose a time of time/productivity in development is to write a bunch of code first and then try to narrow down what went wrong in hindsight, instead of testing each little babystep. 在开发中浪费时间/生产力的最简单方法之一是首先编写一堆代码,然后尝试缩小事后的看法,而不是测试每个小的步骤。 Mistakes get more expensive the later you discover them and the more suspects you have to go through in an investigation. 错误发现的时间越长,您发现错误的可能性就越大,并且在调查中必须经历的疑犯也越多。

I ended up rewriting the method into a boolean which made it return true when colliding and false when not. 我最终将方法重写为一个布尔值,该值使碰撞时返回true,否则返回false。 Here is the new code. 这是新代码。

    public boolean tileCollision() {
    AnimatedSprite player = findPlayer();
    for(int j = 0; j < tileWithinRange.length; j++) {
        Tile tile = tileWithinRange[j];  
        if(tile != null) {
            if(tile.getTileBounds().intersects(player.getBounds()) ) {
                return true;
            }
        }
    }
    return false;
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM