Проблема рендеринга изометрических плиток XNA - PullRequest
0 голосов
/ 01 декабря 2010

В настоящее время я работаю над прототипом игры XNA.Я пытаюсь получить изометрический вид игрового мира (или это отографическое? Я не уверен, какой термин подходит для этой проекции - см. Рисунки).Мир должен основываться на мире плиток из кубических плиток (например, похожем на мир Майнкрафта), и я пытаюсь отобразить его в 2D с использованием спрайтов.

Итак, у меня есть лист спрайтов с верхней граньюкуба, лицевой стороны и боковой (видимой стороны) грани.Я рисую плитки, используя 3 отдельных вызова drawSprite, один для верха, один для стороны, один для фронта, используя исходный прямоугольник, чтобы выбрать грань, которую я хочу нарисовать, и целевой прямоугольник, чтобы установить положение на экране в соответствии св формулу для преобразования из трехмерных мировых координат в изометрические (орфографические?).

(пример спрайта: Sprite)

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

Обратите внимание, что для моего представления мира X слева направо, Y находится внутри экрана снаружиэкран, а Z вверх-вниз.

В этом примере я работаю только с верхними гранями.Вот что я получаю (рисунок):

alt text

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

/// <summary>
/// Draws the world
/// </summary>
/// <param name="spriteBatch"></param>
public void draw(SpriteBatch spriteBatch)
{
    Texture2D tex = null;

    // DRAW TILES
    for (int z = numBlocks - 1; z >= 0; z--)
    {
        for (int y = 0; y < numBlocks; y++)
        {
            for (int x = numBlocks - 1; x >=0 ; x--)
            {

                myTextures.TryGetValue(myBlockManager.getBlockAt(x, y, z), out tex);
                if (tex != null)
                {
                    // TOP FACE
                    if (z == 0)
                    {
                        drawTop(spriteBatch, x, y, z, tex);
                        drawTop(spriteBatch, x, y, z, outlineTexture);
                    }

                    // FRONT FACE
                    if(y == numBlocks -1)
                        drawFront(spriteBatch, x, y, z, tex);

                    // SIDE FACE
                    if(x == 0)
                        drawSide(spriteBatch, x, y, z, tex);

                }
            }
        }
    }
}


private void drawTop(SpriteBatch spriteBatch, int x, int y, int z, Texture2D tex)
        {
            int pX = OffsetX + (int)(x * TEXTURE_TOP_X_OFFRIGHT + y * TEXTURE_SIDE_X);
            int pY = OffsetY + (int)(y * TEXTURE_TOP_Y + z * TEXTURE_FRONT_Y);
            topDestRect.X = pX;
            topDestRect.Y = pY;
            spriteBatch.Draw(tex, topDestRect, TEXTURE_TOP_RECT, Color.White);   
        }

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

Результаты как-то лучше, но все еще не работают должным образом, верхние строки отсутствуют, см. рисунок:

alt text

Есть идеи, почему у меня такая проблема?При первом подходе это может быть своего рода z-боем, но я рисую спрайты в точном порядке, поэтому не должны ли они перезаписать то, что уже есть?

Спасибо всем

Ответы [ 3 ]

1 голос
/ 01 декабря 2010

Ой, извините, ребята, я идиот :) Я запустил пакет с помощью SpriteBatch.begin (SpriteSortMode.BackToFront), но я не использовал z-значение при рисовании. Я должен был использовать SpriteSortMode.Deferred! Сейчас работает нормально. Спасибо всем!

0 голосов
/ 01 декабря 2010

Похоже на субпиксельную точность или проблему масштабирования.Также постарайтесь убедиться, что ваша текстура / ширина / высота плитки равна степени 2 (32, 64, 128 и т. Д.), Поскольку это также может сделать эффект менее плохим.По этим фотографиям очень трудно отличить.

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

0 голосов
/ 01 декабря 2010

Попробуйте изменить размеры исходного и конечного прямоугольников на 1 или 2 пикселя.У меня есть скрытое подозрение, что это как-то связано с тем, как эти прямоугольники обрабатываются как своего рода «контуры» области, которую нужно визуализировать, и некой единственной проблемой.Это не совет специалиста, а интуиция другого программиста.

...