Я создал физическую систему, которая обрабатывает любой объект столкновения с любым объектом столкновения следующим образом:
namespace Collision
{
template <typename T, typename U>
inline void Check(T& t, U& u)
{
if(u.CheckCollision(t.GetCollider()))
{
u.HitBy(t);
t.Hit(u);
}
}
}
и есть несколько других вспомогательных объектов, облегчающих использование, но суть в том, что есть динамические объекты, которые нужно тестировать против статических объектов и других динамических объектов, но статические объекты не нужно проверять.
Я хотел бы что-то вроде этого:
void func()
{
PhysicsWorld world;
shared_ptr<CSphere> ballPhysics(new CSphere(0,0,ballSprite->Width()));
BallCommand ballBehavior;
CBounds bounds(0, 0, 640, 480);
CBox obstacle(200, 150, 10, 10);
Collision::Collidable<CBounds> boundC(bounds);
Collision::Collidable<std::shared_ptr<CSphere>, BallCommand&> ballC(ballPhysics, ballBehavior);
Collision::Collidable<CBox> obstC(obstacle);
world.addStatic(boundC);
world.addDynamic(ballC);
world.addStatic(obstC);
...
...
world.Update();
...
...
}
Я бы хотел вывести контейнеры с помощью функций добавления, чтобы система автоматически обновляла списки типов. Я думаю, что понял, как сгенерировать список типов с помощью функции шаблона, но не понял, как затем получить его там, где он мне нужен, или в какой момент компиляции он завершен.
Если нет, то какая-то система использует два списка типов, которые затем внутренне записывают функцию обновления для перебора всех списков, сопоставляя их друг с другом.
Я читал некоторые книги по Boost MPL и несколько раз читал книгу Андрея. Но я, кажется, увяз в том, как это работает, и на самом деле не перевожу это в то, как я его использую. Я бы хотел, чтобы в книге MPL был еще один раздел с примерами из реального мира.
Мне удалось заставить все части игрового движка взаимодействовать с рендерингом, физикой, коллизиями (я отделяю обнаружение от реакции), вводом, сетью, звуком и т. д. Все в общих чертах. Теперь мне просто нужно держать все вещи в общем виде. После всей этой универсальной работы было бы глупо требовать наследования только для того, чтобы я мог хранить что-то в контейнере, и я не хочу передавать код каждой возможности сбора, поскольку это одно из больших преимуществ универсального программирования.
Я видел, что Джалф указал, что он/она использовал MPL, чтобы сделать что-то подобное, но не вдавался в подробности, чтобы я мог в этом разобраться. Если кто-нибудь знает пример практического использования или где я могу получить больше информации об использовании MPL, я был бы признателен.
Еще раз спасибо!
Обновить
boost MPL и boost Fusion, кажется, делают то, что я хочу, но, похоже, очень мало хороших примеров из реальной жизни для обеих библиотек. Документация для MPL немного больше, чем этот шаблон, и удачи в понимании последствий этого. Fusion немного лучше с "Вот пример, но это только верхушка айсберга!"
Типичный пример Boost MPL — has_xxx. Они используют XXX и xxx в примере, из-за чего трудно увидеть разницу, где XXX (необходимый текст) и Test или CheckType или любой другой различимый тип пользователя можно использовать вместо xxx. Кроме того, нет упоминания о том, что ничего из этого не находится в пространстве имен. Теперь я понимаю, почему Скотт Мейерс сравнил это со сценой в душе в «Психо».
На самом деле это позор, потому что то немногое, что мне удалось скомпилировать и понять, делает действительно полезные вещи, но это так сложно понять, что я бы никогда не потратил столько усилий, если бы занимался поставкой продукта.
Если кто-нибудь знает примеры из реального мира или лучшие ссылки, объяснения или учебник, я был бы признателен.
Обновить
Вот еще код:
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(boundary, ballBehavior);
Collidable<CollisionBox> ballC(circle);
Тогда все, что мне нужно, это вызвать столкновение со всеми моими активными сталкивающимися объектами со всеми моими активными и пассивными объектами.
Я не использую std::function, потому что добавление имен функций делает код более понятным. Но, возможно, это просто унаследованное мышление.
multiple dispatch
. Так что вы можете перечитать связанная глава из книги Андрея... Удачи - person sehe   schedule 26.04.2011