Я пытаюсь создать изометрическую игру в графической библиотеке SDL.
При рендеринге в SDL требуется исходный прямоугольник и целевой прямоугольник. Исходный прямоугольник — это часть текстуры, которую вы загрузили, которую вы хотите визуализировать, а целевой прямоугольник — это область на экране, которую вы визуализируете. Прямоугольники просто состоят из 4 свойств, положения X, положения Y, ширины и высоты.
Теперь скажите, что у меня есть прямоугольный прямоугольник с этими координатами:
X = 20, Y = 10, ширина = 16, высота = 16
Теперь скажите, что я хотел преобразовать это в Изометрические. Для преобразования координат X и Y я бы использовал:
isometricX = cartX - cartY;
isometricY = (cartX + cartY) / 2;
Теперь я не понимаю, что бы я сделал, чтобы преобразовать декартову ширину и высоту в изометрическую ширину и высоту, чтобы создать иллюзию того, что порт обзора перемещается на 45 градусов в одну сторону и на 30 градусов вниз, создавая изометрический вид.
РЕДАКТИРОВАТЬ:
Я хотел бы немного уточнить свой вопрос, поэтому, когда я преобразовываю декартовы координаты в изометрические, я изменяю это:http://i.stack.imgur.com/I79yK.png
к этому:http://i.stack.imgur.com/ZCJg1.png. Итак, теперь я пытаюсь выяснить, как вращать плитки, чтобы они все совпали, и как мне нужно отрегулировать высоту и ширину, чтобы это произошло.
Для начала вам понадобятся следующие операции для преобразования в и изометрические координаты:
isoX = carX + carY;
isoY = carY - carX / 2.0;
carX = (isoX - isoY) / 1.5;
carY = isoX / 3.0 + isoY / 1.5;
прямоугольные углы в верхнем левом и нижнем правом углу становятся 120 градусов, остальные два угла становятся 60 градусов. нижний правый угол становится нижним, верхний левый угол становится верхним. это также предполагает, что у увеличивается с ростом, а х увеличивается с направлением (если ваша система отличается, поменяйте знаки соответственно). посредством подстановки вы можете проверить, что эти операции являются обратными.
для прямоугольника вам нужно преобразовать 4 точки — углы — поскольку они не будут «прямоугольными» для целей SDL (это будет параллелограмм). это легче увидеть численно.
во-первых, присвойте углам имена какого-либо рода. я предпочитаю по часовой стрелке, начиная с левого нижнего угла — эта координата должна быть известна как C1, и имеет связанные X1 и Y1, остальные будут C2-4.
C2 - C3
| |
C1 - C4
затем вычислите их декартовы координаты …
X1 = RECT.X;
Y1 = RECT.Y;
X2 = X1; // moving vertically
Y2 = RECT.Y + RECT.HEIGHT;
X3 = RECT.X + RECT.WIDTH;
Y3 = Y2; // moving horizontally
X4 = X3; // moving vertically
Y4 = RECT.Y;
и, наконец, применить преобразование индивидуально к каждой координате, чтобы получить координаты I1, I2, I3, I4 …
iX1 = X1 + Y1;
iY1 = Y1 - X1 / 2.0;
// etc
и в результате вы получите экранные координаты I1-4, которые принимают эту форму:
I2
/ \
I1 I3
\ /
I4
Но в отличие от этого некачественного изображения, углы для I4 и I2 будут ~ 127 градусов, а для I1 и I3 — ~ 53 градуса. (это может быть точно настроено, чтобы быть точно 60/120, и зависит от коэффициента 2.0 для carX при вычислении isoY — это должно быть sqrt (3), а не 2.0, но достаточно близко)
если вы используете обратное преобразование, вы можете превратить координаты I1-4 в C1-4 или определить координату мира из экранной координаты и т. д.
реализация камеры / видового экрана становится немного сложнее, если только поначалу, но это выходит за рамки того, о чем просили, поэтому я не пойду туда (без дальнейших подталкиваний) …
(Редактировать) Что касается SDL …
SDL не «хорошо играет» с обобщенными преобразованиями. Я не использовал его, но его интерфейс удивительно похож на GDI (windows), с которым я играл ранее для игрового движка и столкнулся с этой проблемой (вращение + масштабирование текстур).
Существует одна (кажется, нестандартная) функция SDL, которая выполняет масштабирование и вращение текстур, но делает это в неправильном порядке, поэтому всегда поддерживает перспективу изображения, и здесь это не то, что нужно.
Как вы уже видели, базовая геометрия будет в порядке, потому что это заливки и линии, которые не нужно масштабировать, а только позиционировать. Но для текстур … Вам нужно будет либо написать код для визуализации текстуры по одному пикселю за раз, либо использовать комбинацию преобразований (масштабирование после поворота), либо наслоение (рисование изометрического квадрата с альфа-маской и рендеринг предварительно вычисленная текстура) и так далее …
Или, конечно, если это вариант для вас, используйте что-то подходящее для необработанных данных геометрии и текстуры, например OpenGL / Direct3D. Лично я бы пошел с OpenGL / SFML для чего-то вроде этого.
К сожалению, я не могу комментировать, чтобы попросить разъяснений, поэтому я должен ответить на вопрос: не можете ли вы преобразовать все четыре точки, тогда из этих точек рассчитать ширину и высоту из преобразованных точек?
X = 20, Y = 10, ширина = 16, высота = 16
как ты сказал
isometricX = cartX - cartY;
isometricY = (cartX + cartY) / 2;
так
isometricX1 = cartX1 - cartY1;
isometricY1 = (cartX1 + cartY1) / 2;
а также
isometricWidth = std::abs(isometricY - isometricY1)
Возможно, есть более эффективный маршрут, но, поскольку я не знаю декартовой геометрии, я не могу найти это решение.
РЕДАКТИРОВАТЬisometricWidth нашла расстояние между двумя точками, а не ширину и высоту
еще одно замечание: вам понадобятся противоположные углы (да, я понимаю, что другой парень, вероятно, гораздо лучший ответ: P)