Я создал физическую систему, которая обрабатывает любой объект столкновения с любым объектом столкновения следующим образом:
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();
...
...
}
Мне бы хотелось вывести контейнеры с помощью функций добавления, чтобы система автоматически обновляла списки типов. Думаю, я понимаю, как создать список типов с помощью функции шаблона, но не знаю, как затем получить его там, где он мне нужен, или в какой момент компиляции он завершен.
Если не это, то некоторая система, использующая два списка типов, n внутренне записывает функцию обновления для перебора всех списков, сопоставляя их друг с другом.
Я читал некоторые книги о повышении MPL и несколько раз читал книгу Андрея. Но я, кажется, зациклен на том, как это работает, и не очень понимаю, как я его использую. Я бы хотел, чтобы у них был еще один раздел о реальных примерах в книге MPL.
Мне удалось заставить все части игрового движка взаимодействовать с рендерингом, физикой, столкновениями (я отделяю обнаружение от реакции), вводом, сетью, звуком и т. Д. Все в общих чертах. Теперь мне просто нужно держать все в общих чертах.После всей этой общей работы было бы глупо требовать наследования только для того, чтобы я мог что-то хранить в контейнере, и я не хочу передавать код для каждой возможности сбора, поскольку это одно из больших преимуществ универсального программирования.
Я видел, как Джалф указал, что он / она использовал MPL для чего-то подобного, но не вдавался в подробности достаточно, чтобы я мог это понять. Если кто-нибудь знает пример практического использования или где я могу получить дополнительную информацию об использовании MPL, я был бы признателен.
Еще раз спасибо!
Обновление
ускоряет MPL и ускоряет Fusion, кажется, что я делаю то, что я хочу, но, похоже, очень мало хороших примеров из реальной жизни обеих библиотек. Документация для MPL немного больше, чем этот шаблон, и удачи в понимании последствий этого. Fusion немного лучше: «Вот пример, но это только верхушка айсберга!»
Типичным примером ускоренного 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);
Затем все, что мне нужно, это вызвать collide со всеми моими активными сталкивающимися объектами против всех моих активных и пассивных объектов.
Я не использую std :: function, потому что добавление имен функций делает код более понятным для меня. Но, возможно, это просто устаревшее мышление.