Питання щодо архітектури ігор з XNA


12

Тож я нарешті зібрався зіграти з XNA і погукав із створенням 2D гри (у мене є маса мистецьких активів від друга, який розробив її на iOS)

Багато речей, здається, легко зробити і вийти з коробки, однак я залитий натхненим купою речей, оскільки більшість літератури (книги, які я придбав, наприклад) не приділяють 2D надто великої уваги.

Я дуже вдячний за будь-які роз’яснення чи вказівку на додаткову інформацію про наступні завдання:

  1. В чому сенс ігрової служби? Я розумію всю ідіому реєстрації об'єкта як сервісу, щоб будь-який інший GameComponent міг схопити його, однак як це вибити просто зробити його, можливо, загальнодоступним чи статичним? Наприклад, моя книга рекомендувала зареєструвати об'єкт SpriteBatch у класі Game.cs. Я не впевнений, наскільки це бажано просто оприлюднити / статично, оскільки у будь-якому випадку має бути лише один екземпляр гри (одиночний)?

  2. Мене бентежить, коли мені слід успадкувати від GameComponent або RenderableGameComponent. Я намагаюся керуватися дизайном / менеджером / контролером, таким чином, щоб усі об'єкти були створені / належать одному менеджеру і однакові для інших. У мене зараз кожен менеджер / контролер успадковується від GameComponent, однак як це виграти, якщо об’єкт гри володіє всіма менеджерами та вручну викликає оновлення на них та малює?

  3. Я помітив, що Initialize викликається перед ContentLoad (), мені це було дратує, оскільки в моєму Initialize - це те, де я хотів би створити деякі мої сутності (наприклад, Sprite, Player тощо), однак я не можу дати їм їх завантаження SpriteSheets або Textures, оскільки виклик для їх завантаження ще не відбувся. Я, можливо, ініціалізую неправильно чи люди просто присвоюють текстуру далі в ContentLoad?

Це, здається, є моїм найбільшим " WTF " не дуже розуміючого

Відповіді:


11

Відповідь на ваше запитання проста: Робіть все, що працює. В ідеалі робити те, що просто і працює. Часто використовувати вбудовану архітектуру не просто, тому що, як ви виявляєте , вам потрібно перестрибувати обручі, щоб структурувати гру так, як вам потрібно.

Щоб відповісти на перше запитання, я надішлю вас на свою відповідь на питання "Навіщо користуватися послугами?" . Коротка відповідь полягає в тому, що сервіси - це хороший спосіб уникнути взаємозв'язку (версії, залежності, розширюваності) питань, з якими ви ніколи не зіткнетеся в автономній грі . Більшу частину часу простіше просто завести член public(а можливо навіть static, якщо ви поспішаєте) і переживати про більш цікаві проблеми.

Щоб відповісти на ваше друге запитання, я надішлю вас на свою відповідь на питання "Які мінуси використання DravableGameComponent для кожного примірника ігрового об'єкта?" а також мої думки щодо ігрової архітектури . Коротка відповідь: немає користі використовувати GameComponentнад просто створенням власних класів та методів виклику, як Drawі Updateви самі. Якщо GameComponentточно відповідає вашій бажаній архітектурі, використовуйте її, але майже завжди це не так.

Використання служб та компонентів стає справді цікавим лише тоді, коли ви створюєте бібліотеку для сторонніх споживань. Сам XNA робить це - у нього є IGraphicsDeviceServiceі GamerServicesComponent, наприклад. Вони відповідають конкретним вимогам для розв’язки, з якими зазвичай не стикаєтесь при розробці гри.

Нарешті, відповідь на ваше третє запитання досить проста: Просто створіть свої ігрові об'єкти в LoadContent. У цьому немає нічого особливого Initialize.

Варто зазначити, що вся Microsoft.Xna.Framework.Gameзбірка не є обов'язковою . Це дає надзвичайно корисну вихідну точку - але це ні в якому разі не слід розглядати як "єдиний правильний спосіб" робити речі.


Дуже цікавий спосіб це побачити. Набагато реалістичніше, ніж моя відповідь. Добре заслужив +1, сер.
Джессі Емонд

У мене є ще одне питання! Як щодо походження, коли ви малюєте для Texture2D. Чи прийнято розміщувати походження в нижній середині текстури? Я намагаюся робити анімацію, і я виявляю, що походження в (0,0) спричиняє злегка зміщення текстури, якщо ширина і висота не однакові
Setheron

@Setheron: Вам справді слід створити нове запитання - оскільки це зовсім не пов'язане з оригінальним запитанням. Я збираюся повернути зміни, які ви внесли до цього питання. Походження для SpriteBatch.Drawвказано в координатах текстури-пікселів відносно лівого верхнього краю текстури (або прямокутника джерела, якщо ви його використовуєте).
Ендрю Рассел

1
@Andrew: Нещодавно я відновив свою гру, щоб вона повністю базувалася на сервісах замість public/ staticвластивостей. Чому? Заповітність. Виключити речі з підходом властивості майже неможливо, тоді як тривіально, якщо все ініціалізовано тим, IServiceProviderщо може бути наповнене всім необхідним класом вашим методом тестування. Це також дозволяє уникнути необхідності інстанціювати сам Gameоб’єкт у вашому тесті, який дуже швидко стає безладним.
Меттью Шарлі

Як осторонь, я все ще маю багато об'єктів публічної власності на Gameоб’єкті. До них просто трапляється доступ через інтерфейси, які підштовхуються до Game.Servicesних, а потім отримують все, щоб отримати те, що їм потрібно.
Меттью Шарлі

3

На ваше перше запитання я мушу визнати, що я не знаю дійсно відповіді. Я думаю, це було б з тієї ж причини, що і для того, що одиночний - це взагалі поганий малюнок. Я посилаюсь на цитату за цим посиланням :

Перша, про яку ми думали (і одна з причин впровадження сервісів) - це надання посилання GraphicsDevice доступним у грі. Спочатку у нас Гра була власником GraphicsDevice та викрити її через властивість типу Game.GraphicsDevice. Проблема з цим полягала в тому, що це жорстко пов’язало GraphicsDevice з грою, не дозволяючи комусь іншому «володіти» пристроєм (наприклад, візуалізатором) і не дозволяти комусь використовувати майбутній оновлений GraphicsDevice, не доставляючи нову версію гри, яка б не стала » не бути сумісним назад.

Для вашого другого запитання я б припустив, що використання таких компонентів було б більш корисним, якщо ви замість цього дотримуєтесь підходу, заснованого на компонентах , як якщо б у вас був список Spriteкомпонентів, які б вміли малювати та оновлювати себе замість менеджер, який вміє оновлювати та малювати кожен спрайт. Я згоден, це звучить так само, але я віддаю перевагу компонентному дизайну, тому що мені дуже подобається об'єктно-орієнтований підхід, який він має.

Що стосується вашого третього запитання, так, ви повинні завантажити будь-яку форму вмісту (активи, шрифти тощо) методом LoadContent. Що стосується ініціалізації, то зазвичай ви створюєте об’єкт програвача в межах функції ініціалізації, а потім завантажуєте його вміст у програмі LoadContent .. Або ви можете просто зробити все це в межах LoadContent, якщо бажаєте.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.