开发者

2D Collision Detection between squares, simple but more specific than boolean + immune to large spacial jumps

Would like to know which direction player hits terrain tile from (just a simple up/down, left/right). Everything I find is either too simple, or is much more complex and seemingly way too much for what I need, like with AABB (granted it's hard to tell, my brain has trouble digesting what amounts to really long equations). What I've got so far is the result of spending better part of today reading and experimenting:

public int move(double toX, double toY) {

    int col = COLLISION_NONE; //these are bit flags, in case I collide with a block to my right as well as below me

    double nextX = mX+(toX*main.getDelta()); //delta regulates speed
    double nextY = mY+(toY*main.getDelta());

    if(mTerrainCollision){

        int w = GameView.GameLoop.TILE_WIDTH;
        int h = GameView.GameLoop.TILE_HEIGHT;

        for(int i = -2; i <= 2; i++) //broad tile picking will be optimized later, better trace around players path
            for(int j = -2; j <= 2; j++) {
                GameTerrain.Block block = main.mTerrain.get(((int)Math.round(mX)/w)+i,((int)Math.round(mY)/h)+j);
                if(block.type != GameTerrain.BLOCK_TYPE_NONE) {

                    if(nextX+w >= block.x() && mX+w <= block.x()){ //COLLISION ON THE RIGHT?
                        if(mY+h > block.y() && mY < block.y()+h) { //<THIS is a problem line, see below
                            nextX = block.x() - w;
                            xMomentum = 0;

                            col |= COLLISION_RIGHT;
                        }
                    }

                    else if(nextX < block.x()+w && mX >= block.x()+w){ //COLLISION ON THE LEFT?
                        if(mY+h > block.y() && mY < block.y()+h) { //same as above, make sure were on the same plane
                            nextX = block.x() + w;
                            xMomentum = 0;

                            col |= COLLISION_LEFT;
                        }
                    }


                    if(nextY+h >= block.y() && mY+h <= block.y()){ //COLLISION ON THE BOTTOM?
                        if(mX+w > block.x() && mX < block.x()+w) { //make sure were on the same plane
                            nextY = block.y() - h;
                            yMomentum = 0;

                            col |= COLLISION_DOWN;
                        }
                    }

                    else if(nextY < block.y()+h && mY >= block.y()+h){ //COLLISION ON THE TOP?
                        if(mX+w > block.x() && mX < block.x()+w) { //make sure were on the same plane
                            nextY = block.y() + h;开发者_JS百科
                            yMomentum = 0;

                            col |= COLLISION_UP;
                        }
                    }
                }
            }
    }

    mX = nextX;
    mY = nextY; 

    return col;

}

It works... mostly. Player won't phase through blocks even after long sleeps making the delta skyrocket. The collision detection itself works unless the player's previous position (mX/mY) are not on the same plane as the block we're checking (see commented line with "THIS..."). Say we're perfectly diagonal to a block and moving straight for it, player will zip right through. I've been scratching my head for a while now trying to figure out how to go about solving this last issue, preferably without a major rehaul of everything, but if it had to come to that oh well! I'm only interested in simple collision data for things like "Did I touch a floor this frame? Ok I can jump", "Am I touching a wall right now? Ok I can wall jump, but not if I also touched a floor", etc.


Grow the wall's AABB by the size of the object's AABB (keeping the center of the wall's AABB fixed), construct a line segment from the object's before and after positions (use the center of the object's AABB), then do a segment-AABB intersection test.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜