Я работаю над школьным проектом по разработке игры. Мы используем двигатель, созданный одной из наших команд. Сборка двигателя мне непонятна и кажется анти-паттерном. Тем не менее, кажется, что никто не может сделать выбор дизайна для меня. Предполагается, что движок использует «компонентный» дизайн, но я его не вижу. Ниже приведен код класса Компонент, Композит и Объект. Короче мой вопрос заключается в следующем: этот код использует допустимый шаблон дизайна или он слишком сложен только ради «реализации шаблона проектирования», вызывая тем самым антипаттерн?
Component.cpp:
#include "Engine\Component.h"#include "Engine\Composite.h"
Component::Component(Composite* parent)
{
this->parent = parent;
}
Component::~Component()
{
}
Entity.cpp
#include "Engine\Entity.h"#include "Engine\Game.h"
Entity::Entity(Composite* parent):Composite(parent)
{
this->mass = 1;
node = NULL;
}
void Entity::update()
{
Composite::update();
this->angularVelocity += this->angularAccelaration;
this->orientation += this->angularVelocity;
this->accelaration = (1 / this->mass) * this->force;
this->velocity += this->accelaration;
this->position += this->velocity;
if (node != NULL)
{
this->node->setPosition(this->position);
this->node->setRotation(this->orientation);
}
}
void Entity::draw()
{
Composite::draw();
if (node == NULL) return;
if (!this->visible)
{
this->node->setVisible(false);
return;
}
this->node->setVisible(true);
this->node->render();
}
void Entity::createNode(std::string modelPath)
{
// Get the mesh
irr::scene::IAnimatedMesh* mesh = Game::getSceneManager()->getMesh(modelPath.c_str());
// Create model entity
this->node = Game::getSceneManager()->addMeshSceneNode( mesh );
this->node->setMaterialFlag(EMF_FOG_ENABLE, true);
}
Entity::~Entity()
{
Composite::~Composite();
if (node != NULL)
{
node->drop();
}
}
Composite.cpp
#include "Engine\Composite.h"
Composite::Composite(Composite* parent):Component(parent)
{
}Composite::~Composite()
{
for (std::list<Component*>::iterator i = components.begin(); i != components.end(); ++i)
{
delete (*i);
}
components.clear();
}
void Composite::handleMessage(unsigned int message, void* data)
{
for (std::list<Component*>::iterator i = components.begin(); i != components.end(); ++i)
{
(*i)->handleMessage(message, data);
}
}
void Composite::update()
{
for (std::list<Component*>::iterator i = components.begin(); i != components.end(); ++i)
{
(*i)->update();
}
}
void Composite::draw()
{
for (std::list<Component*>::iterator i = components.begin(); i != components.end(); ++i)
{
(*i)->draw();
}
}
void Composite::addComponent(Component* component)
{
components.push_back(component);
}
void Composite::removeComponent(Component* component)
{
components.remove(component);
delete component;
}
И следующий фрагмент кода — Player.cpp, использующий как составной, так и объектный объект как гибридный тип объекта (я действительно не понимаю логику).
Player.cpp
#include "Player.h"#include "Messages.h"#include <iostream>
Player::Player(Composite* parent) : Entity(parent)
{
createNode("../assets/sydney.md2");
//i = 0;
//v3f = vector3df(0,0,0);
/*networker = new NetworkComponent();
addComponent(networker);
networker->registerVar(&i);
networker->registerVar(&v3f);*/
}
void Player::update() {
Composite::update();
//std::cout<<i<<std::endl;
//std::cout<<"vectorx="<<v3f.X<<"\n";
}
void Player::handleMessage(unsigned int message, void* data) {
switch(message) {
case DAMAGE: /* Do something */;
}
delete data;
}
Player::~Player()
{
Entity::~Entity();
}
Я вообще не верю, что это компонентный дизайн. Не следует удалять сущность и использовать только Composite и Component. Разве компонентный базовый класс не должен быть пустым и никогда не использоваться напрямую? Как компонент под названием «Rigidbody», содержащий структуру данных для данных твердого тела и некоторые функции, перекрывающие полностью виртуальный базовый класс компонентов?
Размещенный код является вариантом составной шаблон. Этот шаблон дизайна структурный шаблон, который позволяет клиентам обрабатывать отдельные объекты и сложные объекты, например, составленные из нескольких объектов, единообразно. Например, цикл рендеринга может перебирать коллекцию объектов, вызывая draw()
на каждом из них. Поскольку это структурный паттерн, сложно субъективно ответить, является ли это переустройства, поскольку это потребовало бы изучения большего количества иерархий классов и архитектуры.
Тем не менее, ни соглашения об именах классов Component
а также Composite
ни использование составного шаблона проектирования не подразумевает, что это «компонентный» дизайн. Я не был знаком с шаблон компонента игрового программирования, но, по сути, это шаблон стратегии с состоянием, связанным в классе алгоритма, что приводит к упрощенному интерфейсу между strategy
а также context
, В любом случае эти две модели поведенческий шаблоны, которые выполняют взаимозаменяемые и инкапсулированные алгоритмы. Следовательно, опубликованный код не реализует «компонентный» дизайн, так как ни Component
, Composite
, Entity
ни Player
Класс предоставляет средства для инкапсуляции алгоритмов взаимозаменяемо. Например, Entity::update()
всегда будет рассчитывать позицию таким же образом. Это соединение требует Entity
иерархия классов должна быть расширена, если Entity
необходимо использовать другую физическую модель (рассмотрим случай Entity
деформироваться на планету с другим набором физики), а не делегировать Physics
иерархия классов, которые инкапсулируют алгоритмы.
Других решений пока нет …