[Лог #7] Класс рисовальщика.

Темой этого лога станет рендер. Расскажу немного о том как я себе представляю виртуального художника и почему лучше реализовать интерфейс IRender и класс-реализацию CRenderOGL, наример.
80 28 875
24
alexprey, похожим подходом пользуются, например, близзард во втором старкрафте, правда на еще более высоком уровне абстракции.
24
alexprey, не совсем так - элементы иерархии эффектов можно и напрямую дергать, а можно и в очереди ложить и что угодно с ними делать, речь именно о вынесении реализации взаимодействий в отдельную иерархию, а реализация взаимодействия между иерархиями это уже отдельный вопрос.
29
prog, если не ошибаюсь, то это что-то типа MessageQueue?
24
А вот специфические взаимодействия реализуются внутри игровых объектов, например у меня червь может пугать мелкую живность - это реализовано публичным методом Scare() у класса Creature. Червь берёт у игрового движка список объектов в некотором радиусе и каждого "пугает" запуском obj->Scare(this), дальше существо в реализации метода само решает, испугаться ему или нет. Или, например, EMP-пушка обездвиживает на некоторое время механизмы - проще у абстрактного класса MechanicalUnit реализовать метод Paralize(time) и дёргать его напрямую, чем проталкивать OnParalaze() от корневого Object'а - живым юнитам от этого мусора никакой пользы. Если конечно нет парализующих ядов - тогда парализация становится типовым взаимодействием. По здравому смыслу, короче.
А вот тут я сторонник более сложного в реализации, но более гибкого подхода. А именно - взаимодействия делать не напрямую, а через цепочку эффектов. Объясню на твоем-же примере с червями:
  • червь время от времени генерирует эффект "ScareThemAll", относящегося к семейству действующих по области эффектов
  • эффект "ScareThemAll" берет список объектов в радиусе и к каждому применяет эффект "ScareTarget"
  • эффект "ScareTarget" умеет только вызывать метод Scare для цели, что он и делает.
  • у эффекта есть поле "caster", в котором по всей цепочке объектов передается ссылка на первоначальный источник эффекта, в данном случае на червя, что позволяет в эффекте "ScareTarget" сделать obj->Scare(caster)
Причем "ScareThemAll" вполне может быть реализован не отдельным классом, а экземпляром класса AreaEffect с параметрами, в то время как для "ScareTarget" в текущей архитектуре нужен отдельный класс, наследуемый от "TargetEffect".
P.S. все имена и ситуации вымышлены, все совпадения с реальностью абсолютно случайны.
14
Это как реализуешь
Присоединяюсь.
Типовые взаимодействия типа столкновений, срабатываний на расстоянии, трассировки по лучу и прочего должны быть реализованы в движке, чтобы такое взаимодействие в игре везде работало одинаково и реализовывалось в одном месте: GetCollisions(obj), GetObjectsInRadius(obj, radius), GetObjectsOnRay(obj, ray_direction, ray_distance) и т.д.
А вот специфические взаимодействия реализуются внутри игровых объектов, например у меня червь может пугать мелкую живность - это реализовано публичным методом Scare() у класса Creature. Червь берёт у игрового движка список объектов в некотором радиусе и каждого "пугает" запуском obj->Scare(this), дальше существо в реализации метода само решает, испугаться ему или нет. Или, например, EMP-пушка обездвиживает на некоторое время механизмы - проще у абстрактного класса MechanicalUnit реализовать метод Paralize(time) и дёргать его напрямую, чем проталкивать OnParalaze() от корневого Object'а - живым юнитам от этого мусора никакой пользы. Если конечно нет парализующих ядов - тогда парализация становится типовым взаимодействием. По здравому смыслу, короче.
29
Вот как раз об этом. Коллизия подразумевается "прямая" физическая или же триггеры тоже работают ?
Это как реализуешь
DarkDes:
И попадание пули в бочку похоже решается каким-нибудь _gameEngine->RayTrace ? но для трассировки нужны ведь точка (пушка машины) и направление (камера? направление машины?).
Так ты трассировку то как делать будешь? Внешним объектом? Трассировкой должна и заниматься сама пушка, а у нее уже есть эти данные
15
_gameEngine->GetCollisions(this)
OnCollision
Вот как раз об этом. Коллизия подразумевается "прямая" физическая или же триггеры тоже работают ? Я это к тому, что объект "бочка" может быть заминирована и взрываться при попадании объекта в некий радиус\объём.
И попадание пули в бочку похоже решается каким-нибудь _gameEngine->RayTrace ? но для трассировки нужны ведь точка (пушка машины) и направление (камера? направление машины?).
29
DarkDes, объекты не должны взаимодействовать напрямую. Берем пример моей архитектуры, добавляем в контроллер пару событий. OnCollision - столковение, OnDamage - нанесение урона. Для боычки при столкновении проверяем силу удара, отбираем игровые объекты, котороые расположены в определнном радиусе, расчитываем базовый урон, который можно было бы нанести этому объекту, затем вызываем OnDamage. Дальше у машины обрабатываем это событие, расчитываем сопротивление, уменьшая урон и дальше уже уменьшаем ХП
14
У меня, если по-грубому, то так:
class Car : Object
{
    public Car(IGameEngineForObjects engine);

    public bool ProcessIteration(float dt);
    
    public bool Exploide();
    public bool Move();

    private IGameEngineForObjects _engine;
}

bool Car::ProcessIteration(dt)
{
    if(_gameEngine->GetCollisions(this) != null)
    {        
        return Exploide();
    }

    return Move(dt);
}
Для бочки аналогично. Объект оперируя интерфейсом движка, в котором есть только те методы, которые могут понадобиться объектам, запрашивает у движка список объектов, с которыми он сталкивается. Дальше либо объекты друг с другом специфически взаимодействуют.