Java: ошибка в коде обнаружения столкновений в 2D мире - PullRequest
0 голосов
/ 23 марта 2012

это вторая игра, с которой у меня возникают проблемы в той же области ... первая, я даже не знаю, как я это исправил.Система координат также была в двойных числах.

Это код «обновления» для класса физики, который будет унаследован всеми объектами в мире (игроками, врагами, предметами).Все эти объекты должны быть в состоянии подчиняться столкновениям с миром, поэтому ... когда у них есть xSpeed ​​или ySpeed, эта часть кода будет запускаться для применения и "привязывать" объект в правильное пространство, если он попадает в тело(дублированное состояние 2) плитка мира.Размер каждой плитки мира составляет 20х20 пикселей.

Проблема: она отлично работает, за исключением ...

, если вы привязываетесь к нужной плитке, то вы не можете двигаться вверх или вниз.(хотя вы можете двигаться влево, а затем двигаться вверх или вниз)

если вы привязываетесь к нижней плитке, то вы не можете двигаться влево или вправо.(хотя вы можете двигаться вверх, а затем двигаться влево или вправо)

    if(xSpeed<0){
        try{
            int dest = hitbox.x + (int)(xSpeed/20*tick);
            if(Ids.tiles[world[dest/20][hitbox.y/20]].getState() == 2 || Ids.tiles[world[dest/20][(hitbox.y+hitbox.width)/20]].getState() == 2){
                hitbox.x = (int)Math.ceil(dest/20.)*20;
                xSpeed = 0;
            }else{
                hitbox.x += (int)(xSpeed/20*tick);
            }
        }catch(Exception e){
            hitbox.x += (int)(xSpeed/20*tick);
        }
    }else if(xSpeed>0){
        try{
            int dest = hitbox.x+hitbox.width+(int)(xSpeed/20*tick);
            if(Ids.tiles[world[dest/20][hitbox.y/20]].getState() == 2 || Ids.tiles[world[dest/20][(hitbox.y + hitbox.width)/20]].getState() == 2){
                hitbox.x = dest/20*20 - hitbox.width;
                xSpeed = 0;
            }else{
                hitbox.x += (int)(xSpeed/20*tick);
            }
        }catch(Exception e){
            hitbox.x += (int)(xSpeed/20*tick);
        }
    }

    if(ySpeed<0){
        try{
            int dest =  hitbox.y + (int)(ySpeed/20*tick);
            if(Ids.tiles[world[hitbox.x/20][dest/20]].getState() == 2 || Ids.tiles[world[(hitbox.x + hitbox.width)/20][dest/20]].getState() == 2){
                hitbox.y = (int)Math.ceil(dest/20.)*20;
                ySpeed = 0;
            }else{
                hitbox.y +=  (int)(ySpeed/20*tick);;
            }
        }catch(Exception e){
            hitbox.y +=  (int)(ySpeed/20*tick);;
        }
    }else if(ySpeed>0){
        try{
            int dest = hitbox.y + hitbox.height +  (int)(ySpeed/20*tick);
            if(Ids.tiles[world[hitbox.x/20][dest/20]].getState() == 2 || Ids.tiles[world[(hitbox.x + hitbox.width)/20][dest/20]].getState() == 2){
                hitbox.y = dest/20*20 - hitbox.height;
                ySpeed = 0;
            }else{
                hitbox.y +=  (int)(ySpeed/20*tick);;
            }
        }catch(Exception e){
            hitbox.y +=  (int)(ySpeed/20*tick);;
        }
    }

1 Ответ

1 голос
/ 23 марта 2012

Рассмотрим, что происходит при столкновении с правым краем (движение вправо). Это условие проходит:

Ids.tiles[world[dest/20][hitbox.y/20]].getState() == 2

Предположим, что hitbox.width равно 5. Тогда это вернет истину, как только hitbox.x равно 15. Но затем вы сбросите hitbox.x на dest/20*20 - hitbox.width, что будет именно там, где оно уже есть. Затем, в вертикальном направлении, если объект перемещается, то его правый край уже сталкивается с плитками, поэтому он не может двигаться.

Чтобы исправить это, вычтите 1 пиксель из размера хитбокса при его использовании для поиска позиций сетки - конечно, перед делением.

Если бы вы работали в координатах с плавающей точкой, то вы бы использовали Math.ceil((hitbox.x + hitbox.width)/20.0) - 1 для получения аналогичного эффекта без произвольного эпсилона.

...