C ++ игра, дизайн класса и обязанности - PullRequest
5 голосов
/ 26 августа 2009

Я только что прочитал несколько связанных вопросов, которые возникли, когда я набрал тему, поэтому я постараюсь не повторять их.

Я недавно начал пересматривать учебный проект, который я начал два или три года назад - порт C ++ движка Mega Man. Да, я использовал разорванные спрайты. Я также использую библиотеку игрового движка для рисования, музыки и ввода.

Мой оригинальный код был зверским. Хотя его можно (но едва ли) назвать ОО, он полностью упустил суть. Я начал добавлять такие вещи, как интерфейсы, и вырезал много повторяющегося кода. В некоторых вещах я не уверен, потому что дизайн игры иногда становится очень сложным.

Объект, который представляет мою игровую библиотеку, в настоящее время является глобальным (я знаю, что глобальные значения обычно плохие), потому что многие объекты могут полагаться на него здесь и там для таких вещей, как загрузка их произведений искусства или музыки. Как лучше всего вывести этот объект из глобальной области, не передавая пятьдесят параметров всему, что в противном случае использовало бы его напрямую?

Следующий вопрос: Как мы все знаем, Mega Man выпускает много маленьких белых снарядов. В настоящее время объект Player отвечает за объекты Projectile, которые он запускает, обновляя их положение и т. Д. (Буквально, вызывая метод Projectile :: Update () один раз для каждого выстрела внутри метода Player :: Update ()). Это неправильный способ сделать это? Моим первым улучшением было то, что все эти объекты реализовали интерфейс DrawnObject, так что моя игра может просто рисовать все. То же самое для обновлений означало бы, что я заберу контроль над снарядами у игрока и передам его какому-то более широкому игровому объекту. Причина, по которой я сомневаюсь в этом, заключается в том, что это похоже на антипаттерн объекта Бога. Или я по недоразумению сказал антипаттерн? По-прежнему возникает дополнительная сложность - снаряды умирают, если они покидают видимый экран, поэтому любой вызов для обновления снаряда требует от вызывающего доступа доступа к экранному объекту.

Пока все, я вернусь с новыми проблемами, когда доберусь до них. Конец первого поста!

Ответы [ 3 ]

7 голосов
/ 26 августа 2009

Если сделать класс глобальным, я бы использовал singleton, а затем просто вызвал Game :: GetInstance (), который бы возвращал указатель на глобальный класс.

Что касается частиц, я всегда обращался с играми, чтобы создать класс, который управляет всеми объектами. В моем основном цикле игр я бы вызвал функцию классов UpdateObjects, которая просматривала список сохраненных элементов и вызывала каждую из этих функций Update. То же самое с Render и Collision.

2 голосов
/ 26 августа 2009

Объект, представляющий мою игру библиотека в настоящее время является глобальной (я знаю, глобалы обычно плохие) потому что многие объекты могут полагаться на это здесь и там для таких вещей, как загрузка их искусства или Музыка. Какой лучший способ пойти вытаскивая этот объект из глобального сфера, не проходя пятьдесят параметры ко всему, что было бы в противном случае использовать его напрямую?

Я согласен с вышеупомянутым одноэлементным решением.

Следующий вопрос: как мы все знаем, Мега Человек стреляет много белого Снаряды. В настоящее время игрок объект отвечает за Снаряды предметов он стреляет, обновляя их положение и тому подобное (буквально, вызов снаряда :: Update () метод один раз для каждого выстрела, внутри Player :: Update () метод).

Существует принцип гибкой разработки кода, называемый «принцип единой ответственности». В соответствии с этим "НИКОГДА НЕ ДОЛЖНО БЫТЬ БОЛЬШЕ, ЧЕМ ОДНА ПРИЧИНА КЛАСС ДЛЯ ИЗМЕНЕНИЯ. "Так что, я думаю, я бы начал с разделения обязанностей класса Player на отдельные классы: например, один для позиционирования и один для стрельбы.

См. Пример и более по теме SRP

2 голосов
/ 26 августа 2009

В прошлом я занимался дизайном игр, но не могу претендовать на звание эксперта.

Для доступа к объекту в глобальном масштабе, я бы предложил использовать singleton

для движущихся объектов, я бы предложил сделать все родительским классом, который понимает расположение экрана и имеет метод обновления. Каждый раз, когда создается новый объект, добавляйте его в вектор, содержащий все объекты, один раз за кадр, вы проходите через вектор и запускаете обновление для всех объектов.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...