Ошибка положения рендеринга экрана SDL вдоль верхней части окна

Я делаю изометрическую игру сверху вниз, используя SDL 2.0 и C ++, и столкнулся с проблемой.

Когда текстура отображается на экране с помощью SDL_RenderCopyфункция, в тот момент, когда верх текстуры достигает верхней части экрана, он отталкивается на один пиксель, что приводит к отсутствующим границам, показанным на следующем рисунке:

Предварительное редактирование без аннотаций

Постредактировать с аннотациями

Ниже приведена моя функция рендеринга, специфичная для самого мира, так как мир рендерит иначе, чем все остальное в игре, потому что я просто копирую текстуру «источник» вместо загрузки текстуры для каждой плитки в игре, что будет нелепо неэффективно.

//-----------------------------------------------------------------------------
// Rendering

DSDataTypes::Sint32 World::Render()
{
//TODO: Change from indexing to using an interator (pointer) for efficiency
for(int index = 0; index < static_cast<int>(mWorldSize.mX * mWorldSize.mY); ++index)
{
const int kTileType = static_cast<int>(mpTilesList[index].GetType());

//Translate the world so that when camera panning occurs the objects in the world will all be in the accurate position

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

(код сверху сразу продолжен ниже)

        mpTilesList[index].SetRenderOffset(Window::GetPanOffset());

//position (dstRect)
SDL_Rect position;
position.x = static_cast<int>(mpTilesList[index].GetPositionCurrent().mX + Window::GetPanOffset().mX);
position.y = static_cast<int>(mpTilesList[index].GetPositionCurrent().mY + Window::GetPanOffset().mY);
position.w = static_cast<int>(mpTilesList[index].GetSize().mX);
position.h = static_cast<int>(mpTilesList[index].GetSize().mY);

//clip (frame)
SDL_Rect clip;
clip.x = static_cast<int>(mpSourceList[kTileType].GetFramePos().mX);
clip.y = static_cast<int>(mpSourceList[kTileType].GetFramePos().mY);
clip.w = static_cast<int>(mpSourceList[kTileType].GetFrameSize().mX);
clip.h = static_cast<int>(mpSourceList[kTileType].GetFrameSize().mY);

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

(код сверху сразу продолжен ниже)

        //Check to ensure tile is being drawn within the screen size. If so, rendercopy it, else simply skip over and do not render it.
//If the tile's position.x is greather than the left border of the screen
if(position.x > (-mpSourceList[kTileType].GetRenderSize().mX))
{
//If the tile's position.y is greather than the top border of the screen
if(position.y > (-mpSourceList[kTileType].GetRenderSize().mY))
{
//If the tile's position.x is less than the right border of the screen
if(position.x < Window::msWindowSize.w)
{
//If the tile's position.y is less than the bottom border of the screen
if(position.y < Window::msWindowSize.h)
{
SDL_RenderCopy(Window::mspRenderer.get(), mpSourceList[kTileType].GetTexture(), &clip, &position);
}
}
}
}
}

return 0;//TODO
}

0

Решение

У вас может быть ошибка округления, когда вы переводите позиции в целые. Возможно, вам следует округлить до ближайшего целого числа вместо того, чтобы просто взять слово (что и делает ваш актерский состав). Плитка в позиции (0,8, 0,8) будет отображаться в пикселе (0, 0), когда ее, вероятно, следует рендерить в позиции (1, 1).

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

0

Другие решения

Краткий вариант ответа, изложенный внизу:

  • От исправление моей проблемы типов данных, это позволило мне исправить мою математическую библиотеку, Это устранило проблему округления частей пикселей, поскольку при рендеринге не существует такой вещи, как меньше 1, но больше 0 пикселей.

Длинный ответ:

Я полагаю, что проблема была вызвана ошибкой округления с помощью логики смещения, используемой при повороте двумерной сетки в диагональную изометрическую перспективу, причем ошибка округления возникает только при работе с координатами экрана между -1 и +1.

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

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

Причиной всего этого является то, что моя математическая библиотека, которая была шаблонизирована, имела проблему, поскольку большая часть моего кода была основана на пользовательских типах, таких как:

typedef unsigned int Uint32;
typedef signed int Sint32;

Так что я просто использовал DSMathematics::Vector2<float> вместо правильной реализации DSMathematics::Vector2<int>,

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

От исправление моей проблемы типов данных, это позволило мне исправить мою математическую библиотеку, Это устранило проблему округления частей пикселей, поскольку при рендеринге не существует такой вещи, как меньше 1, но больше 0 пикселей.

0