Я работаю над простой блочной игрой-головоломкой.
Игровой процесс состоит в основном из перемещения блоков в игровой зоне, так что это тривиальная физическая симуляция. Моя реализация, однако, на мой взгляд, далека от идеала, и мне интересно, можете ли вы дать мне какие-либо советы о том, как сделать это лучше.
Я разделил код на две части: игровую логику и пользовательский интерфейс, как я делал во многих играх-головоломках:
- Логика игры отвечает за общие правила игры (например, формальная система правил в шахматах).
- Пользовательский интерфейс отображает игровую область и фигуры (например, шахматную доску и фигуры) и отвечает за анимацию (например, анимированное движение шахматных фигур)
Логика игры представляет игровое состояние в виде логической сетки, где каждая единица представляет собой ширину / высоту одной ячейки в сетке. Таким образом, для сетки шириной 6 вы можете перемещать блок шириной 2 четыре раза, пока он не столкнется с границей.
Пользовательский интерфейс берет эту сетку и рисует ее путем преобразования логических размеров в размеры в пикселях (то есть умножает их на константу). Однако, поскольку в игре почти нет игровой логики, мой уровень игровой логики [1] не имеет ничего общего, кроме обнаружения столкновений. Вот как это работает:
- Игрок начинает перетаскивать фигуру
- Пользовательский интерфейс запрашивает игровую логику для области легального перемещения этой фигуры и позволяет игроку перетащить ее в эту область
- Игрок отпускает кусок
- Пользовательский интерфейс привязывает кусок к сетке (чтобы он находился в правильной логической позиции)
- Пользовательский интерфейс сообщает игровой логике новую логическую позицию (с помощью методов-мутаторов, которых я бы предпочел избежать)
Я не совсем доволен этим:
- Я пишу юнит-тесты для своего игрового уровня логики, но не для пользовательского интерфейса, и оказалось, что весь хитрый код в пользовательском интерфейсе: предотвращение столкновения части с другими или границей и привязка ее к сетке.
- Мне не нравится тот факт, что пользовательский интерфейс рассказывает игровой логике о новом состоянии, я бы предпочел, чтобы он вызывал
movePieceLeft()
метод или что-то в этом роде, как в других моих играх, но я не продвинулся далеко с этим подходом, потому что игровая логика ничего не знает о перетаскивании и привязке, которые возможны в пользовательском интерфейсе.
Я думаю, что лучше всего было бы избавиться от моего игрового логического слоя и вместо этого реализовать физический слой. У меня есть несколько вопросов по этому поводу:
- Является ли такой физический слой обычным, или это более типично, чтобы игровой логический слой делал это?
- Будет ли привязка к сетке и коду перетаскивания принадлежать пользовательскому интерфейсу или физическому слою?
- Будет ли такой физический слой работать с размерами пикселей или с какой-то логической единицей, например, с моим игровым логическим слоем?
- Однажды я видел обнаружение столкновений на основе событий в базе кода игры, то есть игрок просто перетаскивал фигуру, пользовательский интерфейс послушно отображал бы ее и уведомлял физическую систему, а физическая система вызывала метод onCollision (). на части, как только столкновение обнаружено. Что чаще встречается? Этот подход или просить области легального движения в первую очередь?
[1] слой , вероятно, не подходит для того, что я имею в виду, но подсистема звучит раздутой, а класс вводит в заблуждение, потому что каждый слой может состоять из нескольких классов.
Ответы:
Я попытаюсь ответить на этот вопрос, поскольку я понимаю, о чем вы спрашиваете, хотя у меня нет большого опыта разработки игр, так как я все еще только учусь.
Насколько я понимаю, вы должны отделить код GUI от игровой логики и доменных объектов, то есть кусочков головоломки. Это действительно три отдельных слоя - и,
layer
на мой взгляд , это подходящий термин. Он часто используется для объяснения концепции разделения каждого уровня объектов системы на подсистемы, которые не зависят друг от друга.В отношении объектно-ориентированного программирования каждый объект должен быть классом. Таким образом, каждая часть вашей головоломки должна состоять из одного класса, а значит, и игрового поля. Игровое поле должно содержать X кусочков головоломки в зависимости от размера и способности движения, которые вы хотите дать игроку.
Итак, вот мои мысли по теме - надеюсь, что это поможет:
В этой архитектуре слой GUI показывает игроку состояние игры, расположение каждой части головоломки. Уровень GUI будет тогда отвечать за получение входных данных игрока и передавать его на нижележащий уровень Game Controller, который затем будет отвечать за обнаружение столкновений. Если их нет, то часть может быть приказана двигаться в этом направлении ввода. Чтобы сделать это, вам просто нужно вызвать этот кусок
MoveLeft
,MoveRight
и т. д. способы заставить часть двигаться. С тем же успехом вы можете сообщить игровому столу, какую фигуру вы хотите переместить, и затем она самостоятельно упорядочивает движение фигуры, а затем фигура движется в требуемом направлении. Эта архитектура облегчает тестирование каждого фрагмента кода на разных уровнях, а затем позволяет выполнять модульное тестирование, интеграционное тестирование и функциональное тестирование.Я знаю, что это может показаться немного запутанным для зрения, и слава богу, если это не так! Если вам потребуется дополнительная информация и помощь, пожалуйста, не стесняйтесь спрашивать, я буду рад помочь как можно лучше, хотя я новичок в разработке игр.
Спасибо за прочтение! знак равно
источник
Position
функции получения свойства, поэтому игровому контроллеру теперь требуется графический интерфейс для отображения этой перемещенной части в этой новой позиции.