Пытаясь использовать шаблоны для двойной диспетчеризации физических столкновений

Я хочу, чтобы компилятор создавал соединения функций для физической системы столкновений. У меня есть тестовая функция столкновения:

template <typename T, typename U>
inline void Collision(T& t, U& u)
{
    if(u.CheckCollision(t.GetCollider()))
    {
        u.HitBy(t);
        t.Hit(u);
    }
}

Затем я использую объект-коллайдер для хранения объекта столкновения.

template <typename T>
class Collidable
{
    T m_Collider;
    VictimEffect m_HitBy;
    MenaceEffect m_Hit;
 public:
    void SetCollider(const T& t) { m_Collider = t; }
    void SetVictim(VictimEffect effect) { m_HitBy = effect; }
    void SetMenace(MenaceEffect effect) { m_Hit = effect; }

    T& GetCollider()
    {
        return m_Collider;
    }
    template <typename V>
    void HitBy(V& menace)
    {
        m_HitBy.HitBy(menace.GetCollider());
    }
    template <typename V>
    void Hit(V& victim)
    {
        m_Hit.Hit(victim.GetCollider());
    }
    template <typename V>
    bool CheckCollision(V& menace)
    {
        return m_Collider.CheckCollision(menace);
    }
};

Я добавил уровень косвенности для функций эффектов

class VictimEffect
{
public:
    template<typename C>
    void HitBy(C&)
    {;}
};

class MenaceEffect
{
public:
    template<typename C>
    void Hit(C&)
    {;}
};

В итоге я хочу получить способ вызова функций в любой объект, который имеет правильную сигнатуру функции, но не требует типов, которые не будут попадать.

class Wall;
class Ball : public MenaceEffect
{
public:
    void Hit(Wall& wall);
    void Hit(Ball& ball);
};

class Wall : public VictimEffect
{
public:
    void HitBy(Ball& ball);
};

Обратите внимание, я не хочу иметь функцию для стены, ударяющейся о стену. Я хочу только написать или предоставить функции для взаимодействия это должно произойти. Я знаю, что это не работает, потому что VictimEffect не «видит» производную функцию.

Я хочу выполнять диспетчеризацию без необходимости указывать параметры шаблона везде, где они используются. Я хочу создать свой коллизируемый эффект отдельно от collidable и передать его объекту столкновения в общем. Я не хочу, чтобы diff Различные сталкивающиеся объекты для каждого набора вещей, с которыми можно столкнуться. В основном я хочу

vector<collidable> movingThings;
vector<collidable> staticThings;
// get iterators ...
Collide(Moving, Static);

. Мне нужно больше уровней косвенного обращения, но я просто не вижу этого. Я знаю, что это можно сделать, потому что вся информация доступна во время компиляции. Нет необходимости в динамическом полиморфном решении.

Любая помощь приветствуется!

Обновление Я пытаюсь создать свою собственную современную (как в книге Андрея) библиотеку игр.Пока у меня сложились отношения в большинстве своем, но этот поставил меня в тупик. Это не проблема, критичная по времени, а проблема, имеющая решающее значение для результатов. Я работаю в играх много лет, и мне не нравится ни один игровой движок, над которым я работал. Он должен быть простым в использовании и легко расширяемым. Теперь, когда консольные компиляторы стали не ужасными, он будет работать на любой платформе.

Вот простой пример того, что я хочу уметь писать.

int main()
{
    // System must come first
    System system(640, 480, false);
    Renderer renderer;
    Mouse mouse;
    Keyboard keys;

    // Make the ball
    Bounce ball;
    Sprite ballSprite("02.bmp");
    CollisionBox ballPhysics;
    BallCommand ballBehavior;

    ball.SpriteMover = boost::bind(&Sprite::Observer<Pos2D>, &ballSprite, _1);
    ball.PhysicsMover = boost::bind(&CollisionBox::Move, &ballPhysics, _1);

    // Make the bounds
    Boundary bounds;

    // Set up Physics
    Collidable<Boundary> boundC;
    boundC.SetCollider(bounds);
    boundC.SetVictim(ballBehavior);

    Collidable<CollisionBox> ballC;
    ballC.SetCollider(ballPhysics);

    PretendPhysics physics;
    physics.SetBall(ballC);
    physics.SetBounds(boundC);

    while(!mouse.LeftClick() && !keys.AnyKey())
    {
        ball.MoveRel(ballBehavior.Delta());
        physics.Update();

        renderer.Clear();
        renderer.Render(ballSprite);
        renderer.SwapBuffers();
    }
}

Вся физика - это незавершенная работа, и я не хочу, чтобы она закончилась, но она приближается. Системный объект инициализирует Windows и средство визуализации, зависящее от платформы. В данном случае это openGL. Он создает все компоненты Windows, хотя компилируется как консольное приложение. Я не хотел, чтобы люди имели дело с main () vs winmain (). Кроме физики наследства нет. Три вызова рендеринга будут заменены одним после того, как я получу сцены в системе. Я планирую использовать то, что написал некоторое время назад, в сочетании с библиотекой шаблонов View Гэри Пауэлла и Мартина Вайзера.

Я знаю, что просто смотрю на это неправильно. Посетитель может помочь изменить мой подход.

Так вот что я пытаюсь сделать.

Обновление 2 ОК. Я получил некоторое вдохновение из комментариев и ответов, и это то, куда я пошел, но я еще не закончил.

template <typename T, typename V = VictimEffect, typename M = MenaceEffect>
class Collidable
{
    T m_Collider;
    V m_HitBy;
    M m_Hit;

public:
    Collidable(T collide, V victim, M menace) : m_Collider(collide), m_HitBy(victim),         m_Hit(menace) {;}
    Collidable(T collide) : m_Collider(collide) {;}
    Collidable(T collide, V victim) : m_Collider(collide), m_HitBy(victim) {;}

    T& GetCollider()
    {
        return m_Collider;
    }

    template <typename V>
    void HitBy(V& menace)
    {
        m_HitBy.HitBy(menace.GetCollider());
    }

    template <typename V>
    void Hit(V& victim)
    {
        m_Hit.Hit(victim.GetCollider());
    }

    template <typename V>
    bool CheckCollision(V& menace)
    {
        return m_Collider.CheckCollision(menace);
    }
};

Тогда, чтобы использовать это, я делаю это

    Collidable<Boundary, BallCommand> boundC(bounds, ballBehavior);
    Collidable<CollisionBox> ballC(ballPhysics);

Всевышний был прав. Я терял информацию о типе, передавая базу. Теперь база нужна только для того, чтобы ловить то, что меня не волнует.

Я думаю, что для своего контейнера я могу использовать список типов, чтобы собрать каждый тип, добавляемый в контейнер, и использовать его для объявления контейнеров определенного типа, которые затем обрабатывают информацию. Однако есть одна загвоздка: я не могу убрать обычные итераторы, было бы проще передавать объекты функций.

возможно, C ++ 0X может помочь с этой новой переменной неизвестного типа. (Я забыл, как это называется).

5
задан Tavison 19 April 2011 в 09:56
поделиться