forked from Revolutionary-Games/Thrive
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add Collision system for handling custom events upon collisions.
squashed commits: Implementation of custom collision events. Some questionable design choices within. (Untested) Updated collision system to new structure. Now uses CollisionHandlerComponent and CollisionSystem. Manifolds used instead of global callback. Fixed previous compile error - a new one has taken it's place (uintptr_tr not defined) Basic working state achieved. m_collisionCallbackKey assignment from lua does not seem to take effect. Also storage and load still needs implementing, and agentabsorber system needs refactoring. Storage and load implemented. AgentAbsorber system & component refactored to use this system. Acceptance tests performed Collision filters added, not fully functional Collision functionality nearly updated. Needs cleanup, testing and integration with agentabsorber. Working CollisionFilter class. Attempt at exposing CollisionFilter to lua. Not successful. Fixes to improve usage of CollisionFilter. Now uses Collision struct instead of typedef to pair of entityIds. Better model for exposure to lua (still doesn't quite work). Cleaned up documentation and header includes. Fixed minor compile error Collision system finalized. - Added a member to Collision to represent the duration of collision represented since last clearCollisions(). This member will allow more fine grained control of collision handling (damage every 0.5 second, etc). - Cleaned up documentation and debugging code. Renamed CollisionHandlerComponent to CollisionComponent. Added removeCollisionGroup to CollisionComponent. Added constructor taking a collision group to CollisionComponent Refactoring of CollisionSystem. Stopped using mutable keyword in collision class and instead uses unordered map. Added a vector<collision*> mirroring the contents of the unordered_map to allow iteration in lua. Changed to using boost::map_values for iteration. Rebased onto master. Fixed setup.lua Various relevant fixes. Code is currently not functioning due to strange bug. Implementation of custom collision events. Some questionable design choices within. (Untested) Updated collision system to new structure. Now uses CollisionHandlerComponent and CollisionSystem. Manifolds used instead of global callback. Fixed previous compile error - a new one has taken it's place (uintptr_tr not defined) Basic working state achieved. m_collisionCallbackKey assignment from lua does not seem to take effect. Also storage and load still needs implementing, and agentabsorber system needs refactoring. Fix typo in Lua script The previous version crashed because the game state passed to CollisionFilter's constructor was nil in Lua and consequently nullptr in C++. Simplify GameState::findSystem No need for complicated iteration. Also, dynamic_cast can only throw an exception if a reference type is cast, not for pointer types. Refactor signature handling of CollisionFilter Returning a pair of references is a little tricky because it's not obvious how the std::pair template will handle it. Returning a reference to a pair, however, is more predictable. Use static initializers when possible Minor refactoring * Use typedefs (i.e. CollisionFilter::Signature) instead of repeating the type * Use emplace when possible, it's more readable than constructing the collection item manually * Rename permutation -> combination Do not register collision filter in Implementation constructor At that point, the m_impl field of the CollisionFilter is not initialized yet (because the Implementation object is not fully constructed). The CollisionSystem asks the filter for its signature, which is saved in the m_impl object. Since this doesn't point to anything useful yet, it crashes. Added CollisionFilter.init and CollisionFilter.shutdown to allow users to create their CollisionFilters in constructors. Removed debugging code. Minor refactorings for CollisionFilter and CollisionSystem Removed typedefs in collision_filter.cpp. Removed minor error in rebasing
- Loading branch information
Showing
17 changed files
with
903 additions
and
45 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,129 @@ | ||
#include "collision_filter.h" | ||
#include <luabind/iterator_policy.hpp> | ||
#include "engine/game_state.h" | ||
#include "scripting/luabind.h" | ||
|
||
|
||
|
||
using namespace thrive; | ||
|
||
struct CollisionFilter::Implementation { | ||
|
||
Implementation( | ||
const std::string& collisionGroup1, | ||
const std::string& collisionGroup2 | ||
) : m_signature(collisionGroup1, collisionGroup2) | ||
{ | ||
} | ||
|
||
CollisionMap m_collisions; | ||
|
||
Signature m_signature; | ||
|
||
CollisionSystem* m_collisionSystem = nullptr; | ||
|
||
}; | ||
|
||
|
||
luabind::scope | ||
CollisionFilter::luaBindings() { | ||
using namespace luabind; | ||
return class_<CollisionFilter>("CollisionFilter") | ||
.def(constructor<const std::string&, const std::string&>()) | ||
.def("init", &CollisionFilter::init) | ||
.def("shutdown", &CollisionFilter::shutdown) | ||
.def("collisions", &CollisionFilter::collisions, return_stl_iterator) | ||
.def("clearCollisions", &CollisionFilter::clearCollisions) | ||
; | ||
} | ||
|
||
|
||
CollisionFilter::CollisionFilter( | ||
const std::string& collisionGroup1, | ||
const std::string& collisionGroup2 | ||
) : m_impl(new Implementation(collisionGroup1, collisionGroup2)) | ||
{ | ||
} | ||
|
||
CollisionFilter::~CollisionFilter(){} | ||
|
||
void | ||
CollisionFilter::init( | ||
GameState* gameState | ||
) { | ||
m_impl->m_collisionSystem = gameState->findSystem<CollisionSystem>(); | ||
m_impl->m_collisionSystem->registerCollisionFilter(*this); | ||
} | ||
|
||
void | ||
CollisionFilter::shutdown() { | ||
m_impl->m_collisionSystem->unregisterCollisionFilter(*this); | ||
m_impl->m_collisionSystem = nullptr; | ||
} | ||
|
||
const CollisionFilter::CollisionIterator | ||
CollisionFilter::collisions() { | ||
return m_impl->m_collisions | boost::adaptors::map_values; | ||
} | ||
|
||
|
||
void | ||
CollisionFilter::addCollision( | ||
Collision collision | ||
) { | ||
CollisionMap::iterator foundCollision = m_impl->m_collisions.find(CollisionId(collision.entityId1, collision.entityId2)); | ||
if (foundCollision != m_impl->m_collisions.end()) | ||
foundCollision->second.addedCollisionDuration += collision.addedCollisionDuration; //Add collision time. | ||
else | ||
{ | ||
CollisionId key(collision.entityId1, collision.entityId2); | ||
m_impl->m_collisions.emplace(key, collision); | ||
} | ||
|
||
} | ||
|
||
|
||
typename CollisionFilter::CollisionIterator::iterator | ||
CollisionFilter::begin() const { | ||
return (m_impl->m_collisions | boost::adaptors::map_values).begin(); | ||
} | ||
|
||
|
||
typename CollisionFilter::CollisionIterator::iterator | ||
CollisionFilter::end() const { | ||
return (m_impl->m_collisions | boost::adaptors::map_values).end(); | ||
} | ||
|
||
|
||
void | ||
CollisionFilter::clearCollisions() { | ||
m_impl->m_collisions.clear(); | ||
} | ||
|
||
|
||
const CollisionFilter::Signature& | ||
CollisionFilter::getCollisionSignature() const { | ||
return m_impl->m_signature; | ||
} | ||
|
||
|
||
size_t | ||
CollisionFilter::IdHash::operator() ( | ||
const CollisionId& collisionId | ||
) const { | ||
std::size_t hash1 = std::hash<EntityId>()(collisionId.first); | ||
std::size_t hash2 = std::hash<EntityId>()(collisionId.second); | ||
// Hash needs to be symmetric so that hash(entityId1, entityId2) == hash(entityId2, entityId1) | ||
return hash1 ^ hash2; | ||
} | ||
|
||
|
||
bool | ||
CollisionFilter::IdEquals::operator() ( | ||
const CollisionId& lhs, | ||
const CollisionId& rhs | ||
) const{ | ||
// Equality needs to be symmetric for collisions | ||
return (lhs.first == rhs.first && lhs.second == rhs.second) || | ||
(lhs.first == rhs.second && lhs.second == rhs.first); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,172 @@ | ||
#pragma once | ||
|
||
#include <boost/range/adaptor/map.hpp> | ||
|
||
#include "bullet/collision_system.h" | ||
|
||
#include <iostream> | ||
#include <string> | ||
|
||
#include <unordered_set> | ||
#include <utility> | ||
|
||
|
||
namespace luabind { | ||
class scope; | ||
} | ||
|
||
namespace thrive { | ||
|
||
class Collision; | ||
class CollisionSystem; | ||
|
||
/** | ||
* @brief Filters for collisions that contain specific collision groups | ||
* | ||
* Collision filter makes it easy for systems and other peices of code to get easy | ||
* access to the right collisions | ||
* | ||
*/ | ||
|
||
class CollisionFilter { | ||
|
||
public: | ||
|
||
using CollisionId = std::pair<EntityId, EntityId>; | ||
|
||
using Signature = std::pair<std::string, std::string>; | ||
|
||
struct IdHash { | ||
std::size_t | ||
operator() ( | ||
const CollisionId& collisionId | ||
) const; | ||
}; | ||
|
||
struct IdEquals { | ||
bool | ||
operator() ( | ||
const CollisionId& lhs, | ||
const CollisionId& rhs | ||
) const; | ||
}; | ||
|
||
using CollisionMap = std::unordered_map<CollisionId, Collision, IdHash, IdEquals>; | ||
using CollisionIterator = boost::range_detail::select_second_mutable_range<CollisionMap>; | ||
|
||
/** | ||
* @brief Constructor | ||
* | ||
* @param collisionGroup1 | ||
* The first collision group to monitor | ||
* | ||
* @param collisionGroup2 | ||
* The second collision group to monitor | ||
* | ||
*/ | ||
CollisionFilter( | ||
const std::string& collisionGroup1, | ||
const std::string& collisionGroup2 | ||
); | ||
|
||
/** | ||
* @brief Destructor | ||
*/ | ||
~CollisionFilter(); | ||
|
||
/** | ||
* @brief Initialized the collision filter | ||
* | ||
* @param gameState | ||
* The gamestate the filter belongs in. | ||
*/ | ||
void | ||
init( | ||
GameState* gameState | ||
); | ||
|
||
/** | ||
* @brief Shuts down the filter. | ||
*/ | ||
void | ||
shutdown(); | ||
|
||
/** | ||
* @brief Lua bindings | ||
* | ||
* Exposes the following \b constructors: | ||
* - CollisionFilter(const std::string&, const std::string&) | ||
* - CollisionFilter::init(GameState*) | ||
* - CollisionFilter::shutdown() | ||
* - CollisionFilter::collisions() | ||
* - CollisionFilter::clearCollisions() | ||
*/ | ||
static luabind::scope | ||
luaBindings(); | ||
|
||
/** | ||
* @brief Returns the collisions that has occoured | ||
* | ||
* Is only reset when clearCollisions() is called | ||
*/ | ||
const CollisionIterator | ||
collisions(); | ||
|
||
/** | ||
* @brief Clears the collisions | ||
*/ | ||
void | ||
clearCollisions(); | ||
|
||
/** | ||
* @brief Adds a collision | ||
* | ||
* @param collision | ||
* Collision to add | ||
*/ | ||
void | ||
addCollision(Collision collision); | ||
|
||
/** | ||
* @brief Iterator | ||
* | ||
* Equivalent to | ||
* \code | ||
* collisions().cbegin() | ||
* \endcode | ||
* | ||
* @return An iterator to the first collision | ||
*/ | ||
typename CollisionIterator::iterator | ||
begin() const; | ||
|
||
/** | ||
* @brief Iterator | ||
* | ||
* Equivalent to | ||
* \code | ||
* collisions().cend() | ||
* \endcode | ||
* | ||
* @return An iterator to the end of the collisions | ||
*/ | ||
typename CollisionIterator::iterator | ||
end() const; | ||
|
||
/** | ||
* @brief Returns the signature of the collision filter | ||
* | ||
* @return | ||
* A pair of the two collision group strings. | ||
*/ | ||
const Signature& | ||
getCollisionSignature() const; | ||
|
||
private: | ||
|
||
struct Implementation; | ||
std::unique_ptr<Implementation> m_impl; | ||
|
||
}; | ||
|
||
} |
Oops, something went wrong.