-----------------------------------------------------------------------------------
For my Asteroids clone, I found myself at odds with my Object class. It had a nice enum called 'Type' that contained the natural "OBJ_ASTEROID", "OBJ_SHIP", etc. However, I found it to be a pain that every time I added a new object, all those other object would have to be recompiled, and I can greatly see this being a huge problem in a game that has more than 5 objects. Taking advice from "Game Coding Complete" (which is a fantastic book, by the way), I decided to just chunk the enum out of the window, and use hashes instead. Because Pheonix uses boost (and by extension, Asteroids uses boost), I decided to write my hash key class using boost. Because of this, it's rather small, but incredibly useful. Here's the entire header:
Code: Select all
#ifndef __HASH_KEY_H__
#define __HASH_KEY_H__
#include <boost/functional/hash.hpp>
#include <boost/algorithm/string.hpp>
#include <string>
class HashKey
{
public:
HashKey()
: hash(0)
{}
HashKey( const std::string& _s )
: hash( hash_function( _s ) )
{}
~HashKey()
{}
/*!
@brief The hash function for hash keys.
This is the central function of this class,
this essentially takes a string and turns it
into a number. Also note that it lowercases
the string, this is to avoid programmers
mixing cases.
*/
static size_t hash_function( const std::string& _s )
{
static boost::hash< std::string> string_hash;
std::string tempstr( _s );
boost::to_lower( tempstr );
return string_hash( tempstr );
}
//! Standard assignment from string.
const HashKey& operator = ( const std::string& _s )
{
(*this) = HashKey( _s );
return *this;
}
//! Standard comparison.
bool operator == ( const HashKey& other ) const
{
return hash == other.hash;
}
//! Comparison against a string, it hashes the string then compares.
bool operator == ( const std::string& other ) const
{
return hash == hash_function( other );
}
//! Implicit conversion to size_t, so that we can easy print, store, or serialize the key.
operator const std::size_t& ()
{
return hash;
}
private:
std::size_t hash;
};
#endif;
Here's a small test of the class:
Code: Select all
#include <hashkey.hpp>
#include <iostream>
int main()
{
HashKey test;
test = "Hello, World!";
std::cout<<test<<std::endl;
std::cout<<HashKey("Hello, World!")<<std::endl;
std::cout<<HashKey("helLo, woRld!")<<std::endl;
std::cout<< ( test == "helLo, woRld!" ? "True" : "False" )<< std::endl;
std::cin.get();
return 0;
}
I hope that you can find some neat uses for this little snippet, it has saved me compile time all over the place (and it serializes well). Here's some snippets of how I used it Asteroids:
Code: Select all
ShipObject( ObjectManager& _m ):
: GameObject(_m), type( "ShipObject" )
{}
..............................................
collision( shared_ptr<GameObject> other )
{
if( other.getType() == "ShipObject" )
{
...
}
}
..............................................
void onEvent( const Event& event )
{
signals[ event.type ].sig();
}