По-перше, я точно знаю, у чому полягає моя проблема малювання, і у мене є різні ідеї, як підійти до її вирішення. Я тут, щоб зрозуміти, як відрегулювати, який кадр намальований, щоб збереглась ізометрична «ілюзія».
Я пишу 2D гру з видом на птахи, яка відбувається в космосі. Я намагаюся використовувати ізометричну графіку в світі, де Up is North, немає обертання ігрового світу, як у традиційних ізометричних іграх (пам’ятайте, гра відбувається в просторі, без місцевості). Ось приклад спрайту, який я намагаюся використати: http://cell.stat-life.com/images/stories/AsteroidOutpost/Spaceship64.png Повертається 64 рази щодо власної вертикальної осі з кутом огляду 35 градусів (так, ізо). Зображення було згенеровано, тому це можна змінити.
Для наочності я продиктував, що північ (вгору) 0 градусів, а схід (праворуч) 90.
Моя проблема полягає в тому, що мій спрайт не завжди виглядає так, як стикається там, де гра вважає, що це пов'язано з різницею в використовуваних 3D-площинах. Не впевнений, чи правильно я використовую термінологію, але мій космічний корабель був повернутий на одну площину, і площина огляду очікує, що речі будуть обернені у власній площині. Ось змалювання проблеми:
http://cell.stat-life.com/images/stories/AsteroidOutpost/ProjectionIssue.png Ліворуч я маю вигляд збоку, праворуч - вид зверху вниз. На вершині у мене є світове космічне судно / спрайт. Знизу я маю те, як виглядає спрайт, коли його малюють на екрані.
У верхньому правому куті - спрощена версія того, як обертався мій космічний корабель (рівномірна ступінь поділу між кожним кадром). У нижньому правому куті розташований кут, на який спрайт виглядає, як він стикається, коли на екрані намальований певний кут. Проблема найбільш очевидна при температурі близько 45 градусів. Ось зображення, накладене лінією "площини екрана", яка вказується у напрямку, до якого повинен бути судно: http://cell.stat-life.com/images/stories/AsteroidOutpost/Spaceship64RedLine.png Червону лінію слід завжди вказувати в точно такому ж напрямку, що і корабель, але, як ви бачите, проблема проекції викликає проблему. Я сподіваюся, що я досить добре описую це питання.
EDIT: Червона лінія обертається на площині екрана, тоді як космічний корабель обертається на "площині корабля", отже, велика різниця між кутом судна та кутом екрана при його малюванні. END EDIT
Це виглядає досить дивним, коли цей корабель стріляє лазерним променем у ціль, що знаходиться в бік, коли він повинен стріляти прямо вперед.
Отже ... рішення, яке я придумав:
- Перестаньте намагатися підробити ізометричний вигляд, ідіть великим або йдіть додому. Поверніть мій світ уже. (PS: це вирішить мою проблему, правда?)
- Змініть аркуш спрайта (якимось чином), щоб у ньому були кадри, які представляють "кут екрану", на який буде розглянута модель. Тож коли я попрошу зображення на 45 градусів, воно буде фактично виглядати так, що воно на екрані 45 градусів.
- Змініть мою спрайтову систему спрайтів, щоб схопити інший кадр із аркуша спрайта (якось), знаючи, що захоплення "нормального" кадру буде виглядати смішно. Тож замість того, щоб захопити 45-градусний кадр, він захопить ... 33-градусний кадр (просто здогадуючись), щоб він виглядав правильно для користувача.
- Просто використовуйте 3D! Людина так набагато простіше
Для одного: яке рішення ви б рекомендували? Я схиляюся до 2, хоча я знаю, що це неправильно. Пам'ятайте, що я маю повний доступ до інструменту генерації спрайтів. Метод 3 був би моїм другим вибором. Обидва ці методи просто вимагають, щоб я застосував деяку математику до кута (кутів), щоб отримати бажаний результат. До речі, я додав туди №4 як жарт, я не хочу переходити на 3D.
Для двох: Використовуючи методи 2 або 3, як би я відрегулював кути вводу чи виходу? Мені не все так добре з 3D-проекціями та 3D-матрицями (не кажучи вже про 2D-матриці), і будь-якою іншою математикою, що може бути використана для досягнення бажаного результату.
Думаючи тут голосно: якщо я візьму одиничний вектор, спрямований у напрямку, в якому я хочу, щоб судно виглядало (на площині екрана), то спроектував це на корабельну площину, а потім зрозумій, який кут між цією проектованою лінією та площиною На північ - у мене повинен бути кут графіки корабля, який я хочу відображати. Правильно? (рішення для №3?) Людина ... Я не можу це зробити.
Редагувати:
Я знаю , що проблема важко візуалізувати зі статичними зображеннями, так що я виконав свою Sprite Library Візуальний Tester для відображення питання: http://cell.stat-life.com/downloads/SpriteLibVisualTest.zip Це вимагає XNA 4.0 Ця програма просто обертаючи спрайт і прорисуючи лінію від його центральної точки назовні під кутом, який гра вважає, що корабель повинен бути стикається.
EDIT 8 вересня
Продовжуючи з мого абзацу "вголос": Замість використання проекції (тому що це виглядає важко) Я думаю, що я міг би взяти одиничний вектор, орієнтований на північ (0x, 1y, 0z), використовую матрицю, щоб повернути його на кут спрайт справді облицьований, потім повернути його знову від "площини огляду" назовні до "площини спрайта" навколо осі X, потім ... сплюснути? вектор (по суті проектує його) назад на площу перегляду, використовуючи лише X і Y (ігноруючи Z). Тоді, використовуючи цей новий сплющений вектор, я міг визначити його кут і використати його для ... чогось чогось. Я подумаю більше пізніше.
EDIT 8 вересня (2)
Я спробував виконати свою ідею згори з деяким успіхом, так! Отже ... щоб отримати червону лінію, щоб виглядати, що вона виходить прямо з мого космічного корабля (лише для тестування), я зробив наступне:
Vector3 vect = new Vector3(0, 1, 0);
vect = Vector3.Transform(vect, Matrix.CreateRotationZ(rotation));
vect = Vector3.Transform(vect, Matrix.CreateRotationY((float)((Math.PI / 2) - MathHelper.ToRadians(AngleFromHorizon))));
Vector2 flattenedVect = new Vector2(vect.X, vect.Y);
float adjustedRotation = (float)(getAngle(flattenedVect.X, flattenedVect.Y));
Де rotation
знаходиться кут екрана і adjustedRotation
зараз цей кут екрану виглядає на площині спрайта. Я не знаю, чому мені потрібно було обертати Y замість X, але це, мабуть, щось із 3D, про що я не знаю.
Отже, зараз у мене є додаткова інформація, але як я можу використовувати це, щоб вибрати більш відповідний кадр? Можливо, замість того, щоб обертатися з площини виду в площину спрайта, а потім проектуючи назад, я повинен спробувати зробити це навпаки. Ось мій спрайт із скоригованою червоною лінією, але те, що я дійсно хочу зробити, - це коригувати модель, а не лінію: http://cell.stat-life.com/images/stories/AsteroidOutpost/Spaceship64RedLineCorrected.png
EDIT 9 вересня
ХОРАЙ! Це виправлено! Я опишу, що я зробив, щоб виправити це:
Я дотримувався порад електронного бізнесу та "скупився" за світовою системою координат (чи розтягувалась ...?). Це по суті рішення №1, хоча я мав враження, що мені доведеться повертати свою світову систему координат по відношенню до системи координат екрану. Неправда! Вгору все ще + y, а справа - + x. Я змінив свої методи WorldToScreen і ScreenToWorld для належного перетворення між координатами світу та екрана. Ці методи можуть бути не оптимальними, але ось єдині два методи в моїй кодовій базі, які довелося змінити.
public Vector2 ScreenToWorld(float x, float y)
{
float deltaX = x - (size.Width / 2f);
float deltaY = y - (size.Height / 2f);
deltaX = deltaX * scaleFactor / (float)Math.Sqrt(3);
deltaY = deltaY * scaleFactor;
return new Vector2(focusWorldPoint.X + deltaX, focusWorldPoint.Y + deltaY);
}
public Vector2 WorldToScreen(float x, float y)
{
float deltaX = x - focusWorldPoint.X;
float deltaY = y - focusWorldPoint.Y;
deltaX = deltaX / scaleFactor * (float)Math.Sqrt(3);
deltaY = deltaY / scaleFactor;
return new Vector2(size.Width / 2f + deltaX, size.Height / 2f + deltaY);
}
Це було все! Зміна цих двох методів вплинула на все інше: те, що я дивився, де об’єкти, де малювали, де я клацав, все. Мій космічний корабель зараз дивиться прямо в ціль, яку він стріляє, і все стає на свої місця. Я буду експериментувати з ортографічною проекцією, побачу, чи це робить все більш "справжнім".