Обнаружить, если спрайт покинул камеру в libgdx?

8

Есть ли способ узнать, если спрайт покинул камеру сцены? или я должен сделать мои операции? :П

Rudy_TM
источник

Ответы:

5

Класс Camera содержит объект Frustum с открытым методом pointInFrustum (точка Vector3), который возвращает значение true, если ваш спрайт находится в области усеченного пространства камеры. Вы также можете взглянуть на пользовательскую вики для других методов отбора. http://code.google.com/p/libgdx-users/wiki/Culling

Мадж
источник
2
pointInFrustum (point) возвращает true, если указанная точка находится внутри усеченного конуса, а не спрайта. Sprite может иметь собственную ширину и высоту, поэтому его нельзя проверить, чтобы он находился внутри экрана, используя этот метод напрямую.
Ариэльсан
@arielsan Пока вы можете проверить, находится ли точка внутри усеченного конуса, вы можете просто проверить, все ли точки спрайта находятся в усеченном конусе.
ТомЦагк
3

Если вы создаете 2D-игру с плитками, вы можете легко реализовать свою собственную отбраковку, которая намного дешевле, так как вы можете выбирать только то, что вам нужно в вашем массиве плиток.

Вещи, которые вы должны знать:

  • Расположение камеры
  • Ширина / высота области просмотра
  • Ширина / высота плитки

Теперь мы можем рассчитать, сколько плиток нужно нарисовать.

  • Всего горизонтальных плиток на экране = viewport.width / tileWidth
  • Всего вертикальных плиток на экране = viewport.height / tileHeight

Математика зависит от того, как все настроено, но очень проста. Например, имеет значение, если в центре экрана находится местоположение камеры, вверху слева или внизу слева.

Вы должны получить что-то вроде этого:

int startX = cameraWorldPosX / tileWidth;
int startY = cameraWorldPosY / tileHeight;

//When you have the position of the camera in the center of the screen you do something like this:

int startX = (cameraWorldPosX - viewport.width / 2) / tileWidth;
int startY = (cameraWorldPosY - viewport.height / 2) / tileHeight;

for (int y = startY; y < startY + viewportWidth / tileWidth; y++)
{
    for (int x = startX; x < startX + viewportHeight / tileHeight; x++)
    {
        //Draw logic
    }
}

Преимущество этого по сравнению с проверкой, находится ли точка в пределах вашего усеченного конуса, заключается в том, что с последним вам нужно выполнять итерацию по каждой точке вместо использования какого-либо простого массива, в котором вы всегда выполняете итерацию по установленному количеству плиток, равному количеству горизонтальных плиток. * вертикальные плитки, которые на самом деле нужно рисовать. Таким образом, вы можете иметь огромные карты и при этом иметь хорошую частоту кадров. К сожалению, это становится все сложнее и сложнее при использовании 3D, но экспоненциально усложняется со свободой, которую пользователь получает с камерой. Вы можете представить себе камеру с фиксированной перспективой, которая движется вместе с персонажем, и ей нужна пара жестко закодированных переменных, чтобы выполнить те же трюки с массивом сеток, представляющих вашу карту.

Madmenyo
источник
0

Просто используйте проверку ограничивающей сферы. (Вы можете рассчитать радиус с помощью Пифагора). Он быстр, как ад, а также работает с вращением. Это не идеально, но никогда не вызывает ложного отбора.

Для специальной оптимизированной версии Intersector имеет некоторые прямоугольники, содержащие методы rectanle, которые тоже могут работать. Но вам нужно рассчитать прямоугольник для камеры самостоятельно.

kalle_h
источник
0

Эта функция проверяет, является ли актер видимым (работает только для 2D). Работает во всех ситуациях, например, когда актер находится внутри группы.

    /**
     * Returns if the actor is visible or not. Useful to implement 2D culling.
     **/
    public static boolean actorIsVisible(Actor actor) {
        Vector2 actorStagePos = actor.localToStageCoordinates(new Vector2(0,0));
        Vector2 actorStagePosTl = actor.localToStageCoordinates(new Vector2(
            actor.getWidth(), 
            actor.getHeight()));

        Vector3 actorPixelPos = new Vector3(actorStagePos.x, actorStagePos.y, 0);
        Vector3 actorPixelPosTl = new Vector3(actorStagePosTl.x, actorStagePosTl.y, 0);

        actorPixelPos = actor.getStage().getCamera().project(actorPixelPos);
        actorPixelPosTl = actor.getStage().getCamera().project(actorPixelPosTl);

        return !(actorPixelPosTl.x < 0 ||
                 actorPixelPos.x > Gdx.graphics.getWidth() ||
                 actorPixelPosTl.y < 0 ||
                 actorPixelPos.y > Gdx.graphics.getHeight()
                );
    }
fermmm
источник