Питання
Коли у вас є двовимірна гра, яка використовує дійсно великі зображення (більші, ніж може підтримувати ваше обладнання), що ви робите? Можливо, є якесь цікаве рішення цієї проблеми, яке раніше у мене не виникало.
Я в основному працюю над своєрідним виробником графічних пригод. Моя цільова аудиторія - це люди, у яких майже немає досвіду розробки ігор та програмування. Якщо ви працювали з такою програмою, чи не вважаєте ви за краще вирішити проблему всередині, а не сказати вам "розділити свої зображення"?
Контекст
Добре відомо, що графічні картки встановлюють набір обмежень щодо розміру текстур, якими вони можуть користуватися. Наприклад, працюючи з XNA, ви обмежуєте максимальний розмір текстури 2048 або 4096 пікселів, залежно від того, який профіль ви вибрали.
Зазвичай це не створює особливих проблем у 2D іграх, оскільки більшість з них мають рівні, які можна побудувати з менших окремих частин (наприклад, плитки або перетворених спрайтів).
Але подумайте про кілька класичних графічних пригодницьких ігор (наприклад, Monkey Island). Кімнати в графічних пригодницьких іграх зазвичай розроблені в цілому, з невеликими або відсутніми повторюваними ділянками, як художник, що працює над пейзажем. Або, можливо, така гра, як Final Fantasy 7, яка використовує великі попередньо надані фони.
Деякі з цих кімнат можуть мати досить великі розміри, які часто охоплюють три або більше ширини екрану. Тепер якщо ми розглянемо ці фони в контексті сучасної гри високої чіткості, вони легко перевищують максимально підтримуваний розмір текстури.
Тепер очевидним рішенням цього є розділити фон на менші ділянки, що підходять до вимог, і намалювати їх поруч. Але чи повинен ви (або ваш художник) бути тим, хто розбиває всі ваші текстури?
Якщо ви працюєте з API високого рівня, чи не варто, можливо, бути готовим розібратися з цією ситуацією та зробити розбивання та збірку текстур внутрішньо (як попередній процес, наприклад, контент конвеєра XNA, або під час виконання)?
Редагувати
Ось що я думав, з точки зору впровадження XNA.
Мій 2D двигун вимагає лише дуже невеликого набору функціональності Texture2D. Я фактично можу зменшити його до цього інтерфейсу:
public interface ITexture
{
int Height { get; }
int Width { get; }
void Draw(SpriteBatch spriteBatch, Vector2 position, Rectangle? source, Color color, float rotation, Vector2 origin, Vector2 scale, SpriteEffects effects, float layerDepth);
}
Єдиний зовнішній метод, який я використовую на Texture2D, це SpriteBatch.Draw (), щоб я міг створити міст між ними, додавши метод розширення:
public static void Draw(this SpriteBatch spriteBatch, ITexture texture, Vector2 position, Rectangle? sourceRectangle, Color color, float rotation, Vector2 origin, Vector2 scale, SpriteEffects effects, float layerDepth)
{
texture.Draw(spriteBatch, position, sourceRectangle, color, rotation, origin, scale, effects, layerDepth);
}
Це дозволить мені використовувати ITexture незмінно, коли я раніше використовував Texture2D.
Тоді я міг би створити дві різні реалізації ITexture, наприклад, RegularTexture та LargeTexture, де RegularTexture просто оберне звичайний Texture2D.
З іншого боку, LargeTexture зберігатиме список Texture2D, кожен з яких відповідає одному з розбитих фрагментів повного зображення. Найважливіша частина полягає в тому, що викликаючи Draw () на LargeTexture, слід мати змогу застосувати всі перетворення та намалювати всі фрагменти так, ніби вони були лише одним суміжним зображенням.
Нарешті, щоб зробити весь процес прозорим, я створив би уніфікований клас завантажувача текстур, який би виступав як заводський метод. Потрібно взяти шлях текстури як параметр і повернути ITexture, який би був або RegularTexture, або LargeTexture, залежно від розміру зображення, що перевищує обмеження чи ні. Але користувачеві не потрібно було знати, хто це.
Трохи перенасичені чи це звучить нормально?