clooneljump/src/collider.cpp

168 lines
6.5 KiB
C++
Raw Normal View History

2014-07-28 11:00:55 +02:00
/*
Copyright 2014 Michele "King_DuckZ" Santullo
This file is part of CloonelJump.
CloonelJump is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
CloonelJump is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with CloonelJump. If not, see <http://www.gnu.org/licenses/>.
*/
#include "collider.hpp"
2014-07-31 20:13:13 +02:00
#include "horzcollisionbar.hpp"
#include "line.hpp"
#include "vector.hpp"
#include "vectormath.hpp"
2014-07-28 11:00:55 +02:00
#include <vector>
#include <ciso646>
#include <cassert>
#include <algorithm>
#if defined(WITH_VERBOSE_COLLIDER) && !defined(NDEBUG)
#define VERBOSE_COLLIDER
#include <iostream>
#endif
namespace cloonel {
namespace {
2014-07-31 20:13:13 +02:00
typedef std::vector<const CollisionBar*> CollisionBarListType;
typedef std::vector<std::pair<Collider::GroupIDType, CollisionBarListType>> CollisionBarGroupListType;
const CollisionBarListType g_empty;
///----------------------------------------------------------------------
///----------------------------------------------------------------------
const CollisionBarListType& findGroup (const CollisionBarGroupListType& parList, Collider::GroupIDType parID) {
for (const auto& itm : parList) {
if (itm.first == parID) {
return itm.second;
}
}
assert(false);
return g_empty;
}
#if !defined(NDEBUG)
///----------------------------------------------------------------------
///----------------------------------------------------------------------
bool isGroupRegistered (const CollisionBarGroupListType& parList, Collider::GroupIDType parID) {
const CollisionBarListType& result = findGroup(parList, parID);
return &g_empty != &result;
}
#endif
///----------------------------------------------------------------------
///----------------------------------------------------------------------
CollisionBarListType& findOrAddGroup (CollisionBarGroupListType& parList, Collider::GroupIDType parID) {
for (auto& itm : parList) {
if (itm.first == parID) {
return itm.second;
}
}
parList.push_back(std::make_pair(parID, CollisionBarListType()));
assert(parList.back().first == parID);
return parList.back().second;
}
///----------------------------------------------------------------------
///----------------------------------------------------------------------
void collide (float parDeltaT, const CollisionBarListType& parGroup1, const CollisionBarListType& parGroup2) {
Line<float, 2> overlap;
for (const auto& bar1 : parGroup1) {
assert(bar1);
for (const auto& bar2 : parGroup2) {
assert(bar2);
if (bar2 == bar1)
continue;
if (Collide(parDeltaT, *bar1, *bar2, overlap)) {
#if defined(VERBOSE_COLLIDER)
std::cout << "Collider: Collision ";
2014-07-31 20:13:13 +02:00
std::cout << "between " << bar1 << " and " << bar2 << "\n";
#endif
const auto dir1 = normalized(bar1->GetPos() - bar1->From());
bar1->InvokeCallback(overlap, dir1);
const auto dir2 = normalized(bar2->GetPos() - bar2->From());
bar2->InvokeCallback(overlap, dir2);
}
}
}
}
2014-07-28 11:00:55 +02:00
} //unnamed namespace
///--------------------------------------------------------------------------
///--------------------------------------------------------------------------
Collider::Collider() {
}
///--------------------------------------------------------------------------
///--------------------------------------------------------------------------
Collider::~Collider() noexcept {
}
///--------------------------------------------------------------------------
///--------------------------------------------------------------------------
2014-07-31 20:13:13 +02:00
void Collider::RunCollisionTests (float parDeltaT) const {
for (const auto& relationship : m_relationships) {
const CollisionBarListType& group1 = findGroup(m_collisionBars, relationship.first);
const CollisionBarListType& group2 = (relationship.first == relationship.second ? group1 : findGroup(m_collisionBars, relationship.second));
collide(parDeltaT, group1, group2);
}
}
///--------------------------------------------------------------------------
///--------------------------------------------------------------------------
void Collider::TieGroups (GroupIDType parGroup1, GroupIDType parGroup2) {
#if defined(VERBOSE_COLLIDER)
std::cout << "Collider: Tying group " << parGroup1 << " to " << parGroup2 << " for collision tests\n";
#endif
2014-07-31 20:13:13 +02:00
assert(m_relationships.end() == std::find(m_relationships.begin(), m_relationships.end(), std::make_pair(parGroup1, parGroup2)));
assert(m_relationships.end() == std::find(m_relationships.begin(), m_relationships.end(), std::make_pair(parGroup2, parGroup1)));
assert(isGroupRegistered(m_collisionBars, parGroup1));
assert(isGroupRegistered(m_collisionBars, parGroup2));
m_relationships.push_back(std::make_pair(parGroup1, parGroup2));
}
///--------------------------------------------------------------------------
///--------------------------------------------------------------------------
void Collider::RegisterBar (GroupIDType parGroup, const CollisionBar* parBar) {
#if defined(VERBOSE_COLLIDER)
std::cout << "Collider: Registering bar " << parBar << " in group " << parGroup << "\n";
#endif
2014-07-31 20:13:13 +02:00
CollisionBarListType& group = findOrAddGroup(m_collisionBars, parGroup);
assert(isGroupRegistered(m_collisionBars, parGroup));
assert(parBar);
group.push_back(parBar);
2014-07-28 11:00:55 +02:00
}
///--------------------------------------------------------------------------
///--------------------------------------------------------------------------
void Collider::UnregisterBar (GroupIDType parGroup, const CollisionBar* parBar) {
assert(isGroupRegistered(m_collisionBars, parGroup));
CollisionBarListType& group = findOrAddGroup(m_collisionBars, parGroup);
auto itdele = std::find(group.begin(), group.end(), parBar);
assert(itdele != group.end());
group.erase(itdele);
}
///--------------------------------------------------------------------------
///--------------------------------------------------------------------------
void Collider::Reset() noexcept {
m_relationships.clear();
m_collisionBars.clear();
}
2014-07-28 11:00:55 +02:00
} //namespace cloonel
#if defined(VERBOSE_COLLIDER)
#undef VERBOSE_COLLIDER
#endif