Я очень новичок в разработке игр, но не в программировании.
Я (снова) играю с игрой типа Понг, используя canvas
элемент JavaScript .
Я создал Paddle
объект, который имеет следующие свойства ...
width
height
x
y
colour
У меня также есть Pong
объект, который имеет такие свойства, как ...
width
height
backgroundColour
draw()
,
draw()
Метод в настоящее время Переустановка canvas
и что , когда встал вопрос.
В случае , если Paddle
объект есть draw()
метод отвечает за его чертеж, или если draw()
на Pong
объекте будет отвечать за разработку своих актеров (я предполагаю , что это правильный термин, пожалуйста , поправьте меня , если я неправильно).
Я подумал, что было бы выгодно Paddle
рисовать себя, когда я создаю экземпляры двух объектов, Player
и Enemy
. Если бы это было не в Pong
-х draw()
, я должен был бы написать подобный код дважды.
Какова лучшая практика здесь?
Спасибо.
источник
Ответы:
Рисовать актеров - не очень хороший дизайн по двум основным причинам:
1) это нарушает принцип единственной ответственности , так как эти актеры, вероятно, должны были выполнить другую работу, прежде чем вы добавили в них код.
2) затрудняет продление; Если каждый тип актера реализует свой собственный рисунок, и вам нужно изменить способ рисования в целом , вам, возможно, придется изменить много кода. Предотвращение чрезмерного использования наследования может облегчить это в некоторой степени, но не полностью.
Лучше для вашего рендерера обрабатывать рисунок. В конце концов, это то, что значит быть рендерером. Метод рисования рендерера должен принимать объект «рендеринга описания», который содержит все необходимое для рендеринга вещи. Ссылки на (возможно, совместно используемые) данные геометрии, специфичные для экземпляра преобразования или свойства материала, такие как цвет и так далее. Затем он рисует это, и ему все равно, каким должно быть это описание рендеринга.
Затем ваши актеры могут держаться за описание рендера, которое они создают сами. Поскольку актеры, как правило, являются типами логической обработки, они могут выдвигать изменения состояния в описании рендера по мере необходимости - например, когда актер получает повреждение, он может установить цвет своего описания рендеринга на красный, чтобы указать это.
Затем вы можете просто выполнить итерацию каждого видимого актера, добавить описание рендера в рендер и позволить ему делать свое дело (в основном; вы можете обобщить это еще дальше).
источник
actor.draw(renderer,x,y)
чемrenderer.draw(actor.getAttribs(),x,y)
.struct RenderDetail { glVAO* vao; int shader; int texture; Matrix4f* transform; }
более или менее для моего рендерера. Таким образом, средство визуализации не заботится о том, что представляют данные, оно просто обрабатывает их. На основании этой информации я также могу решить, следует ли сортировать порядок вызовов отрисовки, чтобы уменьшить общее количество вызовов графического процессора.Шаблон посетитель может быть полезным здесь.
То, что вы можете сделать, это иметь интерфейс Renderer, который знает, как рисовать каждый объект, и метод «себе сам» в каждом действующем субъекте, который определяет, какой (конкретный) метод визуализации вызывать, например
Таким образом, все еще легко портировать на другую графическую библиотеку или фреймворк (однажды я портировал игру с Swing / Java2D на LWJGL и был очень рад, что использовал этот шаблон вместо прохождения
Graphics2D
вокруг).Есть еще одно преимущество: рендерер можно тестировать отдельно от любого кода актера.
источник
В вашем примере вы бы хотели, чтобы объекты Pong реализовывали draw () и отображали сами себя.
Хотя вы не заметите каких-либо существенных преимуществ в проекте такого размера, в целом разделение игровой логики и их визуальное представление (рендеринг) является стоящим занятием.
Под этим я подразумеваю, что у вас будут ваши игровые объекты, которые можно обновить (), но они не имеют представления о том, как они отображаются, их интересует только симуляция.
Тогда у вас будет класс PongRenderer (), который имеет ссылку на объект Pong, и он затем берет на себя ответственность за рендеринг класса Pong (), это может включать рендеринг Paddles или наличие класса PaddleRenderer, чтобы позаботиться об этом.
Разделение проблем в этом случае является вполне естественным, и это означает, что ваши классы могут быть менее раздутыми, и легче изменять способ рендеринга, ему больше не нужно следовать иерархии, которую делает ваше моделирование.
источник
Если бы вы делали это в
Pong
draw (), вам не нужно было бы дублировать код - просто вызовитеPaddle
функцию draw () для каждого из ваших манипуляторов. Таким образом, в вашейPong
ничьей () у вас будетисточник
Каждый объект должен содержать свою собственную функцию рисования, которая должна вызываться кодом обновления игры или кодом рисования. подобно
Это не код, а просто чтобы показать, как рисовать объекты.
источник