Композит, компонент и сущности в игровом движке C++

Я работаю над школьным проектом по разработке игры. Мы используем двигатель, созданный одной из наших команд. Сборка двигателя мне непонятна и кажется анти-паттерном. Тем не менее, кажется, что никто не может сделать выбор дизайна для меня. Предполагается, что движок использует "компонентный" дизайн, но я его не вижу. Ниже приведен код класса Компонент, Композит и Объект. Вкратце мой вопрос заключается в следующем: использует ли этот код допустимый шаблон проектирования или он слишком усложнен только ради "реализации шаблона проектирования", вызывая тем самым антипаттерн?

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", содержащий структуру данных для данных твердого тела и некоторые функции, перекрывающие полностью виртуальный компонентный базовый класс?

1 ответ

Решение

Размещенный код является вариантом составного шаблона. Этот шаблон проектирования является структурным шаблоном, который позволяет клиентам обрабатывать отдельные объекты и сложные объекты, например объекты, состоящие из нескольких объектов, единообразно. Например, цикл рендеринга может перебирать коллекцию объектов, вызывая draw() на каждом из них. Поскольку это структурный паттерн, сложно субъективно ответить, является ли это примером чрезмерного проектирования, так как это потребовало бы изучения большего количества иерархий классов и архитектуры.

Тем не менее, ни соглашения об именах классов Component а также Composite ни использование составного шаблона проектирования не подразумевает, что это "компонентный" дизайн. Я не был знаком с шаблоном компонента игрового программирования, но, по сути, он представляется шаблоном стратегии с состоянием, связанным в классе алгоритма, что приводит к упрощенному интерфейсу между strategy а также context, В любом случае эти два шаблона являются поведенческими шаблонами, которые выполняют взаимозаменяемые и инкапсулированные алгоритмы. Следовательно, опубликованный код не реализует "компонентный" дизайн, так как ни Component, Composite, Entityни Player Класс предоставляет средства для инкапсуляции алгоритмов взаимозаменяемо. Например, Entity::update() всегда будет рассчитывать позицию таким же образом. Это соединение требует Entity иерархия классов должна быть расширена, если Entity необходимо использовать другую физическую модель (рассмотрим случай Entity деформироваться на планету с другим набором физики), а не делегировать Physics иерархия классов, которые инкапсулируют алгоритмы.

Другие вопросы по тегам