Slick2D и JBox2D.Как рисовать - PullRequest
       34

Slick2D и JBox2D.Как рисовать

14 голосов
/ 03 апреля 2012

Прежде чем спросить об этом, я сделал МНОГО поиска в сети. Я просто не могу этого сделать. Мне немного сложно это понять. Итак, как мне нарисовать изображения в правильных положениях экрана, соответствующих телам в мировом положении? Thanx.

Если кто-то еще найдет себя перед тем же препятствием, я отправлю HOW TO, спасибо хорошему объяснению normalocity. Вы можете найти его здесь: http://romeo.akademx.ro/2012/04/06/slick-and-box2d/

Это функция рендеринга:

public void render(GameContainer container, StateBasedGame game, Graphics g)
        throws SlickException {
    g.setBackground(Color.white);

    g.pushTransform();
    g.translate(worldToScreen(body.getPosition()).x, worldToScreen(body.getPosition()).y);
    g.rotate(15, 15, (float) Math.toDegrees(body.getAngle()));
    part.draw();
    g.popTransform();

    g.drawString("Count: " + cont, 5, 40);
    //world.drawDebugData();
}

И это функция, которую я использую для преобразования координат мирового экрана:

public Vec2 screenToWorld(Vec2 screenV) {
    return new Vec2((screenV.x - offset.x) / scaleFactor, yFlip
            * (screenV.y - offset.y) / scaleFactor);
}

public Vec2 worldToScreen(Vec2 worldV) {
    return new Vec2(worldV.x * scaleFactor + offset.x, yFlip * worldV.y
            * scaleFactor + offset.y);
}

Мне также довелось использовать SlickDebugDraw по этой ссылке: http://slick.javaunlimited.net/viewtopic.php?f=19&t=3610&sid=69614ac53aaf5724b808b75173e8e48e

Но его DebugDraw рисует совсем другое, чем моя функция рендеринга. Я немного сбит с толку.

1 Ответ

64 голосов
/ 04 апреля 2012

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

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

  1. Каждый спрайт должен иметь свое местоположение в мире
  2. Ваша "камера" должна отслеживать свое местоположение относительно мира.

Итак, допустим, у вас есть большой, большой мир с пространством 2D-координат (x, y), равным 1 000 000 x 1 000 000 пикселей (здесь я использую пиксели в качестве единицы измерения, но это произвольный выбор, и размер мира не имеет значения, я только что выбрал большой). Затем, скажем, у вас есть «камера», которая указывает на этот мир, и вид этой камеры - это то, что отображается на вашем экране. Дисплей, который дает камера, имеет размер 1024x768 пикселей.

Скажем также, что вы используете клавиши со стрелками для перемещения камеры по всему миру.

Итак, ваше координатное пространство в мире отображается на вашем экране следующим образом:

(0, 0)        +x
      +------------------>
      |
   +y |
      |      *  <= example sprite in your world @ coordinates (x=200, y=200)
      |
     \ /

Когда ваши спрайты перемещаются "вправо", они увеличивают свою x координату. Когда они двигаются «влево», они уменьшают свою x координату. При перемещении "вверх" они уменьшают их y координату (потому что y увеличивается вниз, на мониторах), а при перемещении "вниз" спрайтов увеличивают их y координату .

Теперь, опять же, то, что вы видите на нашем экране, это просто изображение с камеры. Итак, давайте установим, что верхний левый угол камеры находится на (x=500, y=500). Это будет выглядеть примерно так:

(0, 0)        +x
      +---------------------------------->
      |
   +y |
      |      *  <= example sprite in your world @ coordinates (x=200, y=200)
      |
      |
      |         +===================+
      |         |     the area      |
      |         |  that the camera  |
      |         |    "sees" and     |
      |         |   shows on your   |
      |         |       screen      |
      |         +===================+
     \ /

С этой настройкой, скажем, камера находится в точке (500, 500) (то есть верхний левый угол обзора камеры, как показано в этом примере, находится в мировых координатах (500, 500). А поскольку камера показывает область размером 1024x768, противоположный нижний правый угол (500 + 1024, 500 + 768) = (x=1524, y=1268).

Обратите внимание, что спрайт в нашем мире , а не в области обзора этой камеры. Это означает, что когда мы визуализируем вид камеры на экране, мы не увидим спрайт.

Если вместо этого камера переместится на (200, 200), то область обзора камеры будет охватывать мировые координаты от верхнего левого угла @ (200, 200) до нижнего правого угла @ (1224, 968), и выглядеть примерно так:

(0, 0)        +x
      +---------------------------------->
      |   
   +y |  +===================+
      |  |                   |
      |  |   * <= sprite     |
      |  |                   |
      |  |                   | <= camera's view of the world
      |  +===================+
      |
      |
      |
      |
     \ /

Когда камера находится в этом положении, спрайт виден. Если спрайт равен @ (500, 500), а камера - (200, 200), то когда мы рисуем спрайт на экране, спрайт появится, на нашем экране в координатах 300, 300.

Почему?

Потому что, и это действительно ответ на ваш вопрос, , где , который вы рисуете на экране - это спрайт в мире (500, 500), минус местоположение камеры (200, 200), что равно (300, 300).

Итак, для обзора:

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

Но есть еще одна вещь ...

Это действительно неэффективно рисовать всех спрайтов в мире. Вам нужно только нарисовать спрайты, которые находятся в поле зрения камеры, в противном случае вы рисуете то, что не видите на экране, и, следовательно, тратите впустую время рендеринга / CPU / GPU.

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

Чтобы сделать это, вы должны взять размеры вашей камеры (1024x768, в нашем примере) и проверить, чтобы увидетьесли позиция спрайта находится внутри прямоугольника вида камеры - это позиция верхнего левого угла камеры, плюс ширина и высота камеры.

Итак, если наша камера показывает нам вид с разрешением 1024x768 пикселейпо размеру, и его верхний левый угол находится в (200, 200), тогда прямоугольник вида:

(200, 200)                      (1224, 200)
           +===================+
           |                   |
           |    *              |
           |                   |
           |                   |
           +===================+
(200, 968)                      (1224, 968)

Позиция спрайта @ (500, 500) находится в пределах видимости камеры, в этом случае.

Если вам нужно больше примеров, у меня есть рабочая техническая демонстрация Slick2D под названием Pedestrians , в которой есть код, который вы можете посмотреть.Для получения подробной информации о том, как я вычисляю площадь мира, которая должна быть визуализирована, посмотрите на метод render внутри этого файла и обратите особое внимание на startX, startY, stopXstopY переменных, которые для меня контролируют область спрайтов, которые я собираюсь нарисовать.Также следует отметить, что мои спрайты (или «пешеходы») существуют на TileMap, поэтому они не имеют размер 1 пиксель - они имеют собственную ширину и высоту.Это добавляет небольшую сложность к тому, как решить, что рисовать, но в основном сводится к «рисовать то, что в поле зрения камеры, плюс немного больше по краям».

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

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

...