tag:blogger.com,1999:blog-35793123763046297542024-03-05T06:33:26.675-08:00Randy Gaul's Game Programming BlogINSIDE TAKE ON BECOMING A GAME PROGRAMMERCecilSunkurehttp://www.blogger.com/profile/16129986119923492789noreply@blogger.comBlogger54125tag:blogger.com,1999:blog-3579312376304629754.post-88655045788617458552012-10-19T17:23:00.004-07:002012-10-19T17:23:55.689-07:00Moved to new location!<span style="font-family: Trebuchet MS, sans-serif;">I've moved the site to a <a href="http://www.randygaul.net/">new location</a>! All legacy posts were transferred.</span><br />
<span style="font-family: Trebuchet MS, sans-serif;"><br /></span>
<span style="font-family: Trebuchet MS, sans-serif;">Link to new location: </span><a href="http://www.randygaul.net/"><span style="font-family: Trebuchet MS, sans-serif;">http://www.randygaul.net/</span></a>CecilSunkurehttp://www.blogger.com/profile/16129986119923492789noreply@blogger.com0tag:blogger.com,1999:blog-3579312376304629754.post-7806511116383669532012-10-09T14:55:00.000-07:002012-10-09T15:28:11.127-07:00C++ Reflection: Type MetaData: Part 3 - Improvements<span style="font-family: Trebuchet MS, sans-serif;">In our <a href="http://cecilsunkure.blogspot.com/2012/10/c-reflection-type-metadata-part-2-type.html">last article</a> we learned how to store information about a classes's members, however there are a couple key improvements that need to be brought to the MetaData system before moving on.</span><br />
<div>
<span style="font-family: Trebuchet MS, sans-serif;"><br />
</span></div>
<div>
<span style="font-family: Trebuchet MS, sans-serif;">The first issue is with our RemQual struct. In the previous article we had support for stripping off qualifiers such as *, const or &. We even had support for stripping off an R-value reference. However, the RemQual struct had no support for a pointer to a pointer. It is weird that RemQual<int**> would behave differently than RemQual<int*>, and so on. To solve this issue we can cycle down, at compile time, the type through the RemQual struct recursively, until a type arrives at the base RemQual definition. Here's an example:</span></div>
<br />
<div class="code">
<pre><code>//
// RemQual
// Strips down qualified types/references/pointers to a single unqualified type, for passing into
// a templated type as a typename parameter.
//
template <typename T>
struct RemQual
{
typedef T type;
};
template <typename T>
struct RemQual<const T>
{
typedef typename RemQual<T>::type type;
};
template <typename T>
struct RemQual<T&>
{
typedef typename RemQual<T>::type type;
};
template <typename T>
struct RemQual<const T&>
{
typedef typename RemQual<T>::type type;
};
template <typename T>
struct RemQual<T&&>
{
typedef typename RemQual<T>::type type;
};
template <typename T>
struct RemQual<const T *>
{
typedef typename RemQual<T *>::type type;
};</code></pre>
</div>
<br />
<span style="font-family: Trebuchet MS, sans-serif;">As you can see, this differs a bit from our previous implementation. The way it works is by passing in a single type to the RemQual struct via typename T. Then, the templating matches the type provided with one of the overloads and feeds the type back into the RemQual struct with less qualifiers. This acts as some sort of compile-time "recursive" qualifier stripping mechanism; I'm afraid I don't know what to properly call this technique. This is useful for finding out what the "base type" of any given type.</span><br />
<span style="font-family: Trebuchet MS, sans-serif;"><br /></span>
<span style="font-family: Trebuchet MS, sans-serif;">It should be noted that the example code above does not strip pointer qualifiers off of a type. This is to allow the MetaData system to properly provide MetaData instances of pointer types; which is necessary to reflect pointer meta.</span><br />
<span style="font-family: Trebuchet MS, sans-serif;"><br />
</span> <span style="font-family: Trebuchet MS, sans-serif;">It should be noted that in order to support pointer meta, the RemQual struct will need to be modified so it does not strip off the * qualifier. This actually applies to any qualifier you do not wish to have stripped.</span><br />
<span style="font-family: Trebuchet MS, sans-serif;"><br />
</span> <span style="font-family: Trebuchet MS, sans-serif;">There's one last "improvement" one could make to the RemQual struct that I'm aware of. I don't actually consider this an improvement, but more of a feature or decision. There comes a time when the user of a MetaData system may want to write a tidbit of code like the following:</span><br />
<br />
<div class="code">
<pre><code>SendMessage( "Message ID", Param1, Param2 );</code></pre>
</div>
<br />
<span style="font-family: Trebuchet MS, sans-serif;">Say the user wants to send a message object from one place to another. Imagine this message object can take three parameters of any type, and the reflection system can help the constructor of the message figure out the types of the data at run-time (how to actually implement features like this will be covered once Variants and RefVariants are introduced). This means that the message can take three parameters of any type and then take them as payload to deliver elsewhere.</span><br />
<span style="font-family: Trebuchet MS, sans-serif;"><br />
</span> <span style="font-family: Trebuchet MS, sans-serif;">However, there's a subtle problem with the "Message ID" in particular. Param1 and Param2 are assumed to be POD types like float or int, however "Message ID" is a const char * string literal. My understanding of string literals in C++ is that they are of the type: const char[ x ], x being the number of characters in the literal. This poses a problem for our templated MetaCreator, in that every value of x will create a new MetaData instance, as the templating treats each individual value of x as an entire new type. Now how can RemQual handle this? It gets increasingly difficult to actually manage Variants and RefVariant constructors for string literals <a href="http://stackoverflow.com/questions/2589949/c-string-literals-where-do-they-go">for reasons explained here</a>, though this will be tackled in a later article.</span><br />
<span style="font-family: Trebuchet MS, sans-serif;"><br />
</span> <span style="font-family: Trebuchet MS, sans-serif;">There are two methods of handling string literals that I am aware of; the first is to make use of some form of a light-weight wrapper. A small wrapper object can contain a const char * data member, and perhaps an unsigned integer to represent the length, and any number of utility functions for common string operations (concat, copy, compare, etc). The use of such a wrapper would look like:</span><br />
<br />
<div class="code">
<pre><code>SendMessage( S( "Message ID" ), Param1, Param2 );</code></pre>
</div>
<br />
<span style="font-family: Trebuchet MS, sans-serif;">The S would be the class type of the wrapper itself, and the constructor would take a const char *. This would require every place in code that handles a string literal to make use of the S wrapper. This can be quite annoying, but has great performance benefits compared to std::string, especially when some reference counting is used to handle the heap allocated const char * data member holding the string data in order to avoid unnecessary copying. Here's an example skeleton class for such an S wrapper:</span><br />
<br />
<div class="code">
<pre><code>class S
{
public:
S( const char *src ) : data( src ) {}
~S( ) {}
bool IsEqual( const S& rhs ) const;
void Concat( const S& rhs )
{
char *temp = new char[rhs.len + len];
strcpy( temp, data );
strcpy( temp + len, rhs.data );
}
private:
const char *data;
unsigned len;
};</code></pre>
</div>
<br />
<span style="font-family: Trebuchet MS, sans-serif;">As I mentioned before, I found this to be rather annoying; I want my dev team and myself to be able to freely pass along a string literal anywhere and have MetaData handle the type properly. In order to do this, a very ugly and crazy solution was devised. There's a need to create a RemQual struct for every [ ] type for all values of x. This isn't possible. However, it is possible to overload RemQual for a few values of x, at least enough to cover any realistic use of a string literal within C++ code. Observe:</span><br />
<br />
<div class="code">
<pre><code>#define INTERNAL_ARRAY_OVERLOAD( x ) \
template <typename T> \
struct RemQual<T[ x ]> \
{ \
typedef typename RemQual<T *>::type type; \
}; \
\
template <typename T> \
struct RemQual<const T[ x ]> \
{ \
typedef typename RemQual<T *>::type type; \
};
#define ARRAY_OVERLOAD( ) \
INTERNAL_ARRAY_OVERLOAD( __COUNTER__ )</code></pre>
</div>
<br />
<span style="font-family: Trebuchet MS, sans-serif;">The macro ARRAY_OVERLOAD creates a RemQual overload with a value of x. The __COUNTER__ macro (though not standard) increments by one each time the macro is used. This allows for copy/pasting of the ARRAY_OVERLOAD macro, which will generate a lot of RemQual overloads. I created a file with enough overloads to cover any realistically sized string literal. As an alternative to the __COUNTER__ macro, __LINE__ can be used instead, however I imagine it might be difficult to ensure you have one definition per line without any gaps. As far as I know, __COUNTER__ is supported on both GNU and MSVC++.</span><br />
<span style="font-family: Trebuchet MS, sans-serif;"><br />
</span> <span style="font-family: Trebuchet MS, sans-serif;">Not only will the ARRAY_OVERLOAD cover types of string literals, but it will also cover types with array brackets [ ] of any type passed to RemQual.</span><br />
<span style="font-family: Trebuchet MS, sans-serif;"><br />
</span> <span style="font-family: Trebuchet MS, sans-serif;">The second issue is the ability to properly reflect private data members. There are three solutions to reflecting private data that I am aware of. The first is to try to grant access to the MetaData system by specifying that the MetaCreator of the type in question is a friend class. I never really liked the idea of this solution and haven't actually tried it for myself, and so I can't really comment on the idea any further than this.</span><br />
<span style="font-family: Trebuchet MS, sans-serif;"><br />
</span> <span style="font-family: Trebuchet MS, sans-serif;">The next possible solution is to make use of properties. A property is a set of three things: a gettor; a settor; a member. The gettor and settor provide access to the private member stored within the class. The user can then specify gettors and/or settors from the ADD_MEMBER macro. </span><span style="font-family: 'Trebuchet MS', sans-serif;">I haven't implemented this method myself, but would definitely like if I find the time to create such a system. This solution is by far the most elegant of the three choices that I'm presenting. <a href="http://seanmiddleditch.com/journal/2012/02/c-method-type-deduction-tricks/">Here's a link</a> to some information on creating some gettor and settor support for a MetaData system like the one in this article series. This can potentially allow a MetaData system to reflect class definitions that the user does not have source code access to, so long as the external class has gettor and settor definitions that are compatible with the property reflection.</span><br />
<span style="font-family: 'Trebuchet MS', sans-serif;"><br />
</span> <span style="font-family: 'Trebuchet MS', sans-serif;">The last solution is arguably more messy, but it's easier to implement and works perfectly fine. I chose to implement this method in my own project because of how little time it took to set up a working system. Like I said earlier, if I have time I'd like to add property support, though right now I simply have more important things to finish.</span><br />
<span style="font-family: 'Trebuchet MS', sans-serif;"><br />
</span> <span style="font-family: 'Trebuchet MS', sans-serif;">The idea of the last solution is to paste a small macro inside of your class definitions. This small macro then pastes some code within the class itself, and this code grants access to any private data member by using the NullCast pointer trick. This means that in order to reflect private data, you must have source code access to the class in question in order to place your macro. Here's what the new macros might look like, but be warned it gets pretty hectic:</span><br />
<br />
<div class="code">
<pre><code>#define DEFINE_META( TYPE ) \
MetaCreator<remqualptr gt="gt" lt="lt" type="type"> NAME_GENERATOR( )( #TYPE, sizeof( TYPE ), true ); \
RemQualPtr<TYPE>::type *TYPE::NullCast( void ) { return reinterpret_cast<remqualptr gt="gt" lt="lt" type="type">(NULL); } \
void TYPE::AddMember( std::string name, unsigned offset, MetaData *data ) { return MetaCreator<RemQualPtr<TYPE>::type>::AddMember( name, offset, data ); } \
void MetaCreator<RemQualPtr<TYPE>::type>::RegisterMetaData( void ) { TYPE::RegisterMetaData( ); } \
void TYPE::RegisterMetaData( void )
//
// META_DATA
// Purpose : This macro goes on the inside of a class within the public section. It declares
// a few member functions for use by the MetaData system to retrieve information about
// the class.
#define META_DATA( TYPE ) \
static void AddMember( std::string name, unsigned offset, MetaData *data ); \
static RemQual<TYPE>::type *NullCast( void ); \
static void RegisterMetaData( void )</remqualptr></remqualptr></code></pre>
</div>
<br />
<span style="font-family: Trebuchet MS, sans-serif;">The META_DATA macro is to be placed within a class, it places a couple declarations for NullCast, AddMember and RegisterMetaData. The DEFINE_META macro is modified to provide definitions for the method declarations created by the META_DATA macro. This allows the NullCast to retrieve the type to cast to from the DEFINE_META's TYPE parameter. Since AddMember method is within the class itself, it can now have proper access to private data within the class. The AddMember definition within the class then forwards the information it gathers to the AddMember function within the MetaCreator.</span><br />
<span style="font-family: Trebuchet MS, sans-serif;"><br />
</span> <span style="font-family: Trebuchet MS, sans-serif;">In order for the DEFINE_META api to remain the same as before, the META_DATA macro creates a RegisterMetaData declaration within the class itself. This allows the ADD_MEMBER macro to not need to user to supply to type of class to operate upon. This might be a little confusing, but imagine trying to refactor the macros above. Is the RegisterMetaData macro even required to be placed into the class itself? Can't the RegisterMetaData function within the MetaCreator call AddMember on the class type itself? The problem with this is that the ADD_MEMBER macro would require the user to supply the type to the macro like this:</span><br />
<span style="font-family: Trebuchet MS, sans-serif;"><br />
</span><br />
<br />
<div class="code">
<pre><code>#define ADD_MEMBER( TYPE, MEMBER ) \
TYPE::AddMember( #MEMBER, (unsigned)(&(NullCast( )->MEMBER)), META( NullCast( )->MEMBER ))</code></pre>
</div>
<br />
<span style="font-family: Trebuchet MS, sans-serif;">This would be yet another thing the user of the MetaData system would be required to perform, thus cluttering the API. I find that by keeping the system as simple as possible is more beneficial than factoring out the definition of RegisterMetaData from the META_DATA macro.</span><br />
<span style="font-family: Trebuchet MS, sans-serif;"><br />
</span> <span style="font-family: Trebuchet MS, sans-serif;">Here's an example usage of the new META_DATA and DEFINE_META macros:</span><br />
<br />
<div class="code">
<pre><code>class Sprite : public Component
{
public:
Sprite( std::string tex = "scary.png" );
virtual void SendMessage( Message *msg );
const std::string& GetTextureName( void );
void SetTextureName( std::string name );
META_DATA( Sprite );
private:
std::string texture;
};
DEFINE_META( Sprite )
{
ADD_MEMBER( name );
ADD_MEMBER( texture );
}</code></pre>
</div>
<br />
<span style="font-family: Trebuchet MS, sans-serif;">The only additional step required here is for the user to remember to place the META_DATA macro within the class definition. The rest of the API remains as intuitive as before.</span><br />
<span style="font-family: Trebuchet MS, sans-serif;"><br /></span>
<span style="font-family: Trebuchet MS, sans-serif;">Here's a link to a <a href="http://www.mediafire.com/?uui37fxjhe78fim">compileable</a> (in VS2010) example showing everything I've talked about in the MetaData series thus far. The next article in this series will likely be in creating the Variant type for PODs.</span>CecilSunkurehttp://www.blogger.com/profile/16129986119923492789noreply@blogger.com0tag:blogger.com,1999:blog-3579312376304629754.post-43771102386125101502012-10-02T01:56:00.001-07:002012-10-09T14:55:42.013-07:00C++ Reflection: Type MetaData: Part 2 - Type Reduction and Members<span style="font-family: Trebuchet MS, sans-serif;">In the <a href="http://cecilsunkure.blogspot.com/2012/09/c-reflection-class-metadata-introduction.html">last post</a> we learned the very basics of setting up a reflection system. The whole idea is that the user manually adds types into the system using a single simple macro placed within a cpp file, DEFINE_META.</span><br />
<div>
<span style="font-family: Trebuchet MS, sans-serif;"><br />
</span></div>
<div>
<span style="font-family: Trebuchet MS, sans-serif;">In this article I'll talk about type deduction and member reflection, both of which are critical building blocks for everything else.</span></div>
<div>
<span style="font-family: Trebuchet MS, sans-serif;"><br />
</span></div>
<div>
<span style="font-family: Trebuchet MS, sans-serif;">First up is type deduction. When using the templated MetaCreator class:</span></div>
<br />
<div class="code">
<pre><code>template <typename Metatype>
class MetaCreator
{
public:
MetaCreator( std::string name, unsigned size )
{
Init( name, size );
}
static void Init( std::string name, unsigned size )
{
Get( )->Init( name, size );
}
</code></pre>
<pre><code> // Ensure a single instance can exist for this class type
static MetaData *Get( void )
{
static MetaData instance;
return &instance;
}
};</code></pre>
</div>
<br />
<span style="font-family: Trebuchet MS, sans-serif;">Whenever you pass in a const, reference, or pointer qualifier an entire new templated MetaCreator will be constructed by the compiler. This just won't do, as we don't want the MetaData of a const int to be different at all from an int, or any other registered type. There's a simple, yet very quirky, trick that can solve all of our problems. Take a look at this:</span><br />
<br />
<div class="code">
<pre><code>//
// RemQual
// Strips down qualified types/references/pointers to a single unqualified type, for passing into
// a templated type as a typename parameter.
//
template <typename T>
struct RemQual
{
typedef T type;
};
template <typename T>
struct RemQual<const T>
{
typedef T type;
};
template <typename T>
struct RemQual<T&>
{
typedef T type;
};
template <typename T>
struct RemQual<const T&>
{
typedef T type;
};
template <typename T>
struct RemQual<T&&>
{
typedef T type;
};
template <typename T>
struct RemQual<T *>
{
typedef T type;
};
template <typename T>
struct RemQual<const T *>
{
typedef T type;
};</code></pre>
</div>
<br />
<span style="font-family: Trebuchet MS, sans-serif;">I'm actually not familiar with the exact terminology to describe what's going on here, but I'll try my best. There's many template overloads of the first RemQual struct, which acts as the "standard". The standard is just a single plain type T, without any qualifiers and without pointer or reference type. The rest of the templated overloaded version all contain a single typedef which lets the entire struct be used to reference a single un-qualified type by supplying any of the various overloaded types to the struct's typename param.</span><br />
<span style="font-family: Trebuchet MS, sans-serif;"><br />
</span> <span style="font-family: Trebuchet MS, sans-serif;">Overloads for the R-value reference must be added as well in order to strip down to the bare type T.</span><br />
<span style="font-family: Trebuchet MS, sans-serif;"><br />
</span> <span style="font-family: Trebuchet MS, sans-serif;">Now that we have our RemQual (remove qualifiers) struct, we can use it within our META macros to refer to MetaData types. Take a look at some example re-writes of the three META macros:</span><br />
<br />
<div class="code">
<pre><code> //
// META_TYPE
// Purpose: Retrieves the proper MetaData instance of an object by type.
//
#define META_TYPE( TYPE ) (MetaCreator<RemQual<TYPE>::type>::Get( ))
//
// META
// Purpose: Retrieves the proper MetaData instance of an object by an object's type.
//
#define META( OBJECT ) (MetaCreator<RemQual<decltype( OBJECT )>::type>::Get( ))
//
// META_STR
// Purpose : Finds a MetaData instance by string name
//
#define META_STR( STRING ) (MetaManager::Get( STRING ))
//
// DEFINE_META
// Purpose : Defines a MetaCreator for a specific type of data
//
#define DEFINE_META( TYPE ) \
MetaCreator<RemQual<TYPE></code>::type> NAME_GENERATOR( )( #TYPE, sizeof( TYPE ) )</pre>
</div>
<br />
<span style="font-family: Trebuchet MS, sans-serif;">The idea is you feed in the typedef'd type from RemQual into the MetaCreator typename param. This is an example of using macros well; there's no way to screw up the usage of them, and they are still very clean and easy to debug as there isn't really any abuse going on. Feel free to ignore specific META macros you wouldn't actually use. I use all three META_TYPE, META and META_STR. It's a matter of personal preference on what you actually implement in this respect. It will likely be pretty smart to place whatever API is created into a namespace of it's own, however.</span><br />
<span style="font-family: Trebuchet MS, sans-serif;"><br />
</span> <span style="font-family: Trebuchet MS, sans-serif;">And that covers type deduction. There are some other ways of achieving the same effect, like partial template specialization <a href="http://seanmiddleditch.com/journal/2012/01/c-metadata-part-i-singletons-and-lookup/">as covered here</a>, though I find this much simpler.</span><br />
<span style="font-family: Trebuchet MS, sans-serif;"><br />
</span> <span style="font-family: Trebuchet MS, sans-serif;">Next up is register members of structures or classes with the MetaData system. Before anything continues, lets take a look at an example Member struct. A Member struct is a container of the various bits of information we'd like to store about any member:</span><br />
<br />
<div class="code">
<pre><code>//
// Member
// Purpose: Stores information (name and offset of member) about a data member of a specific class. Multiple
// Member objects can be stored in MetaData objects within a std::vector.
//
class Member
{
public:
Member( std::string string, unsigned val, MetaData *meta );
~Member( );
const std::string &Name( void ) const; // Gettor for name
unsigned Offset( void ) const; // Gettor for offset
const MetaData *Meta( void ) const; // Gettor for data
private:
std::string name;
unsigned offset;
const MetaData *data;
};</code></pre>
</div>
<br />
<span style="font-family: Trebuchet MS, sans-serif;">This member above is actually almost exactly what implementation I have in my own reflection as it stands while I write this; there's not a lot needed. You will want a MetaData instance to describe the type of data contained, a name identifier, and an unsigned offset representing the member's location within the containing object. The offset is exceptionally important for automated serialization, which I'll likely be covering after this article.</span><br />
<span style="font-family: Trebuchet MS, sans-serif;"><br />
</span> <span style="font-family: Trebuchet MS, sans-serif;">The idea is that a MetaData instance can contain various member objects. These member objects are contained within some sort of container (perhaps std::vector).</span><br />
<span style="font-family: Trebuchet MS, sans-serif;"><br />
</span> <span style="font-family: Trebuchet MS, sans-serif;">In order to add a member we'll want another another very simple macro. There are two big reasons a macro is efficient in this situation: we can use stringize; there's absolutely no way for the user to screw it up.</span><br />
<span style="font-family: Trebuchet MS, sans-serif;"><br />
</span> <span style="font-family: Trebuchet MS, sans-serif;">Before showing the macro I'd like to talk about how to retrieve the offset. It's very simple. Take the number zero, and turn this into a pointer to a type of object (class or struct). After the typecasting, use the -> operator to access one of the members. Lastly, use the & operator to retrieve the address of the member's location (which will be offset from zero by the -> operator) and typecast this to an unsigned integer. Here's what this looks like:</span><br />
<br />
<div class="code">
<pre><code>#define ADD_MEMBER( MEMBER ) \
AddMember( #MEMBER, (unsigned)(&(NullCast( )->MEMBER)), META( NullCast( )->MEMBER ))</code></pre>
</div>
<br />
<span style="font-family: Trebuchet MS, sans-serif;">This is quite the obtrusive line of code we have here! This is also a good example of a macro used well; it takes a single parameter and applies it to multiple locations. There's hardly any way for the user of this macro to screw up.</span><br />
<span style="font-family: Trebuchet MS, sans-serif;"><br />
</span> <span style="font-family: Trebuchet MS, sans-serif;">NullCast is a function I'll show just after this paragraph. All it does is return a pointer to NULL (memory address zero) of some type. Having this type pointer to address zero, we then use the ADD_MEMBER macro to provide the name of a member to access. The member is then accessed, and the & operator provides an address to this member with an offset from zero. This value is then typecasted to an unsigned integer and and passed along to the AddMember function within the macro. The stringize operator is also used to pass a string representation of the member to the AddMember function, as well as a MetaData instance of whatever the type of data the member is.</span><br />
<span style="font-family: Trebuchet MS, sans-serif;"><br />
</span> <span style="font-family: Trebuchet MS, sans-serif;">Now where does this AddMember function actually go? Where is it from? It's actually placed into a function definition. The function AddMember itself resides within the MetaCreator. This allows the MetaCreator to call the AddMember function of the MetaData instance it holds, which then adds the Member object into the container of Members within the MetaData instance.</span><br />
<span style="font-family: Trebuchet MS, sans-serif;"><br />
</span> <span style="font-family: Trebuchet MS, sans-serif;">Now, the only place that this AddMember function can be called from, building from the previous article, is within the MetaCreator's constructor. The idea is to use the DEFINE_META macro to also create a definition of either the MetaCreator's constructor, or a MetaCreator method that is called from the MetaCreator's constructor. </span><span style="font-family: 'Trebuchet MS', sans-serif;">Here's an example:</span><br />
<br />
<div class="code">
<pre><code>DEFINE_META( GameObject )
{
ADD_MEMBER( ID );
ADD_MEMBER( active );
ADD_MEMBER( components );
}</code></pre>
</div>
<br />
<span style="font-family: Trebuchet MS, sans-serif;">As you can see this formation is actually very intuitive; it has C++-like syntax, and it's very clear what is going on here. A GameObject is being registered in the Meta system, and it has members of ID, active, and components being added to the Meta system. For clarity, here's what the GameObject's actual class definition might look like (assuming component based architecture):</span><br />
<br />
<div class="code">
<pre><code>class GameObject
{
public:<gameobject>
// Sends all components within this object the same message
void SendMessage( Message *msg );
bool HasComponent( std::string& name ) const;
void AddComponent( std::string componentType );
Component *GetComponent( std::string name ) const;
handle GetID( void ) const;
</gameobject></code></pre>
<pre><code><gameobject>
</gameobject></code></pre>
<pre><code><gameobject><pre><code><gameobject> handle ID;</gameobject></code></pre>
// This boolean should always be true when the object is alive. If this is
// set to false, then the ObjectFactory will clean it up and delete this object
// during its inactive sweep when the ObjectFactory's update is called.
bool active;
std::vector<component> components;
</component></gameobject></code></pre>
<pre><code><gameobject><component>private:
// Only to be used by the factory!
GameObject( ) : ID( -1 ), active( true ) {}
~GameObject( );
};</component></gameobject></code></pre>
</div>
<br />
<span style="font-family: Trebuchet MS, sans-serif;">Now lets check out what the new DEFINE_META macro could look like:</span><br />
<br />
<div class="code">
<pre><code>#define DEFINE_META( TYPE ) \
MetaCreator<RemQual<TYPE>::type> NAME_GENERATOR( )( #TYPE, sizeof( TYPE ) ); \
void MetaCreator<RemQual<TYPE>::type>::RegisterMetaData( void )</code></pre>
</div>
<br />
<span style="font-family: Trebuchet MS, sans-serif;">The RegisterMetaData declaration is quite peculiar, as the macro just ends there. What this is doing is setting up the definition of the RegisterMetaData function, so that the ADD_MEMBER macro calls are actually lines of code placed within the definition. The RegisterMetaData function should be called from the MetaCreator's constructor. This allows the user to specify what members to reflect within a MetaData instance of a particular type in a very simple and intuitive way.</span><br />
<span style="font-family: Trebuchet MS, sans-serif;"><br />
</span> <span style="font-family: Trebuchet MS, sans-serif;">Last but not least, lets talk about the NullCast function real quick. It resides within the MetaCreator, as NullCast requires the template's typename MetaType in order to return a pointer to a specific type of data.</span><br />
<span style="font-family: Trebuchet MS, sans-serif;"><br />
</span> <span style="font-family: Trebuchet MS, sans-serif;">And that's that! We can now store information about the members of a class and deduce types from objects in an easily customizeable way.</span><br />
<span style="font-family: Trebuchet MS, sans-serif;"><br />
</span> <span style="font-family: Trebuchet MS, sans-serif;"><a href="http://www.mediafire.com/?2qf5hks4oqtt6iw">Here's a link</a> to a demonstration program, compileable in Visual Studio 2010. I'm sure this could compile in GCC with a little bit of house-keeping as well, but I don't really feel like doing this as I need to get to bed! Here's the output of the program. The format is <type> <size>. For the object, members and their offsets are printed:</span><br />
<br />
<div class="code">
<pre><code>int
4
float
4
std::string
28
Object
8
{
ID
0
active
4
}</code></pre>
</div>
<br />
<span style="font-family: Trebuchet MS, sans-serif;">Now you might notice at some point in time, you cannot reflect private data members! This detail will be covered in a later article. The idea behind it is that you require source code access to the type you want to reflect, and place a small tiny bit of code inside to gain private data access. Either that or make the MetaCreator a friend class (which sounds like a messy solution to me).</span><br />
<span style="font-family: Trebuchet MS, sans-serif;"><br /></span>
<span style="font-family: Trebuchet MS, sans-serif;">And here we have all the basics necessary for automated serialization! We can reflect the names of members, their types, and offsets within an object. This lets the reflection register any type of C++ data within itself.</span>CecilSunkurehttp://www.blogger.com/profile/16129986119923492789noreply@blogger.com0tag:blogger.com,1999:blog-3579312376304629754.post-42792245711901092902012-09-30T17:40:00.000-07:002012-10-05T14:29:48.500-07:00C++ Reflection: Type MetaData: Introduction<span style="font-family: 'Trebuchet MS', sans-serif;">Thinking about how to take things a step further in terms of what your tools can do for you is really important in increasing productivity. This is where a form of reflection can come in very handy. I call the reflection system I'm working on by shorthand of "meta" or "MetaData", though the proper terminology for it would be something more like Class MetaData or Type Reflection. So when I say MetaData I'm referring to data about data, and specifically data about the types of data within your C++ code.</span><br />
<span style="font-family: Trebuchet MS, sans-serif;"><br />
</span> <span style="font-family: Trebuchet MS, sans-serif;">Having a MetaData system allows for information about your data types to be saved during run-time for use during run-time. The C++ compiler compiles away a lot of information, and a lot of this information is very useful. So, a MetaData system saves this information from being compiled away.</span><br />
<span style="font-family: Trebuchet MS, sans-serif;"><br />
</span> <span style="font-family: Trebuchet MS, sans-serif;">So what is the use of such a system? Where here are the things I've constructed so far: simple and powerful debugging features; automated serialization for any type registered with Meta; automic function binding to Lua; Variant and RefVariant class types (objects that can hold any type of data registered within Meta). However these aren't the only things I'll be using the MetaData system for. One could also apply the MetaData to make simple object factories with hardly any code, or property viewing tables for editors with ease. I'm sure there's even more uses as well that I just haven't quite come to terms with. In a way, systems like this can generate tools and functionality <i>for the developer</i> whenever a new class or data type is introduced.</span><br />
<span style="font-family: Trebuchet MS, sans-serif;"><br />
</span> <span style="font-family: Trebuchet MS, sans-serif;">Before we start I want to let the reader know that such a system can be very efficient, efficient enough to run wonderfully within a real-time application like a game. I myself don't know a lot about efficiency or optimization at a low-level, though I do know other programmers who've made such Reflection systems that are very, very fast. So make sure not to have any pre-built misconceptions about a C++ Reflection system before moving on.</span><br />
<span style="font-family: Trebuchet MS, sans-serif;"><br />
</span> <span style="font-family: Trebuchet MS, sans-serif;">I started learning about how to construct a MetaData system from <a href="http://seanmiddleditch.com/journal/2012/01/c-metadata-part-i-singletons-and-lookup/">this post</a>. You can take a look if you like, though it won't be necessary if you just want to learn what I'm trying to teach here. In that post, by a fellow student here at DigiPen, he goes over how to get started with MetaData, but leaves a lot to yet be learned. I'll be modelling my post after his quite a bit, as he does have good content structure for an introduction post.</span><br />
<span style="font-family: Trebuchet MS, sans-serif;"><br />
</span> <span style="font-family: Trebuchet MS, sans-serif;">I'll attempt to document what I've learned here as honestly, there's not any resources on constructing a MetaData system like this anywhere as far as I know. The closest thing I could find was from a Game Programming Gems book, the 5th one chapter 1.4, although it required all classes that wanted to participate to inherit from the MetaData class. This isn't really sufficient if you want to reflect class or structure types you don't have source code access to, and it doesn't support the built-in types at all.</span><br />
<span style="font-family: Trebuchet MS, sans-serif;"><br />
</span> <span style="font-family: Trebuchet MS, sans-serif; font-size: large;">Getting Started</span><br />
<span style="font-family: Trebuchet MS, sans-serif;">To start lets talk about the overall structure of what a MetaData system looks like. I think it's going to best to draw a diagram of what will be achieved from this article:</span><br />
<span style="font-family: Trebuchet MS, sans-serif;"><br />
</span> <br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhe4cc7bc82jqqYERCwWaZxJOFFbvDULZQww89U1Mjxn9LYS3Snj_9XlktJd-S9uEUjVCCC4SbdF2h7fD0QsxG2s9XdmoZDqX69iCx0219SKqvrGsWzvWTAHgTSxxHdGR_6XQbMrjr_otc/s1600/meta.png" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhe4cc7bc82jqqYERCwWaZxJOFFbvDULZQww89U1Mjxn9LYS3Snj_9XlktJd-S9uEUjVCCC4SbdF2h7fD0QsxG2s9XdmoZDqX69iCx0219SKqvrGsWzvWTAHgTSxxHdGR_6XQbMrjr_otc/s1600/meta.png" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Diagram of entire MetaData system layout.</td></tr>
</tbody></table>
<span style="font-family: Trebuchet MS, sans-serif;"><br />
</span> <span style="font-family: Trebuchet MS, sans-serif;">In the above diagram the MetaData objects are the key object in which all important operations are performed. A MetaData object is a non-templated class, allowing them to be stored in a data structure. There is one MetaData object for each type of data registered to the system, and the MetaData object of a corresponding type is a representation of that type. It stores information about whether or not it is a Plain Old Data type (POD), the size of the type, it's members and methods, and name. Inheritance information can be stored along with multiple inheritance information, though I haven't even bothered adding that feature in yet as it's not actually very useful and quite difficult to do properly.</span><br />
<span style="font-family: Trebuchet MS, sans-serif;"><br />
</span> <span style="font-family: Trebuchet MS, sans-serif;">The MetaCreator is a templated class that manages the creation of a single unique MetaData instance. It then adds its instance into the MetaManager which contains it in some sort of map.</span><br />
<span style="font-family: Trebuchet MS, sans-serif;"><br />
</span> <span style="font-family: Trebuchet MS, sans-serif;">The MetaManager is a non-templated class that contains all of the created MetaData instances, and can perform search operations on them to find specific types. I use a map of strings to instances, so I can search by string identifier. I've also placed some other small utility functions into my MetaManager as well.</span><br />
<span style="font-family: Trebuchet MS, sans-serif;"><br />
</span> <span style="font-family: Trebuchet MS, sans-serif; font-size: large;">Client Code</span><br />
<span style="font-family: Trebuchet MS, sans-serif;">Before we get started writing anything, I'd like to try to show some example client code to exemplify <i>why</i> I've taken all this time to make a MetaData system in the first place.</span><br />
<br />
<div class="code">
<pre><code>GameObject *obj = FACTORY->CreateObject( "SampleObject" );
// FACTORY->CreateObject code
GameObject *ObjectFactory::CreateObject( const std::string& fileName )
{
SERIALIZER->OpenFile( fileName );
GameObject *obj = DESERIALIZE( GameObject );
SERIALIZER->CloseFile( );
IDObject( obj );
LUA_SYSTEM->PushGameObject( obj );
return obj;
}
// LUA_SYSTEM->PushGameObject code
void LuaSystem::PushGameObject( GameObject *obj )
{
lua_getglobal( L , "GameObjects" );
lua_pushinteger( L, obj->GetID( ) );
LuaReference *luaObj = (LuaReference *)lua_newuserdata( L, sizeof( LuaReference ) );
luaL_setmetatable( L, META_TYPE( GameObject )->MetaTableName( ) );
luaObj->ID = obj->GetID( );
luaObj->meta = META_TYPE( GameObject ); // grab MetaData instance of this type
lua_settable( L, 1 ); // Stack index 1[3] = 2
// Clear the stack
lua_settop( L, 0 );
}</code></pre>
</div>
<br />
<span style="font-family: Trebuchet MS, sans-serif;">As you can see I have a nice DESERIALIZE macro that can deserialize any type of data registered within within the Reflection. My entire serialization file (includes in and out) is only about 400 lines of code, and I implemented my own custom file format. I also have a LuaReference data type, which contains a handle and a MetaData instance, and allows any class to be sent to Lua via handle. Because of my Meta system I can write very generic and powerful code pretty easily.</span><br />
<span style="font-family: Trebuchet MS, sans-serif;"><br />
</span> <span style="font-family: Trebuchet MS, sans-serif; font-size: large;">Getting Started</span><br />
<span style="font-family: Trebuchet MS, sans-serif;">The first I recommend starting with is to reflect the size of a type, and the name of a type. Here's what a very simple MetaData class could like:</span><br />
<br />
<div class="code">
<pre><code>//
// MetaData
// Purpose: Object for holding various info about any C++ type for the MetaData reflection system.
//
class MetaData
{
public:
MetaData( std::string string, unsigned val ) : name( string ), size( val ) {}
~MetaData( )
const std::string& Name( void ) const { return name; }
unsigned Size( void ) const { return size; }
private:
std::string name;
unsigned size;
}</code></pre>
</div>
<br />
<span style="font-family: Trebuchet MS, sans-serif;">This simple class just stores the size and name of a type of data. The next thing required is the ability to create a unique instance of MetaData. This requires a templated class called the MetaCreator.</span><br />
<br />
<div class="code">
<pre><code>template <typename Metatype>
class MetaCreator
{
public:
MetaCreator( std::string name, unsigned size )
{
Init( name, size );
}
static void Init( std::string name, unsigned size )
{
Get( )->Init( name, size );
}
</code></pre>
<pre><code> // Ensure a single instance can exist for this class type
static MetaData *Get( void )
{
static MetaData instance;
return &instance;
}
};</code></pre>
</div>
<br />
<span style="font-family: Trebuchet MS, sans-serif;">You should be able to see that by passing in a type, perhaps <int> to the MetaCreator, a single MetaData instance becomes available from the Get function, and is associated with the MetaCreator<int> class. Any type can be passed into the Metatype typename. The MetaCreator constructor initializes the MetaData instance. This is important. In the future you'll have MetaData for a class that contains MetaData for POD types. However because of out-of-order initialization, some of the types required to construct your class MetaData instance might not be initialized (as in the Init function will not have been called) yet. However if you use the MetaManager<>::Get( ) function, you can retrieve a pointer to the memory location that will be initialized once the MetaCreator of that specific type is constructed. It should be noted that the construction of a MetaCreator happens within a macro, so that there's absolutely no way of screwing up the type registration (the inside of the macro will become quite... ugly).</span><br />
<span style="font-family: Trebuchet MS, sans-serif;"><br />
</span> <span style="font-family: Trebuchet MS, sans-serif;">Lastly you'll need a place to store all of your MetaData instances: the MetaManager!</span><br />
<br />
<div class="code">
<pre><code>//
// MetaManager
// Purpose: Just a collection of some functions for management of all the
// various MetaData objects.
//
class MetaManager
{
public:
typedef std::map<std::string, const MetaData *> MetaMap;
// Insert a MetaData into the map of objects
static void RegisterMeta( const MetaData *instance );
// Retrieve a MetaData instance by string name from the map of MetaData objects
static const MetaData *Get( std::string name ); // NULL if not found
// Safe and easy singleton for map of MetaData objects
static MetaMap& GetMap( void )
{
// Define static map here, so no need for explicit definition
static MetaMap map;
return map;
}
};</code></pre>
</div>
<br />
<span style="font-family: Trebuchet MS, sans-serif;">And there we have a nice way to store all of our MetaData instances. The Get function is most useful in retrieving a MetaData instance of a type by string name. Now that we have our three major facilities setup, we can talk about the macros involved in actually registering a type within the MetaData system.</span><br />
<br />
<div class="code">
<pre><code> //
// META_TYPE
// Purpose: Retrieves the proper MetaData instance of an object by type.
//
#define META_TYPE( TYPE ) (MetaCreator<TYPE>::Get( ))
//
// META
// Purpose: Retrieves the proper MetaData instance of an object by an object's type.
//
#define META( OBJECT ) (MetaCreator<decltype( OBJECT )>::Get( ))
//
// META_STR
// Purpose : Finds a MetaData instance by string name
//
#define META_STR( STRING ) (MetaManager::Get( STRING ))
//
// DEFINE_META
// Purpose : Defines a MetaCreator for a specific type of data
//
#define DEFINE_META( TYPE ) \
MetaCreator<TYPE> NAME_GENERATOR( )( #TYPE, sizeof( TYPE ) )</code></pre>
</div>
<br />
<span style="font-family: Trebuchet MS, sans-serif;">So far so good. Using the DEFINE_META macro it's pretty easy to add a type to the MetaData system, simply do DEFINE_META( type );. The decltype might be confusing, as it's new. decltype simply returns the type of an object. This allows the user to retrieve a MetaData instance that corresponds to an object's type, without knowing what the object's type is; this lets very generic code be easily written.</span><br />
<span style="font-family: Trebuchet MS, sans-serif;"><br />
</span> <span style="font-family: Trebuchet MS, sans-serif;">NAME_GENERATOR is a bit tricky. Every single instance of a MetaCreator needs to be constructed at global scope- this is the only way to get the Init( ) function to be called, without having to place your DEFINE_META macro in some sort of code scope. Without the constructor of the MetaCreator calling Init, the only way to have any sort of code run by using the DEFINE_META macro is to place it within some scope that is run sometime after main executes. This makes the use of the DEFINE_META macro harder. If you create the MetaCreator at global scope, then you can have the constructor's code run before main executes at all, making the DEFINE_META macro very easy and simple to use.</span><br />
<span style="font-family: Trebuchet MS, sans-serif;"><br />
</span> <span style="font-family: Trebuchet MS, sans-serif;">So then comes the issue of "what do I call my MetaCreator?" arises. The first thing you might think of is, just call it MetaCreator and make it static. This hides the MetaCreator at file scope, allowing the DEFINE_META macro to be used once per file without any naming conflicts. However, what if you need more than one DEFINE_META in a file? The next solution I thought of was to use token pasting: ## operator. Here's an example usage of the token pasting technique:</span><br />
<br />
<div class="code">
<pre><code>DEFINE_META( TYPE ) \
MetaCreator<TYPE> Creator##TYPE( )( #TYPE, sizeof( TYPE ), false )</code></pre>
</div>
<br />
<span style="font-family: Trebuchet MS, sans-serif;">The only problem with this strategy is that you cannot pass in type names with special characters or spaces, as that won't result in a proper token name. The last solution is to use some sort of unique name generation technique. There are two macros __LINE__ and __FILE__ that can be used to generate a unique name each time the macro is used, so long as it is not used twice on the same line of the same file. The __LINE__ and __FILE__ definitions are a bit tedious to use, but I think I have them working properly, like this:</span><br />
<br />
<div class="code">
<pre><code>#define PASTE( _, __ ) _##__
#define NAME_GENERATOR_INTERNAL( _ ) PASTE( GENERATED_NAME, _ )
#define NAME_GENERATOR( ) NAME_GENERATOR_INTERNAL( __COUNTER__ )</code></pre>
</div>
<br />
<span style="font-family: Trebuchet MS, sans-serif;">You have to feed in the __COUNTER__ definition carefully in order to make sure they are translated by the preprocessor into their respective values. A resulting token could look like: GENERATED_NAME__29. This is perfect for creating all of the MetaCreators at global scope on the stack. Without the use of some sort of trick like this, it can be very annoying to have to use a function call to register your MetaData.</span><br />
<span style="font-family: Trebuchet MS, sans-serif;"><br /></span>
<span style="font-family: Trebuchet MS, sans-serif;">Alternatively there are __FILE__ and __LINE__ macros, but they aren't really necessary as the __COUNTER__ does everything we need. The __COUNTER__ however is, I believe, not actually standard.</span><br />
<span style="font-family: Trebuchet MS, sans-serif;"><br />
</span> <span style="font-family: Trebuchet MS, sans-serif;">So far everything is very straightforward, as far as I can tell. Please ask any questions you have in the comments!</span><br />
<span style="font-family: Trebuchet MS, sans-serif;"><br /></span>
<span style="font-family: Trebuchet MS, sans-serif;">It should be noted that const, &, and * types all create different MetaData instances. As such, there is a trick that can be used to strip these off of an object when using the META macro. This will be covered in a subsequent article.</span><br />
<span style="font-family: Trebuchet MS, sans-serif;"><br />
</span> <span style="font-family: Trebuchet MS, sans-serif; font-size: large;">Example Uses</span><br />
<span style="font-family: Trebuchet MS, sans-serif;">Now lets check out some example client code of what our code can actually do!</span><br />
<br />
<div class="code">
<pre><code>DEFINE_META( int );
DEFINE_META( float );
DEFINE_META( double );
DEFINE_META( std::string );
void main( void )
{
std::cout << META_TYPE( int )->Name( ); // output: "int"
std::cout << META_TYPE( float )->Size( ); // output: "4"
std::string word = "This is a word";
std::cout << META( word )->Name( ); // output: "std::string"
std::cout << META_STR( "double" )->Size( ); // output: "8"
if(META( word ) != META_TYPE( int ) // address comparison
{
std::cout << "This object is not an int!";
}
}</code></pre>
</div>
<br />
<span style="font-family: Trebuchet MS, sans-serif;">And there we have it! An extremely easy to use DEFINE_META macro that stores name and size information of any type, including class and struct types.</span><br />
<span style="font-family: Trebuchet MS, sans-serif;"><br /></span>
<span style="font-family: Trebuchet MS, sans-serif; font-size: large;">Future Posts</span><br />
<span style="font-family: Trebuchet MS, sans-serif;">For future posts I look forward to writing about automated Lua binding, Variants and RefVariants, automated Serialization, factory usage, messaging, and perhaps other topics as well! These topics are really rather huge, so please by patient in that it may take a while to cover everything.</span><br />
<span style="font-family: Trebuchet MS, sans-serif;"><br /></span>
<span style="font-family: Trebuchet MS, sans-serif;"><a href="http://cecilsunkure.blogspot.com/2012/10/c-reflection-type-metadata-part-2-type.html">Link to second article</a> in series.</span>CecilSunkurehttp://www.blogger.com/profile/16129986119923492789noreply@blogger.com2tag:blogger.com,1999:blog-3579312376304629754.post-26843563868217349992012-09-04T14:39:00.000-07:002012-09-04T15:32:02.686-07:00Simple Smart Pointers<span style="font-family: Trebuchet MS, sans-serif;">This is going to be the first of many posts abandoning C and heading into C++. I stuck around in C for as long as could, but now heading into my Sophomore year it's time to make the switch.</span><br />
<span style="font-family: Trebuchet MS, sans-serif;"><br />
</span> <span style="font-family: Trebuchet MS, sans-serif;">There are many different implementations and goals of what a smart pointer can be or attempt to achieve. As far as I can see, the term "smart pointer" is a pretty general term that means some sort of extra functionality wrapped around normal pointers. However the smart pointer should be able to behave just like a normal pointer, so overloading of the * and -> operators will be done.</span><br />
<span style="font-family: Trebuchet MS, sans-serif;"><br />
</span> <span style="font-family: Trebuchet MS, sans-serif;">In previous game projects (the ones I written in C in my portfolio) had an issue where when a bit of data was deleted or modified, all other code required to be made aware of such act. This required extra work by the programmer to ensure that no pointers within the program could be accessed if the data they pointed to was modified in an undesirable way (perhaps deleted or converted to another type, or moved). The smart pointer implementation will solve this problem by making it seem like all smart pointers to a single location update each other automatically. Additionally, I wanted to add a little more functionality for ease of use and convenience, of which I'll talk about later in the article.</span><br />
<span style="font-family: Trebuchet MS, sans-serif;"><br />
</span> <span style="font-family: Trebuchet MS, sans-serif;">Here's an example of a problem situation that can arise from misusing ordinary pointers:</span><br />
<br />
<div class="code">
<pre><code>SomeFunction
{
ObjectAddress = newly allocated object
}
Some Other Function
{
Delete data at ObjectAdress
}
Last Function
{
ObjectAddress.GetName( ) // Is object deleted yet?
}</code></pre>
</div>
<br />
<span style="font-family: Trebuchet MS, sans-serif;">I decided to make my smart pointers handle based. A handle system is where some sort of identifier (ID) is mapped to a value by <a href="http://cecilsunkure.blogspot.com/2012/07/hash-tables.html">mapping functionality</a>, i.e. std::map. This is extremely useful, as one can now place a layer of indirection between an identifier and its associated value. The reason this is useful goes into many different scenarios, but pertaining to smart pointers we can have a single point of access to the address a smart pointer holds.</span><br />
<br />
<div class="code">
<pre><code>template <typename TYPE>
class SmartPtr
{
public:
SmartPtr( handle val = NULL ): ID( val ) {};
~SmartPtr( );
TYPE *GetPtr( void ) const;
handle GetID( void ) const { return ID; }
TYPE *operator->( void );
TYPE operator*( void );
private:
handle ID;
static HandleMap<TYPE> handleMap;
};</code></pre>
</div>
<br />
<span style="font-family: Trebuchet MS, sans-serif;">Here are the barebones for our smart pointer. The SmartPtr holds an ID, where handle is a typedef'd integer. GetPtr( ) indexes the handleMap (handleMap should be a class to wrap around std::map, to provide inserting and erasing methods) with the SmartPtr's ID to retrieve the pointer value the ID maps to. The SmartPtr itself is templated for a specific type of pointer, this way each different type of data to be pointed to has a different statically defined handleMap. This is a benefit to the amount of unique handles your game can generate. The SmartPtr can be constructed with a handle value, and has a gettor for the handle ID itself.</span><br />
<span style="font-family: Trebuchet MS, sans-serif;"><br />
</span> <span style="font-family: Trebuchet MS, sans-serif;">Now whenever the pointer mapped by a specific ID is modified within the handleMap, all subsequent requests to that value will be updated throughout all other SmartPtr instances with the same ID. This is because the only point of access to the pointer value is through the map itself, meaning there's actually only one pointer mapped by an ID at any given time, although there can be many SmartPtrs with the ID mapping to that single value.</span><br />
<span style="font-family: Trebuchet MS, sans-serif;"><br />
</span> <span style="font-family: Trebuchet MS, sans-serif;">However you may be wondering about how to generate the handle ID itself, as each one needs to be unique. It's very simple: start your first handle at the integer value of 1, and then for every subsequent ID mapped to a new value, add one to the previously used ID. This will give you millions of unique IDs, which is well than more enough for basically any game ever, especially in this case as each type has its own handleMap altogether. The ID value of 0 can be reserved for a NULL pointer to allow to check at any given time if a SmartPtr's handle is valid.</span><br />
<br />
<span style="font-family: Trebuchet MS, sans-serif;">As for the implementation of -> and *, you should use your utility GetPtr( ) function for them. -> will simply require a returning of GetPtr( ), and * will dereference the value returned by GetPtr( ), or return NULL if the value from GetPtr( ) is NULL. In this way your SmartPtr class will behave exactly like an ordinary pointer.</span><br />
<span style="font-family: Trebuchet MS, sans-serif;"><br />
</span> <span style="font-family: Trebuchet MS, sans-serif;">Additionally operator overloads for comparisons, or even pointer arithmetic, can be implemented as well. I implemented equality comparisons.</span><br />
<span style="font-family: Trebuchet MS, sans-serif;"><br />
</span> <span style="font-family: Trebuchet MS, sans-serif;">Lastly, I needed a way to handle inserting a pointer into the handleMap, and consequently erasing it from the map as well. I decided to make the SmartPtr handle this automatically with its constructor and destructor. Currently the example SmartPtr interface I've shown above supports constructing a SmartPtr from an already-generated handle, assuming the handle generation is external the SmartPtr itself. However overloading the constructor to receive a TYPE pointer allows for insertion of this TYPE * into the handleMap automatically. Here's an example:</span><br />
<br />
<div class="code">
<pre><code>template <typename TYPE>
SmartPtr<TYPE>::SmartPtr( TYPE *ptr )
{
ID = handleMap.InsertPtr( ptr );
clearOnDestruct = true;
}</code></pre>
</div>
<br />
<span style="font-family: Trebuchet MS, sans-serif;">The constructor inserts the ptr of TYPE into the handleMap by calling a method called InsertPtr( ). The return value is used to initialize the SmartPtr's ID data member. A bool called clearOnDestruct is required to be set, and this will be talked about later.</span><br />
<span style="font-family: Trebuchet MS, sans-serif;"><br /></span>
<span style="font-family: Trebuchet MS, sans-serif;">The InsertPtr( ) is a custom-defined method for your handleMap class. It should just insert a new pointer with a newly generated ID. On destruction of the SmartPtr, if the bool clearOnDestruct is set, the pointer can erase the slot in the handleMap for that ID. This way SmartPtr can contain a pointer for you, perhaps within a linked list or some other data structure.</span><br />
<span style="font-family: Trebuchet MS, sans-serif;"><br /></span>
<span style="font-family: Trebuchet MS, sans-serif;">Lastly, a method called DeletePtr( ) should be implemented to allow delete to be called on the data the SmartPtr contains. This SmartPtr implementation isn't supposed to act as any sort of garbage collection: no reference counting is done. Heap memory contained by a SmartPtr must be explicitly deleted with DeletePtr( ) by design. This way SmartPtr's can easily contain heap allocated memory as well. Here's a diagram showing the flow of a SmartPtr:</span><br />
<span style="font-family: Trebuchet MS, sans-serif;"><br /></span>
<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgmN7BIyXKG817Lc-K0d_bpgGXBTOfbzwJHhAuPaeDtDTrKRmlTffoSEyo3wltqJvF22EyMH0mzvq08TiTPTVlVF3O5VQq1GEo0XQsGC_CS9fL-Dj8XkQNOls3uUwOTna_ClIY1AdRQUxk/s1600/SmartPointer.png" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgmN7BIyXKG817Lc-K0d_bpgGXBTOfbzwJHhAuPaeDtDTrKRmlTffoSEyo3wltqJvF22EyMH0mzvq08TiTPTVlVF3O5VQq1GEo0XQsGC_CS9fL-Dj8XkQNOls3uUwOTna_ClIY1AdRQUxk/s1600/SmartPointer.png" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Flow of a smart pointer. Can either reference an ID (left), or contain an inserted pointer (right).</td></tr>
</tbody></table>
<span style="font-family: Trebuchet MS, sans-serif;"><br /></span>
<span style="font-family: Trebuchet MS, sans-serif;">Like I said, there are many different ways to implement smart pointers, and many different things they can achieve. However the details here are just what I decided to use to solve specific problems for projects I work on.</span><br />
<span style="font-family: Trebuchet MS, sans-serif;"><br /></span>
<span style="font-family: Trebuchet MS, sans-serif;">Additional reading:</span><br />
<br />
<ul>
<li><span style="font-family: Trebuchet MS, sans-serif;">C++ for Game Programmers - Noel Llopis: Chapter 12</span></li>
<li><span style="font-family: Trebuchet MS, sans-serif;">Modern C++ Design - Andrei Alexandrescu: Chapter 7</span></li>
</ul>
CecilSunkurehttp://www.blogger.com/profile/16129986119923492789noreply@blogger.com0tag:blogger.com,1999:blog-3579312376304629754.post-28663427389703320612012-08-26T20:08:00.000-07:002012-08-26T21:50:36.082-07:00Easy Buttons for your Game<span style="font-family: Trebuchet MS, sans-serif;">In my past couple game projects, I never had a proper button system; every clickable button I wrote was ad-hoc and thusly very annoying to write.</span><br />
<span style="font-family: Trebuchet MS, sans-serif;"><br />
</span> <span style="font-family: Trebuchet MS, sans-serif;">I came up with a really simple but flexible button system for my C projects. This post is going to be pretty short, so here's a diagram to summarize everything:</span><br />
<span style="font-family: Trebuchet MS, sans-serif;"><br />
</span> <br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEizTPiN4gfK0rlLjcTTXtL-u6eoQHidu4pD-AEOfUabQVSNxVLjfuvomMiIEmgMUa6HUNMQsUGtDz7ED4bGswawms_bHJ6PiE_oRvfjvZLjC5ChTy2ekFn3qMEmDl3GKJ5xfJjI7UI08sQ/s1600/Button_System.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEizTPiN4gfK0rlLjcTTXtL-u6eoQHidu4pD-AEOfUabQVSNxVLjfuvomMiIEmgMUa6HUNMQsUGtDz7ED4bGswawms_bHJ6PiE_oRvfjvZLjC5ChTy2ekFn3qMEmDl3GKJ5xfJjI7UI08sQ/s1600/Button_System.png" /></a></div>
<span style="font-family: Trebuchet MS, sans-serif;"><br />
</span> <span style="font-family: Trebuchet MS, sans-serif;">As you can see, the button object takes a function pointer as a parameter during construction. This function is what I refer to as exec. The exec function allows for a button to perform any action on-click. The exec function can take a general purpose parameter, perhaps defaulted to type int or void pointer. Within the exec function any necessary typecasting can be hidden away within it.</span><br />
<span style="font-family: Trebuchet MS, sans-serif;"><br />
</span> <span style="font-family: Trebuchet MS, sans-serif;">The exec functions will often times have additional dependencies throughout your program, in order to provide their desired functionality. For example I might need my exec function to create a live game object on-click. I'd need to include any headers required for creating game objects into my button system in order for this to work. </span><span style="font-family: 'Trebuchet MS', sans-serif;">For this reason the exec functions should be abstracted into their own separate file.</span><br />
<span style="font-family: Trebuchet MS, sans-serif;"><br />
</span> <span style="font-family: Trebuchet MS, sans-serif;">Alternatively one can make use of a <a href="http://cecilsunkure.blogspot.com/2012/07/hash-tables.html">map of identifiers</a> to exec pointers in order to cut down on file dependencies. By mapping, of perhaps a string identifier, to an exec pointer the button class can then take the identifier upon creation rather than the pointer itself. The various exec functions can then be placed into file systems that pertain to the type of functionality the exec function itself provides. A registration of each exec function into the table would be required.</span><br />
<span style="font-family: Trebuchet MS, sans-serif;"><br />
</span> <span style="font-family: Trebuchet MS, sans-serif;">As for button behavior, I decided to create a few different types of Update functions for each button. Once a button has detected an on-click and has called its exec function, the Update function is called each cycle until the button is ready to detect another click and call its exec again. Since there can be multiple types of buttons each requiring its own unique update, the button object also takes a pointer to an Update function on creation. Here's a couple examples of button updates I've written:</span><br />
<br />
<div class="code">
<pre><code>//
// ButtonUpdateStandard
// Purpose: Standard update function for a generic button.
//
RETURN_TYPE ButtonUpdateStandard( BUTTON *self, float dt )
{
// Update dt only if non-zero.
// For example when exec is called, set dt to 0.001 (seconds)
// to begin debounce timer.
if(self->dt != 0)
{
self->dt += dt;
}
// Debounce
if(self->dt > STANDARD_BUTTON_DEBOUNCE && !IsKeyPressed( VK_LBUTTON ))
{
self->dt = 0;
}
if(self->dt == 0)
{
VECTOR2D pos = { 0 };
pos.x_ = (float)GLOBAL_INPUTS.xPos;
pos.y_ = (float)GLOBAL_INPUTS.yPos;
// Test for button press
if(IsKeyPressed( VK_LBUTTON ))
{
if(StaticPointToStaticRect( &pos, &self->rect ))
{
{
self->exec( self );
// Initiate debounce
self->dt = 0.0001f;
// End list caller routine if blocking
if(self->isBlocking)
return RETURN_FAILURE;
}
}
}
}
return RETURN_SUCCESS;
}
//
// ButtonUpdateBrush
// Purpose: Standard update function for a generic button.
//
RETURN_TYPE ButtonUpdateBrush( BUTTON *self, float dt )
{
// Update dt only if non-zero.
// For example when exec is called, set dt to 0.001 (seconds)
// to begin debounce timer.
if(self->dt != 0)
{
self->dt += dt;
}
// Debounce
if(self->dt > BRUSH_BUTTON_DEBOUNCE)
{
self->dt = 0;
}
if(self->dt == 0)
{
VECTOR2D pos = { 0 };
pos.x_ = (float)GLOBAL_INPUTS.xPos;
pos.y_ = (float)GLOBAL_INPUTS.yPos;
// Test for button press
if(IsKeyPressed( VK_LBUTTON ))
{
if(StaticPointToStaticRect( &pos, &self->rect ))
{
{
self->exec( self );
// Initiate debounce
self->dt = 0.000001f;
// End list caller routine if blocking
if(self->isBlocking)
return RETURN_FAILURE;
}
}
}
}
return RETURN_SUCCESS;
}</code></pre>
</div>
<br />
<span style="font-family: Trebuchet MS, sans-serif;">These two buttons act like a standard button press in most GUI systems. One has a slight delay for how fast you can actually click the button, and a debouncer that requires a release of the mouse key before update actually starts using DT to calculate the current time duration. The other acts more like a spray brush where you can just hold down the click button on have exec called repeatedly with a pause between calls.</span>CecilSunkurehttp://www.blogger.com/profile/16129986119923492789noreply@blogger.com0tag:blogger.com,1999:blog-3579312376304629754.post-7323134987700985592012-08-23T16:05:00.000-07:002012-08-24T00:17:53.111-07:00Game Object Factory: Distributed Factory<span style="font-family: Trebuchet MS, sans-serif;">When creating game objects within your game, you will likely want to start using new or malloc all over the place. This is bad! Every object should have a clear owner, and there should be a single interface for creating any object. Take a look at this code:</span><br />
<br />
<div class="code">
<pre><code>void ExampleFunc( void )
{
object *GO = new SomeGameObjectType( );</code></pre>
<pre><code> // Who owns this object?</code></pre>
<pre><code> // What headers do I need to include?
}</code></pre>
</div>
<br />
<span style="font-family: Trebuchet MS, sans-serif;">The above code does work, although it creates a giant mess of file dependencies. Suddenly one would require a header file for all the various object definitions in order to use the new operator everywhere. Furthermore, handling of attaching the object to some sort of owner will have to be done everywhere that the new keyword is used.</span><br />
<span style="font-family: Trebuchet MS, sans-serif;"><br />
</span> <span style="font-family: Trebuchet MS, sans-serif;">A factory should be used to create game objects in a unified way. Here's an example of the simplest form of an object factory:</span><br />
<br />
<div class="code">
<pre><code>
#include "RedBlock.h"
#include "BlueEnemy.h"
#include "FireBall.h"
// ID is an enumeration
object *CreateObject( ID type )
{
switch( ID )
{
case REDBLOCK:
return new RedBlock( );
case BLUENEMY:
return new BlueEnemy( );
case FIREBALL:
return new FireBall( );
}
}</code></pre>
</div>
<br />
<span style="font-family: Trebuchet MS, sans-serif;">However there are some problems with this type of factory. One is that the factory will still have annoying file dependencies requiring the user to make another include, and modify the switch statement each time a new game object is designed. Examine the following:</span><br />
<br />
<div class="code">
<pre><code>// Map strings to object types
void ExampleFunc( void )
{
object *GO = CreateObject( "RedBlock" );
}</code></pre>
</div>
<br />
<span style="font-family: Trebuchet MS, sans-serif;">The above example shows the usage of the object factory when strings are mapped to types of objects. This setup is the ideal interface one would desire, as a single include to the ObjectFactory header is all that is required to create any type of object. The previous examples were mapping integers of an enumeration type to object types, which would require modification to the switch statement run in the enum, as well as manual updating to the enumeration itself.</span><br />
<span style="font-family: Trebuchet MS, sans-serif;"><br />
</span> <span style="font-family: Trebuchet MS, sans-serif;">So now that we've identified the ideal interface for creating game objects, we still need to make sure that the game objects created have a clear owner. Mapping of strings to game object types will need to be implemented, and cutting down on file dependencies of the the GameObjectFactory file itself is still something to be solved as well. By using a map (perhaps std::map) or <a href="http://cecilsunkure.blogspot.com/2012/07/hash-tables.html">hash table</a> we can use a string identifier to fetch some value. Here's what we want our factory to look like:</span><br />
<br />
<div class="code">
<pre><code>object *CreateObject( char *type )
{
return map[type]->Create( );
}</code></pre>
</div>
<br />
<span style="font-family: Trebuchet MS, sans-serif;">By mapping a string to a creator function of the type of object desired, all file dependencies except that of those required to utilize the table (map in the above example) are eliminated. Furthermore, whenever a new game object type is designed, all that is needed to be done to ensure compatibility with our factory is a single registration call.</span><br />
<span style="font-family: Trebuchet MS, sans-serif;"><br />
</span> <span style="font-family: Trebuchet MS, sans-serif;">There are some details about the Create function that should be discussed. The Create function is specific to each type of game object, and the interface for each Create function needs to be identical. To ensure this, each type of game object should have a single class called the creator. The creator object for each class derives from a base Creator class to ensure a clear and consistent interface.</span><br />
<br />
<div class="code">
<pre><code>// Base class
class Creator
{
virtual object *Create( void );
virtual ~Creator( void );
}
// In another file...
// Specific derived creator for a single object type
class RedBlockCreator : public Creator
{
virtual object *Create( void )
{
return new RedBlock( );
}
}
// In another file...
// Register all game object creators in a single place in a unified way!
void RegisterCreators( void )
{
map->register( "RedBlock", new RedBlockCreator( ) );
// Or use a macro like I did:
REGISTER_CREATOR( RedBlock );
}</code></pre>
</div>
<br />
<span style="font-family: Trebuchet MS, sans-serif;">What we've now created is called a distributed factory. All file dependencies are hidden by registration in using a hash table data structure to provide the mapping of typeless strings to actual types of game objects. The creation of objects has a unified interface, and there's a single access point (the object factory) that allows the creation of all types of game objects that are registered within its data table of types. There's one last small problem to solve: who owns the created objects? This answer can of course vary, but luckily there can be a single point of object management, like so:</span><br />
<br />
<div class="code">
<pre><code>object *CreateObject( char *type )
{
object *newObject = NULL;
newObject = map[type]->Create( );
// Single point of management
... any other code necessary, like init, counting, etc.
ObjectList->Insert( newObject );
return newObject;
}</code></pre>
</div>
<br />
<span style="font-family: Trebuchet MS, sans-serif;">And there we have it! A properly structured object factory. To further the awesome might of the factory, one could easily add in deserialization to the factory, since the factory is already working with abstract strings as type identifiers. Serialization, however, is for a future post!</span><br />
<span style="font-family: Trebuchet MS, sans-serif;"><br /></span>
<span style="font-family: Trebuchet MS, sans-serif;">Factories like this also interface very well with scripting languages :)</span><br />
<span style="font-family: Trebuchet MS, sans-serif;"><br /></span>
<span style="font-family: Trebuchet MS, sans-serif;">Additional reading:<br />C++ for Game Programmers: Noel Llopis - Chapter 13</span>CecilSunkurehttp://www.blogger.com/profile/16129986119923492789noreply@blogger.com3tag:blogger.com,1999:blog-3579312376304629754.post-45160456961234847712012-08-10T04:27:00.001-07:002012-08-22T01:06:12.430-07:00Generic Programming in C<span style="font-family: Trebuchet MS, sans-serif;"><a href="http://en.wikipedia.org/wiki/Generic_programming">Generic programming</a> is style of programming that is typeless, as in the type of data to be used is not determined at the time the code was written. In C++ this is achieved with templating. </span><span style="font-family: 'Trebuchet MS', sans-serif;">I know of two ways to perform generic programming in C. One way is to use pointer typecasting. </span><span style="font-family: 'Trebuchet MS', sans-serif;">It's important to understand that when you typecast a pointer no data is modified within the pointer; how the data the pointer points to is interpreted is changed. This can be utilized to create generic algorithms and functionality.</span><br />
<br />
<span style="font-family: 'Trebuchet MS', sans-serif;">For example a linked list data structure can be created utilizing pointer typecasting where the data to be held by a node is typecasted to a single type no matter what the actual type of the data is. Usually a void * is used in this case to prevent a dereference to data of unknown type. However, this method can only be used when access to the data held by the node (the data pointed by the void *) does not need to be accessed.</span><br />
<span style="font-family: 'Trebuchet MS', sans-serif;"><br />
</span> <span style="font-family: 'Trebuchet MS', sans-serif;">A more well-rounded (in my opinion) approach to generic programming in C is to make use of the preprocessor directive ##.</span><br />
<span style="font-family: 'Trebuchet MS', sans-serif;"><br />
</span> <span style="font-family: 'Trebuchet MS', sans-serif;">## pastes two tokens together to create a new token. Usage of the ## operator is known as token pasting, or token concatenation. There's a <a href="https://www.google.com/search?q=token+pasting+c&sugexp=chrome,mod=2&sourceid=chrome&ie=UTF-8#hl=en&safe=off&sclient=psy-ab&q=c+token+pasting+concatentation+operator&oq=c+token+pasting+concatentation+operator&gs_l=serp.3...5759.9999.2.10396.23.19.3.0.0.2.107.1264.18j1.19.0...0.0...1c.jnjF-epCtmg&pbx=1&bav=on.2,or.r_gc.r_pw.r_qf.&fp=5704db8c962dc0db&biw=1360&bih=667">whole lot of documentation on the ## operator</a>. If you're not familiar with it, you need to do some familiarizing before reading on.</span><br />
<span style="font-family: 'Trebuchet MS', sans-serif;"><br />
</span> <span style="font-family: 'Trebuchet MS', sans-serif;">All it does is take two tokens within a macro and stick them together to create a new token. Example:</span><br />
<br />
<div class="code"><pre><code>#define PASTE_TOKENS( a, b ) \
a##b
PASTE_TOKENS( var, val ); // output: varval</code></pre></div><br />
<span style="font-family: Trebuchet MS, sans-serif;">In the above example varval will need to be defined in order to avoid compiler errors, perhaps by using it as the name of a variable to define.</span><br />
<span style="font-family: Trebuchet MS, sans-serif;"><br />
</span> <span style="font-family: Trebuchet MS, sans-serif;">Token pasting is utilized to solve an age old problem in C of creating various functions to achieve the same problem. For example, I've written many linked lists in C and one day, I finally decide "I will never write another linked list in C". I'm sick and tired of having to write a new set of functions for each type of data that I need a new linked list for.</span><br />
<span style="font-family: Trebuchet MS, sans-serif;"><br />
</span> <span style="font-family: Trebuchet MS, sans-serif;">By using the ## operator one can automate the process of duplicating code to create new functions and new definitions based off of data type. This is much like templating in C++, except not nearly as user-friendly, yet still fun and satisfying to try.</span><br />
<span style="font-family: Trebuchet MS, sans-serif;"><br />
</span> <span style="font-family: Trebuchet MS, sans-serif;">Since there's a great need in C to duplicate code for various data types, and the ## operator allows us to create new tokens with two other tokens, we can use the type of the data to create a new name for a new set of functionality for each type of data desired.</span><br />
<span style="font-family: Trebuchet MS, sans-serif;"><br />
</span> <span style="font-family: Trebuchet MS, sans-serif;">Examine the following:</span><br />
<br />
<div class="code"><pre><code>// Old C style "function overloading"
int INT_MAX( int a, int b )
{
return (a > b) ? a : b;
}
float FLOAT_MAX( float a, float b )
{
return (a > b) ? a : b;
}
double DOUBLE_MAX( double a, double b )
{
return (a > b) ? a : b;
}
// Generic definition
#define GENERIC_MAX( TYPE ) \
TYPE TYPE##_MAX( TYPE a, TYPE b ) \
{ \
return (a > b) ? a : b; \
}</code></pre></div><br />
<span style="font-family: Trebuchet MS, sans-serif;">As you can see, it can be really annoying to write different code for different types of data, when the code itself is highly redundant or even identical. However by providing the GENERIC_MAX macro a data type, a new function can be automatically generated by the C preprocessor! The MAX token is concatenated with the TYPE parameter to form a new function definition. Providing the GENERIC_MAX macro with type int will result in a new function being defined named int_MAX. Creating new sets of functionality of anything can be as simple as declaring or defining with a couple calls to a macro.</span><br />
<span style="font-family: Trebuchet MS, sans-serif;"><br />
</span> <span style="font-family: Trebuchet MS, sans-serif;">It might seem a bit self-defeating however to have to figure out what the new name of your generated function is going to be in order to call it. A very simple utility macro should be used to wrap around your generated generic functions. More information on how to do this is shown later in the post.</span><br />
<span style="font-family: Trebuchet MS, sans-serif;"><br />
</span> <span style="font-family: Trebuchet MS, sans-serif;">This can be taken further and be applied to even an abstract data type, such as a linked list. I've constructed myself a generic linked list.</span><br />
<br />
<div class="code"><pre><code>//
// DECLARE_NODE
// Purpose: Declares a node of a specific type.
//
#define DECLARE_NODE( TYPE ) \
typedef struct _NODE_##TYPE \
{ \
TYPE data; \
struct _NODE_##TYPE *next; \
} NODE_##TYPE;</code></pre></div><br />
<span style="font-family: Trebuchet MS, sans-serif;">The above code is an example definition of a macro that defines a generic node type. The type of the node is used in creating new name definitions wherever the node's type is required in the structure definition.</span><br />
<br />
<div class="code"><pre><code>//
// DEFINE_FUNC( TYPE )
// Purpose: Defines a function to create a node of specified type.
//
#define DEFINE_FUNC( TYPE ) \
NODE_##TYPE *NODE_CREATE_##TYPE( TYPE data ) \
{ \
NODE_##TYPE *newNode = \
(NODE_##TYPE *)malloc( sizeof( NODE_##TYPE ) ); \
newNode->data = data; \
newNode->next = NULL; \
return newNode; \
}</code></pre></div><br />
<span style="font-family: Trebuchet MS, sans-serif;">Above is an example of how to define a macro to define a function to create a new node of specified type based on the previous node definition.</span><br />
<span style="font-family: Trebuchet MS, sans-serif;"><br />
</span> <span style="font-family: Trebuchet MS, sans-serif;">You might be thinking that it would be a bit annoying to call so many different define and declare macros for each structure and function. You can actually just declare all structures and function prototypes within a single macro, I called mine DECLARE_LIST, which declares all structure types and function prototypes, as well as some utility macros required to use the generic linked list. I also have a DEFINE_LIST macro that defines all functions used in the generic linked list.</span><br />
<span style="font-family: Trebuchet MS, sans-serif;"><br />
</span> <span style="font-family: Trebuchet MS, sans-serif;">For abstract data types such as lists or stacks or queues, you'll probably want some additional utility functions to actually call the various generic functions you've defined. Here is an example set of utility functions I've made for my generic linked list:</span><br />
<br />
<div class="code"><pre><code>//
// LIST_CONSTRUCT
// Purpose: Constructs and returns a new list object of specified type.
//
#define LIST_CONSTRUCT( TYPE ) \
LIST_CONSTRUCT_##TYPE( )
//
// NODE_CREATE
// Purpose: Constructs and returns a new node of a specified type.
//
#define NODE_CREATE( TYPE, data, DeleteData, order ) \
NODE_CREATE_##TYPE( data, DeleteData, order )
//
// LIST_INSERT
// Purpose: Inserts a node of specified type in position determined by the order
// data member.
//
#define LIST_INSERT( TYPE, listSelf, node ) \
LIST_INSERT_##TYPE( listSelf, node )
//
// LIST_REMOVE
// Purpose: Removes (deallocates) a node of a specified type from a list.
//
#define LIST_REMOVE( TYPE, node ) \
LIST_REMOVE_##TYPE( node )
//
// LIST_DESTROY
// Purpose: Removes (deallocates) a list and all its nodes of a specified type.
//
#define LIST_DESTROY( TYPE, listSelf ) \
LIST_DESTROY_##TYPE( listSelf )
//
// LIST_CALLER
// Purpose: Uses a callback on all nodes while supplying a specified param.
//
#define LIST_CALLER( TYPE, self, callback, param ) \
LIST_CALLER_##TYPE( self, callback, param )
//
// LIST_TYPE
// Purpose: Returns the type of LIST that pertains to TYPE.
//
#define LIST_TYPE( TYPE ) \
LIST_##TYPE
//
// NODE_TYPE
// Purpose: Returns the type of NODE that pertains to TYPE.
//
#define NODE_TYPE( TYPE ) \
NODE_##TYPE</code></pre></div><br />
<span style="font-family: Trebuchet MS, sans-serif;">As you can see wrappers for the various generic functions are needed to properly call them (unless you want to manually figure out what the name of the function generated for whatever type you're currently using is). There's also a couple macros for getting the generated type associated with a provided type.</span><br />
<br />
<a href="javascript:expandcollapse('subtopic0001')">Click Here for Source Code</a><br />
<span class="posthidden" id="subtopic0001"><br />
<div class="code"><pre>////////////////////////////////////////////////////
// Copyright (c) 2012 ICRL
// See the file LICENSE.txt for copying permission.
//
// Original Author: Randy Gaul
// Date: 8/9/2012
// Contact: r.gaul@digipen.edu
////////////////////////////////////////////////////
#pragma once
#include "StringHash.h"
//
// DECLARE_LIST
// Purpose: Declares a linked list of a specific type on the heap.
//
#define DECLARE_LIST( TYPE ) \
typedef struct _NODE_##TYPE \
{ \
TYPE data; \
void (*DeleteData)( TYPE ); \
int order; \
struct _NODE_##TYPE *next; \
struct _NODE_##TYPE *prev; \
} NODE_##TYPE; \
\
struct _LIST_##TYPE; \
\
typedef struct _LIST_VTABLE_##TYPE \
{ \
void (*Destroy) ( struct _LIST_##TYPE *self ); \
NODE_##TYPE *(*CreateNode)( TYPE data, void (*DeleteData)( TYPE ), int order ); \
RETURN_TYPE (*Insert) ( struct _LIST_##TYPE *self, NODE_##TYPE *node ); \
void (*Remove) ( NODE_##TYPE *node ); \
} _LIST_VTABLE_##TYPE; \
\
extern const _LIST_VTABLE_##TYPE LIST_VTABLE_##TYPE; \
\
typedef struct _LIST_##TYPE \
{ \
NODE_##TYPE *list; \
const _LIST_VTABLE_##TYPE *vtable; \
} LIST_##TYPE; \
\
LIST_##TYPE *LIST_CONSTRUCT_##TYPE( void ); \
NODE_##TYPE *NODE_CREATE_##TYPE( TYPE data, void (*DeleteData)( TYPE data ), int order ); \
RETURN_TYPE LIST_INSERT_##TYPE ( LIST_##TYPE *self, NODE_##TYPE *node ); \
void LIST_REMOVE_##TYPE ( NODE_##TYPE *node ); \
void LIST_DESTROY_##TYPE ( LIST_##TYPE *self ); \
void LIST_CALLER_##TYPE ( LIST_##TYPE *self, RETURN_TYPE (*callback)( NODE_##TYPE *, void * ), void *param ); \
TYPE LIST_PEEK_##TYPE ( LIST_##TYPE *self )
//
// DEFINE_LIST
// Purpose: Defines a linked list of a specific type on the heap.
//
#define DEFINE_LIST( TYPE ) \
const _LIST_VTABLE_##TYPE LIST_VTABLE_##TYPE = \
{ \
LIST_DESTROY_##TYPE, \
NODE_CREATE_##TYPE, \
LIST_INSERT_##TYPE, \
LIST_REMOVE_##TYPE \
}; \
\
LIST_##TYPE *LIST_CONSTRUCT_##TYPE( void ) \
{ \
LIST_##TYPE *linkedList = (LIST_##TYPE *)malloc( sizeof( LIST_##TYPE ) ); \
linkedList->list = NULL; \
linkedList->vtable = &LIST_VTABLE_##TYPE; \
return linkedList; \
} \
\
NODE_##TYPE *NODE_CREATE_##TYPE( TYPE data, void (*DeleteData)( TYPE ), int order ) \
{ \
NODE_##TYPE *newNode = (NODE_##TYPE *)malloc( sizeof( NODE_##TYPE ) ); \
newNode->data = data; \
newNode->DeleteData = DeleteData; \
newNode->order = order; \
newNode->next = NULL; \
newNode->prev = NULL; \
return newNode; \
} \
\
RETURN_TYPE LIST_INSERT_##TYPE ( LIST_##TYPE *self, NODE_##TYPE *node ) \
{ \
NODE_##TYPE *scan = NULL; \
if(!self) \
return RETURN_FAILURE; \
\
scan = self->list; \
\
if(scan) /* if list is not empty */ \
{ \
while(scan->next) \
{ \
if(scan->order <= node->order) \
break; \
scan = scan->next; \
} \
\
/* beginning of list */ \
if(!scan->prev) \
{ \
node->next = scan; \
scan->prev = node; \
self->list = node; \
} \
/* if not at end of list */ \
else if(scan->next) \
{ \
node->next = scan; \
node->prev = scan->prev; \
scan->prev->next = node; \
scan->prev = node; \
} \
else \
{ \
if(scan->prev) /* If more than one item in list */ \
{ \
if(scan->order <= node->order) \
{ \
node->next = scan; \
node->prev = scan->prev; \
scan->prev->next = node; \
scan->prev = node; \
} \
else \
{ \
node->prev = scan; \
scan->next = node; \
} \
} \
else /* One item in list */ \
{ \
/* Place before or after depending on zOrder */ \
if(scan->order <= node->order) \
{ \
scan->prev = node; \
node->next = scan; \
self->list = node; \
} \
else \
{ \
scan->next = node; \
node->prev = scan; \
} \
} \
} \
} \
else /* if list is empty */ \
{ \
self->list = node; \
} \
\
return RETURN_SUCCESS; \
} \
\
void LIST_REMOVE_##TYPE ( NODE_##TYPE *node ) \
{ \
if(node->prev) \
{ \
node->prev->next = node->next; \
if(node->next) \
{ \
node->next->prev = node->prev; \
} \
} \
else if(node->next) \
{ \
node->next->prev = NULL; \
} \
\
if(node->DeleteData) \
{ \
node->DeleteData( node->data ); \
} \
free( node ); \
} \
\
void LIST_DESTROY_##TYPE ( LIST_##TYPE *self ) \
{ \
NODE_##TYPE *temp = NULL; \
NODE_##TYPE *scan = self->list; \
\
while(scan) \
{ \
temp = scan->next; \
self->vtable->Remove( scan ); \
scan = temp; \
} \
\
free( self ); \
} \
\
void LIST_CALLER_##TYPE ( LIST_##TYPE *self, RETURN_TYPE (*callback)( NODE_##TYPE *, void * ), void *param ) \
{ \
NODE_##TYPE *scan = self->list, *temp = NULL; \
\
while(scan) \
{ \
temp = scan->next; \
/* Stop the callback process if return type is not 0 */ \
if(callback( scan, param )) \
{ \
scan = temp; \
return; \
} \
scan = temp; \
} \
} \
\
TYPE LIST_PEEK_##TYPE ( LIST_##TYPE *self ) \
{ \
return self->list->data; \
}
//
// LIST_CONSTRUCT
// Purpose: Constructs and returns a new list object of specified type.
//
#define LIST_CONSTRUCT( TYPE ) \
LIST_CONSTRUCT_##TYPE( )
//
// NODE_CREATE
// Purpose: Constructs and returns a new node of a specified type.
//
#define NODE_CREATE( TYPE, data, DeleteData, order ) \
NODE_CREATE_##TYPE( data, DeleteData, order )
//
// LIST_INSERT
// Purpose: Inserts a node of specified type in position determined by the order
// data member.
// Notes: Will return RETURN_FAILURE if list pointer is NULL.
//
#define LIST_INSERT( TYPE, listSelf, node ) \
LIST_INSERT_##TYPE( listSelf, node )
//
// LIST_REMOVE
// Purpose: Removes (deallocates) a node of a specified type from a list.
//
#define LIST_REMOVE( TYPE, node ) \
LIST_REMOVE_##TYPE( node )
//
// LIST_DESTROY
// Purpose: Removes (deallocates) a list and all its nodes of a specified type.
//
#define LIST_DESTROY( TYPE, listSelf ) \
LIST_DESTROY_##TYPE( listSelf )
//
// LIST_CALLER
// Purpose: Uses a callback on all nodes while supplying a specified param.
//
#define LIST_CALLER( TYPE, self, callback, param ) \
LIST_CALLER_##TYPE( self, callback, param )
//
// LIST_PEEK
// Purpose: Returns the data of the first in the list.
//
#define LIST_PEEK( TYPE, self ) \
LIST_PEEK_##TYPE( self )
//
// General data type handling. These functions must be used to handle list and node
// objects/pointers directly.
//
#define LIST_TYPE( TYPE ) \
LIST_##TYPE
#define NODE_TYPE( TYPE ) \
NODE_##TYPE
</pre></div></span><br />
<br />
<span style="font-family: Trebuchet MS, sans-serif;"><b><span style="font-size: large;">Drawbacks</span></b>:</span><br />
<span style="font-family: Trebuchet MS, sans-serif;">There is one major drawback to the ## operator strategy; you cannot use * in the type name, or spaces in the type name. If you need to use a pointer as your type, you'll have to typedef your pointer into a single valid token and pass the typedef'd type to the generic macros.</span><br />
<span style="font-family: Trebuchet MS, sans-serif;"><br />
</span> <span style="font-family: Trebuchet MS, sans-serif;">There is another thing that can be considered a drawback: you cannot have a pointer to a macro. As such debugging macros can be very very tedious. I myself had to generate a processed file and compile with the expanded macro in order to pinpoint where I originally had some compiling errors when creating my generic linked list.</span>CecilSunkurehttp://www.blogger.com/profile/16129986119923492789noreply@blogger.com6tag:blogger.com,1999:blog-3579312376304629754.post-11497899948168767342012-08-10T03:16:00.000-07:002012-08-10T03:26:53.846-07:00Object Oriented C: Virtual Table (vtable)<span style="font-family: Trebuchet MS, sans-serif;">I wrote a previous post on <a href="http://cecilsunkure.blogspot.com/2012/04/object-oriented-c-class-like-structures.html">Class-Like Structures</a> for usage in C, in order to create objects that would allow for both inheritance and polymorphism. However, it's annoying to keep a pointer to each type of required function for each type of object, and often times you'll need fancy typecasting in multiple locations in order to avoid compiler warnings.</span><br />
<div>
<span style="font-family: Trebuchet MS, sans-serif;"><br />
</span></div>
<div>
<span style="font-family: Trebuchet MS, sans-serif;">In C++ each class that contains methods also has a virtual table (vtable). A vtable is simply a pointer to a collection of function pointers. In C++ member functions pointers (pointers to member functions, or methods) aren't actually the exact same as function pointers, but the concept of the vtable in C++ is the same as in C; the vtable keeps track of what functions are available for use by the object.</span></div>
<div>
<span style="font-family: Trebuchet MS, sans-serif;"><br />
</span></div>
<div>
<span style="font-family: Trebuchet MS, sans-serif;">Luckily the murkiness of member function pointers are completely avoided when working with C and pure function pointers. A vtable in C can consist of a structure with each data member as a function pointer, or an array of function pointers. Whichever style chosen should be chosen based on preference as either method of implementation can be fine. I personally like using a structure.</span><br />
<span style="font-family: Trebuchet MS, sans-serif;"><br />
</span> <span style="font-family: Trebuchet MS, sans-serif;">Lets take a look at the structure defined in my older post:</span></div>
<br />
<div class="code">
<pre><code>typedef struct _GameObj
{
int HP;
Vector2D_ position;
GAME_OBJ_TYPE ID;
Image_ *image;
void (*Construct)( GameObj_ *self );
void (*Init)( GameObj_ *self );
void (*Update)( GameObj_ *self );
void (*Draw)( GameObj_ *self );
void (*Destroy)( GameObj_ *self );
} GameObj_;</code></pre>
</div>
<br />
<span style="font-family: Trebuchet MS, sans-serif;">This structure requires memory space for each location. This is unnecessary and a bit annoying to handle during initialization, and can lead to annoying typecasting in various locations. Here's what the new object should look like if we introduce a vtable:</span><br />
<br />
<div class="code">
<pre><code>typedef struct _GameObj
{
int HP;
Vector2D_ position;
GAME_OBJ_TYPE ID;
Image_ *image;
const _GAMEOBJECT_VTABLE *vtable;
} GameObj_;</code></pre>
</div>
<br />
<span style="font-family: Trebuchet MS, sans-serif;">This cuts the size of memory required for the virtual functions for this particular object down by a factor of 5. Here is what the definition of the vtable can look like:</span><br />
<br />
<div class="code">
<pre><code>typedef struct _GAMEOBJECT_VTABLE
{
void (*Construct)( struct _GAMEOBJECT *self );
void (*Init) ( struct _GAMEOBJECT *self );
void (*set) ( struct _GAMEOBJECT *self );
void (*Update) ( struct _GAMEOBJECT *self );
void (*Draw) ( struct _GAMEOBJECT *self );
void (*Destroy) ( struct _GAMEOBJECT *self );
} _GAMEOBJECT_VTABLE;</code></pre>
</div>
<br />
<span style="font-family: Trebuchet MS, sans-serif;">Since a vtable is in use in the game object, typecasting may be necessary if the parameters of the various functions of the vtable differ from object to object. However a single typecast is all that is necessary during initialization. Typecasting the vtable itself to change the parameters of the functions within the vtable doesn't actually modify any memory. It's important to understand that when you typecast a pointer (and consequently a vtable pointer) no data is modified within the pointer; how the data the pointer points to is interpreted is changed.</span><br />
<span style="font-family: Trebuchet MS, sans-serif;"><br />
</span> <span style="font-family: Trebuchet MS, sans-serif;">So what about the code for this typecasting? Here's a small example of some initialization code for initializing the vtable data member:</span><br />
<br />
<div class="code">
<pre><code>const _SOME_OTHER_VTABLE SOME_OTHER_VTABLE = {
SomeOtherConstruct,
SomeOtherInit,
SomeOtherSet,
SomeOtherUpdate,
SomeOtherDraw,
SomeOtherDestroy
};
((GAMEOBJECT *)object)->vtable_ =
(const _GAMEOBJECT_VTABLE *)(&SOME_OTHER_VTABLE);
// Example invocation of an object's vtable's function
object->vtable->Destroy( object );
((</code>SOME_OTHER_VTABLE *)object->vtable)->SomeOtherUpdate( other params );</pre>
</div>
<br />
<span style="font-family: Trebuchet MS, sans-serif;">It's important to note that some extra parentheses are required to force typecasting to occur to avoid confusing operator precedence issues. The vtable should be initialized directly after allocation of the object. This ensures that the vtable pointer will never be accessed without being initialized.</span><br />
<span style="font-family: Trebuchet MS, sans-serif;"><br />
</span> <span style="font-family: Trebuchet MS, sans-serif;">The definitions of the SomeOther functions can have any type of parameters to your heart's desire!</span><br />
<span style="font-family: Trebuchet MS, sans-serif;"><br />
</span> <span style="font-family: Trebuchet MS, sans-serif;">It may be a bit confusing having a Construct function within the vtable when allocation of the object and initialization of the vtable data member happen outside of the Construct function. This is because you cannot actually call the Construct function from the vtable until the vtable is allocated and initialized. Handling of creation of objects would be best done with the <a href="http://en.wikipedia.org/wiki/Factory_method_pattern">Factory Pattern</a>.</span><br />
<span style="font-family: Trebuchet MS, sans-serif;"><br />
</span> <span style="font-family: Trebuchet MS, sans-serif;">I'll likely write a post in the near future on the factory pattern :)</span>CecilSunkurehttp://www.blogger.com/profile/16129986119923492789noreply@blogger.com0tag:blogger.com,1999:blog-3579312376304629754.post-3077158087175980472012-07-03T22:36:00.002-07:002012-07-23T09:07:05.648-07:00Collision: Basic 2D Collision Detection + Jump Physics<span style="font-family: 'Trebuchet MS', sans-serif;">This post will cover some various collision techniques for use in 2D games. Types of collisions to be covered in this article are:</span><br />
<ul>
<li><span style="font-family: 'Trebuchet MS', sans-serif;">Static point to static circle </span></li>
<li><span style="font-family: 'Trebuchet MS', sans-serif;">Static circle to static circle</span> </li>
<li><span style="font-family: 'Trebuchet MS', sans-serif;">Static point to static rectangle</span></li>
<li><span style="font-family: 'Trebuchet MS', sans-serif;">Static rectangle to static rectangle</span></li>
<li><span style="font-family: 'Trebuchet MS', sans-serif;">Static circle to static rectangle</span></li>
<li><span style="font-family: 'Trebuchet MS', sans-serif;">Jumping physics (optimal equation technique)</span></li>
</ul>
<div>
<span style="font-family: 'Trebuchet MS', sans-serif; font-size: large;">Static Circle to Static Point</span></div>
<div>
<span style="font-family: 'Trebuchet MS', sans-serif;">In order to detect whether or not a point is colliding with a circle there are only a few very simple checks required. Luckily a circle is simply a radius and a point. Find the distance from the center of your circle and your colliding point, and check to see if it is larger, greater, or smaller than the radius. Larger means that the point is outside the circle, the same means the point is directly on the edge, and smaller means a collision is occuring.</span></div>
<br />
<div class="code">
<code>// Given that CP is the center of the circle, P is the point,<br />
// and R is the radius<br />
if dist( CP, P ) is equal to R: Collision or Non-Collision (you choose)<br />
if dist( CP, P ) is greater than R: No collision<br />
if dist( CP, P ) is less than R: Collision</code></div>
<br />
<span style="font-family: 'Trebuchet MS', sans-serif; font-size: large;">Static Circle to Static Circle</span><br />
<span style="font-family: 'Trebuchet MS', sans-serif;">This collision test is going to be the exact same as Point to Circle, with one difference: you will be comparing the distance from the center of the circles to the radius of the first circle added with the radius of the second circle. This should make sense since the only time two circles will intersect is when their distances are smaller than their radii. Just be sure to avoid this scenario:</span><br />
<span style="font-family: 'Trebuchet MS', sans-serif;"><br />
</span><br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiH2oC9d6Jbvwe959dw57brEtAOeeOlh7D7HZjLWVw3qYeo6e_jcSRZkmrubx3PxqgXfXzrNusd0X9FVPP-TxqupG1dNyBTNJ0Fip0okmz0QZWea5IKPtQTSTyDD-lH2f1Uo-G3D8T3XY4/s1600/Circle_Internal_Tangent.png" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiH2oC9d6Jbvwe959dw57brEtAOeeOlh7D7HZjLWVw3qYeo6e_jcSRZkmrubx3PxqgXfXzrNusd0X9FVPP-TxqupG1dNyBTNJ0Fip0okmz0QZWea5IKPtQTSTyDD-lH2f1Uo-G3D8T3XY4/s1600/Circle_Internal_Tangent.png" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Internally tangent intersection.</td></tr>
</tbody></table>
<span style="font-family: 'Trebuchet MS', sans-serif;"><br />
</span><br />
<span style="font-family: 'Trebuchet MS', sans-serif;">This internally tangent intersection can be avoided by checking for whether or not the distance between the circles' centers is smaller than the radii combined <i>before</i> checking to see if the distances are equal.</span><br />
<span style="font-family: 'Trebuchet MS', sans-serif;"><br />
</span><br />
<span style="font-family: 'Trebuchet MS', sans-serif; font-size: large;">Static Point to Static Rectangle Collision</span><br />
<span style="font-family: 'Trebuchet MS', sans-serif;">This algorithm is extremely straightforward. Think of a rectangle as four values: top, left, bottom and right. Here are the checks required to see if a point is within a square or not (it shouldn't require much of any explanation):</span><br />
<span style="font-family: 'Trebuchet MS', sans-serif;"><br />
</span><br />
<br />
<div class="code">
<code>// B is bottom of the rectangle<br />
// T is top of the rectangle<br />
// L is the left side of the rectangle<br />
// R is the right side of the rectangle<br />
// P is the point<br />
// Perform the following checks:<br />
if(P.X < L) and if(P.X > R)<br />
and if(P.Y < B) and if(P.Y > T)<br />
then no collision</code></div>
<br />
<span style="font-family: 'Trebuchet MS', sans-serif;">All of these conditions will fail if there is a collision. To check for a tangent point, check to see if the point's X value equals the left or right side, while being under the top and above the bottom. Vice versa for the top and bottom tangents. This algorithm is going to be very similar to the ActionScript hittest function.</span><br />
<span style="font-family: 'Trebuchet MS', sans-serif;"><br />
</span><br />
<span style="font-family: 'Trebuchet MS', sans-serif; font-size: large;">Static Rectange to Static Rectangle</span><br />
<span style="font-family: 'Trebuchet MS', sans-serif;">Rectangle to rectangle collision is very simple as well. This should be quite similar to the point to rectangle, except we just use some basic logic to make sure none of the sides of the two rectangles are between each other's sides.</span><br />
<br />
<div class="code">
<code>// Given rectangles A and B<br />
if(leftA > rightB) or<br />
if(leftB > rightA) or<br />
if(topA < bottomB) or<br />
if(topB < bottomA)<br />
then no collision</code></div>
<br />
<span style="font-family: 'Trebuchet MS', sans-serif; font-size: large;">Circle to Rectangle Collision</span><br />
<span style="font-family: 'Trebuchet MS', sans-serif;">Circle to rectangle collision is going to be the most complicated algorithm here. First consider a circle to consist of only a point and a radius. The way we detected two circles colliding was by checking the distances from the centers to their radii. Sadly, a rectangle does not have a radius. However, given the closest point on the rectangle to the center of the circle, we can apply the same algorithm as the Static Point to Static Circle collision detection. All we need do now is find out how to find the closest point on the rectangle to the circle's center.</span><br />
<span style="font-family: 'Trebuchet MS', sans-serif;"><br />
</span><br />
<span style="font-family: 'Trebuchet MS', sans-serif;">To find this point, clamp a copy of the circle's center coordinate to the edges of the rectangle:</span><br />
<br />
<div class="code">
<code>// "Clamping" a point to the side of a rectangle</code><br />
<code>// Given left right bottom and top are sides of a rectangle</code><br />
<code>// P is a new variable created and assigned the value of the</code><br />
<code>// circle's center -- do not modify the circle's coordinate<br />
Point P (new copy of the circles center) = Circle's Center<br />
if(P.X > right) then P.X = right<br />
else(P.X < left) then P.X = left</code><br />
<code><br />
</code><br />
<code>if(P.Y > top) then P.Y = top<br />
else(P.Y < bottom) then P.Y = bottom then no collision</code></div>
<br />
<span style="font-family: 'Trebuchet MS', sans-serif;">After the above code is run point P will be somewhere on the edge of the rectangle and will also be the closest point along the rectangle's sides to the center of the circle. Now compare the distance from these two points to the radius with the Static Point to Static Circle algorithm. Results will be the same.</span><br />
<br />
<span style="font-family: 'Trebuchet MS', sans-serif; font-size: large;">Optimization of Distance Formula</span><br />
<span style="font-family: 'Trebuchet MS', sans-serif;">By using some simple algebra one can remove the sqrt function from the distance formula for the purpose of checking two values:</span><br />
<span style="font-family: 'Trebuchet MS', sans-serif;"><br />
</span><br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhcTgk_9Cstd_JJq_YL_I9sGsthfstJmwZhAa8J6ru9bQPfP2U8h1LlxkIbCcZBM-r1UlPq62BjaH2_Md5Td896yBErqEgkogcxsCCQc3voCha-j7wGgTbGowxAf3GTgCPSEJjOdt7A_zA/s1600/Distance_Squared.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhcTgk_9Cstd_JJq_YL_I9sGsthfstJmwZhAa8J6ru9bQPfP2U8h1LlxkIbCcZBM-r1UlPq62BjaH2_Md5Td896yBErqEgkogcxsCCQc3voCha-j7wGgTbGowxAf3GTgCPSEJjOdt7A_zA/s1600/Distance_Squared.png" /></a></div>
<span style="font-family: 'Trebuchet MS', sans-serif;"><br />
</span><br />
<span style="font-family: 'Trebuchet MS', sans-serif;">This allows one to compare the distance squared with another distance squared; multiplication is much faster than a sqrt function. This should be applied to all of the above collision algorithms that require a distance function between two points.</span><br />
<span style="font-family: 'Trebuchet MS', sans-serif;"><br />
</span><br />
<span style="font-family: 'Trebuchet MS', sans-serif; font-size: large;">Jumping Physics Technique</span><br />
<span style="font-family: 'Trebuchet MS', sans-serif;">There are a few different ways to have a character jump in a game. I'm going to share a singular way that I find very efficient and effective. As detailed <a href="http://cecilsunkure.blogspot.com/2012/02/basic-2d-vector-physics.html">here</a> in my article on simple physics integration, in order to move something along the screen you are required to use the following equations:</span><br />
<br />
<div class="code">
<code>pos.x += vel.x * dt; <br />
pos.yx += vel.y * dt; <br />
vel.x += accel.x * dt;<br />
vel.y += accel.y * dt;</code></div>
<br />
<span style="font-family: 'Trebuchet MS', sans-serif;">This works just fine for moving images around! In order to simulate a jump you suddenly add a large value to the image's y velocity, and then apply a negative acceleration on it each timestep. Like I said, this works just fine. However as a designer this is a headache. How are you going to tweak the jumping height? Just apply random values to the velocity and guess/check to see how high the character goes? It would be best to be able to set how high you'd like the character to jump, and use some form of automation so solve for the necessary velocity.</span><br />
<br />
<span style="font-family: 'Trebuchet MS', sans-serif;">This equation comes from a conservation of energy. Take a look at the algebraic manipulation:</span><br />
<span style="font-family: 'Trebuchet MS', sans-serif;"><br />
</span><br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhWSJSb53dcqP9qoy6pg-_dRVxNNP7w5l2c_Fvh_FXETUG9wr29BSfIwURXsl_1HZRHQrAwH3xp2jr3b756P6Fz1AfEAJoHbYSvXQh3qoPPQwi1grL9TYdUWtlv6Ya7qiaVSjOaxozhk9I/s1600/Conservation_of_Energy_Equation.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhWSJSb53dcqP9qoy6pg-_dRVxNNP7w5l2c_Fvh_FXETUG9wr29BSfIwURXsl_1HZRHQrAwH3xp2jr3b756P6Fz1AfEAJoHbYSvXQh3qoPPQwi1grL9TYdUWtlv6Ya7qiaVSjOaxozhk9I/s1600/Conservation_of_Energy_Equation.png" /></a></div>
<br />
<span style="font-family: 'Trebuchet MS', sans-serif;">The equation you start with represents an upward jump. The two sides are equal due to energy being conserved throughout the jump. At the start of a jump (and the end, assuming the start and end positions are the same y value) all of the energy is kinetic, thrusting the object upward. As it slows down energy is converted into potential energy, which is the distance from the ground the object is currently at. Once all kinetic energy is used potential energy is maxed out, which means this is the peak of the jump. We can take advantage of the fact that the kinetic energy is zeroed out and come up with a simple equation to solve for the necessary upward velocity to reach a specific height. Here's what the final equation can look like in use within code to initialize the y velocity for a jump:</span><br />
<br />
<div class="code">
<code>// JUMP_HEIGHT will usually be in tiles.<br />
// Example: perhaps to jump exactly 3 tiles, or 4<br />
vel.y = sqrt( 2.f * -GRAVITY * JUMP_HEIGHT );</code></div>
<br />
<span style="font-family: 'Trebuchet MS', sans-serif;">This technique not only can be used on jumping characters but projectiles as well. I find this equation exceptionally useful in initializing various values! An optimization to this function would be to pre-compute the velocity by hand and assign it to y velocities of objects from a constant. This method would work well in any situation where the velocity of the jumping height is not changing throughout the duration of the game (perhaps turrets shooting bullets in the same path over and over, or an enemy with only one type of jump).</span>CecilSunkurehttp://www.blogger.com/profile/16129986119923492789noreply@blogger.com0tag:blogger.com,1999:blog-3579312376304629754.post-21177643412284955912012-07-03T12:55:00.000-07:002012-09-04T15:49:36.205-07:00Windows Console Game: AsciiEngine<span style="font-family: 'Trebuchet MS', sans-serif;">I've been creating a <a href="http://cecilsunkure.blogspot.com/2011/11/windows-console-game-setting-up-window.html">series of posts</a> about creating a Window's console game from scratch in C. This post will act as a culmination of many different posts throughout my blog in the form of an open source game engine called AsciiEngine.</span><br />
<br />
<span style="font-family: 'Trebuchet MS', sans-serif;">AsciiEngine is a game engine for Windows XP, Vista, and Win7 that allows the user to easily create and display images within a Windows console. The engine also automates the tedious task of customizing aspects of the console, such as a font or palette color.</span><br />
<span style="font-family: 'Trebuchet MS', sans-serif;"><br /></span>
<span style="font-family: 'Trebuchet MS', sans-serif; font-size: large;">Here's the link for AsciiEngine (visual studio 2010 project + source files): </span><a href="https://github.com/RandyGaul/AsciiEngine" style="font-family: 'Trebuchet MS', sans-serif; font-size: x-large;">LINK</a>
<br />
<span style="font-family: 'Trebuchet MS', sans-serif;"><br /></span>
<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj-rWv8YVn_EVi-plbxftejUdH8ia0y2yc68zB-4pq9d24U57TNlXhbqx4I4bJ4VxFFnVW9oM5AFDMcCIZkKd5me5i9coAMPjOzOL45twu8hLUariYZcoYutLPpVLYa3rxwHI2qxJXFSEw/s1600/1.png" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj-rWv8YVn_EVi-plbxftejUdH8ia0y2yc68zB-4pq9d24U57TNlXhbqx4I4bJ4VxFFnVW9oM5AFDMcCIZkKd5me5i9coAMPjOzOL45twu8hLUariYZcoYutLPpVLYa3rxwHI2qxJXFSEw/s1600/1.png" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Man with sword!</td></tr>
</tbody></table>
<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh_DWyFvmzMgu1_f4tJtlRpI9RX-VSHQSbmLgGqMiY_cG82oLJ_Tfv_lT3WMbbOpo8_YYq6wvFLkta74IyewXfhogXpsK_JVGomSTMq9c5RbCJ5higk7jTrx_08ngQ0YxZ1TPwErt46hlo/s1600/2.png" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh_DWyFvmzMgu1_f4tJtlRpI9RX-VSHQSbmLgGqMiY_cG82oLJ_Tfv_lT3WMbbOpo8_YYq6wvFLkta74IyewXfhogXpsK_JVGomSTMq9c5RbCJ5higk7jTrx_08ngQ0YxZ1TPwErt46hlo/s1600/2.png" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Screenshot from older included demo~~</td></tr>
</tbody></table>
<br />
<span style="font-family: 'Trebuchet MS', sans-serif;">By using AsciiEngine, users can easily construct interactive programs (games!) without the overhead of setting up all of the various system components required to run a game within the Windows console.</span><br />
<span style="font-family: 'Trebuchet MS', sans-serif;"><br />
</span><br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjdJW7YzRL0UiiS12cmGxuWa8TW9cEGMWAYADylPypwwKYerjEo4rp_wV2ZDw4C3Cijbu7MlDD5TqlygvTN5x4IemjPww3CQpLSaPaUfG6e9j3G0DVOq9KfpMyKuZ3Hx3lUZxj_4WudHPE/s1600/AsciiEngine_Demo.PNG" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" height="208" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjdJW7YzRL0UiiS12cmGxuWa8TW9cEGMWAYADylPypwwKYerjEo4rp_wV2ZDw4C3Cijbu7MlDD5TqlygvTN5x4IemjPww3CQpLSaPaUfG6e9j3G0DVOq9KfpMyKuZ3Hx3lUZxj_4WudHPE/s400/AsciiEngine_Demo.PNG" width="400" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Screenshot of the old AsciiEngine demo. Pressing enter pastes<br />
sun images onto random locations.</td></tr>
</tbody></table>
<br />
<span style="font-family: 'Trebuchet MS', sans-serif;">AsciiEngine is documented heavily in-code and is open source - I want anyone willing to be able to learn from the example code provided.</span><br />
<br />
<span style="font-family: 'Trebuchet MS', sans-serif;">Features include:</span><br />
<ul>
<li><span style="font-family: 'Trebuchet MS', sans-serif;">Complete game loop</span></li>
<ul>
<li><span style="font-family: 'Trebuchet MS', sans-serif;">Game loop integrated into Game State Manager via function pointers</span></li>
</ul>
<li><span style="font-family: 'Trebuchet MS', sans-serif;">Game State Manager</span></li>
<ul>
<li><span style="font-family: 'Trebuchet MS', sans-serif;">Allows for easy management/creation/deletion of game states</span></li>
</ul>
<li><span style="font-family: 'Trebuchet MS', sans-serif;">Functioning framerate controller</span></li>
<ul>
<li><span style="font-family: 'Trebuchet MS', sans-serif;">Allows the setting of framerate with a #define macro</span></li>
<li><span style="font-family: 'Trebuchet MS', sans-serif;">Prevents large timesteps from passing through the program with a cap</span></li>
</ul>
<li><span style="font-family: 'Trebuchet MS', sans-serif;">Various console related functions for easy customization of the console window</span></li>
<li><span style="font-family: 'Trebuchet MS', sans-serif;">Complete graphics functions set for drawing 2D images</span></li>
<li><span style="font-family: 'Trebuchet MS', sans-serif;">Input template complete for simple keystroke detection and mouse event handling</span></li>
<ul>
<li><span style="font-family: 'Trebuchet MS', sans-serif;">Easily customizeable to include <a href="http://cecilsunkure.blogspot.com/2011/11/windows-console-game-event-handling.html">more functionality</a></span></li>
</ul>
<li><span style="font-family: 'Trebuchet MS', sans-serif;">Complete and very simple PRNG</span></li>
<li><span style="font-family: 'Trebuchet MS', sans-serif;">Simple image format that allows for variable size</span></li>
<li><span style="font-family: 'Trebuchet MS', sans-serif;">Integrated hash table for storing images</span></li>
<ul>
<li><span style="font-family: 'Trebuchet MS', sans-serif;">Allows for an optimized lookup, e.g.: TableLookup( "ImageName" )</span></li>
<li><span style="font-family: 'Trebuchet MS', sans-serif;">Extremely simple creation/deletion of images</span></li>
</ul>
<li><span style="font-family: 'Trebuchet MS', sans-serif;">Implementation of my <a href="http://cecilsunkure.blogspot.com/2012/07/collision-basic-2d-collision-detection.html">simple 2D collision library</a></span></li>
<li><span style="font-family: 'Trebuchet MS', sans-serif;">Implementation of my <a href="http://cecilsunkure.blogspot.com/2012/02/basic-2d-vector-physics.html">simple 2D vector library</a></span></li>
<li><span style="font-family: 'Trebuchet MS', sans-serif;">Highly organised object manager using the factory pattern</span></li>
<ul>
<li><span style="font-family: 'Trebuchet MS', sans-serif;">Allows for easy creation/handling/deletion of game objects</span></li>
<li><span style="font-family: 'Trebuchet MS', sans-serif;">Incredibly simple to create new object types</span></li>
</ul>
<ul>
</ul>
<li><span style="font-family: 'Trebuchet MS', sans-serif;">Implemented my <a href="http://cecilsunkure.blogspot.com/2012/04/binary-collision-maps-platformer.html">Tile mapping -- Binary Collision</a></span> <span style="font-family: 'Trebuchet MS', sans-serif;">library</span></li>
<ul>
</ul>
<li><a href="http://cecilsunkure.blogspot.com/2011/11/windows-console-game-event-handling.html" style="font-family: 'Trebuchet MS', sans-serif;">Image editor</a></li>
<li><span style="font-family: 'Trebuchet MS', sans-serif;">file output</span></li>
<li><span style="font-family: Trebuchet MS, sans-serif;">Automatic image file loading and parsing</span></li>
<li><span style="font-family: 'Trebuchet MS', sans-serif;">Messaging system Object to object + global messaging system</span></li>
<li><span style="font-family: Trebuchet MS, sans-serif;">Component base game object system (now renamed to game entity)</span></li>
<li><span style="font-family: Trebuchet MS, sans-serif;">New <a href="http://cecilsunkure.blogspot.com/2012/08/easy-buttons-for-your-game.html">button class</a> for easy UI creation</span></li>
<li><span style="font-family: Trebuchet MS, sans-serif;">Integration of generic Hash Table and Linked Lists</span></li>
<li><span style="font-family: Trebuchet MS, sans-serif;">Simple serialization and deserialization support.</span></li>
</ul>
<br />
<span style="font-family: 'Trebuchet MS', sans-serif;"><span style="font-size: large;">Here's the link for AsciiEngine (visual studio 2010 project + source files): <a href="https://github.com/RandyGaul/AsciiEngine">LINK</a></span></span><br />
<br />
<span style="font-family: 'Trebuchet MS', sans-serif;">Now hopefully I can see some console games created with true Ascii art! Please let me know if anyone creates a console game, or uses AsciiEngine to create a console game. I would be thrilled to see some projects from other people, as I just love Ascii art games, especially ones within the Windows console.</span><br />
<br />
<span style="font-family: 'Trebuchet MS', sans-serif;">Series on creating a Windows Console game:</span><br />
<ul>
<li><a href="http://cecilsunkure.blogspot.com/2011/11/windows-console-game-setting-up-window.html"><span style="font-family: 'Trebuchet MS', sans-serif;">Setting up the Window</span></a></li>
<li><a href="http://cecilsunkure.blogspot.com/2011/11/windows-console-game-writing-to-console.html"><span style="font-family: 'Trebuchet MS', sans-serif;">Writing to the Console</span></a></li>
<li><a href="http://cecilsunkure.blogspot.com/2011/11/windows-console-game-event-handling.html"><span style="font-family: 'Trebuchet MS', sans-serif;">Event Handling</span></a></li>
<li><a href="http://cecilsunkure.blogspot.com/2011/12/windows-console-game-set-custom-color.html"><span style="font-family: 'Trebuchet MS', sans-serif;">Custom Color Palette and Font Size</span></a></li>
<li><a href="http://cecilsunkure.blogspot.com/2011/12/windows-console-game-painters-algorithm.html"><span style="font-family: 'Trebuchet MS', sans-serif;">Painter's Algorithm</span></a></li>
<li><span style="font-family: 'Trebuchet MS', sans-serif;"><a href="http://cecilsunkure.blogspot.com/2012/02/windows-console-game-variable-sized.html">Variable Sized Object</a></span></li>
<li><span style="font-family: 'Trebuchet MS', sans-serif;"><a href="http://cecilsunkure.blogspot.com/2012/07/windows-console-game-ascii-engine.html">Ascii Engine</a></span></li>
</ul>
<div>
<span style="font-family: 'Trebuchet MS', sans-serif; font-size: large;">How to use AsciiEngine:</span></div>
<div>
<span style="font-family: 'Trebuchet MS', sans-serif;">Using AsciiEngine is very easy. It's available <a href="https://github.com/RandyGaul/AsciiEngine">here</a> on github.</span></div>
<div>
<span style="font-family: 'Trebuchet MS', sans-serif;"><br />
</span></div>
<div>
<span style="font-family: 'Trebuchet MS', sans-serif;">Almost all code creation you'll do with AsciiEngine will be in creating/modifying game state files. Since AsciiEngine uses a GameStateManager (GSM) you'll have to create your own states. More information about what a GSM can be found <a href="http://cecilsunkure.blogspot.com/2012/02/game-program-design-game-state-manager.html">here</a>. Creating a state is as easy as copy/paste from the example state within the download archive of AsciiEngine. Integrating a new state into the GSM should be straightforward if you examine the currently existing code.</span></div>
<div>
<span style="font-family: 'Trebuchet MS', sans-serif;"><br />
</span></div>
<div>
<span style="font-family: 'Trebuchet MS', sans-serif;">Once a state is created all that is left to do for the user is to simply write code within the state! Almost all code written will be within the Update function. During the Update function all game logic will occur. Drawing specific functions should occur only with the stat's Draw function - this allows for easy implementation of the <a href="http://cecilsunkure.blogspot.com/2011/12/windows-console-game-painters-algorithm.html">Painter's Algorithm</a>.</span><br />
<span style="font-family: 'Trebuchet MS', sans-serif;"><br />
</span><br />
<span style="font-family: 'Trebuchet MS', sans-serif;">To switch states there are three global variables within the GameStateManager.c file. These are nextState, currentState and previousState. In order to switch states simply change nextState to the desired state to switch to. The main loop will then call the Unload and Free function automatically of the current state you are in, and then load and initialize the next state automatically as well.</span></div>
<div>
<span style="font-family: 'Trebuchet MS', sans-serif;"><br />
</span></div>
<div>
<span style="font-family: 'Trebuchet MS', sans-serif;">Creation of Game Objects can be handled any way by the user, I've written documentation on a very simple way of creating and handling <a href="http://cecilsunkure.blogspot.com/2012/04/object-oriented-c-class-like-structures.html">Game Objects</a> here, and it works extremely well with the GSM organization throughout AsciiEngine. I've implemented my own method of handling objects with the Factory pattern! Using the ObjectFactory within AsciiEngine it's very easy to handle game objects, as well as create new ones. See code for documentation -- it should mostly be copy/paste to create a new object. UPDATE: Game objects are now called Game Entities. As such, all game entities are now component based! Please see the source on github for details. A post in the future about component-based architecture will likely be written.</span><br />
<span style="font-family: 'Trebuchet MS', sans-serif;"><br />
</span><br />
<span style="font-family: 'Trebuchet MS', sans-serif; font-size: large;">Creating Images:</span><br />
<span style="font-family: 'Trebuchet MS', sans-serif;">Creating images in Ascii art will require a good tool for more complicated images. <a href="http://forums.tigsource.com/index.php?topic=14588.0">Here</a>'s an interesting thread on a few different programs for such. Perhaps it might be a good idea to create your own tool in the Windows console with AsciiEngine! Here's some additional documentation to pursue the idea of creating your own drawing tool: <a href="http://cecilsunkure.blogspot.com/2011/11/windows-console-game-event-handling.html">link</a>.</span><br />
<div class="separator" style="clear: both; text-align: center;">
<a href="http://i.imgur.com/366q2.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="271" src="http://i.imgur.com/366q2.png" width="320" /></a><a href="http://i117.photobucket.com/albums/o67/MCBooga/ascii_city.png" imageanchor="1" style="background-color: white; margin-left: 1em; margin-right: 1em;"><img border="0" height="240" src="http://i117.photobucket.com/albums/o67/MCBooga/ascii_city.png" width="320" /></a></div>
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
<div class="separator" style="clear: both; text-align: left;">
<span style="font-family: 'Trebuchet MS', sans-serif; font-size: large;">Updating AsciiEngine</span></div>
<div class="separator" style="clear: both; text-align: left;">
<span style="font-family: 'Trebuchet MS', sans-serif;">I'm completely open to most all suggestions on AsciiEngine. I've never written anything open-source before, so there may be good insight that'd help the project out! Feel free to contact me about questions on how to use AsciiEngine, or for feature requests, or just to talk/show off thing you've made :)</span></div>
</div>
CecilSunkurehttp://www.blogger.com/profile/16129986119923492789noreply@blogger.com2tag:blogger.com,1999:blog-3579312376304629754.post-44692024599949558672012-07-01T00:13:00.000-07:002012-07-02T14:18:18.179-07:00Hash Tables: Introduction<span style="font-family: 'Trebuchet MS', sans-serif;">I've just set up my first hash table after a bit of studying; it's time to write about it! <a href="https://www.google.com/webhp?sourceid=chrome-instant&ie=UTF-8#hl=en&gs_nf=1&tok=Ts3hiJ0-y7jVw7g-I-aCKA&pq=broad%20phasing&cp=6&gs_id=s&xhr=t&q=docendo+discimus&pf=p&safe=off&sclient=psy-ab&oq=docend&gs_l=&pbx=1&bav=on.2,or.r_gc.r_pw.r_qf.,cf.osb&fp=a2e370afc0354df8&biw=1360&bih=667">Docendo discimus</a> ~</span><br />
<br />
<span style="font-family: 'Trebuchet MS', sans-serif;">Wikipedia has a nice definition of what a hash table is: <a href="http://en.wikipedia.org/wiki/Hash_table">LINK</a>.</span><br />
<blockquote class="tr_bq">
<span style="font-family: sans-serif; font-size: 13px; line-height: 20px;">In </span><a href="http://en.wikipedia.org/wiki/Computer_science" style="background-image: none; color: #0b0080; font-family: sans-serif; font-size: 13px; line-height: 20px; text-decoration: none;" title="Computer science">computer science</a><span style="font-family: sans-serif; font-size: 13px; line-height: 20px;">, a </span><b style="font-family: sans-serif; font-size: 13px; line-height: 20px;">hash table</b><span style="font-family: sans-serif; font-size: 13px; line-height: 20px;"> or </span><b style="font-family: sans-serif; font-size: 13px; line-height: 20px;">hash map</b><span style="font-family: sans-serif; font-size: 13px; line-height: 20px;"> is a </span><a href="http://en.wikipedia.org/wiki/Data_structure" style="background-image: none; color: #0b0080; font-family: sans-serif; font-size: 13px; line-height: 20px; text-decoration: none;" title="Data structure">data structure</a><span style="font-family: sans-serif; font-size: 13px; line-height: 20px;"> that uses a </span><a href="http://en.wikipedia.org/wiki/Hash_function" style="background-image: none; color: #0b0080; font-family: sans-serif; font-size: 13px; line-height: 20px; text-decoration: none;" title="Hash function">hash function</a><span style="font-family: sans-serif; font-size: 13px; line-height: 20px;"> to map identifying values, known as </span><a href="http://en.wikipedia.org/wiki/Unique_key" style="background-image: none; color: #0b0080; font-family: sans-serif; font-size: 13px; line-height: 20px; text-decoration: none;" title="Unique key">keys</a><span style="font-family: sans-serif; font-size: 13px; line-height: 20px;"> (e.g., a person's name), to their associated </span><a href="http://en.wikipedia.org/wiki/Value_(mathematics)" style="background-image: none; color: #0b0080; font-family: sans-serif; font-size: 13px; line-height: 20px; text-decoration: none;" title="Value (mathematics)">values</a><span style="font-family: sans-serif; font-size: 13px; line-height: 20px;"> (e.g., their telephone number). Thus, a hash table implements an </span><a href="http://en.wikipedia.org/wiki/Associative_array" style="background-image: none; color: #0b0080; font-family: sans-serif; font-size: 13px; line-height: 20px; text-decoration: none;" title="Associative array">associative array</a><span style="font-family: sans-serif; font-size: 13px; line-height: 20px;">. The hash function is used to transform the key into the index (the </span><i style="font-family: sans-serif; font-size: 13px; line-height: 20px;">hash</i><span style="font-family: sans-serif; font-size: 13px; line-height: 20px;">) of an </span><a href="http://en.wikipedia.org/wiki/Array_data_type" style="background-image: none; color: #0b0080; font-family: sans-serif; font-size: 13px; line-height: 20px; text-decoration: none;" title="Array data type">array</a><span style="font-family: sans-serif; font-size: 13px; line-height: 20px;"> element (the </span><i style="font-family: sans-serif; font-size: 13px; line-height: 20px;">slot</i><span style="font-family: sans-serif; font-size: 13px; line-height: 20px;"> or </span><i style="font-family: sans-serif; font-size: 13px; line-height: 20px;">bucket</i><span style="font-family: sans-serif; font-size: 13px; line-height: 20px;">) where the corresponding value is to be sought.</span></blockquote>
<br />
<span style="font-family: 'Trebuchet MS', sans-serif;">The idea of setting up a hash table is that by using a hash function you can index an array without actually knowing what the index is.</span><br />
<span style="font-family: 'Trebuchet MS', sans-serif;"><br />
</span><br />
<span style="font-family: 'Trebuchet MS', sans-serif;">For example say you have an array of structures that look like this:</span><br />
<br />
<div class="code">
<code>typedef struct _ASSETFILE<br />
{</code><br />
<code> char *fileName_;</code><br />
<code> assetFile *asset_;</code><br />
<code> } ASSETFILE;</code></div>
<br />
<span style="font-family: 'Trebuchet MS', sans-serif;">This array holds structures that represent asset files for some sort of project (images, sounds, data, etc). Imagine you want anyone to be able to access any asset file in this array by using a function like so: </span><span style="color: #444444; font-family: 'Courier New', Courier, monospace;">FindAsset( "filename" );</span><span style="font-family: 'Trebuchet MS', sans-serif;">. How would you go about creating this FindAsset function? The easiest way would be to use a linear search starting at the beginning of the array. Simply compare the string of the parameter passed to the FindAsset function with the string within the ASSETFILE structure until a match is found.</span><br />
<span style="font-family: 'Trebuchet MS', sans-serif;"><br />
</span><br />
<span style="font-family: 'Trebuchet MS', sans-serif;">This can be a slow search. Perhaps the next optimization would be to order the entire list alphabetically from lowest to highest. This would allow a binary search through the array by using strcmp from the standard library. There wouldn't be any faster search method than a binary search in this scenario. Inserting into an ordered list would require a binary search as well.</span><br />
<span style="font-family: 'Trebuchet MS', sans-serif;"><br />
</span><br />
<span style="font-family: 'Trebuchet MS', sans-serif;">However by using a hash function you can achieve even faster searches. By using a hash function you can convert the filename provided to the FindAsset function directly into an index to index the array of ASSETFILE structs. The filename is what is called a key. By hashing a key an index to the hash table is generated, and the corresponding ASSETFILE struct can be accessed very quickly. It's important to note that the order in which the entries are stored into slots is random. A good hash function will randomly map keys to indices with an even distribution (avoids clustering).</span><br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi5HLlT1gkX-J7PwGvzGYeFUyGLa4eFlquye2DFg0iN_58JqkAYbVQ58qJp6tUaRA4dFeUR3bTtcA0JLXAPJRuscEUI1G4k5VRreWDNcHxddL5wXOPKK2VpU-bX5HgRhSkMF_9s7vJXr6E/s1600/2.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="245" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi5HLlT1gkX-J7PwGvzGYeFUyGLa4eFlquye2DFg0iN_58JqkAYbVQ58qJp6tUaRA4dFeUR3bTtcA0JLXAPJRuscEUI1G4k5VRreWDNcHxddL5wXOPKK2VpU-bX5HgRhSkMF_9s7vJXr6E/s320/2.png" width="320" /></a><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjtM3S7xjdsL1MQPrXaK6ZIJkowL0MnEPXKh_RDcpItB6q-vRtBr7yTNcmuS0AR2PbExfXxze502_Nn_VLdoneDalvxEOt1nz4w9lA3dK-uceHs5oDR4TS5ryfvKyXTMHvy23KfmPC5E-Y/s1600/1.png" imageanchor="1" style="background-color: white; margin-left: 1em; margin-right: 1em;"><img border="0" height="247" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjtM3S7xjdsL1MQPrXaK6ZIJkowL0MnEPXKh_RDcpItB6q-vRtBr7yTNcmuS0AR2PbExfXxze502_Nn_VLdoneDalvxEOt1nz4w9lA3dK-uceHs5oDR4TS5ryfvKyXTMHvy23KfmPC5E-Y/s320/1.png" width="320" /></a></div>
<span style="font-family: 'Trebuchet MS', sans-serif;">The relationship between keys and indices is not a one to one ratio however. Keys to indices is of a one-to-many ratio -that is multiple keys can resolve to the same address. Each key must be unique, however, in order for the hash table to function properly.</span>
<br />
<span style="font-family: 'Trebuchet MS', sans-serif;"><br /></span><br />
<span style="font-family: 'Trebuchet MS', sans-serif;">In short, using a hash table allows for indexing of an array by some other type of data than simply an integer. </span><span style="font-family: 'Trebuchet MS', sans-serif;">There are many different hash functions available on the internet, and a simple google search will yield many results.</span><br />
<span style="font-family: 'Trebuchet MS', sans-serif;"><br />
</span><br />
<span style="font-family: 'Trebuchet MS', sans-serif;">I've set up a demonstration program to show the usage of a hash function <a href="http://www.mediafire.com/download.php?mp2ej7evh8mbb23">here</a>. I handle collisions with something called linear probing. A collision is whenever a key maps to a location in the table that already contains an entry (two or more keys are resolving to the same slot). A collision can be resolved in many different ways, though the way I chose in my sample program was linear probing. Linear probing is simply moving down one slot in the table until a free slot is found. The entry to insert is then placed. Each time the index is incremented (or decremented, direction doesn't matter as long as your are consistent) to find an empty slot it is called a probe. This means that for each lookup you'll need to compare the key to the entry being looked at and check for a match, as when you get a hashed index it doesn't necessarily mean that the key you have had been placed into that entry; a previous key may have inserted a value there already. When attempting a lookup first check the slot the hash resolves to. If no match is found, check the next slot (using the same direction as before) until you find a key match, or an empty slot. If you find an empty slot then that means your lookup concluded that no entry matches in your table.</span><br />
<span style="font-family: 'Trebuchet MS', sans-serif;"><br />
</span><br />
<span style="font-family: 'Trebuchet MS', sans-serif;">Linear probing forms clusters of entries, however, since you resolve collision by placing entries into the next available slot. Each entry placed into the table increases the chances of a collision, and as the table fills up a lot of time ends up being spent on probing looking for an empty slot. There are ways of breaking up these clusters like double hashing, or by having each slot point to a linked list of entries. However with a good hash function clusters can be kept to a minimum as long as the table doesn't get too full.</span><br />
<span style="font-family: 'Trebuchet MS', sans-serif;"><br /></span><br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi-3j-X2IE_WDyb8nqhH8w5PM_lUiJvOx2oOxUPsoF_hjOlz2NyOZtlVFyOpYaEg41hCp7pBR8MzzwyhnnOO9r7cXexGjXCYQPYxF5LeT6GCMh2WyAp1FJWDpIBP3HLItdGHCT1nrC_TJ8/s1600/LinearProbeCollisionClusters.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="219" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi-3j-X2IE_WDyb8nqhH8w5PM_lUiJvOx2oOxUPsoF_hjOlz2NyOZtlVFyOpYaEg41hCp7pBR8MzzwyhnnOO9r7cXexGjXCYQPYxF5LeT6GCMh2WyAp1FJWDpIBP3HLItdGHCT1nrC_TJ8/s640/LinearProbeCollisionClusters.png" width="640" /></a></div>
<br />
<span style="font-family: 'Trebuchet MS', sans-serif;">Load factor is a term that represents the total number of current entries divided by the table size. Once a hash table has a load factor of .7 or so linear probing starts getting dramatically slow.</span><br />
<span style="font-family: 'Trebuchet MS', sans-serif;"><br />
</span><br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="http://upload.wikimedia.org/wikipedia/commons/thumb/1/1c/Hash_table_average_insertion_time.png/362px-Hash_table_average_insertion_time.png" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" src="http://upload.wikimedia.org/wikipedia/commons/thumb/1/1c/Hash_table_average_insertion_time.png/362px-Hash_table_average_insertion_time.png" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Image from Wikipedia. As you can see once the load factor of the table hits around .8 the time spent probing increases dramatically.</td></tr>
</tbody></table>
<span style="font-family: 'Trebuchet MS', sans-serif;"><br />
</span><br />
<span style="font-family: 'Trebuchet MS', sans-serif;">In order to retrieve an entry from the hash table (with linear probing, as in my sample program) all you'd have to do is take your key and pass it to your hash function. Once this is done you'll have the index to start your search. Check to see if the key matches the key within the index. If it does not match then increment (or decrement, whatever direction you probe in you must do here for consistency) the index by one and compare again. Once a match is found the lookup function has done its job! If no match is found and the search function runs into an empty slot, that means that no match had been found. Here's the lookup function from the sample program:</span><br />
<br />
<div class="code">
<span style="font-family: monospace;">char *TableLookup( const char *Key, char *table[] )</span><br />
<span style="font-family: monospace;">{</span><br />
<span style="font-family: monospace;"> unsigned index = UHashMod( Key, TABLESIZE );</span><br />
<span style="font-family: monospace;"> unsigned indexStart = index;</span><br />
<br />
<span style="font-family: monospace;"> // Only search through clusters, don't hop over empty entries</span><br />
<span style="font-family: monospace;"> while(!IsEmpty( table, index ))</span><br />
<span style="font-family: monospace;"> {</span><br />
<span style="font-family: monospace;"> // Break from loop if found matching entry</span><br />
<span style="font-family: monospace;"> if(table[index] != DELETED)</span><br />
<span style="font-family: monospace;"> {</span><br />
<span style="font-family: monospace;"> if(strcmp(table[index], Key) == 0)</span><br />
<span style="font-family: monospace;"> break;</span><br />
<span style="font-family: monospace;"> }</span><br />
<br />
<span style="font-family: monospace;"> ++index;</span><br />
<br />
<span style="font-family: monospace;"> // wraparound to beginning of table</span><br />
<span style="font-family: monospace;"> if(index == TABLESIZE)</span><br />
<span style="font-family: monospace;"> {</span><br />
<span style="font-family: monospace;"> index = 0;</span><br />
<span style="font-family: monospace;"> }</span><br />
<br />
<span style="font-family: monospace;"> // If searched entire table</span><br />
<span style="font-family: monospace;"> if(indexStart == index)</span><br />
<span style="font-family: monospace;"> {</span><br />
<span style="font-family: monospace;"> return NULL;</span><br />
<span style="font-family: monospace;"> }</span><br />
<span style="font-family: monospace;"> }</span><br />
<br />
<span style="font-family: monospace;"> return table[index];</span><br />
<span style="font-family: monospace;">}</span></div>
<br />
<span style="font-family: 'Trebuchet MS', sans-serif;">In the above example the data stored in the table was the same as the key, so the return type is a pointer to the stored data in this instance. In order to support the deletion of entries you must mark a slot as deleted. This is because if a slot is simply marked as empty, then it can mess up the order of searches! Searching relies on the fact that collisions are resolved with linear probing. If you delete an entry that had previous collisions, the entries next to it will not be found in searches. However if you mark slots as "deleted" with a special value, than you can modify searching to not stop on "deleted" slots, and you can modify insertion to insert values into slots that are marked "deleted". You can see in the above code that searches hop over deleted slots, but stop at empty ones.</span><br />
<span style="font-family: 'Trebuchet MS', sans-serif;"><br />
</span><br />
<span style="font-family: 'Trebuchet MS', sans-serif;">Now lets talk about this hash function. Creating hash functions seems very difficult, but luckily for around 50 or so years research has been put into them, and as such there lots of well documented hash functions and hash libraries all over the place. Here's the one I chose to use in my demonstration program:</span><br />
<br />
<div class="code">
<span style="font-family: monospace;">// Hashing function from Program 14.2 in the Sedgewick book</span><br />
<span style="font-family: monospace;">unsigned UHashMod( const char *Key, unsigned TableSize )</span><br />
<span style="font-family: monospace;">{</span><br />
<span style="font-family: monospace;"> unsigned hash = 0; // Initial value of hash</span><br />
<span style="font-family: monospace;"> unsigned rand1 = 31415; // "Random" 1</span><br />
<span style="font-family: monospace;"> unsigned rand2 = 27183; // "Random" 2</span><br />
<br />
<span style="font-family: monospace;"> while (*Key)</span><br />
<span style="font-family: monospace;"> {</span><br />
<span style="font-family: monospace;"> hash = hash * rand1; // Multiply hash by random</span><br />
<span style="font-family: monospace;"> hash = (hash + *Key); // Add in current char, keep within TableSize</span><br />
<span style="font-family: monospace;"> rand1 = (rand1 * rand2); // Update rand1 for next "random" number</span><br />
<span style="font-family: monospace;"> Key++;</span><br />
<span style="font-family: monospace;"> }</span><br />
<br />
<span style="font-family: monospace;"> return hash % TableSize;</span><br />
<span style="font-family: monospace;">}</span></div>
<br />
<span style="font-family: 'Trebuchet MS', sans-serif;">The hash function is simply converting the string into a random (yet consistent) interpretation as an integer. This integer is then modulo'd with the TableSize variable, which is the size of the table to be inserted into to ensure that it is placed randomly within the bounds of the table.</span><br />
<span style="font-family: 'Trebuchet MS', sans-serif;"><br />
</span><br />
<span style="font-family: 'Trebuchet MS', sans-serif;">Here's the output of the sample hash table program I wrote. It creates a table with 157 slots (more on why I chose 157 later -hint: it's prime), and then reads a text file line by line and inserts each individual line into the table with a hash function. I then run a demonstration with a hash lookup function. I created support for deletion of entries, and the program gracefully handles the entire table being full (this is easily detected when a search goes through the array and ends up where it started by wrapping from the last element to the first):</span><br />
<br />
<div class="code">
<span style="font-family: monospace;">Dump table contents (length 157 char pointers):</span><br />
<span style="font-family: monospace;"> * NULL</span><br />
<span style="font-family: monospace;"> * NULL</span><br />
<span style="font-family: monospace;"> * NULL</span><br />
<span style="font-family: monospace;"> Lexicon</span><br />
<span style="font-family: monospace;"> Tiger Express</span><br />
<span style="font-family: monospace;"> Tiny Tim</span><br />
<span style="font-family: monospace;"> Beer cans</span><br />
<span style="font-family: monospace;"> Bottle</span><br />
<span style="font-family: monospace;"> I LEIK TOITLES</span><br />
<span style="font-family: monospace;"> * NULL</span><br />
<span style="font-family: monospace;"> * NULL</span><br />
<span style="font-family: monospace;"> * NULL</span><br />
<span style="font-family: monospace;"> * NULL</span><br />
<span style="font-family: monospace;"> * NULL</span><br />
<span style="font-family: monospace;"> * NULL</span><br />
<span style="font-family: monospace;"> * NULL</span><br />
<span style="font-family: monospace;"> * NULL</span><br />
<span style="font-family: monospace;"> * NULL</span><br />
<span style="font-family: monospace;"> * NULL</span><br />
<span style="font-family: monospace;"> * NULL</span><br />
<span style="font-family: monospace;"> * NULL</span><br />
<span style="font-family: monospace;"> * NULL</span><br />
<span style="font-family: monospace;"> * NULL</span><br />
<span style="font-family: monospace;"> * NULL</span><br />
<span style="font-family: monospace;"> * NULL</span><br />
<span style="font-family: monospace;"> * NULL</span><br />
<span style="font-family: monospace;"> * NULL</span><br />
<span style="font-family: monospace;"> * NULL</span><br />
<span style="font-family: monospace;"> * NULL</span><br />
<span style="font-family: monospace;"> * NULL</span><br />
<span style="font-family: monospace;"> * NULL</span><br />
<span style="font-family: monospace;"> Teeter Totter</span><br />
<span style="font-family: monospace;"> * NULL</span><br />
<span style="font-family: monospace;"> * NULL</span><br />
<span style="font-family: monospace;"> test2</span><br />
<span style="font-family: monospace;"> * NULL</span><br />
<span style="font-family: monospace;"> * NULL</span><br />
<span style="font-family: monospace;"> das</span><br />
<span style="font-family: monospace;"> Snickerdoodle</span><br />
<span style="font-family: monospace;"> So many probes >.<</span><br />
<span style="font-family: monospace;"> * NULL</span><br />
<span style="font-family: monospace;"> * NULL</span><br />
<span style="font-family: monospace;"> * NULL</span><br />
<span style="font-family: monospace;"> * NULL</span><br />
<span style="font-family: monospace;"> test</span><br />
<span style="font-family: monospace;"> * NULL</span><br />
<span style="font-family: monospace;"> Baha Blast</span><br />
<span style="font-family: monospace;"> * NULL</span><br />
<span style="font-family: monospace;"> WTF</span><br />
<span style="font-family: monospace;"> * NULL</span><br />
<span style="font-family: monospace;"> SC Original</span><br />
<span style="font-family: monospace;"> * NULL</span><br />
<span style="font-family: monospace;"> * NULL</span><br />
<span style="font-family: monospace;"> * NULL</span><br />
<span style="font-family: monospace;"> * NULL</span><br />
<span style="font-family: monospace;"> Schism</span><br />
<span style="font-family: monospace;"> * NULL</span><br />
<span style="font-family: monospace;"> * NULL</span><br />
<span style="font-family: monospace;"> * NULL</span><br />
<span style="font-family: monospace;"> * NULL</span><br />
<span style="font-family: monospace;"> asd</span><br />
<span style="font-family: monospace;"> Tylanol</span><br />
<span style="font-family: monospace;"> * NULL</span><br />
<span style="font-family: monospace;"> * NULL</span><br />
<span style="font-family: monospace;"> * NULL</span><br />
<span style="font-family: monospace;"> * NULL</span><br />
<span style="font-family: monospace;"> Contraceptor</span><br />
<span style="font-family: monospace;"> * NULL</span><br />
<span style="font-family: monospace;"> ---> DELETED</span><br />
<span style="font-family: monospace;"> * NULL</span><br />
<span style="font-family: monospace;"> * NULL</span><br />
<span style="font-family: monospace;"> * NULL</span><br />
<span style="font-family: monospace;"> * NULL</span><br />
<span style="font-family: monospace;"> * NULL</span><br />
<span style="font-family: monospace;"> Dignity</span><br />
<span style="font-family: monospace;"> popo</span><br />
<span style="font-family: monospace;"> BrooD WaR</span><br />
<span style="font-family: monospace;"> * NULL</span><br />
<span style="font-family: monospace;"> * NULL</span><br />
<span style="font-family: monospace;"> * NULL</span><br />
<span style="font-family: monospace;"> * NULL</span><br />
<span style="font-family: monospace;"> * NULL</span><br />
<span style="font-family: monospace;"> Quadruple</span><br />
<span style="font-family: monospace;"> * NULL</span><br />
<span style="font-family: monospace;"> Typo</span><br />
<span style="font-family: monospace;"> * NULL</span><br />
<span style="font-family: monospace;"> * NULL</span><br />
<span style="font-family: monospace;"> alphabet</span><br />
<span style="font-family: monospace;"> StarCraft 2</span><br />
<span style="font-family: monospace;"> Rover Dover</span><br />
<span style="font-family: monospace;"> Extra power</span><br />
<span style="font-family: monospace;"> phantom</span><br />
<span style="font-family: monospace;"> * NULL</span><br />
<span style="font-family: monospace;"> * NULL</span><br />
<span style="font-family: monospace;"> * NULL</span><br />
<span style="font-family: monospace;"> Mountaineous</span><br />
<span style="font-family: monospace;"> * NULL</span><br />
<span style="font-family: monospace;"> skdjf</span><br />
<span style="font-family: monospace;"> a</span><br />
<span style="font-family: monospace;"> b</span><br />
<span style="font-family: monospace;"> * NULL</span><br />
<span style="font-family: monospace;"> Carbon</span><br />
<span style="font-family: monospace;"> This is a string!</span><br />
<span style="font-family: monospace;"> * NULL</span><br />
<span style="font-family: monospace;"> * NULL</span><br />
<span style="font-family: monospace;"> * NULL</span><br />
<span style="font-family: monospace;"> Alexis</span><br />
<span style="font-family: monospace;"> * NULL</span><br />
<span style="font-family: monospace;"> * NULL</span><br />
<span style="font-family: monospace;"> DIuasplOis</span><br />
<span style="font-family: monospace;"> Duplicate</span><br />
<span style="font-family: monospace;"> Contraption</span><br />
<span style="font-family: monospace;"> * NULL</span><br />
<span style="font-family: monospace;"> * NULL</span><br />
<span style="font-family: monospace;"> * NULL</span><br />
<span style="font-family: monospace;"> Beasty Boys</span><br />
<span style="font-family: monospace;"> * NULL</span><br />
<span style="font-family: monospace;"> * NULL</span><br />
<span style="font-family: monospace;"> * NULL</span><br />
<span style="font-family: monospace;"> * NULL</span><br />
<span style="font-family: monospace;"> * NULL</span><br />
<span style="font-family: monospace;"> * NULL</span><br />
<span style="font-family: monospace;"> * NULL</span><br />
<span style="font-family: monospace;"> Turdy Nerdy</span><br />
<span style="font-family: monospace;"> Meek</span><br />
<span style="font-family: monospace;"> * NULL</span><br />
<span style="font-family: monospace;"> Plasma</span><br />
<span style="font-family: monospace;"> * NULL</span><br />
<span style="font-family: monospace;"> asdf</span><br />
<span style="font-family: monospace;"> Turtles</span><br />
<span style="font-family: monospace;"> Flayva Flave</span><br />
<span style="font-family: monospace;"> Bumble Bee</span><br />
<span style="font-family: monospace;"> * NULL</span><br />
<span style="font-family: monospace;"> * NULL</span><br />
<span style="font-family: monospace;"> * NULL</span><br />
<span style="font-family: monospace;"> * NULL</span><br />
<span style="font-family: monospace;"> OMG</span><br />
<span style="font-family: monospace;"> * NULL</span><br />
<span style="font-family: monospace;"> * NULL</span><br />
<span style="font-family: monospace;"> * NULL</span><br />
<span style="font-family: monospace;"> tab</span><br />
<span style="font-family: monospace;"> * NULL</span><br />
<span style="font-family: monospace;"> LOL</span><br />
<span style="font-family: monospace;"> tad</span><br />
<span style="font-family: monospace;"> * NULL</span><br />
<span style="font-family: monospace;"> <3</span><br />
<span style="font-family: monospace;"> Lionheart</span><br />
<span style="font-family: monospace;"> * NULL</span><br />
<span style="font-family: monospace;"> Nonchalant</span><br />
<span style="font-family: monospace;"> Supercalifragilisticexpialladocious</span><br />
<span style="font-family: monospace;"> * NULL</span><br />
<span style="font-family: monospace;"> * NULL</span><br />
<span style="font-family: monospace;"> I lover yous</span><br />
<span style="font-family: monospace;"> * NULL</span><br />
<span style="font-family: monospace;"> * NULL</span><br />
<span style="font-family: monospace;"> Digestion</span><br />
<span style="font-family: monospace;"> Avalanche</span><br />
<br />
<span style="font-family: monospace;">Table lookup demonstration: <key index></span><br />
<span style="font-family: monospace;">Lexicon 3 | Tiger Express 3 | Tiny Tim 5 | Beer cans 3 | Bottle 5 | I LEIK TOITL</span><br />
<span style="font-family: monospace;">ES 6 | Teeter Totter 31 | test2 34 | das 37 | Snickerdoodle 38 | So many probes</span><br />
<span style="font-family: monospace;">>.< 39 | test 44 | Baha Blast 46 | WTF 48 | SC Original 50 | Schism 55 | asd 60</span><br />
<span style="font-family: monospace;">| Tylanol 60 | Contraceptor 66 | Dignity 74 | popo 75 | BrooD WaR 76 | Quadruple</span><br />
<span style="font-family: monospace;"> 82 | Typo 84 | alphabet 87 | StarCraft 2 88 | Rover Dover 88 | Extra power 90 |</span><br />
<span style="font-family: monospace;"> phantom 91 | Mountaineous 95 | skdjf 97 | a 97 | b 98 | Carbon 101 | This is a</span><br />
<span style="font-family: monospace;">string! 102 | Alexis 106 | DIuasplOis 109 | Duplicate 110 | Contraption 111 | Be</span><br />
<span style="font-family: monospace;">asty Boys 115 | Turdy Nerdy 123 | Meek 123 | Plasma 126 | asdf 128 | Turtles 128</span><br />
<span style="font-family: monospace;"> | Flayva Flave 129 | Bumble Bee 129 | OMG 136 | tab 140 | LOL 142 | tad 142 | <</span><br />
<span style="font-family: monospace;">3 145 | Lionheart 146 | Nonchalant 148 | Supercalifragilisticexpialladocious 148</span><br />
<span style="font-family: monospace;"> | I lover yous 152 | Digestion 155 | Avalanche 156 |</span><br />
<br />
<span style="font-family: monospace;">Error count: 0</span><br />
<span style="font-family: monospace;">Probe count: 19</span><br />
<span style="font-family: monospace;">Entry Count: 58</span><br />
<span style="font-family: monospace;">Table size: 157</span><br />
<span style="font-family: monospace;">Duplicate entries: 2</span><br />
<span style="font-family: monospace;">Load factor: 0.369427</span></div>
<br />
<span style="font-family: 'Trebuchet MS', sans-serif;">The text file I used is provided in the <a href="http://www.mediafire.com/download.php?mp2ej7evh8mbb23">source</a>. Note that duplicate entries were handled by taking no action. I felt that there wasn't a need to hold duplicates within a hash table, and simply just reported that duplicates were found. Here are some final notes I took from one of my CS courses:</span><br />
<ul>
<li><span style="font-family: 'Trebuchet MS', sans-serif;">Hash tables rely on the fact that the data is uniformly and randomly distributed.</span></li>
<li><span style="font-family: 'Trebuchet MS', sans-serif;">Since we cannot control the data that is provided (from the user), we must ensure that it is randomly distributed by hashing it. </span></li>
<li><span style="font-family: 'Trebuchet MS', sans-serif;">Hash tables whose size is a prime number help to insure good distribution. Also, table sizes that are a power of 2 work well if the stride (second hash in double hashing) is an odd number. </span></li>
<li><span style="font-family: 'Trebuchet MS', sans-serif;">Since the data is not sorted in any meaningful way, operations such as displaying all items in a sorted fashion are expensive. (Use another data structure for that operation.)</span></li>
</ul>
<div>
<span style="font-family: 'Trebuchet MS', sans-serif;">There are many different types of collision resolution for hash tables. Using chaining (linked lists) seems to be a great way to store lots of data. The chains can even be ordered to allow for optimized searching (though this is unlikely to be worth the trouble). However for a small amount of keys and a small table, linear probing should work perfectly fine. There are also other probing methods, such as quadratic probing, double hashing, pseudo random probing (seeding with the key). If probing is the collision method chosen, then support for growing the hash table like a vector may need to be implemented, depending on the requirements of the table. Chaining avoids the growing issue altogether.</span><br />
<span style="font-family: 'Trebuchet MS', sans-serif;"><br />
</span><br />
<span style="font-family: 'Trebuchet MS', sans-serif;">I will be using the code constructed here for my next large project. It will actually be solving the hypothetical issue described at the beginning of the post! This will be very handy, as nobody will have to manually keep track of any files anymore; I'll have code traverse a single directory full of assets and then automatically add them as entries to a hash table. Lookups will be highly optimized (which is important, lookups are highly common in a game project).</span><br />
<span style="font-family: 'Trebuchet MS', sans-serif;"><br />
</span><br />
<span style="font-family: 'Trebuchet MS', sans-serif;">Additional resources:</span><br />
<ul>
<li><span style="font-family: 'Trebuchet MS', sans-serif;"><a href="http://www.azillionmonkeys.com/qed/hash.html">http://www.azillionmonkeys.com/qed/hash.html</a> </span></li>
<li><a href="http://burtleburtle.net/bob/hash/doobs.html"><span style="font-family: 'Trebuchet MS', sans-serif;">http://burtleburtle.net/bob/hash/doobs.html</span></a> </li>
</ul>
</div>CecilSunkurehttp://www.blogger.com/profile/16129986119923492789noreply@blogger.com0tag:blogger.com,1999:blog-3579312376304629754.post-48165827933928565802012-06-26T11:00:00.001-07:002012-06-26T15:02:41.612-07:00Custom Scripting Language<span style="font-family: 'Trebuchet MS', sans-serif;">Not so long ago I helped create a game called <a href="http://cecilsunkure.blogspot.com/2012/06/ancient-forest-and-grumpy-monsters-game.html">Ancient Forest and Grumpy Monsters</a>. We wanted a very easy way of creating levels for our game, and so one of our programmers named Colton created a very useful map editor, which we actually shipped along with our final product for consumer use. However our team also wanted a way to create interactive events within the levels without writing a lot of repetitive C code. The goal was to create something that would also potentially allow consumers to use for creating their own scenarios as well. Note: For this game we used only C (a limitation on the semester project)! Another limitation of the project was that we cannot use any scripting language unless we create one ourselves. I don't remember the reasoning behind this, but I believe it was to keep the scope of projects to a minimum.</span><br />
<span style="font-family: 'Trebuchet MS', sans-serif;"><br />
</span><br />
<span style="font-family: 'Trebuchet MS', sans-serif;">We decided to create an event based scripting language for our game. The functionality of the scripting language allows the user to write scripts in plaintext and load the instructions from the text during run-time. This allowed for very rapid level development and gameplay testing! A designer can easily create a script for a level, and then load the level from the game without compiling any code at all. Sadly we didn't actually utilize the tool to its full potential during development, but it was an interesting learning experience to create the tool nonetheless.</span><br />
<span style="font-family: 'Trebuchet MS', sans-serif;"><br />
</span><br />
<span style="font-family: 'Trebuchet MS', sans-serif;">There are a few different parts of the scripting language that work together to create the functionality used in our levels: read in the script from the text file; parse the text input into usable data structures.</span><br />
<span style="font-family: 'Trebuchet MS', sans-serif;"><br />
</span><br />
<span style="font-family: 'Trebuchet MS', sans-serif;">In order to parse the text I decided to use a simple state machine. The state machine works by passing it a single token at a time. The state machine then returns some form of output depending on what token was passed to it and at what state the machine was in. This let me define trees of different action paths to follow, while having those actions stay rather modular. Here's a diagram of example functionality of such a state machine:</span><br />
<span style="font-family: 'Trebuchet MS', sans-serif;"><br />
</span><br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh5rlLNV2oNVdN4kroymT5M6zgUpXiiLI5ypfbc8Q9L_7DFYKVnLRYLavnD16TLyTQehKAaiLLDdZclFO5JbfJRjyBZ_PttPxEIlcNzluv4LRlb4LF4WImk_3Doth90pzGB55CxKsGs2yo/s1600/ScriptingStateMachine.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh5rlLNV2oNVdN4kroymT5M6zgUpXiiLI5ypfbc8Q9L_7DFYKVnLRYLavnD16TLyTQehKAaiLLDdZclFO5JbfJRjyBZ_PttPxEIlcNzluv4LRlb4LF4WImk_3Doth90pzGB55CxKsGs2yo/s1600/ScriptingStateMachine.png" /></a></div>
<span style="font-family: 'Trebuchet MS', sans-serif;"><br />
</span><br />
<span style="font-family: 'Trebuchet MS', sans-serif;">In this state machine it only responds to a few different tokens: Start; End; Red; Blue. In this example all other tokens received would result in a return of NULL and no action would be taken. The best thing about this setup is it is context sensitive. I can receive the same token at different points in the tree path (this example tree has only two branches) and take different actions.</span><br />
<span style="font-family: 'Trebuchet MS', sans-serif;"><br />
</span><br />
<span style="font-family: 'Trebuchet MS', sans-serif;">In written code the state machine was actually just one very large switch statement, with the different cases being a large enumeration. Here's some example code of what a portion of the state manager can look like:</span><br />
<br />
<div class="code">
<span style="font-family: monospace;">PARSE_STATE ParseStateManager( char *token )</span><br />
<span style="font-family: monospace;">{</span><br />
<span style="font-family: monospace;"> switch( ParseState )</span><br />
<span style="font-family: monospace;"> {</span><br />
<span style="font-family: monospace;"> case PARSE_START:</span><br />
<span style="font-family: monospace;"> if(strcmp( token, "START" ) == EQUAL_TO)</span><br />
<span style="font-family: monospace;"> {</span><br />
<span style="font-family: monospace;"> ParseState = PARSE_EVENT_LIST;</span><br />
<span style="font-family: monospace;"> }</span><br />
<span style="font-family: monospace;"> else</span><br />
<span style="font-family: monospace;"> {</span><br />
<span style="font-family: monospace;"> return PARSE_NONE;</span><br />
<span style="font-family: monospace;"> }</span><br />
<span style="font-family: monospace;"> break;</span><br />
<span style="font-family: monospace;"> case PARSE_EVENT_LIST:</span><br />
<span style="font-family: monospace;"> if(strcmp( token, "EVENT 1" ) == EQUAL_TO)</span><br />
<span style="font-family: monospace;"> {</span><br />
<span style="font-family: monospace;"> ...</span><br />
<span style="font-family: monospace;"> do stuff</span><br />
<span style="font-family: monospace;"> ...</span><br />
<span style="font-family: monospace;"> }</span><br />
<span style="font-family: monospace;"> else</span><br />
<span style="font-family: monospace;"> {</span><br />
<span style="font-family: monospace;"> return PARSE_NONE;</span><br />
<span style="font-family: monospace;"> }</span><br />
<span style="font-family: monospace;"> break;</span><br />
<code> }</code></div>
<br />
<span style="font-family: 'Trebuchet MS', sans-serif;">Reading in the data should be separated as much as possible from the state machine and the handling/creating of data structures. This way code created can possibly be reused in the future. Luckily I didn't have to write a function to retrieve a token from a text file, as <a href="https://www.google.com/search?sugexp=chrome,mod=6&sourceid=chrome&ie=UTF-8&q=strtok">strtok</a> is apart of the standard C library. I was on a very tight time-budget and the creation of my own tokenizer would have likely doubled the dev time of the entire scripting language system.</span><br />
<span style="font-family: 'Trebuchet MS', sans-serif;"><br />
</span><br />
<span style="font-family: 'Trebuchet MS', sans-serif;">During the file read I used a single call to <a href="https://www.google.com/search?sugexp=chrome,mod=6&sourceid=chrome&ie=UTF-8&q=strtok">fgets</a> to read in the entire file's contents all at once and place it into a buffer. I would then call strtok on the buffer created until the end of the buffer had been reached.</span><br />
<span style="font-family: 'Trebuchet MS', sans-serif;"><br />
</span><br />
<span style="font-family: 'Trebuchet MS', sans-serif;">Now for the most interesting part! The interface and implementation of the events within the scripting language. We used structures for all of the different objects, and with the use of void pointers and function pointers it was fairly easy to design an interesting interface. Here's a few different structure definitions used:</span><br />
<br />
<div class="code">
<span style="font-family: monospace;"></span><br />
<span style="font-family: monospace;">typedef struct _CONDITION</span><br />
<span style="font-family: monospace;">{</span><br />
<span style="font-family: monospace;"> CONDITION_ID ID;<span class="Apple-tab-span" style="white-space: pre;"> </span>// The type of condition</span><br />
<span style="font-family: monospace;"> void *param;<span class="Apple-tab-span" style="white-space: pre;"> </span>// The condition's parameters</span><br />
<span style="font-family: monospace;">} CONDITION_;</span><br />
<br />
<span style="font-family: monospace;">typedef struct _ACTION</span><br />
<span style="font-family: monospace;">{</span><br />
<span style="font-family: monospace;"> ACTION_ID ID;<span class="Apple-tab-span" style="white-space: pre;"> </span>// The type of action</span><br />
<span style="font-family: monospace;"> BOOL active; // Inactive or not</span><br />
<span style="font-family: monospace;"> void *param;<span class="Apple-tab-span" style="white-space: pre;"> </span>// The action's parameters</span><br />
<span style="font-family: monospace;">} ACTION_;</span><br />
<br />
<span style="font-family: monospace;">typedef struct _EVENT</span><br />
<span style="font-family: monospace;">{</span><br />
<span style="font-family: monospace;"><span style="white-space: pre;"> </span>VALUE numConditions;</span><br />
<span style="font-family: monospace;"><span style="white-space: pre;"> </span>CONDITION_ *conditions;</span><br />
<span style="font-family: monospace;"><span style="white-space: pre;"> </span>VALUE numActions;</span><br />
<span style="font-family: monospace;"><span style="white-space: pre;"> </span>ACTION_ *actions;</span><br />
<span style="font-family: monospace;"><span style="white-space: pre;"> </span>PRESERVE_COUNT preserveCount; // The amount of times this event will fire</span><br />
<span style="font-family: monospace;">} EVENT_;</span><br />
<br /></div>
<br />
<span style="font-family: 'Trebuchet MS', sans-serif;">As you can see we created an event object which is comprised of conditions and actions. The idea is that while the game is running it holds a list of events. This list is traversed and whenever an active event is found (preserve count was not zero) it then would check all of the conditions. If each condition were true then the actions would then be taken. After all actions are complete the preserve count of the event would be decremented by one.</span><br />
<span style="font-family: 'Trebuchet MS', sans-serif;"><br />
</span><br />
<span style="font-family: 'Trebuchet MS', sans-serif;">The definitions of conditions and actions were generalized structures with void pointers called param. This param would point to a data structure that represents some sort of condition or action. In order to tell what sort of data the void pointer is pointing to each condition and action has a data member of an ID (from an enumeration). The param pointer can by typecasted into the particular type of condition or action it is pointing to.</span><br />
<span style="font-family: 'Trebuchet MS', sans-serif;"><br />
</span><br />
<span style="font-family: 'Trebuchet MS', sans-serif;">There's one type of action we created which is called "Create unit at location". This structure looked like so:</span><br />
<br />
<div class="code">
<span style="font-family: monospace;">typedef struct _CREATE_UNIT_AT</span><br />
<span style="font-family: monospace;">{</span><br />
<span style="font-family: monospace;"> OBJECT_TYPE unit_id; // The type of unit to create</span><br />
<span style="font-family: monospace;"> LOCATION_ location1; // The tile to create at</span><br />
<span style="font-family: monospace;">} CREATE_UNIT_AT_;</span></div>
<br />
<span style="font-family: 'Trebuchet MS', sans-serif;">The only data that this structure holds is the parameters necessary to call a function. So the conditions list within an event is just a list of parameters, and each parameter is meant to go to a corresponding function. So each condition and each action type actually have a corresponding function that receives parameters held within events. In the above example, there would be an action (perhaps called CREATE_UNIT_AT) that would receive a _CREATE_UNIT_AT structure as its parameter. The same works with conditions except the return type for conditions is boolean, as it's simply testing to see if a series of checks pass or not.</span><br />
<span style="font-family: 'Trebuchet MS', sans-serif;"><br />
</span><br />
<span style="font-family: 'Trebuchet MS', sans-serif;">The state machine, talked about earlier, is what actually creates the and fills out these data structures of conditions, actions, and events depending on what tokens are passed to it from the input file.</span><br />
<span style="font-family: 'Trebuchet MS', sans-serif;"><br />
</span><br />
<span style="font-family: 'Trebuchet MS', sans-serif;">And that's that! This system reads in a text file of instructions of specific syntax as defined by the developer. This data from the file is then parsed by a tokenizer and state machine and translated into data structures. These data structures are comprised of an array of events. Each event holds an array of conditions and actions. During run-time the game traverses the array of events and checks the conditions of all active events. If all conditions of a particular event pass (return boolean true), then each action in the event's array of actions is called.</span><br />
<span style="font-family: 'Trebuchet MS', sans-serif;"><br />
</span><br />
<span style="font-family: 'Trebuchet MS', sans-serif;">Using this condition and action based scripting language we were able to create loads of different dynamic and interactive events within our levels in a very easy to use and time-efficient manner.</span><br />
<span style="font-family: 'Trebuchet MS', sans-serif;"><br />
</span><br />
<span style="font-family: 'Trebuchet MS', sans-serif;">Here's a final example of a functional scripting file:</span><br />
<br />
<div class="code">
<span style="font-family: monospace;">START NUM_EVENTS: 4</span><br />
<br />
<span style="font-family: monospace;">EVENT PRESERVE 1</span><br />
<span style="font-family: monospace;"> NUM_CONDITIONS: 1</span><br />
<span style="font-family: monospace;"> CONDITION UNIT_EXIST</span><br />
<span style="font-family: monospace;"> AT_LEAST 5 PLAYER_DEFTREE_OBJ</span><br />
<span style="font-family: monospace;"> NUM_ACTIONS: 2</span><br />
<span style="font-family: monospace;"> ACTION CREATE_UNIT_AT</span><br />
<span style="font-family: monospace;"> ENEMY_WIZARDTOWER_OBJ 8 12</span><br />
<span style="font-family: monospace;"> ACTION CREATE_UNIT_AT</span><br />
<span style="font-family: monospace;"> ENEMY_WIZARDTOWER_OBJ 11 8</span><br />
<br />
<span style="font-family: monospace;">EVENT PRESERVE 1</span><br />
<span style="font-family: monospace;"> NUM_CONDITIONS: 1</span><br />
<span style="font-family: monospace;"> CONDITION UNIT_EXIST</span><br />
<span style="font-family: monospace;"> AT_LEAST 5 PLAYER_OFFTREE_OBJ</span><br />
<span style="font-family: monospace;"> NUM_ACTIONS: 2</span><br />
<span style="font-family: monospace;"> ACTION CREATE_UNIT_AT</span><br />
<span style="font-family: monospace;"> ENEMY_TOWER_OBJ 8 14</span><br />
<span style="font-family: monospace;"> ACTION CREATE_UNIT_AT</span><br />
<span style="font-family: monospace;"> ENEMY_TOWER_OBJ 12 11</span><br />
<br />
<span style="font-family: monospace;">EVENT PRESERVE 1</span><br />
<span style="font-family: monospace;"> NUM_CONDITIONS: 1</span><br />
<span style="font-family: monospace;"> CONDITION UNIT_EXIST_AT</span><br />
<span style="font-family: monospace;"> AT_LEAST 1 PLAYER_REGTREE_OBJ 2 12 5 14</span><br />
<span style="font-family: monospace;"> NUM_ACTIONS: 1</span><br />
<span style="font-family: monospace;"> ACTION CREATE_UNIT_AT</span><br />
<span style="font-family: monospace;"> ENEMY_TOWER_OBJ 7 15</span><br />
<br />
<span style="font-family: monospace;">EVENT PRESERVE 1</span><br />
<span style="font-family: monospace;"> NUM_CONDITIONS: 1</span><br />
<span style="font-family: monospace;"> CONDITION UNIT_EXIST_AT</span><br />
<span style="font-family: monospace;"> AT_LEAST 1 PLAYER_REGTREE_OBJ 12 1 14 3</span><br />
<span style="font-family: monospace;"> NUM_ACTIONS: 1</span><br />
<span style="font-family: monospace;"> ACTION CREATE_UNIT_AT</span><br />
<span style="font-family: monospace;"> ENEMY_TOWER_OBJ 14 5</span><br />
<br />
<span style="font-family: monospace;">END</span></div>
<br />
<span style="font-family: 'Trebuchet MS', sans-serif;">This file creates four events. Altogether these events create opposing towers if the player places tree structures at certain areas during gameplay. This simulates the opponent expanding their forces in reaction to the player taking specific actions.</span><br />
<span style="font-family: 'Trebuchet MS', sans-serif;"><br /></span><br />
<span style="font-family: 'Trebuchet MS', sans-serif;">You might have noticed that the writer of this file would have to manually write down how many actions are in an event, how many conditions are in an event, and how many events in total there are. This is so so that the state machine parsing the text file's data can allocate the correct amount of memory space before translating the script's contents of how to fill in the memory allocated. It would be entirely possible to add the feature to the parser that checks the size of everything before translating, though this feature would have taken a lot of time during the development of our project, and the returns were just not great enough to warrant such. Consequently the scripting language can easily cause crashes if any of the numbers of events, conditions, or actions are incorrect.</span><br />
<span style="font-family: 'Trebuchet MS', sans-serif;"><br /></span><br />
<span style="font-family: 'Trebuchet MS', sans-serif;">There was also little to no error checking implemented within the scripting language. Error checking would be handled by the state machine if it were to be created.</span><br />
<span style="font-family: 'Trebuchet MS', sans-serif;"><br /></span><br />
<span style="font-family: 'Trebuchet MS', sans-serif;">The start and end tokens are also a bit redundant, as detecting whether or not you're at the beginning or end of the input file can be automated, however the requirement of having START and END within the script made for development of the scripting language system much faster. Time was very valuable when this game was being made!</span><br />
<span style="font-family: 'Trebuchet MS', sans-serif;"><br /></span><br />
<span style="font-family: 'Trebuchet MS', sans-serif;">There was however support for comments within the file. Comments are handled by the state machine. We decided that whenever a # character is tokenized, all subsequent tokens are ignored and no actions are to be taken until another # token is found. This lets you encapsulate blocks of multi-line text within comment characters. These act like old C-style comments :)</span>CecilSunkurehttp://www.blogger.com/profile/16129986119923492789noreply@blogger.com0tag:blogger.com,1999:blog-3579312376304629754.post-72875370432071128082012-06-26T09:18:00.000-07:002012-09-01T10:04:32.542-07:00Ancient Forest and Grumpy Monsters<span style="font-family: 'Trebuchet MS', sans-serif;">Hello all! I've been away for a little while over the summer. This summer is the one that came right after my Freshman year, and so I wasn't able to get an internship. This means that this summer is likely going to be the last one I'll ever have to really just relax. So I took a month or two off from programming and did some other things. I've been working a lot at hotkeyit.com creating content.</span><br />
<span style="font-family: 'Trebuchet MS', sans-serif;"><br />
</span><br />
<span style="font-family: 'Trebuchet MS', sans-serif;">I've finally have a finished product to show off from my second semester at DigiPen! The game is called: Ancient Forest and Grumpy Monsters. The whole idea is to as an ancient magical forest to fight off a faction of Grumpy Monsters! Placing down tree structures is the main mechanic. These structures act as defensive towers, spawn creatures of the forest, and spread purification onto the land to counteract the spreading corruption of the Grumpy Monsters.</span><br />
<br />
<center>
<iframe allowfullscreen="allowfullscreen" frameborder="0" height="315" src="http://www.youtube.com/embed/plH9uLq6LRA" width="420"></iframe></center>
<br />
<span style="font-family: 'Trebuchet MS', sans-serif;">Here's a little info on the team qMopey that created the game:</span><br />
<span style="font-family: 'Trebuchet MS', sans-serif;"></span><br />
<span style="font-family: 'Trebuchet MS', sans-serif;">The team, qMopey, is a team of four programmers that are currently attending DigiPen IT that are developing the game Ancient Forest and Grumpy Monsters. This game is our second semester project. The game was coded in C using a DigiPen in-house DirectX library. The only functionality used from this library was loading images into memory, and displaying them on screen -even mesh creation is handled by our team. The team consists of:</span><br />
<ul>
<li><span style="font-family: 'Trebuchet MS', sans-serif;">Anh Do</span></li>
<li><span style="font-family: 'Trebuchet MS', sans-serif;">Kevin Giang</span></li>
<li><span style="font-family: 'Trebuchet MS', sans-serif;">Colton DeGraw</span></li>
<li><span style="font-family: 'Trebuchet MS', sans-serif;">Randy Gaul (CecilSunkure)</span></li>
</ul>
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="http://i.imgur.com/ZcWcP.png" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" height="181" src="http://i.imgur.com/ZcWcP.png" width="320" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Gameplay Screenshot of corruption and purified land.</td></tr>
</tbody></table>
<span style="font-family: 'Trebuchet MS', sans-serif;">In order to gain resources you place any structure underneath a sun tile! Each tree under a sun tile produces a single extra income point.</span><br />
<span style="font-family: 'Trebuchet MS', sans-serif;"><br />
</span><br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="http://i.imgur.com/5kaUB.gif" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" src="http://i.imgur.com/5kaUB.gif" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Aren't the sunrays absolutely adorable?</td></tr>
</tbody></table>
<span style="font-family: 'Trebuchet MS', sans-serif;">As the player progresses through the campaign levels new monsters and technologies are introduced. Here are a couple images of some of the various units on the Grumpy Monster's unit roster:</span><br />
<div class="separator" style="clear: both; text-align: center;">
<a href="http://i.imgur.com/XUOj1.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="http://i.imgur.com/XUOj1.png" /></a><a href="http://i.imgur.com/8qArG.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="http://i.imgur.com/8qArG.png" /></a> </div>
<span style="font-family: 'Trebuchet MS', sans-serif;">Here's the <span style="font-size: large;">download</span> link to the actual game's installer:</span><br />
<span style="font-family: 'Trebuchet MS', sans-serif;"><a href="http://www.mediafire.com/download.php?zgrr8hwpykdy465">LINK</a></span><br />
<span style="font-family: 'Trebuchet MS', sans-serif;"></span><br />
<span style="font-family: 'Trebuchet MS', sans-serif;">RANDOM TRIVIA:</span><br />
<ul>
<li><span style="font-family: 'Trebuchet MS', sans-serif;">21786 lines of code</span></li>
<li><span style="font-family: 'Trebuchet MS', sans-serif;">220 source files </span></li>
<li><span style="font-family: 'Trebuchet MS', sans-serif;">1 million hours of work (joking, but it felt like 1 million)</span></li>
<li><span style="font-family: 'Trebuchet MS', sans-serif;">All art was created by programmers on the team who actually get no class credit for the art</span></li>
<li><span style="font-family: 'Trebuchet MS', sans-serif;">Anh Do is terrible at the game Lol</span></li>
</ul>
CecilSunkurehttp://www.blogger.com/profile/16129986119923492789noreply@blogger.com0tag:blogger.com,1999:blog-3579312376304629754.post-78455259773862084092012-04-08T19:21:00.000-07:002012-04-08T23:09:50.085-07:00Object Oriented C: Class-like Structures<span style="font-family: 'Trebuchet MS', sans-serif;">During my second semester while attending DigiPen IT I had to create a game in C. Since I wasn't allowed to use C++ until my Sophomore year for this game project I had to come up with a way of having strong organization during development. Class-like structures in C that allowed for <a href="http://en.wikipedia.org/wiki/Polymorphism_in_object-oriented_programming">polymorphism</a> and <a href="http://en.wikipedia.org/wiki/Inheritance_(object-oriented_programming)">inheritance</a> were implemented! Virtual functions were also used to organize the functionalities of each type of object into a universal format!</span><br />
<div>
<span style="font-family: 'Trebuchet MS', sans-serif;"><br />
</span></div>
<div>
<span style="font-family: 'Trebuchet MS', sans-serif;">In C the basic data structure is, well a structure. This is the tool used to create all <a href="http://en.wikipedia.org/wiki/Object_(computer_science)">objects</a>. Here's the sort of thing you'd see for a typical game object:</span></div>
<br />
<div class="code">
<code>typedef struct _GameObj<br />
{</code><br />
<code> int HP;</code><br />
<code> Vector2D_ position;</code><br />
<code> Image_ *image;<br />
} GameObj_ </code></div>
<br />
<span style="font-family: 'Trebuchet MS', sans-serif;">As you can see there's data members for HP, the vector position and a pointer to the image.</span><br />
<span style="font-family: 'Trebuchet MS', sans-serif;"><br />
</span><br />
<span style="font-family: 'Trebuchet MS', sans-serif;">There's a lot of limitations to a setup like this, however. It's difficult to write generalized functions that work on any type of game object you might have. You'd likely write different functions to handle your different types of game objects in order to handle the different needs of each type of object. Things start getting very difficult as complexity in your game objects arises, and the complexity of the project arises. There becomes a need for a higher form of organization in order to keep development moving along steadily.</span><br />
<span style="font-family: 'Trebuchet MS', sans-serif;"><br />
</span><br />
<span style="font-family: 'Trebuchet MS', sans-serif;">A solution is to add in an enumeration type to the game object, so the GameObj_ struct becomes a generalized structure. This would allow you to write generalized functions for common actions, such as updating position, or damaging units. Although it isn't a good idea to have a singular structure as your only game object. You'd have to place everything that every type of object in your entire project would require into this single structure, and it'd be very hectic and waste a lot of memory, as some objects would not use data members other objects would. You could then split your GameObj_ structure into various different structure definitions for your different types of objects. This would allow you to write separate functions for different types of objects, and you could cycle your list and call them as necessary depending on what type of structure each object is.</span><br />
<span style="font-family: 'Trebuchet MS', sans-serif;"><br />
</span><br />
<span style="font-family: 'Trebuchet MS', sans-serif;">It would be best, however, to be able to have a way to organize the different functions each type of game object could have into a single standard set. </span><span style="font-family: 'Trebuchet MS', sans-serif;">For example I used the following functions for each game object that was designed in my semester project: Construct, Init, Update, Draw, Destroy. By placing all functionality of each object into these separate functions you can easily copy and paste old code for reuse of new objects, thus limiting the amount of work the developer needs do. Here's a short detail of what each category would do for each game object:</span><br />
<br />
<ul>
<li><span style="font-family: 'Trebuchet MS', sans-serif;">Construct - deals with allocation of any necessary space.</span></li>
<li><span style="font-family: 'Trebuchet MS', sans-serif;">Init - Initialization; sets the starting values for all the space allocated. Things like HP, the image pointer, and anything else needed.</span></li>
<li><span style="font-family: 'Trebuchet MS', sans-serif;">Update - this function generally had the most code within it. This handles all updating of the object, and should be time-based. All calculations are made relative to the amount of time elapsed since the previous calculations. Attacks are fired, HP is modified, the object perhaps moves around, etc.</span></li>
<li><span style="font-family: 'Trebuchet MS', sans-serif;">Draw - simply handles rendering of the object onto the screen.</span></li>
<li><span style="font-family: 'Trebuchet MS', sans-serif;">Destroy - handles all deallocation of space allocated in the Construct funtion.</span></li>
</ul>
<br />
<span style="font-family: 'Trebuchet MS', sans-serif;">The great benefit of this type of setup is that there's a universal format for all game objects to function within the game. This allows for generalized code to be written. For example if there's a list of these game objects within your game, then you can cycle through the list and call each one's draw function and draw the entire list in an automated and organized manner. All you'd have to do is call the correct draw function based on the type of the object.</span><br />
<span style="font-family: 'Trebuchet MS', sans-serif;"><br />
</span><br />
<span style="font-family: 'Trebuchet MS', sans-serif;">To further this concept one could also place function pointers into each structure, and these function pointers point to the object's specific set of functions. A structure with this sort of style could look like so:</span><br />
<br />
<div class="code">
<pre><code>typedef struct _GameObj
{
int HP;
Vector2D_ position;
GAME_OBJ_TYPE ID;
Image_ *image;
void (*Construct)( GameObj_ *self );
void (*Init)( GameObj_ *self );
void (*Update)( GameObj_ *self );
void (*Draw)( GameObj_ *self );
void (*Destroy)( GameObj_ *self );
} GameObj_;</code></pre>
</div>
<br />
<span style="font-family: 'Trebuchet MS', sans-serif;">When a new object is created these pointers can be set to the functions that correspond with the type of unit being created. These are what I referred to as virtual functions. It would then be very easy to create loops to cycle through lists of the different types of objects and call each function based on the current state of the game. For example, here's some code that could call all of the update functions for a linked list of a specific type of object:</span><br />
<br />
<div class="code">
<pre><code>while(node)
{
node->Update( node );
node = node->next;
}</code></pre>
</div>
<br />
<span style="font-family: 'Trebuchet MS', sans-serif;">This is very useful, but you'd still have to separate your objects into different lists for each type of game object available, since each game object would be made up of different types of structures.</span><br />
<span style="font-family: 'Trebuchet MS', sans-serif;"><br />
</span><br />
<span style="font-family: 'Trebuchet MS', sans-serif;">The next step in organizing all of our game object related code is to generalize the GameObj structure itself. There is a way to do this without actually having a single structure definition that you have to cram all of your data members into. The idea is to utilize pointer typecasting.</span><br />
<span style="font-family: 'Trebuchet MS', sans-serif;"><br />
</span><br />
<span style="font-family: 'Trebuchet MS', sans-serif;">Take our first GameObj_ structure and lets look at our modified version that could be for perhaps a Bat object in a game:</span><br />
<br />
<div class="code">
<pre><code>typedef struct _BatObj
{
int HP;
Vector2D_ position;
Image_ *image;
GAME_OBJ_TYPE ID;
void (*Construct)( GameObj_ *self );
void (*Init)( GameObj_ *self );
void (*Update)( GameObj_ *self, const float dt );
void (*Draw)( GameObj_ *self );
void (*Destroy)( GameObj_ *self );
POISON poisonMultiplier;
} BatObj_</code></pre>
</div>
<br />
<span style="font-family: 'Trebuchet MS', sans-serif;">This setup will allow a programmer to have a GameObj_ structure have any type of desired ID, and have their corresponding function pointers point to any particular set of functions depending on what the ID is. A switch statement run on the ID can achieve the task of setting these function pointers. Then within a specific set of functions for a type of game object a pointer typecast can be used on the self parameter to treat the passed data as any type of data. The typecasting can be dealt with within the functions themselves. Here's an example set for a bat object:</span><br />
<span style="font-family: 'Trebuchet MS', sans-serif;"><br />
</span><br />
<div class="code">
<pre><code>BatUpdate( GameObject_ *self, const float dt )
{
((Bat_ *)self)->poisonMultiplier += dt;
}</code></pre>
</div>
<br />
<span style="font-family: 'Trebuchet MS', sans-serif;">By typecasting the self pointer as a Bat_ structure, you can then have access to whatever data was passed through the self pointer as if the data were actually a Bat_ structure. This is extremely useful as you can now write functions that manipulate the data members that all different types of objects have in common. In this case, the only new data member a bat had was its poisonMultiplier. However if the pointer to the Bat_ struct was not typecasted as a Bat_ struct, the data of the rest of the members could have been accessed as if it were a GameObject_ structure. This can now be done with all game objects created as long as the layout of the structure for the first nine data members are all identical in each type of game object created. Now all game objects can be placed into a single list and their functions can all be called by generalized code, instead of creating different code to handle each different type of object. The only code that needs to be re-written is code that handles the differing data members differently.</span><br />
<span style="font-family: 'Trebuchet MS', sans-serif;"><br />
</span><br />
<span style="font-family: 'Trebuchet MS', sans-serif;">The reason this works is because when you typecast a Bat_ structure as a GameObject_ structure, the C language doesn't care that you cannot access the data of the poisonMultiplier any longer. As far as your program is concerned you are actually manipulating a GameObject_ structure -and you are; the top portion of a Bat_ structure is identical in memory to that of a GameObject_ structure. This achieves Polymorphism and Inheritance. The Bat_ structure inherits all of the GameObject_ data members, and adds on its own unique ones. The virtual functions allow for different behavior of the game objects, even though the top portion of each GameObj_ structure is identical.</span><br />
<span style="font-family: 'Trebuchet MS', sans-serif;"><br />
</span><br />
<span style="font-family: 'Trebuchet MS', sans-serif;">Here's another example of another type of game object that can be created:</span><br />
<br />
<div class="code">
<pre><code>typedef struct _VeryLargeBat
{
int HP;
Vector2D_ position;
Image_ *image;
GAME_OBJ_TYPE ID;
void (*Construct)( GameObj_ *self );
void (*Init)( GameObj_ *self );
void (*Update)( GameObj_ *self, const float dt );
void (*Draw)( GameObj_ *self );
void (*Destroy)( GameObj_ *self );
POISON poisonMultiplier;
int size;
int armor;
} VeryLargeBat_;</code></pre>
</div>
<br />
<span style="font-family: 'Trebuchet MS', sans-serif;">This VeryLargeBat_ structure inherits the data members of the Bat_ structure, which inherits data members of the GameObj_ structure. This allows for a VeryLargeBat to successfully use all functions that manipulate GameObj_ structures, as well as those that manipulate Bat_ structures. It also now has the ability to have its own specialized functions that only work on VeryLargeBat_ objects as well! Perhaps the size can become a factor in how much damage it deals, and the armor can reduce damage from enemies somehow within an algorithm.</span><br />
<span style="font-family: 'Trebuchet MS', sans-serif;"><br />
</span><br />
<span style="font-family: 'Trebuchet MS', sans-serif;">There's one last thing you can do to make things a whole lot easier for yourself. You can modify your derived structs to contain structures of inherited structs like so (much less error prone and easier to read):</span><br />
<br />
<div class="code">
<pre><code>typedef struct _Bat
{
GameObj_ gameObj;
POISON poisonMultiplier;
} Bat_;
typedef struct _VeryLargeBat
{
Bat_;
int size;
int armor;
} VeryLargeBat_;</code></pre>
</div>
<br />
<span style="font-family: 'Trebuchet MS', sans-serif;">Reference: </span><a href="http://www.planetpdf.com/codecuts/pdfs/ooc.pdf">http://www.planetpdf.com/codecuts/pdfs/ooc.pdf</a>CecilSunkurehttp://www.blogger.com/profile/16129986119923492789noreply@blogger.com22tag:blogger.com,1999:blog-3579312376304629754.post-6474033196246233002012-04-05T13:18:00.000-07:002012-07-02T09:23:41.027-07:00Tile Maps: Binary Collision<span style="font-family: 'Trebuchet MS', sans-serif;">Back in the day binary collision maps (also known as a type of tile map) were used as a simple and efficient way to check for collision between an object with coordinates of floating point value, and square blocks. What sorts of games used binary collision arrays? Well, pretty much any game that had square tile based levels likely used some form of binary collision, here's a few NES screenshots:</span><br />
<span style="font-family: 'Trebuchet MS', sans-serif;"><br />
</span><br />
<div class="separator" style="clear: both; text-align: center;">
</div>
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgdkXJFu2FJA6iE6iRuS_4vNKwJAbjIp9nFP9tPLao41SLa56SPv8-yhJeC4-zjl5_Q8oIl1-wSfTSia31j_kg3t5OIKCTjJgeInTWpG1v3JZqcyAfYdjxQgymhavBfWqrZu4fL8qMzyaY/s1600/220px-Legend_of_Zelda_NES.PNG" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgdkXJFu2FJA6iE6iRuS_4vNKwJAbjIp9nFP9tPLao41SLa56SPv8-yhJeC4-zjl5_Q8oIl1-wSfTSia31j_kg3t5OIKCTjJgeInTWpG1v3JZqcyAfYdjxQgymhavBfWqrZu4fL8qMzyaY/s1600/220px-Legend_of_Zelda_NES.PNG" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Zelda</td></tr>
</tbody></table>
<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgRDE3kz0luto7yJ5PgIWJEwVePDGe60W2kNwz8GMr9wHNDYhOU6YjTYqD1kodfFkCTsbqxv3-zth9Lt-R0CFt5zZ2XN52EQA5Sx4WjtzIbUGvMHzexeWvGLOOyaxS5EJqWg_NM7oqStuQ/s1600/GFDE_screenshot.png" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" height="292" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgRDE3kz0luto7yJ5PgIWJEwVePDGe60W2kNwz8GMr9wHNDYhOU6YjTYqD1kodfFkCTsbqxv3-zth9Lt-R0CFt5zZ2XN52EQA5Sx4WjtzIbUGvMHzexeWvGLOOyaxS5EJqWg_NM7oqStuQ/s320/GFDE_screenshot.png" width="320" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Mario</td></tr>
</tbody></table>
<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgRpgMEZHFuSoFjUHles3pcqEsNr1nD6Nf5Nhyphenhyphen7Fpvgs_ho9EZVXVi9vb9ovLVaKIVOFlqpZki8M7353GuLpnjJ57qzYyYzmWDctjga2NsHHAPjdon3ETCFAIUBjS4uT70Sn9djiHQxPbk/s1600/Metroid-Nes_1.jpg" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" height="281" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgRpgMEZHFuSoFjUHles3pcqEsNr1nD6Nf5Nhyphenhyphen7Fpvgs_ho9EZVXVi9vb9ovLVaKIVOFlqpZki8M7353GuLpnjJ57qzYyYzmWDctjga2NsHHAPjdon3ETCFAIUBjS4uT70Sn9djiHQxPbk/s320/Metroid-Nes_1.jpg" width="320" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Metroid</td></tr>
</tbody></table>
<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjqzVCCWthr44Z9T6eIQ-3Tj3th5OrzEbccKUWwtVYRxQ5CsQghA0KPKFMFYCqYQfeRBJiZztqcpbirMJIovfPWfVIM_E4xP1nXDe1-G0_1JilTNJsNRjrGDk8EPbAXl_kiNIbuDZUjvJs/s1600/Zelda1_2.png" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjqzVCCWthr44Z9T6eIQ-3Tj3th5OrzEbccKUWwtVYRxQ5CsQghA0KPKFMFYCqYQfeRBJiZztqcpbirMJIovfPWfVIM_E4xP1nXDe1-G0_1JilTNJsNRjrGDk8EPbAXl_kiNIbuDZUjvJs/s1600/Zelda1_2.png" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Zelda</td></tr>
</tbody></table>
<span style="font-family: 'Trebuchet MS', sans-serif;">A binary collision array is an array of booleans representing collision or non-collision. In our above examples any square tile that the player could not walk on, or was not empty space would have been represented by a value meaning collision. There would then be a separate array of the same dimensions as the binary collision array, which would represent the different images to draw for each tile.</span><br />
<span style="font-family: 'Trebuchet MS', sans-serif;"><br />
</span><br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEievhNy7JwPNUhjxoBhimhDG_YIyiF5SIDV69IQjyV3_rJ6hNAj5emBeCGVFXACjwuI5Xbn5SZggso8nFrfkjw2x6BoaFOv1GS4tHyKrbKPth8rEud8pNuwBbq7ZUIpcoeeKFIUUcHvOGk/s1600/arrays.PNG" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEievhNy7JwPNUhjxoBhimhDG_YIyiF5SIDV69IQjyV3_rJ6hNAj5emBeCGVFXACjwuI5Xbn5SZggso8nFrfkjw2x6BoaFOv1GS4tHyKrbKPth8rEud8pNuwBbq7ZUIpcoeeKFIUUcHvOGk/s1600/arrays.PNG" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Example Collision and Data Arrays</td></tr>
</tbody></table>
<span style="font-family: 'Trebuchet MS', sans-serif;"><br />
</span><br />
<span style="font-family: 'Trebuchet MS', sans-serif;">Above is an example of what the collision and data arrays might look like for the Zelda screenshot with a bridge. Each 1 would be a block that is unwalkable by the character, and each 0 would be a space the character could walk on. The data array holds different numbers, and each number would represent a different image. These image values could perhaps have been stored in some sort of enumeration, or a CBlock in assembly.</span><br />
<span style="font-family: 'Trebuchet MS', sans-serif;"><br />
</span><br />
<span style="font-family: 'Trebuchet MS', sans-serif;">Though, how is the character handled? The character in these games seems to have a position of floating point value. I'm not actually sure if they did or didn't for optimization reasons, but what I'll show you uses a floating point coordinate for different characters/enemies. Here's an image showing an example of a floating point coordinate perhaps representing the player's character:</span><br />
<span style="font-family: 'Trebuchet MS', sans-serif;"><br />
</span><br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhivB5jSqixIRApLeJgRtVB1WYM-6iocLWhsAuMiWHkcevvQuIPoC-F_4aRgV0wZn-QHYuT7vFCSeAcYAUODgMqEyOQYFv6LwdOtxIz54VmKCHkS349RCwEY3Uln7LfCjMzipXjIm5P-zc/s1600/FloatCoord.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="211" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhivB5jSqixIRApLeJgRtVB1WYM-6iocLWhsAuMiWHkcevvQuIPoC-F_4aRgV0wZn-QHYuT7vFCSeAcYAUODgMqEyOQYFv6LwdOtxIz54VmKCHkS349RCwEY3Uln7LfCjMzipXjIm5P-zc/s320/FloatCoord.png" width="320" /></a></div>
<span style="font-family: 'Trebuchet MS', sans-serif;"><br />
</span><br />
<span style="font-family: 'Trebuchet MS', sans-serif;">This point would represent the center of the position of the player. The image drawn for this character at this point would be centered directly onto the point. So now how does one go about detecting when the sides of an image on this point are touching a box that represents collision? In order to do that I'll show a method I've learned called "hotspots".</span><br />
<span style="font-family: 'Trebuchet MS', sans-serif;"><br />
</span><br />
<span style="font-family: 'Trebuchet MS', sans-serif;">Hotspots are simply points that are offsets of a coordinate, like the coordinate above. The smallest amount of offset hotspots you can have that I'd recommend is four: one for each side of your square image. When implementing a binary collision array for a simple platformer, I found that eight hotspots worked very well. Here's an example image showing eight hotspots on the edges of a square:</span><br />
<span style="font-family: 'Trebuchet MS', sans-serif;"><br />
</span><br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjkuNhF8ojg4_Tkg-SEhPIOkggpxcIvJsDhcP2osHOBCOR7YM3ZXdA8wTGoBU5VlLrkGxDZR2bV3Kc94clcKCPQGTuc3-jgTFpfCEYfzFQtxfAiFJdB7JPqAMVbhotgdRqutOOzKJYVlB8/s1600/hotspot.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjkuNhF8ojg4_Tkg-SEhPIOkggpxcIvJsDhcP2osHOBCOR7YM3ZXdA8wTGoBU5VlLrkGxDZR2bV3Kc94clcKCPQGTuc3-jgTFpfCEYfzFQtxfAiFJdB7JPqAMVbhotgdRqutOOzKJYVlB8/s1600/hotspot.png" /></a></div>
<span style="font-family: 'Trebuchet MS', sans-serif;"><br />
</span><br />
<span style="font-family: 'Trebuchet MS', sans-serif;">Each of those dots are offset by 1/4 of the square's side length, and 1/2 of the square's side length. For example the bottom two hotspots are offset from the center by -1/2 * side length (assuming origin bottom left of the screen). By using these hotspots you can then detect when any of these hotspots points are within the bounds of a binary tile. There are multiple ways to do this, but the way I chose to was to just floor the floating point value of each hotspot and look at only the integer value left. You can do these with an integer typecast, or a floor function. This works since any floating point value in the range of 1.0 through less then 2.0 will still be within the coordinate tile of 1. If this float truncation is confusing, read the next paragraph, if you understand go ahead and skip the next paragraph.</span><br />
<span style="font-family: 'Trebuchet MS', sans-serif;"><br />
</span><br />
<span style="font-family: 'Trebuchet MS', sans-serif;">Say you have a coordinate of 3.7 and 4.3 representing one of your hotspots, and you need to check to see if this coordinate is within a tile that represents collision. If you take a look you'll realize that all values from 3.0 to just before 4.0 are all within the x axis on of the value 3 (as in on column 3 of your grid). This goes the same for 4.3; all values from 4.0 through just before 5.0 are in row 4. This means that any coordinate from 3.0 - 3.99999, 4.0 - 4.999999 are within the tile of 3, 4. So then to check to see where any floating point coordinate is on your integer coordinate system, just throw away your decimal value and treat your float as an integer. 3.7 would be 3, and 4.3 would be 4. Thus your resulting coordinate is 3, 4.</span><br />
<span style="font-family: 'Trebuchet MS', sans-serif;"><br />
</span><br />
<span style="font-family: 'Trebuchet MS', sans-serif;">Once this is accomplished you can then execute your code to move the character back to the tile they are currently on. This can be done by also flooring the value of the character's coordinate (not the hotspots). However, you want to snap your character back to the closest tile, not just floor the entire floating point value. To do this you use a simple trick:</span><br />
<br />
<div class="code">
<code>coordinate = (int)(coordinate + 0.5f);<br />
</code></div>
<br />
<span style="font-family: 'Trebuchet MS', sans-serif;">This will round your floating point number to the nearest tile by offset the decimal portion of your value by 0.5.</span><br />
<span style="font-family: 'Trebuchet MS', sans-serif;"><br /></span><br />
<span style="font-family: 'Trebuchet MS', sans-serif;">Lastly, if you ever implement a coordinate system like here I suggest normalizing your coordinate system. That is have one tile be represented by the value of 1. This allows for simpler mathematics, and allows you to easily transform (scale, rotate, translate) your entire grid/game to whatever exact size you desire. If you normalize your entire grid in your data, you can separate the drawing logic from your data thus decoupling your code overall.</span><br />
<span style="font-family: 'Trebuchet MS', sans-serif;"><br /></span><br />
<span style="font-family: 'Trebuchet MS', sans-serif;">Here's a screenshot for a platformer I worked on for a CS assignment! I had a normalized grid system with the origin represented by the bottom left of the map. I was scaling this map by a factor of 3. I also implemented some simple AI with a statemachine for the red guys! They walk left and right up the edge of their platform, and turn around at the edge, or turn around when they hit a wall.</span><br />
<span style="font-family: 'Trebuchet MS', sans-serif;"><br /></span><br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiJHoluUFStxKxi4GwFVxKMUYQT-zkJs-mh_MaTMEKSPTU_LLKS-ORvzuTsBU9swEfC-mjojuaHHFwWsV23q8CsBGkjMKTi3Cla53HpgyfLCb8ZHN4ejqueDJ16zsZaPWErDDlWjFwLRDM/s1600/platformer.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="228" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiJHoluUFStxKxi4GwFVxKMUYQT-zkJs-mh_MaTMEKSPTU_LLKS-ORvzuTsBU9swEfC-mjojuaHHFwWsV23q8CsBGkjMKTi3Cla53HpgyfLCb8ZHN4ejqueDJ16zsZaPWErDDlWjFwLRDM/s320/platformer.png" width="320" /></a></div>
<span style="font-family: 'Trebuchet MS', sans-serif;"><br /></span>CecilSunkurehttp://www.blogger.com/profile/16129986119923492789noreply@blogger.com2tag:blogger.com,1999:blog-3579312376304629754.post-69552494342445979092012-02-22T12:44:00.000-08:002012-02-23T09:50:19.021-08:00Basic 2D Vector Physics: Acceleration, Orientation and Friction<span style="font-family: 'Trebuchet MS',sans-serif;">This post aims at covering the basics of 2D vector physics, that of which can be used in application to create something like <a href="http://www.youtube.com/watch?v=zDdKNJnv_VQ">this Asteroids project</a> for my CS230 class.</span><br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<object width="320" height="266" class="BLOGGER-youtube-video" classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" codebase="http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=6,0,40,0" data-thumbnail-src="http://0.gvt0.com/vi/zDdKNJnv_VQ/0.jpg"><param name="movie" value="http://www.youtube.com/v/zDdKNJnv_VQ&fs=1&source=uds" />
<param name="bgcolor" value="#FFFFFF" />
<embed width="320" height="266" src="http://www.youtube.com/v/zDdKNJnv_VQ&fs=1&source=uds" type="application/x-shockwave-flash"></embed></object></div>
<br />
<br />
<span style="font-family: 'Trebuchet MS',sans-serif;">The simplest way I know of to move an image across the screen over time is by using a static velocity and apply it to the the position of an image every time-step:</span><br />
<br />
<span style="font-family: 'Courier New',Courier,monospace;">pos += vel * dt;</span><br />
<br />
<span style="font-family: 'Courier New',Courier,monospace;">dt</span><span style="font-family: 'Trebuchet MS',sans-serif;"> should be calculated every frame loop and passed to this equation, this way your displacement will be time-based instead of frame-based. To calculate dt you can use the following flowchart:</span><br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEihSOMx_kXZx2vhJSRAyBiZPo9Vkk_MW0VVERcbPpia3mIDzzcOVDMkBGGwpKj3ZpH7jxyCa6TuFSiqJQQRSVjCJ2Rnkjivf447fJhsYC2DVNP_ULzXoSSM5m3kngRW0dSod0zdJfVE4PM/s1600/Time.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="400" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEihSOMx_kXZx2vhJSRAyBiZPo9Vkk_MW0VVERcbPpia3mIDzzcOVDMkBGGwpKj3ZpH7jxyCa6TuFSiqJQQRSVjCJ2Rnkjivf447fJhsYC2DVNP_ULzXoSSM5m3kngRW0dSod0zdJfVE4PM/s400/Time.png" width="267" /></a></div>
<br />
<span style="font-family: 'Trebuchet MS',sans-serif;"><br />
</span><br />
<span style="font-family: 'Trebuchet MS',sans-serif;">In order to have variable velocity you can apply the same idea from our displacement (position) equation. To change velocity over time and have acceleration and deceleration you can use:</span><br />
<br />
<span style="font-family: 'Courier New',Courier,monospace;">vel += accel * dt;</span><br />
<br />
<span style="font-family: 'Trebuchet MS',sans-serif;">Pretty simple! However in order to apply this in programming you'll break up the x and y velocities into separate values like so:</span><br />
<br />
<span style="font-family: 'Courier New',Courier,monospace;">pos.x += vel.x * dt;</span> <br />
<span style="font-family: 'Courier New',Courier,monospace;">pos.yx += vel.y * dt;</span> <br />
<span style="font-family: 'Courier New',Courier,monospace;">vel.x += accel.x * dt;</span><br />
<span style="font-family: 'Courier New',Courier,monospace;">vel.y += accel.y * dt;</span><span style="font-family: 'Trebuchet MS',sans-serif;"><br />
</span><br />
<span style="font-family: 'Trebuchet MS',sans-serif;">Now what about turning, and a sense of orientation? It's no use if your object can only go in a single line, which is all the above equations will support if implemented alone. Your object should have a data member to hold it's orientation in <a href="http://en.wikipedia.org/wiki/Radian">radians</a>. If you don't really have a mental grasp of radians, that's fine. Take a look at the unit circle: <a href="https://www.google.com/search?hl=en&gs_nf=1&tok=gMyvI5Rfcz-aWmUHUcyJEg&cp=7&gs_id=1d&xhr=t&q=unit+circle&safe=off&gs_upl=&bav=on.2,or.r_gc.r_pw.r_qf.,cf.osb&biw=1360&bih=667&um=1&ie=UTF-8&tbm=isch&source=og&sa=N&tab=wi&ei=XEpFT6DUMsjWiALJ1JXcDg">link</a>. In order to know the value of any given 2D direction relative to a standard axis (x and y plane not rotated or anything) just look on the graph in that direction. For example straight upward in radians is pi / 2. Straight downwards is 3 * pi / 2. Very simple. The unit circle is just a way of representing directions as a value. The range of this value is 0 through 2 * pi.</span><br />
<br />
<span style="font-family: 'Trebuchet MS',sans-serif;">You can initialize your object's direction value with a preset or randomized value within the range of zero through 2 * pi. However it's easier to implement calculations in 2D if you set your range of values to pi to -pi (see below psuedo code for reason why). This means, for example, a full 360 degree angle is represented by either zero or -pi. The downward direction, for example, would be -pi / 2. Once you have this set up, you can easily use this radians orientation value to find a direction vector for your object. A direction vector is a vector whose length is 1, which allows you as a programmer to multiply it by a value and easily get a vector in a specific direction of a specific length.</span><br />
<br />
<span style="font-family: 'Trebuchet MS',sans-serif;">For example say your object has an x velocity of 6 and y velocity of 10. Every timestep you'll move by a factor of 6 to the right and up by 10. This is all good, and the distance the ship will cover can be found with the Pythagorean theorem: sqrt( 6^2 + 10^2 ). But, what if you want the ship to move 5 units in a direction per timestep? What if you want to be able to easily move your object around in any direction by 5 units per timestep? This is going to be pretty difficult without doing what's called normalization. Normalizing a vector is the process of taking a direction vector, like (6, 10) and generating a vector that points in the exact same direction, whose value is equal to 1.</span><br />
<br />
<span style="font-family: 'Trebuchet MS',sans-serif;">If you are able to find a direction vector of the direction your object is going, you can easily multiply the x and y components by 5, and achieve your goal. If your direction vector is derived from your radians orientation (like I said we'd do), then you can get the direction vector no matter what direction you are going, all the while you can modify your orientation value however you like! In order to get your normalized direction vector from your angle of orientation, just use:</span><br />
<br />
<span style="font-family: 'Courier New',Courier,monospace;">dirVect.x = cos( radianOrientation );</span><br />
<span style="font-family: 'Courier New',Courier,monospace;">dirVect.y = sin( radianOrientation );</span><br />
<br />
<span style="font-family: 'Trebuchet MS',sans-serif;">You now know all the necessary ideas needed to implement some simple 2D vector physics! You can rotate your object's orientation with addition/subtraction on your radians value, and then move your ship according to the angle of orientation by a specific velocity value, all the while updating your velocity with a constant acceleration value.</span><br />
<br />
<span style="font-family: 'Trebuchet MS',sans-serif;">Here's a (psuedo) code example:</span><br />
<br />
<div class="code">
<code>// Find current direction vector</code><br />
<code>dirVect.x = cos( radianOrientation );</code><br />
<code>dirVect.y = sin( radianOrientation );<br />
<br />
// Apply forward acceleration<br />
if(keypress( UP ))</code><br />
<span style="font-family: monospace;"> vel.x += ACCELERATION_FORWARD * dirVect.x * dt;</span><br />
<code> vel.y += ACCELERATION_FORWARD * dirVect.y * dt;</code><br />
<code> // Simulate friction</code><br />
<code> vel.x *= .99</code><br />
<code> vel.y *= .99</code><br />
<code><br />
</code><br />
<code>// Apply backward acceleration (negative forward)</code><br />
<code>if(keypress( DOWN ))</code><br />
<code> vel.x += ACCELERATION_BACKWARD * dirVect.x * dt;<br />
vel.y += ACCELERATION_BACKWARD * dirVect.y * dt;</code><br />
<code> // Simulate friction</code><br />
<code> vel.x *= .99</code><br />
<code> vel.y *= .99</code><br />
<code><br />
</code><br />
<code>// Add a value scaled by dt to rotate orientation</code><br />
<code>if(keypress( LEFT ))</code><br />
<code> radianOrientation += ROTATION_SPEED * dt;</code><br />
<code> // Bound checking for pi and -pi<br />
if radianOrientation > PI</code><br />
<code> radianOrientation = -PI</code><br />
<code> else if radianOrientation < -PI</code><br />
<code> radianOrientation = PI</code><br />
<code><br />
</code><br />
<code>// Subtract a value scaled by dt to rotate orientation</code><br />
<div style="font-family: 'Times New Roman';">
<code><code>if(keypress( RIGHT ))</code></code></div>
<div style="font-family: 'Times New Roman';">
<code><code> radianOrientation -= ROTATION_SPEED * dt;</code></code></div>
<code> // Bound checking for pi and -pi</code><br />
<div style="font-family: 'Times New Roman';">
<code><code> if radianOrientation > PI</code></code></div>
<div style="font-family: 'Times New Roman';">
<code><code> radianOrientation = -PI</code></code></div>
<div style="font-family: 'Times New Roman';">
<code><code> else if radianOrientation < -PI</code></code></div>
<div style="font-family: 'Times New Roman';">
<code><code> radianOrientation = PI</code></code><br />
<code><code><br />
</code></code><br />
<code><code>// Update position with our new calculated values</code></code><br />
<code><code>pos.x += vel.x * dt</code></code><br />
<code><code>pos.y += vel.y * dt</code></code></div>
</div>
<br />
<span style="font-family: 'Trebuchet MS',sans-serif;">Another thing to try to explain is the reason for the range of pi to -pi. Using a range of pi to -pi allows for easy calculations because it makes the lower half of the unit circle negative, which means you can directly apply resulting values from sin and cos onto your velocity/displacement, and move your image in all four directions (up, down, left, and right).</span><br />
<br />
<span style="font-family: 'Trebuchet MS',sans-serif;">Now, what if you need to solve for the angle between two points? This could be useful for homing missiles, or AI. Knowing the angle between an enemy and the player, for instance, could be used to let the enemy know which direction to go from there. In order to solve for the angle between two points I used <a href="http://www.gamedev.net/topic/318640-how-to-get-angle-between-two-points/">atan2</a>:</span><br />
<br />
<div class="code">
<code>angle = atan2( player.y - enemy.y, player.x - enemy.x )<br />
</code></div>
<br />
<span style="font-family: 'Trebuchet MS',sans-serif;">This lets me find the angle between two points, namely between an enemy object and the player. You can then use this result and compare it with the angle of orientation of the enemy in order to deduce of the enemy should turn clockwise or counterclockwise, or anything else you'd want!</span><br />
<br />
<span style="font-family: 'Trebuchet MS',sans-serif;">You may have noticed those lines that multiply the velocity by .99 after the update calculation was made. This actually simulates friction. The higher the velocity gets the greater the reduction per timestep! This will allow your object to accelerate slower the faster it goes, until it reaches an equilibrium. It should also seem to float friction-less at slower speeds. You can use a larger or smaller value for different amounts of simulated friction.</span><br />
<br />
<span style="font-family: 'Trebuchet MS',sans-serif;">And there you have it -all the essential concepts required to implement a game using simple 2D vector physics!</span>CecilSunkurehttp://www.blogger.com/profile/16129986119923492789noreply@blogger.com4tag:blogger.com,1999:blog-3579312376304629754.post-81815135972223162422012-02-21T16:28:00.000-08:002012-02-21T18:17:00.669-08:00Game Program Structuring/Design: Game State Manager<div style="font-family: "Trebuchet MS",sans-serif;">
<span style="font-size: small;">Not too long ago I created my own first game from scratch in pure C. I struggled most with program design. I'd like to share what I've learned about a proper game state manager.</span></div>
<div style="font-family: "Trebuchet MS",sans-serif;">
<span style="font-size: small;"><br />
</span></div>
<div style="font-family: "Trebuchet MS",sans-serif;">
<span style="font-size: small;">A game state manager is a method of creating a highly organized main game loop, which is generalized to the point that it can apply to any situation without pre-runtime modification of code. The game should always be in a state during runtime. That state could be the main menu, a pause screen, or a specific level or scenario. A state is divided up into multiple categories, and these categories are generalized enough to apply to every state the game can be in.</span></div>
<div style="font-family: "Trebuchet MS",sans-serif;">
<span style="font-size: small;"><br />
</span></div>
<div style="font-family: "Trebuchet MS",sans-serif;">
<span style="font-size: small;">The idea is to use <a href="http://www.cprogramming.com/tutorial/function-pointers.html">function pointers</a>, and a specific set of them. There are six different functions to know:</span></div>
<ul style="font-family: "Trebuchet MS",sans-serif;">
<li><span style="font-size: small;">Load</span></li>
<li><span style="font-size: small;">Initialize</span></li>
<li><span style="font-size: small;">Update</span></li>
<li><span style="font-size: small;">Draw</span></li>
<li><span style="font-size: small;">Free</span></li>
<li><span style="font-size: small;">Unload</span></li>
</ul>
<div style="font-family: "Trebuchet MS",sans-serif;">
<span style="font-size: small;">These are the six functions that will make up your main loop, and once constructed your main loop should need little to no modification throughout the development of your game. Each function represents a category of functionality during a state. Every state consists of these categories. Each different state will have six functions designed for each of the function pointers in the main loop to point to them. This way your main loop will simply point to different states with its six pointers whenever you want to switch from one state to another.</span></div>
<div style="font-family: "Trebuchet MS",sans-serif;">
<span style="font-size: small;"><br />
</span></div>
<div style="font-family: "Trebuchet MS",sans-serif;">
<span style="font-size: small;">The load function takes care of loading all of a state's necessary data. Load should be called only once per state -not even if the state restarts. Load also initializes the loaded data. This function is called first when a state starts.</span></div>
<div style="font-family: "Trebuchet MS",sans-serif;">
<span style="font-size: small;"><br />
</span></div>
<div style="font-family: "Trebuchet MS",sans-serif;">
<span style="font-size: small;">The initialize function prepares the state's data to be used initially. It should not load any data, only prepare it. This allows a fast restart of a state in the event a restart is required -no loading or unloading will be involved in a state restart.</span></div>
<div style="font-family: "Trebuchet MS",sans-serif;">
<span style="font-size: small;"><br />
</span></div>
<div style="font-family: "Trebuchet MS",sans-serif;">
<span style="font-size: small;">The update function uses a change in time (dt) to hand off to necessary functions to update the game in realtime. dt is defined as the time elapsed since the last call to update. Input should be gathered once per update call before calculations are made. All gameplay logic should happen in this state, and all live objects should be updated here.</span></div>
<div style="font-family: "Trebuchet MS",sans-serif;">
<span style="font-size: small;"><br />
</span></div>
<div style="font-family: "Trebuchet MS",sans-serif;">
<span style="font-size: small;">The draw function renders all required images onto the screen, and additionally plays any desired sound effects. A well organized program will send data off to a graphics manager in this state, allowing further decoupling of major system and logic components.</span></div>
<div style="font-family: "Trebuchet MS",sans-serif;">
<span style="font-size: small;"><br />
</span></div>
<div style="font-family: "Trebuchet MS",sans-serif;">
<span style="font-size: small;">The free function is what frees any objects or data no longer required, and sets the state up for switching or restarting. No data is unloaded (image sources, sound sources, meshes, etc). The idea is to set everything up to be initialized cleanly again.</span></div>
<div style="font-family: "Trebuchet MS",sans-serif;">
<span style="font-size: small;"><br />
</span></div>
<div style="font-family: "Trebuchet MS",sans-serif;">
<span style="font-family: 'Trebuchet MS', sans-serif;">The unload function is called during state termination, and unloads all data loaded in the load state. Here is an example of a properly set up game flow of a main loop:<span style="font-size: small;"> </span></span><br />
<div class="code">
<code>Initialize system components</code><br />
<code>GSM_Initialize( firstState )<br />
while not quitting<br />
if currentState is quitting<br />
nextState is Quit<br />
if currentState is restart<br />
currentState is previousState<br />
nextState is previousState<br />
else<br />
GSM_Update( )<br />
Load( )<br />
Initialize( )<br />
while currentState is nextState<br />
Update<br />
gather input<br />
get dt<br />
update game logic<br />
Draw( )<br />
Free( )<br />
if nextState is Restart<br />
previousState is currentState<br />
currentState is nextState<br />
else<br />
Unload( )<br />
previousState is currentState<br />
currentState is nextState<br />
Unload<br />
</code></div>
<br />
<span style="font-family: 'Trebuchet MS', sans-serif;"><span style="font-size: small;">By analyzing the setup of the above game flow you should be able to see how it works. To change a state, you simply modify the global variables currentState and nextState. previousState is then kept on-hand automatically. GSM_Update is responsible for updating the function pointers Load, Initialize, Update, Draw, Free and Unload whenever a state is started. In the event the global variable currentState changes, these function pointers will then change to their appropriate values via a switch statement. This switch statement lies within the GSM_Update function. The switch runs on the value of currentState, and once it finds a match it assigns the function pointers in the main loop to the appropriate matching state. Here is an example of a GSM_Update function:</span></span></div>
<br />
<div class="code">
<code>// Update the Game State Manager by syncing the three state indicators to their<br />
// corresponding function pointers (all six of them).<br />
int GSM_Update( void )<br />
{<br />
switch(currentState)<br />
{<br />
case Level_1:<br />
Load = &Level1_Load;<br />
Initialize = &Level1_Initialize;<br />
Update = &Level1_Update;<br />
Draw = &Level1_Draw;<br />
Free = &Level1_Free;<br />
Unload = &Level1_Unload;<br />
break;<br />
case Level_2:<br />
Load = &Level2_Load;<br />
Initialize = &Level2_Initialize;<br />
Update = &Level2_Update;<br />
Draw = &Level2_Draw;<br />
Free = &Level2_Free;<br />
Unload = &Level2_Unload;<br />
break;<br />
case MapEditor:<br />
Load = &MapEditor_Load;<br />
Initialize = &MapEditor_Initialize;<br />
Update = &MapEditor_Update;<br />
Draw = &MapEditor_Draw;<br />
Free = &MapEditor_Free;<br />
Unload = &MapEditor_Unload;<br />
break;<br />
case Presentation:<br />
Load = &PresentationLoad;<br />
Initialize = &PresentationInitialize;<br />
Update = &PresentationUpdate;<br />
Draw = &PresentationDraw;<br />
Free = &PresentationFree;<br />
Unload = &PresentationUnload;<br />
break;<br />
/*case Template:<br />
Load = &Load;<br />
Initialize = &Initialize;<br />
Update = &Update;<br />
Draw = &Draw;<br />
Free = &Free;<br />
Unload = &Unload;<br />
break;*/<br />
case Restart:<br />
break;<br />
case Quit:<br />
break;<br />
}<br />
return RETURN_SUCCESS;<br />
}</code></div>
<br />
<span style="font-family: 'Trebuchet MS', sans-serif;"><span style="font-size: small;">And there you have it; a proper organizational setup to allow an excellent method of managing game states. Using this sort of organization allows for each state to have a universal format which allows for modification of states, additions of states, and deletions of states during development to be very easy and time-efficient.</span></span>CecilSunkurehttp://www.blogger.com/profile/16129986119923492789noreply@blogger.com2tag:blogger.com,1999:blog-3579312376304629754.post-68621266608064879532012-02-20T13:05:00.000-08:002012-07-03T12:57:58.383-07:00Window's Console Game: Variable Sized Object<span style="font-family: 'Trebuchet MS', sans-serif;">In the previous post I had talked a little bit about <a href="http://cecilsunkure.blogspot.com/2011/12/windows-console-game-painters-algorithm.html">image ordering, and image transparency</a>. The way the image data was held in memory was very quirky! We had to create an entire header file for each image, and each image had to be an entirely different structure definition due to arrays of data being different from image to image. I'd like to show you a method that makes use of some clever macros in order to achieve an interesting variable-sized image structure! The idea was actually brought to me by a friend of mine named Malcolm Smith. Here's the structure design for an object to be dynamically sized during run-time, in our case for images:</span><br />
<div>
<span style="font-family: 'Trebuchet MS', sans-serif;"><br />
</span></div>
<div class="code">
<code>typedef struct _Image</code><br />
<div style="font-family: 'Times New Roman';">
<code><span style="font-family: monospace;">{</span></code></div>
<div style="font-family: 'Times New Roman';">
<code><span style="font-family: monospace;"> int width;</span> </code></div>
<div style="font-family: 'Times New Roman';">
<code><span class="Apple-tab-span" style="white-space: pre;"><span style="font-family: monospace;"> int height;</span></span></code></div>
<code><span style="white-space: pre;"> unsigned char *</span><span style="white-space: pre;">chars</span><span style="white-space: pre;">;</span></code><br />
<code><span style="white-space: pre;"> unsigned char *colors;</span></code><br />
<div style="font-family: 'Times New Roman';">
<code><span style="font-family: monospace;">} Image_;</span></code></div>
</div>
<span style="font-family: 'Trebuchet MS', sans-serif;"><br />
</span><br />
<span style="font-family: 'Trebuchet MS', sans-serif;">In the above structure we have two pointers, one to chars and one to colors. These pointers will point to arrays of unsigned characters, which is the datatype that represents both colors and characters for the Window's console. In order to access these arrays, you should recall that the name of an array can be treated the same as a pointer to the first element in the array. So after we allocate space for our arrays we'll need to initialize </span><span style="font-family: 'Courier New', Courier, monospace;">chars</span><span style="font-family: 'Trebuchet MS', sans-serif;"> and </span><span style="font-family: 'Courier New', Courier, monospace;">colors</span><span style="font-family: 'Trebuchet MS', sans-serif;"> properly by setting them to point to the first element in our arrays.</span><br />
<span style="font-family: 'Trebuchet MS', sans-serif;"><br />
</span><br />
<span style="font-family: 'Trebuchet MS', sans-serif;">In order to go about allocating our space properly we need to allocate the space of the Image_ structure, space for the width * the size of our character array * height, and finally space for our color array * width * height. Here's a call to malloc to this in one single swoop:</span><br />
<span style="font-family: 'Trebuchet MS', sans-serif;"><br />
</span><br />
<div class="code">
<code>Image_ *image = (Image_ *)malloc( sizeof( Image_ ) +</code><br />
<span style="font-family: monospace;"> sizeof( width * height * sizeof( unsigned char ) +</span><br />
<span style="font-family: monospace;"> sizeof( width * height * sizeof( unsigned char ) );</span></div>
<br />
<span style="font-family: 'Trebuchet MS', sans-serif;">The nice thing about this sort of allocation is that it isn't broken up into separate allocation calls, which speeds up the process since allocation is slow. This also keeps all the parts of memory in the same location in memory all adjacent to one another, as opposed to who knows where in memory when malloc is called multiple times, thus lessening memory fragmentation.</span><br />
<span style="font-family: 'Trebuchet MS', sans-serif;"><br />
</span><br />
<span style="font-family: 'Trebuchet MS', sans-serif;">Now we have our problem of getting our chars and colors pointers to point to their proper locations in memory. We aren't going to set up a conventional array of pointers, like proper C would dictate. Instead we'll use a couple macros to help us index the array ourselves, thus saving some references and memory in the process. We'll make use of a few macros to take over the job from the compiler; observe:</span><br />
<span style="font-family: 'Trebuchet MS', sans-serif;"><br />
</span><br />
<div class="code">
<code>#define unsigned char CHAR</code><br />
<code>#define unsigned char COL</code><br />
<br />
<code>#define PtrAdd( ptr, offset ) \</code><br />
<code> (((char *)ptr) + offset)</code><br />
<code><br />
<code>#define CharAt( image, x, y ) \</code><br />
<code> (CHAR *)(PtrAdd( image->chars, ((y) * image->width + (x)) * sizeof( CHAR ) ))</code><br />
<code> </code> <br />
<code>#define ColorAt( image, x, y ) \</code><br />
<code> (COL *)(PtrAdd( image->colors, ((y) * image->width + (x)) * sizeof( COL ) ))</code><br />
<br />
</code></div>
<br />
<span style="font-family: 'Trebuchet MS', sans-serif;">The first macro is a nice macro to have as it is generalized. It simply takes a pointer and an offset in bytes, then returns a pointer in memory that is ahead (or behind) the original pointer by the offset bytes. It's a macro for pointer addition/subtraction that works by typecasting the pointer supplied as a char, which is a byte in size, thus forcing the addition of the offset to work in chunks of 8 bits. As such the units of offset is in bytes. This can be used to initialize our chars and colors pointer!</span><br />
<span style="font-family: 'Trebuchet MS', sans-serif;"><br />
</span><br />
<div class="code">
<code>// Initialize chars pointer to directly after Image_ struct</code><br />
<code>image->chars = PtrAdd( image, sizeof( Image_ ) );</code><br />
<br />
<code>// Initialize colors pointer to directly after chars array</code><br />
<code>image->colors = PtrAdd( image->chars, width * height * sizeof( CHAR );</code></div>
<br />
<span style="font-family: 'Trebuchet MS', sans-serif;">Now that we can properly initialize our pointers in our struct, it's time to start making use of our CharAt and ColorAt macros to index our two arrays! First though lets initialize our arrays to zero with a looping function.</span><br />
<span style="font-family: 'Trebuchet MS', sans-serif;"><br />
</span><br />
<div class="code">
<code>void ZeroImage( Image_ *image )<br />
{<br />
int x, y; // used for indexing</code><br />
<code> CHAR *thisChar;</code><br />
<code> COL *thisColor;</code><br />
<br />
<code> for(y = 0; y < image->height; y++)</code><br />
<code> {</code><br />
<code> for(x = 0; x < image->width; x++)</code><br />
<code> {</code><br />
<code> thisChar = CharAt( image, x, y );</code><br />
<code> *thisChar = 0;</code><br />
<code> }</code><br />
<code> }</code><br />
<br />
<div style="font-family: 'Times New Roman';">
<code><code> for(y = 0; y < image->height; y++)</code></code></div>
<div style="font-family: 'Times New Roman';">
<code><code> {</code></code></div>
<div style="font-family: 'Times New Roman';">
<code><code> for(x = 0; x < image->width; x++)</code></code></div>
<div style="font-family: 'Times New Roman';">
<code><code> {</code></code></div>
<div style="font-family: 'Times New Roman';">
<code><code> thisColor = ColorAt( image, x, y );</code></code></div>
<div style="font-family: 'Times New Roman';">
<code><code> *thisColor = 0;</code></code></div>
<div style="font-family: 'Times New Roman';">
<code><code> }</code></code></div>
<div style="font-family: 'Times New Roman';">
<code><code> }</code></code></div>
<code> }</code></div>
<br />
<span style="font-family: 'Trebuchet MS', sans-serif;">A function that loops through all elements of the chars and colors array is very easy to write with our macros. You might be able to guess how we're going to fill out our arrays. You can actually copy/paste the ZeroImage function and change the lines that assign a zero to lines that assign a character value. You can use the x and y iterators to index an array of image data as well! Here's an example function:</span><br />
<span style="font-family: 'Trebuchet MS', sans-serif;"><br />
</span><br />
<div class="code">
<code></code><br />
<code>void ImageSet( Image_ *image, CHAR *charData, COL *colorData )</code><br />
<code>{</code><br />
<div style="font-family: 'Times New Roman';">
<code><code> int x, y; // used for indexing</code></code></div>
<div style="font-family: 'Times New Roman';">
<code><code> CHAR *thisChar;</code></code></div>
<div style="font-family: 'Times New Roman';">
<code><code> COL *thisColor;</code></code></div>
<br />
<code> for(y = 0; y < image->height; y++)</code><br />
<code> {</code><br />
<code> for(x = 0; x < image->width; x++)</code><br />
<code> {</code><br />
<code> thisChar = CharAt( image, x, y );</code><br />
<code> *thisChar = charData[(y * image->width) + x];</code><br />
<code> }</code><br />
<code> }</code><br />
<br />
<code> for(y = 0; y < image->height; y++)</code><br />
<code> {</code><br />
<code> for(x = 0; x < image->width; x++)</code><br />
<code> {</code><br />
<code> thisColor = ColorAt( image, x, y );</code><br />
<code> *thisColor = colorData[(y * image->width) + x];</code><br />
<code> }</code><br />
<code> }</code><br />
<code> }</code></div>
<br />
<span style="font-family: 'Trebuchet MS', sans-serif;">Now all you'd need in order to implement this variable-sized image format is image data! You can write image data by hand, use <a href="http://forums.tigsource.com/index.php?topic=14588.0">some interesting tools</a>, or parse the data from an image (like a BMP) yourself. Later on in another future post I may perhaps write about how to parse a BMP for it's image data. For now however, I suggest getting comfortable with the tools I've linked to.</span><br />
<br />
<br />
<span style="font-family: 'Trebuchet MS', sans-serif;">Series on creating a Windows Console game:</span><br />
<ul>
<li><a href="http://cecilsunkure.blogspot.com/2011/11/windows-console-game-setting-up-window.html"><span style="font-family: 'Trebuchet MS', sans-serif;">Setting up the Window</span></a></li>
<li><a href="http://cecilsunkure.blogspot.com/2011/11/windows-console-game-writing-to-console.html"><span style="font-family: 'Trebuchet MS', sans-serif;">Writing to the Console</span></a></li>
<li><a href="http://cecilsunkure.blogspot.com/2011/11/windows-console-game-event-handling.html"><span style="font-family: 'Trebuchet MS', sans-serif;">Event Handling</span></a></li>
<li><a href="http://cecilsunkure.blogspot.com/2011/12/windows-console-game-set-custom-color.html"><span style="font-family: 'Trebuchet MS', sans-serif;">Custom Color Palette and Font Size</span></a></li>
<li><a href="http://cecilsunkure.blogspot.com/2011/12/windows-console-game-painters-algorithm.html"><span style="font-family: 'Trebuchet MS', sans-serif;">Painter's Algorithm</span></a></li>
<li><span style="font-family: 'Trebuchet MS', sans-serif;"><a href="http://cecilsunkure.blogspot.com/2012/02/windows-console-game-variable-sized.html">Variable Sized Object</a></span></li>
<li><span style="font-family: 'Trebuchet MS', sans-serif;"><a href="http://cecilsunkure.blogspot.com/2012/07/windows-console-game-ascii-engine.html">Ascii Engine</a></span></li>
</ul>
<br />
<ul>
</ul>CecilSunkurehttp://www.blogger.com/profile/16129986119923492789noreply@blogger.com1tag:blogger.com,1999:blog-3579312376304629754.post-4751075747191741052011-12-05T13:10:00.001-08:002012-07-03T12:58:07.392-07:00Windows Console Game: Painter's Algorithm<span class="Apple-style-span" style="font-family: 'Trebuchet MS', sans-serif;"></span><br />
<span class="Apple-style-span" style="font-family: 'Trebuchet MS', sans-serif;">The previous post in this series was on a wonderful bag of tricks used to <a href="http://cecilsunkure.blogspot.com/2011/12/windows-console-game-set-custom-color.html">set a custom color palette</a> (awesome!) and change the font and font size. In this post we'll be going over the <a href="http://en.wikipedia.org/wiki/Painter's_algorithm">painter's algorithm</a>, and how to actually make use of it in your game.</span><br />
<span class="Apple-style-span" style="font-family: 'Trebuchet MS', sans-serif;"><br />
</span><br />
<span class="Apple-style-span" style="font-family: 'Trebuchet MS', sans-serif;">The painter's algorithm is a very simple priority paradigm which dictates when you place what image onto the screen.</span><br />
<span class="Apple-style-span" style="font-family: 'Trebuchet MS', sans-serif;"><br />
</span><br />
<span class="Apple-style-span" style="font-family: 'Trebuchet MS', sans-serif;">For example suppose you have three different images; the sky, a cloud, and the sun. You want to display these images, but you don't want the sun overlapping a cloud (physically impossible), or even worse have the blue sky overlap everything. To solve this you simply draw images onto the screen starting with the one that is going to be furthest back in terms of depth, which would be the sky.</span><br />
<span class="Apple-style-span" style="font-family: 'Trebuchet MS', sans-serif;"><br />
</span><br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhW0dqutiSTuH4IU20hmfvlucs1alS1t8p0JdGFoRD6rotQCJ_VoctQD7yndLUEJehlbGlD66x12QnLF0Q2eX4MzXnLHY4QEWdhmStJUbr2Y4j58gA1OrB1VvBaQhVUzgkvcAay8PsU38w/s1600/a1.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="198" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhW0dqutiSTuH4IU20hmfvlucs1alS1t8p0JdGFoRD6rotQCJ_VoctQD7yndLUEJehlbGlD66x12QnLF0Q2eX4MzXnLHY4QEWdhmStJUbr2Y4j58gA1OrB1VvBaQhVUzgkvcAay8PsU38w/s320/a1.png" width="320" /></a></div>
<div style="text-align: center;">
<span class="Apple-style-span" style="font-family: 'Trebuchet MS', sans-serif;"><i>Example of drawing sky, then sun, then cloud. Correct.</i></span></div>
<span class="Apple-style-span" style="font-family: 'Trebuchet MS', sans-serif;"><br />
</span><br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgZikTIlF_l7P1piCrPFXZUHCQUufypLEOmeUnHBuH0mAFDXKV8Eh2U0XCLq4jlfV-x66HqwY-uPF7kw0UrYXBe_AArYUXe8Aw2aNQu5ahrMAaVU5tGiaMPnFm1NjDmTu80jeVqXJlvwUI/s1600/a2.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="198" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgZikTIlF_l7P1piCrPFXZUHCQUufypLEOmeUnHBuH0mAFDXKV8Eh2U0XCLq4jlfV-x66HqwY-uPF7kw0UrYXBe_AArYUXe8Aw2aNQu5ahrMAaVU5tGiaMPnFm1NjDmTu80jeVqXJlvwUI/s320/a2.png" width="320" /></a></div>
<div style="text-align: center;">
<span class="Apple-style-span" style="font-family: 'Trebuchet MS', sans-serif;"><i>Example of drawing sky, then cloud, then sun. Wrong.</i></span></div>
<span class="Apple-style-span" style="font-family: 'Trebuchet MS', sans-serif;"><br />
</span><br />
<span class="Apple-style-span" style="font-family: 'Trebuchet MS', sans-serif;">If we recall the <a href="http://cecilsunkure.blogspot.com/2011/11/windows-console-game-event-handling.html">article on event handling</a>, the article actually taught a method for producing and writing images to the screen by using header files to hold image data and a function to write images to an array (or buffer) of CHAR_INFO structures. Using the same system, you can create images in header files and then write them to the screen in the correct order so that images overlap each other at the proper times. The way you go about this is to have your array of CHAR_INFO structures for writing images to. Then once you've manipulated the array (or buffer) all you want, you then pass it to the WriteConsoleOutput function and place it onto the screen in one fell swoop.</span><br />
<span class="Apple-style-span" style="font-family: 'Trebuchet MS', sans-serif;"><br />
</span><br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhOSBR1DEKnGiFxKqsYdq8ucdMpNM7Xszil5m3fgB-otjSFlMHJSIodOHQto_sa17L8Z7_8dTlM-Hws8K8l65Zp0Zgku0fEJ5j2cf-RIsG87zAaT1j8UDBtF9FCxpREt4dAfZhS0tAmWZY/s1600/Capture.PNG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="174" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhOSBR1DEKnGiFxKqsYdq8ucdMpNM7Xszil5m3fgB-otjSFlMHJSIodOHQto_sa17L8Z7_8dTlM-Hws8K8l65Zp0Zgku0fEJ5j2cf-RIsG87zAaT1j8UDBtF9FCxpREt4dAfZhS0tAmWZY/s320/Capture.PNG" width="320" /></a></div>
<div style="text-align: center;">
<span class="Apple-style-span" style="font-family: 'Trebuchet MS', sans-serif;"><i>Here's a screenshot of a demo program I wrote just for this specific purpose!</i></span></div>
<div style="text-align: center;">
<span class="Apple-style-span" style="font-family: 'Trebuchet MS', sans-serif;"><i>Rendering of images with transparency using painter's algorithm.</i></span></div>
<div style="text-align: center;">
<span class="Apple-style-span" style="font-family: 'Trebuchet MS', sans-serif;"><i>Note: Read <a href="http://cecilsunkure.blogspot.com/2011/12/windows-console-game-set-custom-color.html">this article</a> for info on resizing font, this will allow</i></span></div>
<div style="text-align: center;">
<span class="Apple-style-span" style="font-family: 'Trebuchet MS', sans-serif;"><i>you to have square characters like in the image above (8x8).</i></span></div>
<span class="Apple-style-span" style="font-family: 'Trebuchet MS', sans-serif;"><br />
</span><br />
<span class="Apple-style-span" style="font-family: 'Trebuchet MS', sans-serif;">Building from our knowledge gained in the previous posts, I've put together a nice demo that displays the images above, and lets you draw on the screen with the left and right clicks of the mouse. Lets examine some of the code:</span><br />
<br />
<div class="code">
<code></code><br />
<code>#ifndef FILESUNH</code><br />
<code>#define FILESUNH</code><br />
<code><br />
</code><br />
<code>/* A SUN background! */</code><br />
<code><br />
</code><br />
<code>#define SUNW 15</code><br />
<code>#define SUNH 15</code><br />
<code><br />
</code><br />
<code>typedef struct</code><br />
<code>{</code><br />
<code> int width;</code><br />
<code> int height;</code><br />
<code> int chars[SUNW * SUNH];</code><br />
<code> int colors[SUNW * SUNH];</code><br />
<code>} _SUN;</code><br />
<code><br />
</code><br />
<code>_SUN SUN = </code><br />
<code>{</code><br />
<code> SUNW,</code><br />
<code> SUNH,</code><br />
<code> {</code><br />
<code> 255,255,255,255,255,255,255,177,255,255,255,255,255,255,255,</code><br />
<code> 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,</code><br />
<code> 255,255,255,177,255,255,255,177,255,255,255,177,255,255,255,</code><br />
<code> 255,255,255,255,177,255,255,255,255,255,177,255,255,255,255,</code><br />
<code> 255,255,255,255,255,255,177,177,177,255,255,255,255,255,255,</code><br />
<code> 255,255,255,255,255,177,178,219,178,177,255,255,255,255,255,</code><br />
<code> 255,255,255,255,177,178,219,219,219,178,177,255,255,255,255,</code><br />
<code> 177,255,177,255,177,219, 94,219, 94,219,177,255,177,255,177,</code><br />
<code> 255,255,255,255,177,178,219,126,219,178,177,255,255,255,255,</code><br />
<code> 255,255,255,255,255,177,178,219,178,177,255,255,255,255,255,</code><br />
<code> 255,255,255,255,255,255,177,177,177,255,255,255,255,255,255,</code><br />
<code> 255,255,255,255,177,255,255,255,255,255,177,255,255,255,255,</code><br />
<code> 255,255,255,177,255,255,255,177,255,255,255,177,255,255,255,</code><br />
<code> 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,</code><br />
<code> 255,255,255,255,255,255,255,177,255,255,255,255,255,255,255,</code><br />
<code> },</code><br />
<code> {</code><br />
<code> 0, 0, 0, 0, 0, 0, 0, 62, 0, 0, 0, 0, 0, 0, 0,</code><br />
<code> 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,</code><br />
<code> 0, 0, 0, 62, 0, 0, 0, 62, 0, 0, 0, 62, 0, 0, 0,</code><br />
<code> 0, 0, 0, 0, 62, 0, 0, 0, 0, 0, 62, 0, 0, 0, 0,</code><br />
<code> 0, 0, 0, 0, 0, 0, 62, 62, 62, 0, 0, 0, 0, 0, 0,</code><br />
<code> 0, 0, 0, 0, 0, 62, 62, 14, 62, 62, 0, 0, 0, 0, 0,</code><br />
<code> 0, 0, 0, 0, 62, 62, 14, 14, 14, 62, 62, 0, 0, 0, 0,</code><br />
<code> 62, 0, 62, 0, 62, 14,224, 14,224, 14, 62, 0, 62, 0, 62,</code><br />
<code> 0, 0, 0, 0, 62, 62, 14,224, 14, 62, 62, 0, 0, 0, 0,</code><br />
<code> 0, 0, 0, 0, 0, 62, 62, 14, 62, 62, 0, 0, 0, 0, 0,</code><br />
<code> 0, 0, 0, 0, 0, 0, 62, 62, 62, 0, 0, 0, 0, 0, 0,</code><br />
<code> 0, 0, 0, 0, 62, 0, 0, 0, 0, 0, 62, 0, 0, 0, 0,</code><br />
<code> 0, 0, 0, 62, 0, 0, 0, 62, 0, 0, 0, 62, 0, 0, 0,</code><br />
<code> 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,</code><br />
<code> 0, 0, 0, 0, 0, 0, 0, 62, 0, 0, 0, 0, 0, 0, 0,</code><br />
<code> }</code><br />
<code>};</code><br />
<code><br />
</code><br />
<code>#endif /* FILESUNH */</code><br />
<code> </code></div>
<br />
<span class="Apple-style-span" style="font-family: 'Trebuchet MS', sans-serif;">The above code is the header file for the image of the sun. As shown in this article, you can easily create new images! The most interesting thing about this image is the 255 character code in the chars array. This code is actually used for transparency. I modified our old writeImageToBuffer code to account for transparency by adding in a single if statement. If the loop finds a character of 255, it does nothing and skips the character. This will leave whatever character was already written in that particular location alone, thus creating transparency! Take a look at the new writeImageToBuffer function:</span><br />
<br />
<div class="code">
<code></code><br />
<code>/* Writes an image to the buffer */</code><br />
<code>void writeImageToBuffer(CHAR_INFO buffer[], int chars[], int colors[], int imageBUFFERWIDTH, int imageBUFFERHEIGHT, int xoffset, int yoffset)</code><br />
<code>{</code><br />
<code> int x, y;</code><br />
<code> </code><br />
<code> /* Keep xoffset and yoffset within the screen's boundaries */</code><br />
<code> boundCheck(&xoffset, &yoffset);</code><br />
<code> </code><br />
<code> for (y = 0; y < imageBUFFERHEIGHT; ++y)</code><br />
<code> {</code><br />
<code> for (x = 0; x < imageBUFFERWIDTH; ++x)</code><br />
<code> {</code><br />
<code> if (chars[x + imageBUFFERWIDTH * y] != (unsigned char)255)</code><br />
<code> {</code><br />
<code> buffer[(x + xoffset) + BUFFERWIDTH * (y + yoffset)].Char.AsciiChar =</code><br />
<code> chars[x + imageBUFFERWIDTH * y];</code><br />
<code> buffer[(x + xoffset) + BUFFERWIDTH * (y + yoffset)].Attributes =</code><br />
<code> colors[x + imageBUFFERWIDTH * y];</code><br />
<code> }</code><br />
<code> }</code><br />
<code> }</code><br />
<code> return;</code><br />
<code>}</code><br />
<code> </code></div>
<br />
<span class="Apple-style-span" style="font-family: 'Trebuchet MS', sans-serif;">As I said, there's simply a new if statement to make sure that the character 255 is not written onto the screen. 255 in ASCII is a character you'll more than likely find pretty useless, as it just fills the whole space with foreground, though you have the exact same thing with 219 without any nasty side affects that 255 can ensue on your code. Basically 255 is the perfect ASCII index for transparency as it's pretty much useless as anything else.</span><br />
<span class="Apple-style-span" style="font-family: 'Trebuchet MS', sans-serif;"><br />
</span><br />
<span class="Apple-style-span" style="font-family: 'Trebuchet MS', sans-serif;">The last thing to show in this demo is the order in which you actually write images onto the buffer, being sky sun and cloud. This is really simple as shown here:</span><br />
<br />
<div class="code">
<code></code><br />
<code>writeImageToBuffer(consoleBuffer, SKY.chars, SKY.colors, SKY.width, SKY.height, 0, 0);</code><br />
<code>writeImageToBuffer(consoleBuffer, SUN.chars, SUN.colors, SUN.width, SUN.height, 10, 5);</code><br />
<code>writeImageToBuffer(consoleBuffer, CLOUD.chars, CLOUD.colors, CLOUD.width, CLOUD.height, 15, 11);</code><br />
<code> </code></div>
<br />
<span class="Apple-style-span" style="font-family: 'Trebuchet MS', sans-serif;">And there you have it! By ensuring that you write images in the correct order in terms of depth, you overwrite images farther back with images closer up creating a proper sense of depth to the viewer.</span><br />
<span class="Apple-style-span" style="font-family: 'Trebuchet MS', sans-serif;"><br />
</span><br />
<span class="Apple-style-span" style="font-family: 'Trebuchet MS', sans-serif;">The next post in this series is on a more flexible image structure format to allow a <a href="http://cecilsunkure.blogspot.com/2012/02/windows-console-game-variable-sized.html">variable sized structure</a>.</span><br />
<br />
<br />
<span style="font-family: 'Trebuchet MS', sans-serif;">Series on creating a Windows Console game:</span><br />
<ul>
<li><a href="http://cecilsunkure.blogspot.com/2011/11/windows-console-game-setting-up-window.html"><span style="font-family: 'Trebuchet MS', sans-serif;">Setting up the Window</span></a></li>
<li><a href="http://cecilsunkure.blogspot.com/2011/11/windows-console-game-writing-to-console.html"><span style="font-family: 'Trebuchet MS', sans-serif;">Writing to the Console</span></a></li>
<li><a href="http://cecilsunkure.blogspot.com/2011/11/windows-console-game-event-handling.html"><span style="font-family: 'Trebuchet MS', sans-serif;">Event Handling</span></a></li>
<li><a href="http://cecilsunkure.blogspot.com/2011/12/windows-console-game-set-custom-color.html"><span style="font-family: 'Trebuchet MS', sans-serif;">Custom Color Palette and Font Size</span></a></li>
<li><a href="http://cecilsunkure.blogspot.com/2011/12/windows-console-game-painters-algorithm.html"><span style="font-family: 'Trebuchet MS', sans-serif;">Painter's Algorithm</span></a></li>
<li><span style="font-family: 'Trebuchet MS', sans-serif;"><a href="http://cecilsunkure.blogspot.com/2012/02/windows-console-game-variable-sized.html">Variable Sized Object</a></span></li>
<li><span style="font-family: 'Trebuchet MS', sans-serif;"><a href="http://cecilsunkure.blogspot.com/2012/07/windows-console-game-ascii-engine.html">Ascii Engine</a></span></li>
</ul>
<br />
<ul>
</ul>
<br />
<span class="Apple-style-span" style="font-family: 'Trebuchet MS', sans-serif;"> </span>CecilSunkurehttp://www.blogger.com/profile/16129986119923492789noreply@blogger.com5tag:blogger.com,1999:blog-3579312376304629754.post-39376741440164418982011-12-01T14:25:00.001-08:002012-07-03T12:58:12.305-07:00Windows Console Game: Set Custom Color Palette and Font Size<span class="Apple-style-span" style="font-family: 'Trebuchet MS', sans-serif;">Last post the topic was of <a href="http://cecilsunkure.blogspot.com/2011/11/windows-console-game-event-handling.html">event handling</a>, this article is going to cover a treat! I have recently been graced with a great sample source code of a program that can alter the windows console font, color palette, and font size. If you've ever searched for methods of changing these aspects, if you're like me, you'd have found a whole lot of nothing. Luckily, like I mentioned, someone gave me some sample source code that I'd like to share.</span><br />
<span class="Apple-style-span" style="font-family: 'Trebuchet MS', sans-serif;"><br />
</span><br />
<span class="Apple-style-span" style="font-family: 'Trebuchet MS', sans-serif;">The source code, as I was told and will now tell you, is filled with a whole lot of a whole lot of ugliness, undocumented Windows functions, and magic. Despite these scary facts this source code is pretty easy to use and grants access to some very nice to have features, that can make the creating of a console game much prettier! For example say you are creating an ASCII game in the Windows Console and realize that you're stuck with the default key size of 8x12 pixels. This sucks. Now constructing square images is going to be a gigantic pain! It would be wonderful if you could have all of your characters simply be squares! Well, there's a nice 8x8 Terminal font that is available to use.</span><br />
<span class="Apple-style-span" style="font-family: 'Trebuchet MS', sans-serif;"><br />
</span><br />
<span class="Apple-style-span" style="font-family: 'Trebuchet MS', sans-serif;">Here are the source files:</span><br />
<ul>
<li><span class="Apple-style-span" style="font-family: 'Trebuchet MS', sans-serif;"><a href="http://www.mediafire.com/?vd89kh4poixkjqk">source</a></span></li>
</ul>
<div>
<span class="Apple-style-span" style="font-family: 'Trebuchet MS', sans-serif;">I've modified the files so that they should compile cleanly in Visual Studio 2010, and in GCC 4.X.X. Once compiled the exe should run a short demo displaying a few different things, including modifying the console's color palette and setting it to the default colors, changing the font type, and changing the font size.</span></div>
<div>
<span class="Apple-style-span" style="font-family: 'Trebuchet MS', sans-serif;"><br />
</span></div>
<div>
<span class="Apple-style-span" style="font-family: 'Trebuchet MS', sans-serif;">This all works by using a few functions from kernel32.dll, some of which are undocumented and thus very difficult to use. I don't know exactly how everything works, and a good amount of it I don't understand whatsoever - though this is to be expected when messing with things that don't have documentation. The goal is for me to explain just what is necessary to understand the idea of what's going on so you can apply these desired features to your own console application.</span></div>
<div>
<span class="Apple-style-span" style="font-family: 'Trebuchet MS', sans-serif;"><br />
</span></div>
<div>
<span class="Apple-style-span" style="font-family: 'Trebuchet MS', sans-serif;">Lets start off by explaining the main function.</span></div>
<br />
<div class="code">
<code></code><br />
<pre style="background-color: #f6f6f6; line-height: 1.1em; margin-bottom: 0.5em; margin-top: 0.5em; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; text-align: left;"><code><span class="kt" style="color: #9966cc; font-weight: 700; line-height: 13px;">int</span> <span class="nf">main</span><span class="p">(</span><span class="kt" style="color: #9966cc; font-weight: 700; line-height: 13px;">void</span><span class="p">)</span>
<span class="p">{</span>
<span class="cm" style="color: #669933; font-style: italic; line-height: 13px;">/* Setting the color palette to the default colors</span>
<span class="cm" style="color: #669933; font-style: italic; line-height: 13px;"> /* Browse MSDN for COLORREF to learn more about these RGB values */</span>
<span class="n">COLORREF</span> <span class="n">palette</span><span class="p">[</span><span class="mi" style="line-height: 13px;">16</span><span class="p">]</span> <span class="o">=</span>
<span class="p">{</span>
<span class="mh" style="line-height: 13px;">0x00000000</span><span class="p">,</span> <span class="mh" style="line-height: 13px;">0x00800000</span><span class="p">,</span> <span class="mh" style="line-height: 13px;">0x00008000</span><span class="p">,</span> <span class="mh" style="line-height: 13px;">0x00808000</span><span class="p">,</span>
<span class="mh" style="line-height: 13px;">0x00000080</span><span class="p">,</span> <span class="mh" style="line-height: 13px;">0x00800080</span><span class="p">,</span> <span class="mh" style="line-height: 13px;">0x00008080</span><span class="p">,</span> <span class="mh" style="line-height: 13px;">0x00c0c0c0</span><span class="p">,</span>
<span class="mh" style="line-height: 13px;">0x00808080</span><span class="p">,</span> <span class="mh" style="line-height: 13px;">0x00ff0000</span><span class="p">,</span> <span class="mh" style="line-height: 13px;">0x0000ff00</span><span class="p">,</span> <span class="mh" style="line-height: 13px;">0x00ffff00</span><span class="p">,</span>
<span class="mh" style="line-height: 13px;">0x000000ff</span><span class="p">,</span> <span class="mh" style="line-height: 13px;">0x00ff00ff</span><span class="p">,</span> <span class="mh" style="line-height: 13px;">0x0000ffff</span><span class="p">,</span> <span class="mh" style="line-height: 13px;">0x00ffffff</span>
<span class="p">};</span>
<span class="cm" style="color: #669933; font-style: italic; line-height: 13px;">/* Search MSDN for the RGB macro to easily generate COLORREF values */</span>
<span class="n">SetConsolePalette</span><span class="p">(</span><span class="n">palette</span><span class="p">,</span> <span class="mi" style="line-height: 13px;">6</span><span class="p">,</span> <span class="mi" style="line-height: 13px;">6</span><span class="p">,</span> <span class="s" style="color: #cc9933; font-weight: 700; line-height: 13px;">L""</span><span class="p">);</span>
<span class="n">printf</span><span class="p">(</span><span class="s" style="color: #cc9933; font-weight: 700; line-height: 13px;">"Small default font.</span><span class="se" style="color: #cc9933; font-weight: 700; line-height: 13px;">\n</span><span class="s" style="color: #cc9933; font-weight: 700; line-height: 13px;">"</span><span class="p">);</span>
<span class="n">Sleep</span><span class="p">(</span><span class="mi" style="line-height: 13px;">2000</span><span class="p">);</span>
<span class="n">SetConsolePalette</span><span class="p">(</span><span class="n">palette</span><span class="p">,</span> <span class="mi" style="line-height: 13px;">1</span><span class="p">,</span> <span class="mi" style="line-height: 13px;">2</span><span class="p">,</span> <span class="s" style="color: #cc9933; font-weight: 700; line-height: 13px;">L"Lucida Console"</span><span class="p">);</span>
<span class="n">printf</span><span class="p">(</span><span class="s" style="color: #cc9933; font-weight: 700; line-height: 13px;">"Too tiny to read Lucida!</span><span class="se" style="color: #cc9933; font-weight: 700; line-height: 13px;">\n</span><span class="s" style="color: #cc9933; font-weight: 700; line-height: 13px;">"</span><span class="p">);</span>
<span class="n">Sleep</span><span class="p">(</span><span class="mi" style="line-height: 13px;">2000</span><span class="p">);</span>
<span class="k" style="color: #0033cc; font-weight: 700; line-height: 13px;">if</span> <span class="p">(</span><span class="n">windowsVersionTest</span><span class="p">())</span>
<span class="p">{</span>
<span class="n">SetConsolePalette</span><span class="p">(</span><span class="n">palette</span><span class="p">,</span> <span class="mi" style="line-height: 13px;">8</span><span class="p">,</span> <span class="mi" style="line-height: 13px;">12</span><span class="p">,</span> <span class="s" style="color: #cc9933; font-weight: 700; line-height: 13px;">L"Consolas"</span><span class="p">);</span>
<span class="n">printf</span><span class="p">(</span><span class="s" style="color: #cc9933; font-weight: 700; line-height: 13px;">"More of a normal Consolas size.</span><span class="se" style="color: #cc9933; font-weight: 700; line-height: 13px;">\n</span><span class="s" style="color: #cc9933; font-weight: 700; line-height: 13px;">"</span><span class="p">);</span>
<span class="p">}</span>
<span class="k" style="color: #0033cc; font-weight: 700; line-height: 13px;">else</span>
<span class="p">{</span>
<span class="n">SetConsolePalette</span><span class="p">(</span><span class="n">palette</span><span class="p">,</span> <span class="mi" style="line-height: 13px;">8</span><span class="p">,</span> <span class="mi" style="line-height: 13px;">12</span><span class="p">,</span> <span class="s" style="color: #cc9933; font-weight: 700; line-height: 13px;">L"Lucidas"</span><span class="p">);</span>
<span class="n">printf</span><span class="p">(</span><span class="s" style="color: #cc9933; font-weight: 700; line-height: 13px;">"More of a normal Lucidas size.</span><span class="se" style="color: #cc9933; font-weight: 700; line-height: 13px;">\n</span><span class="s" style="color: #cc9933; font-weight: 700; line-height: 13px;">"</span><span class="p">);</span>
<span class="p">}</span>
<span class="n">Sleep</span><span class="p">(</span><span class="mi" style="line-height: 13px;">2000</span><span class="p">);</span>
<span class="n">SetConsolePalette</span><span class="p">(</span><span class="n">palette</span><span class="p">,</span> <span class="mi" style="line-height: 13px;">43</span><span class="p">,</span> <span class="mi" style="line-height: 13px;">72</span><span class="p">,</span> <span class="s" style="color: #cc9933; font-weight: 700; line-height: 13px;">L"Lucida Console"</span><span class="p">);</span>
<span class="n">printf</span><span class="p">(</span><span class="s" style="color: #cc9933; font-weight: 700; line-height: 13px;">"Huge Lucida!</span><span class="se" style="color: #cc9933; font-weight: 700; line-height: 13px;">\n</span><span class="s" style="color: #cc9933; font-weight: 700; line-height: 13px;">"</span><span class="p">);</span>
<span class="n">getchar</span><span class="p">();</span>
<span class="k" style="color: #0033cc; font-weight: 700; line-height: 13px;">return</span> <span class="mi" style="line-height: 13px;">0</span><span class="p">;</span>
<span class="p">}</span></code></pre>
<code> </code></div>
<br />
<span class="Apple-style-span" style="font-family: 'Trebuchet MS', sans-serif;">This function has an array of hex numbers at the top. These numbers correspond to the color palette in the Windows Console's properties:</span><br />
<span class="Apple-style-span" style="font-family: 'Trebuchet MS', sans-serif;"><br />
</span><br />
<div class="separator" style="clear: both; text-align: center;">
<a href="http://i.imgur.com/hHeeM.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="http://i.imgur.com/hHeeM.png" /></a></div>
<span class="Apple-style-span" style="font-family: 'Trebuchet MS', sans-serif;"><br />
</span><br />
<span class="Apple-style-span" style="font-family: 'Trebuchet MS', sans-serif;">The eight colors above correspond to the eight elements of the palette array. You can change them to any RBG value, and you can test out different values like in the screenshot above, by messing with the Red Blue and Green color value fields. Just be sure to leave the left two digits in your hex values as 0, as only the first six digits are used.</span><br />
<span class="Apple-style-span" style="font-family: 'Trebuchet MS', sans-serif;"><br />
</span><br />
<span class="Apple-style-span" style="font-family: 'Trebuchet MS', sans-serif;">SetConsolePalette is a wrapper function that sets a console's palette, console font size, and console font. The first parameter is a color palette, the second is the font's x dimension, third is the font's y dimension, and last is the name of the font you wish to switch to in the form of a <a href="http://stackoverflow.com/questions/1810343/is-a-wide-character-string-literal-starting-with-l-like-lhello-world-guarantee">wide character literal</a>. Available fonts are Terminal, Lucidas, and Consolas by default. In order to have more available, you have to make them! Making fonts is definitely outside of the scope of this article, however. It should be noted that Consolas is only available in Vista/7 versions of Windows, and not available in XP. If you want to use the Terminal font, on lines 109 and 139 you must set the value of the 0 to 0x30. Which line you modify depends on your OS. Just modify both of those lines if you don't know which corresponds to one you need.</span><br />
<span class="Apple-style-span" style="font-family: 'Trebuchet MS', sans-serif;"><br />
</span><br />
<span class="Apple-style-span" style="font-family: 'Trebuchet MS', sans-serif;">That is about all the info you really need to simply use the source code! If you want to try to learn more, study the comments throughout the source code and/or ask me questions in the comments section. You can also try googling bits of the source code and see what you come up with. Googling CONSOLE_INFO came up with a lot of variations of the source I've posted, with some differing comments throughout the source files.</span><br />
<span class="Apple-style-span" style="font-family: 'Trebuchet MS', sans-serif;"><br />
</span><br />
<span class="Apple-style-span" style="font-family: 'Trebuchet MS', sans-serif;">I haven't created my own custom font yet, though I did find a nice tool <a href="http://www.cylog.org/graphics/rasterfonteditor.jsp">here</a> for editing and developing raster fonts. In the near future I'll probably create my own custom font for the console game(s) I'm creating as school projects. The next article in this series is on <a href="http://cecilsunkure.blogspot.com/2011/12/windows-console-game-painters-algorithm.html">painter's algorithm</a>.</span><br />
<br />
<br />
<span style="font-family: 'Trebuchet MS', sans-serif;">Series on creating a Windows Console game:</span><br />
<ul>
<li><a href="http://cecilsunkure.blogspot.com/2011/11/windows-console-game-setting-up-window.html"><span style="font-family: 'Trebuchet MS', sans-serif;">Setting up the Window</span></a></li>
<li><a href="http://cecilsunkure.blogspot.com/2011/11/windows-console-game-writing-to-console.html"><span style="font-family: 'Trebuchet MS', sans-serif;">Writing to the Console</span></a></li>
<li><a href="http://cecilsunkure.blogspot.com/2011/11/windows-console-game-event-handling.html"><span style="font-family: 'Trebuchet MS', sans-serif;">Event Handling</span></a></li>
<li><a href="http://cecilsunkure.blogspot.com/2011/12/windows-console-game-set-custom-color.html"><span style="font-family: 'Trebuchet MS', sans-serif;">Custom Color Palette and Font Size</span></a></li>
<li><a href="http://cecilsunkure.blogspot.com/2011/12/windows-console-game-painters-algorithm.html"><span style="font-family: 'Trebuchet MS', sans-serif;">Painter's Algorithm</span></a></li>
<li><span style="font-family: 'Trebuchet MS', sans-serif;"><a href="http://cecilsunkure.blogspot.com/2012/02/windows-console-game-variable-sized.html">Variable Sized Object</a></span></li>
<li><span style="font-family: 'Trebuchet MS', sans-serif;"><a href="http://cecilsunkure.blogspot.com/2012/07/windows-console-game-ascii-engine.html">Ascii Engine</a></span></li>
</ul>
<br />
<ul>
</ul>CecilSunkurehttp://www.blogger.com/profile/16129986119923492789noreply@blogger.com4tag:blogger.com,1999:blog-3579312376304629754.post-14022678204434989372011-11-26T11:21:00.001-08:002012-07-03T12:58:17.950-07:00Windows Console Game: Event Handling<span class="Apple-style-span" style="font-family: 'Trebuchet MS', sans-serif;">The last post in this series was on <a href="http://cecilsunkure.blogspot.com/2011/11/windows-console-game-writing-to-console.html">writing to the console</a>; this post I'd like to go over handling events within the Windows Console. There are two </span><a href="http://msdn.microsoft.com/en-us/library/windows/desktop/ms682079%28v=vs.85%29.aspx" style="font-family: 'Trebuchet MS', sans-serif;">types of events</a><span class="Apple-style-span" style="font-family: 'Trebuchet MS', sans-serif;"> we're interested in: </span><a href="http://msdn.microsoft.com/en-us/library/windows/desktop/ms684166%28v=vs.85%29.aspx" style="font-family: 'Trebuchet MS', sans-serif;">Keyboard Events</a><span class="Apple-style-span" style="font-family: 'Trebuchet MS', sans-serif;"> and </span><a href="http://msdn.microsoft.com/en-us/library/windows/desktop/ms684239%28v=vs.85%29.aspx" style="font-family: 'Trebuchet MS', sans-serif;">Mouse Events</a><span class="Apple-style-span" style="font-family: 'Trebuchet MS', sans-serif;">. The rest of the type of events we're going to ignore (and MSDN actually advises this on a couple internally used event types). In order to read keyboard events and mouse events, we need to get a record of all events that have occurred to the console since the last time these events were retrieved. This can be done with the following console functions: </span><a href="http://msdn.microsoft.com/en-us/library/windows/desktop/ms683207%28v=vs.85%29.aspx" style="font-family: 'Trebuchet MS', sans-serif;">GetNumberOfConsoleInputEvents</a><span class="Apple-style-span" style="font-family: 'Trebuchet MS', sans-serif;">; </span><a href="http://msdn.microsoft.com/en-us/library/windows/desktop/ms684961%28v=VS.85%29.aspx" style="font-family: 'Trebuchet MS', sans-serif;">ReadConsoleInput</a><span class="Apple-style-span" style="font-family: 'Trebuchet MS', sans-serif;">.</span><br />
<span class="Apple-style-span" style="font-family: 'Trebuchet MS', sans-serif;"><br />
</span><br />
<span class="Apple-style-span" style="font-family: 'Trebuchet MS', sans-serif;">In order to read the console's input buffer (the record of events that have happened from input, including user input), we have to know how many events there are in order to <a href="http://cecilsunkure.blogspot.com/search/label/Malloc">dynamically allocate memory</a> to store those events. This is where GetNumberOfConsoleInputEvents comes. It takes the read handle and a <a href="http://msdn.microsoft.com/en-us/library/aa383751%28v=vs.85%29.aspx">DWORD</a> <a href="http://cecilsunkure.blogspot.com/search/label/Pointers">pointer</a> as its parameters, and places the number of events there are in the address pointed by the DWORD pointer.</span><br />
<br />
<div class="code">
<code></code><br />
<br />
<code>/* Read console input buffer and return malloc'd INPUT_RECORD array */</code><br />
<code>DWORD getInput(INPUT_RECORD **eventBuffer)</code><br />
<code>{</code><br />
<code> /* Variable for holding the number of current events, and a point to it */</code><br />
<code> DWORD numEvents = 0;</code><br />
<code><br />
</code><br />
<code> /* Variable for holding how many events were read */</code><br />
<code> DWORD numEventsRead = 0;</code><br />
<code><br />
</code><br />
<code> /* Put the number of console input events into numEvents */</code><br />
<code> GetNumberOfConsoleInputEvents(rHnd, &numEvents);</code><br />
<code><br />
</code><br />
<code> if (numEvents) /* if there's an event */</code><br />
<code> {</code><br />
<code> /* Allocate the correct amount of memory to store the events */</code><br />
<code> *eventBuffer = malloc(sizeof(INPUT_RECORD) * numEvents);</code><br />
<code> </code><br />
<code> /* Place the stored events into the eventBuffer pointer */</code><br />
<code> ReadConsoleInput(rHnd, *eventBuffer, numEvents, &numEventsRead);</code><br />
<code> }</code><br />
<code><br />
</code><br />
<code> /* Return the amount of events successfully read */</code><br />
<code> return numEventsRead;</code><br />
<code>}</code><br />
<br />
<code> </code></div>
<br />
<span class="Apple-style-span" style="font-family: 'Trebuchet MS', sans-serif;">The above code is a function that places an array of INPUT_RECORD structures into the content of the pointer pointed by the parameter eventBuffer. If you're confused about the double asterisk **, then read the rest of the paragraph. If you already understand what this function is doing, skip to the next paragraph. The asterisk, known as the dereference operator, can be read as "the content pointed by". In order for this getInput function to place the INPUT_RECORD structs into the address pointed by a pointer, we have to pass a pointer to a pointer to the function -otherwise we'd only pass the value of a pointer to the function, which isn't what we want. Then, to access the the pointer we passed, we'd use one asterisk. To access the value pointed by the pointer that is pointed to by the parameter pointer, we must use a second *. See the below diagram for a visual representation. On the left, Pointer 1 is dereferenced giving you direct access to Pointer2. Pointer2 is dereferenced giving you direct access to the INPUT_RECORD. The right side of the diagram uses two dereferences to directly access INPUT_RECORD in a single stroke.</span><br />
<span class="Apple-style-span" style="font-family: 'Trebuchet MS', sans-serif;"><br />
</span><br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgV-JEGFoFEcMCXc-QOejksCx-rYeGVx29FdPKjYfAqeIvYZ5PLNP4TLjOrfO5dqt7ZjEpUTLI5iMsmZHSJuwvmqtfb_9HwN4_ELBvypoxG24nWgfS-U1UGhwW42xXLI0V6bm0lhWtvGXk/s1600/pointers.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgV-JEGFoFEcMCXc-QOejksCx-rYeGVx29FdPKjYfAqeIvYZ5PLNP4TLjOrfO5dqt7ZjEpUTLI5iMsmZHSJuwvmqtfb_9HwN4_ELBvypoxG24nWgfS-U1UGhwW42xXLI0V6bm0lhWtvGXk/s1600/pointers.png" /></a></div>
<span class="Apple-style-span" style="font-family: 'Trebuchet MS', sans-serif;"><br />
</span><br />
<span class="Apple-style-span" style="font-family: 'Trebuchet MS', sans-serif;">Now that we have a function for getting the INPUT_RECORD structs, we need to be able to loop through each structure and analyze what kind of record it is, and depending on what it does we can do whatever action we like.</span><br />
<br />
<div class="code">
<span class="Apple-style-span" style="font-family: monospace;"></span><br />
<span class="Apple-style-span" style="font-family: monospace;">while(1)</span><br />
<span class="Apple-style-span" style="font-family: monospace;"> {</span><br />
<span class="Apple-style-span" style="font-family: monospace;"> /* Get the input and number of events successfully obtained */</span><br />
<span class="Apple-style-span" style="font-family: monospace;"> numEventsRead = getInput(&eventBuffer);</span><br />
<span class="Apple-style-span" style="font-family: monospace;"> </span><br />
<span class="Apple-style-span" style="font-family: monospace;"> /* if more than 0 are read */</span><br />
<span class="Apple-style-span" style="font-family: monospace;"> if (numEventsRead)</span><br />
<span class="Apple-style-span" style="font-family: monospace;"> {</span><br />
<span class="Apple-style-span" style="font-family: monospace;"> /* loop through the amount of records */</span><br />
<span class="Apple-style-span" style="font-family: monospace;"> for (i = 0; i < numEventsRead; i++)</span><br />
<span class="Apple-style-span" style="font-family: monospace;"> {</span><br />
<span class="Apple-style-span" style="font-family: monospace;"> /* check each event */</span><br />
<span class="Apple-style-span" style="font-family: monospace;"> switch (eventBuffer[i].EventType)</span><br />
<span class="Apple-style-span" style="font-family: monospace;"> {</span><br />
<span class="Apple-style-span" style="font-family: monospace;"> /* if type of event is a KEY_EVENT */</span><br />
<span class="Apple-style-span" style="font-family: monospace;"> case KEY_EVENT:</span><br />
<span class="Apple-style-span" style="font-family: monospace;"> switch (eventBuffer[i].Event.KeyEvent.wVirtualKeyCode)</span><br />
<span class="Apple-style-span" style="font-family: monospace;"> {</span><br />
<span class="Apple-style-span" style="font-family: monospace;"> /* if escape key is pressed*/</span><br />
<span class="Apple-style-span" style="font-family: monospace;"> case VK_ESCAPE:</span><br />
<span class="Apple-style-span" style="font-family: monospace;"> return 0;</span><br />
<span class="Apple-style-span" style="font-family: monospace;"> }</span><br />
<span class="Apple-style-span" style="font-family: monospace;"> }</span><br />
<span class="Apple-style-span" style="font-family: monospace;"> }</span><br />
<span class="Apple-style-span" style="font-family: monospace;"> }</span><br />
<span class="Apple-style-span" style="font-family: monospace;"> }</span></div>
<br />
<span class="Apple-style-span" style="font-family: 'Trebuchet MS', sans-serif;">The above code continuously loops until a user presses the escape key on their keyboard, which then makes the program close. This works by getting the INPUT_RECORD structs into the pointer eventBuffer (which points to type INPUT_RECORD) using our getInput function, and placing the return value thereof into numEventsRead. The loop then checks for a KEY_EVENT, and if found checks to see if the escape key was pressed. Similarly, you can check to see if a MOUSE_EVENT occurred in this very same way. If you understood what I've explained thus far in all of this series, you should be able to check for any keypress, with the help of the <a href="http://msdn.microsoft.com/en-us/library/windows/desktop/ms645540%28v=vs.85%29.aspx">virtual keycode page</a>, and then do something thereafter.</span><br />
<span class="Apple-style-span" style="font-family: 'Trebuchet MS', sans-serif;"><br />
</span><br />
<span class="Apple-style-span" style="font-family: 'Trebuchet MS', sans-serif;">Now how about writing something onto the console when you click your left mouse button? The first thing you'd need is to be able to check for a MOUSE_EVENT record, and get the mouse's x and y coordinates from the MOUSE_EVENT structure. Here's an example of a case to do such a thing:</span><br />
<br />
<div class="code">
<code></code><br />
<code>case MOUSE_EVENT:</code><br />
<code> offsetx = eventBuffer[i].Event.MouseEvent.dwMousePosition.X;</code><br />
<code> offsety = eventBuffer[i].Event.MouseEvent.dwMousePosition.Y;</code><br />
<code> if (eventBuffer[i].Event.MouseEvent.dwButtonState == FROM_LEFT_1ST_BUTTON_PRESSED)</code><br />
<code> {</code><br />
<code> writeImageToBuffer(consoleBuffer, REDRECTANGLE.chars, REDRECTANGLE.colors, REDRECTANGLE.width, REDRECTANGLE.height, offsetx - 1, offsety - 1);</code><br />
<code> write = YES;</code><br />
<code> }</code><br />
<code> </code></div>
<br />
<span class="Apple-style-span" style="font-family: 'Trebuchet MS', sans-serif;">This indexes the INPUT_RECORD structs when a <a href="http://msdn.microsoft.com/en-us/library/windows/desktop/ms684239%28v=vs.85%29.aspx">MOUSE_EVENT</a> structure is found, and then accesses the data members X and Y, as detailed <a href="http://msdn.microsoft.com/en-us/library/windows/desktop/ms684239%28v=vs.85%29.aspx">here</a>, and places the values of the x and y position into two integers. The large constant FROM_LEFT_1ST_BUTTON_PRESSED is a Microsoft definition for a left-click. Now what is this writeImageToBuffer function? That doesn't seem to be a MSDN documented function... Well it's not! It's a simple function I wrote to write any image onto the screen buffer, given the correct parameters. The image it is writing is called REDRECTANGLE, which is actually a structure defined in a file I've written called redRectangle.h. The red rectangle is a square of 9 red characters, so to write this square onto where the user clicks, you must use offsetx - 1, and offsety -1, otherwise the top left of the red rectangle image will be placed on the left-click location, instead of the center.</span><br />
<span class="Apple-style-span" style="font-family: 'Trebuchet MS', sans-serif;"><br />
</span><br />
<span class="Apple-style-span" style="font-family: 'Trebuchet MS', sans-serif;">Now lets check out redRectangle.h so you can see how I've set up the image of REDRECTANGLE!</span><br />
<br />
<div class="code">
<code></code><br />
<code>/* redRectangle.h */</code><br />
<code><br />
</code><br />
<code>#ifndef FILEREDRECTANGLEH</code><br />
<code>#define FILEREDRECTANGLEH</code><br />
<code><br />
</code><br />
<code>/* A red rectangle! */</code><br />
<code><br />
</code><br />
<code>#define REDRECTANGLEW 3</code><br />
<code>#define REDRECTANGLEH 3</code><br />
<code><br />
</code><br />
<code>typedef struct</code><br />
<code>{</code><br />
<code> int width;</code><br />
<code> int height;</code><br />
<code> int chars[REDRECTANGLEW * REDRECTANGLEH];</code><br />
<code> int colors[REDRECTANGLEW * REDRECTANGLEH];</code><br />
<code>} _REDRECTANGLE;</code><br />
<code><br />
</code><br />
<code>_REDRECTANGLE REDRECTANGLE = </code><br />
<code>{</code><br />
<code> REDRECTANGLEW,</code><br />
<code> REDRECTANGLEH,</code><br />
<code> {</code><br />
<code> 219, 219, 219,</code><br />
<code> 219, 219, 219,</code><br />
<code> 219, 219, 219,</code><br />
<code> },</code><br />
<code> {</code><br />
<code> 4 , 4 , 4 ,</code><br />
<code> 4 , 4 , 4 ,</code><br />
<code> 4 , 4 , 4 ,</code><br />
<code> }</code><br />
<code>};</code><br />
<code><br />
</code><br />
<code>#endif /* FILEREDRECTANGLEH */</code><br />
<code> <br />
</code></div>
<span class="Apple-style-span" style="font-family: 'Trebuchet MS', sans-serif;">This was the cleanest way I could think of for setting up an image that should be compatible with all versions of C. I'll start explaining from the top of the file. The two preprocessor directives ifndef and define are used to see if FILEREDRECTANGLEH is defined yet or not. If it is not yet defined, then the entire contents of the file will be included wherever an include of this file is placed. If the define FILEREDRECTANGLEH is already defined, it means that you've already included this file somewhere, and so the entire contents of the file will be skipped!</span><br />
<span class="Apple-style-span" style="font-family: 'Trebuchet MS', sans-serif;"><br />
</span><br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEikVPzFe0FgjNuR_tDJ22Ea20RkWuHtms8akyrk8X1bxJ5WIDWaxNAeVIQWemH-E5B_QTZkAxu5uqKQwq_TV2x5x_5zg8uxB3PUlQ-kNFRDA4unNEEh9Pigwkh3So1ZIaFtu4XZp_CA0tk/s1600/Capture.PNG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEikVPzFe0FgjNuR_tDJ22Ea20RkWuHtms8akyrk8X1bxJ5WIDWaxNAeVIQWemH-E5B_QTZkAxu5uqKQwq_TV2x5x_5zg8uxB3PUlQ-kNFRDA4unNEEh9Pigwkh3So1ZIaFtu4XZp_CA0tk/s1600/Capture.PNG" /></a></div>
<div style="text-align: center;">
<span class="Apple-style-span" style="font-family: 'Trebuchet MS', sans-serif;"><i>Screenshot of the final demonstration program, drawing on the window!</i></span></div>
<span class="Apple-style-span" style="font-family: 'Trebuchet MS', sans-serif;"><br />
</span><br />
<span class="Apple-style-span" style="font-family: 'Trebuchet MS', sans-serif;">I have two defines for each image I write in this format, and they represent width and height as 3 in this image. These defines are critical for declaring a REDRECTANGLE, as the size needs to be defined at compile, since a template for the structure needs to be created for the program to run, and as such you need to know the size of the arrays within the REDRECTANGLE structure in order to properly place it in memory! However, the use of defines in this way makes it very simple to create other copies of images. For example, to create a new image called BLUETRIANGLE, you simply use find and replace (ctrl + h for a lot of programs) and replace all instances of REDRECTANGLE, with BLUERECTANGLE. You then would modify the color and character arrays to contain the correct data, and change the WIDTH/HEIGHT values for the defines accordingly. The structure called _REDRECTANGLE is typedef'd allowing declaration of variables by skipping writing the annoying legacy struct keyword. An instance of _REDRECTANGLE called REDRECTANGLE is then declared and initialized with the arrays containing the values for the ASCII characters, and color values.</span><br />
<span class="Apple-style-span" style="font-family: 'Trebuchet MS', sans-serif;"><br />
</span><br />
<span class="Apple-style-span" style="font-family: 'Trebuchet MS', sans-serif;">Using this format in conjunction with the writeImageToBuffer function, you can pretty easily create new images and write them with limited amounts of code! Now lets check out a finished product: <a href="http://codepad.org/uuNESM4l">link</a> (I didn't want to post the entire unwieldy thing here).</span><br />
<span class="Apple-style-span" style="font-family: 'Trebuchet MS', sans-serif;"><br />
</span><br />
<span class="Apple-style-span" style="font-family: 'Trebuchet MS', sans-serif;">The last thing to mention is that if you update the screen with WriteConsoleOutputA every loop, you'll probably see little flickers as the screen is updated. This is simply a limitation of the function WriteConsoleOutputA. There are a few solutions to this. The easiest solution I've come up with is to just update screen less often, and I chose to do this by limiting the time in which the screen is updated to only when the consoleBuffer is changed. Another solution is to keep track of which portions of the screen you actually need to update, and call WriteConsoleOutputA and only write with the smallest portion of the screen as possible. Also supposedly if you update the screen with the same characters and colors multiple times it increases the chance of flickering lines, so this means you should try to avoid doing so. Lastly, you can multi-thread your program, and place just the call to WriteConsoleOutput within the additional thread. I do the first solution with a simple if statement:</span><br />
<br />
<div class="code">
<code></code><br />
<code> /* If write is 1, meaning the screen needs to be updated */</code><br />
<code> if (write)</code><br />
<code> {</code><br />
<code> /* Write our character buffer (a single character currently) to the console buffer */</code><br />
<code> WriteConsoleOutputA(wHnd, consoleBuffer, characterBufferSize, characterPosition, &consoleWriteArea);</code><br />
<code> write = NO;</code><br />
<code> }</code><br />
<code> </code></div>
<br />
<span class="Apple-style-span" style="font-family: 'Trebuchet MS', sans-serif;">This will only call the WriteConsoleOutputA function when write is not 0.</span><br />
<span class="Apple-style-span" style="font-family: 'Trebuchet MS', sans-serif;"><br />
</span><br />
<span class="Apple-style-span" style="font-family: 'Trebuchet MS', sans-serif;">The <a href="http://codepad.org/uuNESM4l">entire final program</a> demonstrates drawing a square image on the screen on left-click, and a red dot to the screen on right click. There is boundary checking on the click coordinates to prevent indexing outside of the screen!</span><br />
<span class="Apple-style-span" style="font-family: 'Trebuchet MS', sans-serif;"><br />
</span><br />
<span class="Apple-style-span" style="font-family: 'Trebuchet MS', sans-serif;">You might by now have realized that the characters you're writing to the screen are oddly shaped rectangles. What about nice square characters? Square characters are essential for creating a nice game :( Well the <a href="http://cecilsunkure.blogspot.com/2011/12/windows-console-game-set-custom-color.html">next post in this series</a> covers setting the console's font, font size, and even the color palette!</span><br />
<br />
<br />
<span style="font-family: 'Trebuchet MS', sans-serif;">Series on creating a Windows Console game:</span><br />
<ul>
<li><a href="http://cecilsunkure.blogspot.com/2011/11/windows-console-game-setting-up-window.html"><span style="font-family: 'Trebuchet MS', sans-serif;">Setting up the Window</span></a></li>
<li><a href="http://cecilsunkure.blogspot.com/2011/11/windows-console-game-writing-to-console.html"><span style="font-family: 'Trebuchet MS', sans-serif;">Writing to the Console</span></a></li>
<li><a href="http://cecilsunkure.blogspot.com/2011/11/windows-console-game-event-handling.html"><span style="font-family: 'Trebuchet MS', sans-serif;">Event Handling</span></a></li>
<li><a href="http://cecilsunkure.blogspot.com/2011/12/windows-console-game-set-custom-color.html"><span style="font-family: 'Trebuchet MS', sans-serif;">Custom Color Palette and Font Size</span></a></li>
<li><a href="http://cecilsunkure.blogspot.com/2011/12/windows-console-game-painters-algorithm.html"><span style="font-family: 'Trebuchet MS', sans-serif;">Painter's Algorithm</span></a></li>
<li><span style="font-family: 'Trebuchet MS', sans-serif;"><a href="http://cecilsunkure.blogspot.com/2012/02/windows-console-game-variable-sized.html">Variable Sized Object</a></span></li>
<li><span style="font-family: 'Trebuchet MS', sans-serif;"><a href="http://cecilsunkure.blogspot.com/2012/07/windows-console-game-ascii-engine.html">Ascii Engine</a></span></li>
</ul>
<br />
<ul>
</ul>CecilSunkurehttp://www.blogger.com/profile/16129986119923492789noreply@blogger.com2tag:blogger.com,1999:blog-3579312376304629754.post-66125751045558327022011-11-16T15:47:00.001-08:002012-02-20T13:46:42.444-08:00Windows Console Game: Writing to the Console<div style="font-family: "Trebuchet MS",sans-serif;">
<span style="font-size: small;">Previously I showed you all how to <a href="http://cecilsunkure.blogspot.com/2011/11/windows-console-game-setting-up-window.html">set up a console window</a>! Now l</span>ets talk about writing to the Windows console. One can use printf, or fprintf, but those options aren't really exactly ideal; you don't have a desired amount of control. We're going to use the function <a href="http://msdn.microsoft.com/en-us/library/windows/desktop/ms687404%28v=VS.85%29.aspx">WriteConsoleOutput</a> in order to write a buffer of characters (array of characters) onto the console's screen buffer. The screen buffer is the inside of your game's window in which characters are written to and appear. In order to use the WriteConsoleOutput function, you have to pass to it a buffer of characters, which is really just an array of characters. The character buffer will be comprised of an array of<a href="http://msdn.microsoft.com/en-us/library/windows/desktop/ms682013%28v=VS.85%29.aspx"> CHAR_INFO</a> structures, which is a Microsoft defined type that comes from windows.h. Lets get started with just writing a single character to the screen.</div>
<div style="font-family: "Trebuchet MS",sans-serif;">
<span style="font-size: small;"><br />
</span></div>
<div style="font-family: "Trebuchet MS",sans-serif;">
<span style="font-size: small;">In C characters are enclosed letters or numbers enclosed in single quotes, like so: 'c'. Characters in c, like 'c', are treated very similarly to integers. The main difference is that the range of a character (unsigned) is from 0 to 255, where a range of integers reaches much much higher. Due to this a character variable will be one byte in memory (8 bits). You can actually write in your code 'c', and it will be treated as the value of whatever the ascii value of C is, which is 99 in decimal. You can even write c - 8, and it will be treated as 99 - 8. Here is my favorite chart for all the values of all the ascii characters available, note the indices are in hexidecimal:</span></div>
<div style="font-family: "Trebuchet MS",sans-serif;">
<span style="font-size: x-small;"><br />
</span></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="http://benryves.com/tutorials/winconsole/ascii.gif" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="317" src="http://benryves.com/tutorials/winconsole/ascii.gif" width="400" /></a></div>
<div style="font-family: "Trebuchet MS",sans-serif;">
<span style="font-size: x-small;"><br />
</span></div>
<div style="font-family: "Trebuchet MS",sans-serif;">
<br /></div>
<div style="font-family: "Trebuchet MS",sans-serif;">
<span style="font-size: small;">The <a href="http://msdn.microsoft.com/en-us/library/windows/desktop/ms682013%28v=VS.85%29.aspx">CHAR_INFO</a> structure contains two data members; a character and its attributes. The character can either be a unicode or ascii character. We're going to stick with ascii characters within the Char.AsciiChar data member (remember, this is just an integer with a range of 0-255). The Attributes data member is a WORD type, which is just a Microsoft defined type. The WORD type is simply a 16-bit unsigned integer with a range of 0 through 65535. The Attributes data member can be viewed simply as a byte of data with the following value representations as colors:</span></div>
<ul style="font-family: "Trebuchet MS",sans-serif;">
<li><span style="font-size: small;"><b>FOREGROUND_BLUE - </b>0x0001</span></li>
<li><span style="font-size: small;"><b>FOREGROUND_GREEN - </b>0x0002</span></li>
<li><span style="font-size: small;"><b>FOREGROUND_RED</b></span><span style="font-size: small;"><b> - </b>0x0004</span></li>
<li><span style="font-size: small;"><b>FOREGROUND_INTENSITY</b></span><span style="font-size: small;"><b> - </b>0x0008</span></li>
<li><span style="font-size: small;"><b>BACKGROUND_BLUE</b></span><span style="font-size: small;"><b> - </b>0x0010</span></li>
<li><span style="font-size: small;"><b>BACKGROUND_GREEN</b></span><span style="font-size: small;"><b> - </b>0x0020</span></li>
<li><span style="font-size: small;"><b>BACKGROUND_RED</b></span><span style="font-size: small;"><b> - </b>0x0040</span></li>
<li><span style="font-size: small;"><b>BACKGROUND_INTENSITY</b></span><span style="font-size: small;"><b> - </b>0x0080</span></li>
</ul>
<div style="font-family: "Trebuchet MS",sans-serif;">
<span style="font-size: small;">These values are the different colors accessible for use within the Windows console. The values are represented in hexadecimal, and should be viewed as a byte:</span></div>
<span style="font-size: small;"><br />
</span><br />
<div class="separator" style="clear: both; text-align: center;">
<span style="font-size: small;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiT9993g9zl4H82OnHEkqYAnJIus0URCz28IJGN7ZS4O2CaZ-Ck4VsXx3MOcmGCuFEBMS3YgPC_UMiMy-pUyJsYGhKCTEbq1DZvWdJbAVNjQ9d1M9Qz0LbVuqHJ70O8zZN53MANtiKildw/s1600/byte.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiT9993g9zl4H82OnHEkqYAnJIus0URCz28IJGN7ZS4O2CaZ-Ck4VsXx3MOcmGCuFEBMS3YgPC_UMiMy-pUyJsYGhKCTEbq1DZvWdJbAVNjQ9d1M9Qz0LbVuqHJ70O8zZN53MANtiKildw/s1600/byte.png" /> </a></span></div>
<div class="separator" style="clear: both; text-align: center;">
<span style="font-size: small;"><br />
</span></div>
<div class="separator" style="clear: both; font-family: "Trebuchet MS",sans-serif; text-align: left;">
<span style="font-size: small;"> In the picture above I've shown a single byte, which is 8 bits of information. Each bit can be either a 1 or a 0. The first bit is on the right (at least for this representation). If you wish for your Attributes data member to contain the value blue, then you set the first bit of this byte to 1. The second bit represents whether or not you want to add green to your color, and so on and so forth. The above image would contain the values of blue, red, and intensity. This value would be in decimal format 1 + 4 + 8, which is 13. Intensity brightens the color to be displayed. Knowing this will allow us to construct whatever color we like with some simple addition! For the first color lets mix blue, green, and intensity for a value of 11.</span></div>
<div class="separator" style="clear: both; font-family: "Trebuchet MS",sans-serif; text-align: left;">
<span style="font-size: small;"><br />
</span></div>
<div class="separator" style="clear: both; font-family: "Trebuchet MS",sans-serif; text-align: left;">
<span style="font-size: small;">Here is what MSDN says for the WriteConsoleOutput function in regards to parameters required:</span></div>
<div class="separator" style="clear: both; text-align: left;">
<br /></div>
<div class="code">
<pre>BOOL WINAPI WriteConsoleOutput(
__in HANDLE hConsoleOutput,
__in const CHAR_INFO *lpBuffer,
__in COORD dwBufferSize,
__in COORD dwBufferCoord,
__inout PSMALL_RECT lpWriteRegion
);</pre>
</div>
<br />
<div style="font-family: "Trebuchet MS",sans-serif;">
<span style="font-size: small;">hConsoleOutput is simply the output handle for our window, *lpBuffer is a pointer to a buffer of CHAR_INFO structures, dwBufferSize is the size of the buffer in character elements, dwBufferCoord is the location on your console screen buffer in which to write the image, and lpWriteRegion is just a pointer to a COORD structure for dictating which portion of the console to write to. Here's some code using this knowledge to write a character to the screen:</span></div>
<br />
<div class="code">
<pre>#include <windows.h> /* for HANDLE type, and console functions */
#include <stdio.h> /* standard input/output */
HANDLE wHnd; /* write (output) handle */
HANDLE rHnd; /* read (input handle */
int main(void)
{
/* Window size coordinates, be sure to start index at zero! */
SMALL_RECT windowSize = {0, 0, 69, 34};
/* A COORD struct for specificying the console's screen buffer dimensions */
COORD bufferSize = {70, 35};
/* Setting up different variables for passing to WriteConsoleOutput */
COORD characterBufferSize = {1, 1};
COORD characterPosition = {0, 0};
SMALL_RECT consoleWriteArea = {0, 0, 0, 0};
/* A CHAR_INFO structure containing data about a single character */
CHAR_INFO characterQ;
characterQ.Char.AsciiChar = 'Q'; /* Setting the Char.Ascii data member of characterQ to the value of 'Q' */
/* Setting up the color values for our Q character: blue + green + intensity */
characterQ.Attributes = FOREGROUND_BLUE | FOREGROUND_GREEN |
FOREGROUND_INTENSITY;
/* initialize handles */
wHnd = GetStdHandle(STD_OUTPUT_HANDLE);
rHnd = GetStdHandle(STD_INPUT_HANDLE);
/* Set the console's title */
SetConsoleTitle("Our shiny new title!");
/* Set the window size */
SetConsoleWindowInfo(wHnd, TRUE, &windowSize);
/* Set the screen's buffer size */
SetConsoleScreenBufferSize(wHnd, bufferSize);
/* Write our character buffer (a single character currently) to the console buffer */
WriteConsoleOutputA(wHnd, &characterQ, characterBufferSize, characterPosition, &consoleWriteArea);
getchar();</pre>
<pre>}</pre>
</div>
<div style="font-family: "Trebuchet MS",sans-serif;">
<div style="font-family: "Trebuchet MS",sans-serif;">
<span style="font-size: small;">The code above prints the character Q to the screen in a bright cyan color. This probably seems like a lot of work to write a single character to the screen, and it sort of is. But in actuality this isn't really how you want to write every character onto the screen. The WriteConsoleOutput function is a very slow function, and so you want to call it as little as possible. You may have heard of a term called "double buffer", well we're going to use a double buffer to do all of our modifying of a buffer off-screen, and once all our modifications are finished we can write a single image to the screen all in one go. To create this buffer, simply create an array of CHAR_INFO structures and initialize all of the Char.AsciiChar and Attribute data members! Here's an example of looping through an array of CHAR_INFOs and assigning random colors to a single Char type.</span></div>
</div>
<div class="code">
<pre>#include <windows.h> /* for HANDLE type, and console functions */
#include <stdio.h> /* standard input/output */
#include <stdlib.h> /* included for rand */
#define WIDTH 70
#define HEIGHT 35
HANDLE wHnd; /* write (output) handle */
HANDLE rHnd; /* read (input handle */
int main(void)
{
int x, y;
srand(time(0));
/* Window size coordinates, be sure to start index at zero! */
SMALL_RECT windowSize = {0, 0, WIDTH - 1, HEIGHT - 1};
/* A COORD struct for specificying the console's screen buffer dimensions */
COORD bufferSize = {WIDTH, HEIGHT};
/* Setting up different variables for passing to WriteConsoleOutput */
COORD characterBufferSize = {WIDTH, HEIGHT};
COORD characterPosition = {0, 0};
SMALL_RECT consoleWriteArea = {0, 0, WIDTH - 1, HEIGHT - 1};
/* A CHAR_INFO structure containing data about a single character */
CHAR_INFO consoleBuffer[WIDTH * HEIGHT];
/* initialize handles */
wHnd = GetStdHandle(STD_OUTPUT_HANDLE);
rHnd = GetStdHandle(STD_INPUT_HANDLE);
/* Set the console's title */
SetConsoleTitle("Our shiny new title!");
/* Set the window size */
SetConsoleWindowInfo(wHnd, TRUE, &windowSize);
/* Set the screen's buffer size */
SetConsoleScreenBufferSize(wHnd, bufferSize);
for (y = 0; y < HEIGHT; ++y)
{
for (x = 0; x < WIDTH; ++x)
{
consoleBuffer[x + WIDTH * y].Char.AsciiChar = (unsigned char)219;
consoleBuffer[x + WIDTH * y].Attributes = rand() % 256;
}
}
/* Write our character buffer (a single character currently) to the console buffer */
WriteConsoleOutputA(wHnd, consoleBuffer, characterBufferSize, characterPosition, &consoleWriteArea);
getchar();
}</pre>
</div>
<div style="font-family: "Trebuchet MS",sans-serif;">
<span style="font-size: small;">The above code is creating a buffer called consoleBuffer, of a single dimensional array with the number of elements equal to WIDTH times HEIGHT, both of which are now defined at the top of the file. There is a loop that loops through all of the CHAR_INFO's Char.AsciiChar data member, and Attributes data members initializing them. You can see how I'm assigning a <a href="http://cecilsunkure.blogspot.com/search/label/PRNG">random value</a> using rand, and seeding the table at the beginning of the code with <a href="http://cecilsunkure.blogspot.com/search/label/PRNG">srand</a>.</span><br />
<br />
<span style="font-size: small;">You might be a little confused by the </span>x + WIDTH * y portion of the code. I've created a single dimensional array of elements WIDTH * HEIGHT, and in order to index the array during a loop as if it were a two dimensional array, you need to use a formula. The idea behind the formula is to figure out what row you want to access, by taking the number of elements in a row and multiplying it by a value. To access the first row, you multiply the WIDTH value by 0. To access the fifth row, you'd multiply WIDTH by five. This works since as the single dimensional array is written to the screen with WriteConsoleOutput, it wraps around the screen buffer once ever WIDTH elements. Then, access a specific element within that row you add in your x value.<br />
<span style="font-size: small;"> </span><br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjvH-H5zOsfbJJbmj33VPdZXoDnehUd6qB1d_iBcat9LLk30jSEel0i6Mmwktj2kGDIZwtSgVDfjC6WQoasjgnPvAinCIh1QxBi7Wx6IVC-Mb6_EvVH5b4fYOJIjwNwYrP9-3tEXj81R9U/s1600/randomcolors.PNG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="312" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjvH-H5zOsfbJJbmj33VPdZXoDnehUd6qB1d_iBcat9LLk30jSEel0i6Mmwktj2kGDIZwtSgVDfjC6WQoasjgnPvAinCIh1QxBi7Wx6IVC-Mb6_EvVH5b4fYOJIjwNwYrP9-3tEXj81R9U/s400/randomcolors.PNG" width="400" /></a></div>
</div>
<div style="font-family: "Trebuchet MS",sans-serif;">
<span style="font-size: small;"><br />
</span></div>
<span style="font-size: small;"><span style="font-family: 'Trebuchet MS', sans-serif;">And there you have it! A method for writing an image onto the screen of any given size on any location of the console's screen buffer! The next post in this series will be on <a href="http://cecilsunkure.blogspot.com/2011/11/windows-console-game-event-handling.html">Event Handling</a>.</span></span><br />
<span style="font-size: small;"><span style="font-family: 'Trebuchet MS', sans-serif;"><br /></span></span><br />
List of all posts completed thus far:<br />
<ul>
<li><a href="http://cecilsunkure.blogspot.com/2011/11/windows-console-game-setting-up-window.html">Setting up the Window</a></li>
<li><a href="http://cecilsunkure.blogspot.com/2011/11/windows-console-game-writing-to-console.html">Writing to the Console</a></li>
<li><a href="http://cecilsunkure.blogspot.com/2011/11/windows-console-game-event-handling.html">Event Handling</a></li>
<li><a href="http://cecilsunkure.blogspot.com/2011/12/windows-console-game-set-custom-color.html">Custom Color Palette and Font Size</a></li>
<li><a href="http://cecilsunkure.blogspot.com/2011/12/windows-console-game-painters-algorithm.html">Painter's Algorithm</a></li>
<li><a href="http://cecilsunkure.blogspot.com/2012/02/windows-console-game-variable-sized.html">Variable Sized Object</a></li>
</ul>
<span style="font-family: 'Trebuchet MS', sans-serif; font-size: small;">
Source(s):<br />
<a href="http://benryves.com/">http://benryves.com/</a><br />
<a href="http://msdn.microsoft.com/en-us/library/windows/desktop/ms682073%28v=vs.85%29.aspx">http://msdn.microsoft.com/en-us/library/windows/desktop/ms682073(v=vs.85).aspx</a></span><span style="font-size: small;"><span style="font-family: 'Trebuchet MS', sans-serif;"><span style="font-family: 'Trebuchet MS', sans-serif;"> </span></span></span>CecilSunkurehttp://www.blogger.com/profile/16129986119923492789noreply@blogger.com6tag:blogger.com,1999:blog-3579312376304629754.post-65406750845681192362011-11-16T10:34:00.001-08:002012-07-03T12:58:26.748-07:00Windows Console Game: Setting up the Window<a href="http://i117.photobucket.com/albums/o67/MCBooga/ascii_city.png" imageanchor="1" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"><img border="0" height="240" src="http://i117.photobucket.com/albums/o67/MCBooga/ascii_city.png" width="320" /></a>Have you ever seen cool looking games made with purely ASCII graphics? For example the image on the right is an amazing mock-up of an idea for a game that seems to revolve around creating some sort of city on a platform to defend from air-based attackers. I've done a bit of research, and have actually begun a project of creating an entire game from scratch by using the Windows Console as the platform. This is a great way for newer programmers to jump into game development for the following reasons:<br />
<ul>
<li>Easy construction of graphics. All the graphics are just ASCII characters with varying colors!</li>
<li> Very little overhead required to get a project up and running. The Windows Console is a very simple platform to get started on.</li>
<li>All the documentation you would ever need can be found on MSDN and abroad.</li>
<li>The Windows Console is packaged with every version of the Windows OS that is popular today, so no extra anything is needed to be downloaded or installed in order to get coding.</li>
</ul>
<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="http://i.imgur.com/366q2.png" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" height="271" src="http://i.imgur.com/366q2.png" width="320" /></a></div>
This post is the first in a series that will show you some techniques that will allow you to create a game within the Windows Console. <a href="http://msdn.microsoft.com/en-us/library/windows/desktop/ms682073%28v=vs.85%29.aspx">MSDN Documentation</a> at this link contains all the info of all the documented functions available to manipulate the windows console programmatically. Most info in this post will be an explanation of the MSDN documentation with example code on how to use it. On the left is a screenshot from a game I'm developing called TerraNisi, which revolves around a walking tree character that has a goal of saving his Forest from spreading fire ghouls!<br />
<br />
The first thing you need to do is set up handles for your window. The handles of a window are what the Windows OS use to identify and manipulate a window. A handle datatype looks like this: <span style="color: #666666; font-family: 'Courier New', Courier, monospace;">HANDLE</span>. This type is defined within windows.h with a <span style="color: #444444; font-family: 'Courier New', Courier, monospace;">typedef</span>, and thus you can declare variables of the <span style="color: #444444; font-family: 'Courier New', Courier, monospace;">HANDLE</span> type once you include windows.h to your project. Once we set them up we have access to manipulate our own window! Observe the following code that simply sets up handles, and calls getchar in order to pause the program once opened so you can see the window:<br />
<br />
<div class="code">
<code>#include <windows.h> /* for HANDLE type, and console functions */<br />#include <stdio.h> /* standard input/output */<br /><br />HANDLE wHnd; /* write (output) handle */<br />HANDLE rHnd; /* read (input handle */<br /><br />int main(void)<br />{<br /> /* initialize handles */<br /> wHnd = GetStdHandle(STD_OUTPUT_HANDLE);<br /> rHnd = GetStdHandle(STD_INPUT_HANDLE);<br /> getchar();<br />}<br />
</code></div>
<br />
This code doesn't do much but set up and initialize some handles for our window. Lets set the text title for the window, as this is the simplest thing I know how to do with console functions:<br />
<br />
<div class="code">
<code>#include <windows.h> /* for HANDLE type, and console functions */<br />#include <stdio.h> /* standard input/output */<br /><br />HANDLE wHnd; /* write (output) handle */<br />HANDLE rHnd; /* read (input handle */<br /><br />int main(void)<br />{<br /> /* initialize handles */<br /> wHnd = GetStdHandle(STD_OUTPUT_HANDLE);<br /> rHnd = GetStdHandle(STD_INPUT_HANDLE);<br /> <br /> SetConsoleTitle("Our shiny new title!");<br /> <br /> getchar();<br />}</code></div>
<br />
Now the title of your window should say "Our shiny new title!". Congrats! You've used another console function called SetConsoleTitle! Moving on to something a little more difficult, lets try using <a href="http://msdn.microsoft.com/en-us/library/windows/desktop/ms686125%28v=VS.85%29.aspx">SetConsoleWindowInfo</a>.<br />
<ul>
<li>This function takes three parameters: the first is the output handle the screen's buffer</li>
<li>The second is a boolean - if this parameter is <span style="color: #444444; font-family: 'Courier New', Courier, monospace;">TRUE</span> the coordinates specify the new upper-left and lower-right corners of the window. If it is <span style="color: #444444; font-family: 'Courier New', Courier, monospace;">FALSE</span>, the coordinates are relative to the current window-corner coordinates. <span style="color: #444444; font-family: 'Courier New', Courier, monospace;">TRUE</span> and <span style="color: #444444; font-family: 'Courier New', Courier, monospace;">FALSE</span> are defined within windows.h as 1 and 0, and if you don't understand the previous sentence I suggest just leaving this parameter as <span style="color: #444444; font-family: 'Courier New', Courier, monospace;">TRUE</span>.</li>
<li>The third parameter is a <a href="http://msdn.microsoft.com/en-us/library/windows/desktop/ms686311%28v=VS.85%29.aspx" style="font-family: "Courier New",Courier,monospace;">SMALL_RECT</a> <a href="http://cecilsunkure.blogspot.com/search/label/Structures">structure</a> containing the size of the new window. This parameter will set the window's edges to a size smaller than the screen's buffer. This means you cannot make it larger than the default buffer size of 80x300 (width x height) until you change the buffer size, which I'll cover momentarily.</li>
</ul>
Observe:<br />
<br />
<div class="code">
<code>#include <windows.h> /* for HANDLE type, and console functions */<br />#include <stdio.h> /* standard input/output */<br /><br />HANDLE wHnd; /* write (output) handle */<br />HANDLE rHnd; /* read (input handle */<br /><br />int main(void)<br />{<br /> /* Window size coordinates, be sure to start index at zero! */<br /> SMALL_RECT windowSize = {0, 0, 69, 34};<br /> <br /> /* initialize handles */<br /> wHnd = GetStdHandle(STD_OUTPUT_HANDLE);<br /> rHnd = GetStdHandle(STD_INPUT_HANDLE);<br /> <br /> /* Set the console's title */<br /> SetConsoleTitle("Our shiny new title!");<br /> <br /> /* Set the window size */<br /> SetConsoleWindowInfo(wHnd, TRUE, &windowSize);<br /> <br /> getchar();<br />}</code></div>
<br />
I chose to set the window size to 70 by 35, which is a decent size for some sort of game. Now you have successfully changed your window size! However you should immediately notice an ugly scroll bar on the right side of your console, and at the bottom of the console. This scroll bar is there because the console's screen buffer (the inside of the window) is larger than the window. To remedy this simply change the size of the screen buffer to that of your window coordinates with the <a href="http://msdn.microsoft.com/en-us/library/windows/desktop/ms686044%28v=VS.85%29.aspx">SetConsoleScreenBufferSize</a> function. This function has only two parameters: the output handle and <a href="http://msdn.microsoft.com/en-us/library/windows/desktop/ms682119%28v=VS.85%29.aspx" style="font-family: "Courier New",Courier,monospace;">COORD</a> <a href="http://cecilsunkure.blogspot.com/search/label/Structures">struct</a> for the buffer size. Observe:<br />
<br />
<div class="code">
<code>#include <windows.h> /* for HANDLE type, and console functions */<br />#include <stdio.h> /* standard input/output */<br /><br />HANDLE wHnd; /* write (output) handle */<br />HANDLE rHnd; /* read (input handle */<br /><br />int main(void)<br />{<br /> /* Window size coordinates, be sure to start index at zero! */<br /> SMALL_RECT windowSize = {0, 0, 69, 34};<br /><br /> /* A COORD struct for specificying the console's screen buffer dimensions */<br /> COORD bufferSize = {70, 35};<br /><br /> /* initialize handles */<br /> wHnd = GetStdHandle(STD_OUTPUT_HANDLE);<br /> rHnd = GetStdHandle(STD_INPUT_HANDLE);<br /><br /> /* Set the console's title */<br /> SetConsoleTitle("Our shiny new title!");<br /><br /> /* Set the window size */<br /> SetConsoleWindowInfo(wHnd, TRUE, &windowSize);<br /><br /> /* Set the screen's buffer size */<br /> SetConsoleScreenBufferSize(wHnd, bufferSize);<br /><br /> getchar();<br />}</code></div>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="http://i.imgur.com/5Hh7u.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="251" src="http://i.imgur.com/5Hh7u.png" width="320" /></a></div>
Thus far we have created the initialization of a nice console window! The next step is to begin writing things onto the console with a double buffering system! This may sound fancy, but in actually it's very simple in this project. The <a href="http://cecilsunkure.blogspot.com/2011/11/windows-console-game-writing-to-console.html">next post</a> in this series will be devoted to this!<br />
<br />
<br />
<span style="font-family: 'Trebuchet MS', sans-serif;">Series on creating a Windows Console game:</span><br />
<ul>
<li><a href="http://cecilsunkure.blogspot.com/2011/11/windows-console-game-setting-up-window.html"><span style="font-family: 'Trebuchet MS', sans-serif;">Setting up the Window</span></a></li>
<li><a href="http://cecilsunkure.blogspot.com/2011/11/windows-console-game-writing-to-console.html"><span style="font-family: 'Trebuchet MS', sans-serif;">Writing to the Console</span></a></li>
<li><a href="http://cecilsunkure.blogspot.com/2011/11/windows-console-game-event-handling.html"><span style="font-family: 'Trebuchet MS', sans-serif;">Event Handling</span></a></li>
<li><a href="http://cecilsunkure.blogspot.com/2011/12/windows-console-game-set-custom-color.html"><span style="font-family: 'Trebuchet MS', sans-serif;">Custom Color Palette and Font Size</span></a></li>
<li><a href="http://cecilsunkure.blogspot.com/2011/12/windows-console-game-painters-algorithm.html"><span style="font-family: 'Trebuchet MS', sans-serif;">Painter's Algorithm</span></a></li>
<li><span style="font-family: 'Trebuchet MS', sans-serif;"><a href="http://cecilsunkure.blogspot.com/2012/02/windows-console-game-variable-sized.html">Variable Sized Object</a></span></li>
<li><span style="font-family: 'Trebuchet MS', sans-serif;"><a href="http://cecilsunkure.blogspot.com/2012/07/windows-console-game-ascii-engine.html">Ascii Engine</a></span></li>
</ul>
<br />
<ul>
</ul>
<br />
Source(s):<br />
<a href="http://benryves.com/">http://benryves.com/</a><br />
<a href="http://msdn.microsoft.com/en-us/library/windows/desktop/ms682073(v=vs.85).aspx">http://msdn.microsoft.com/en-us/library/windows/desktop/ms682073(v=vs.85).aspx</a>CecilSunkurehttp://www.blogger.com/profile/16129986119923492789noreply@blogger.com9tag:blogger.com,1999:blog-3579312376304629754.post-35448882572203188332011-11-15T21:49:00.000-08:002012-08-02T11:41:04.033-07:00I Want to Learn Programming, but I Know Nothing!<span class="Apple-style-span" style="font-family: 'Trebuchet MS', sans-serif;">I want this post to be a great resource for people who have absolutely zero knowledge of programming to be able to pick up and start coding in the language C. I feel I have a fair level of empathy for those just starting to learn (since I started learning not too long ago), and want to write this post out before I get too competent as a programmer and forget my empathy altogether!</span><br />
<br />
<span class="Apple-style-span" style="font-family: 'Trebuchet MS', sans-serif;">So you want to learn to program. Great! So you're reading this article, and here you'll learn to start with C on a Windows Operating System. Starting with C is an excellent place to start, as it grounds you with a very solid base of understanding for programming in general, that of which I feel is easily transferable to other languages. I even feel that once you learn the basics of C and transfer to another language (I recommend Python!) you'll be better off in the long run than if you started with another language and then moved to C (perhaps start with Java and move to C). I won't get into deep details about this point as that's out of the scope of this article, but you should definitely take my word on the matter.</span><br />
<span class="Apple-style-span" style="font-family: 'Trebuchet MS', sans-serif;"><br /></span><br />
<span class="Apple-style-span" style="font-family: 'Trebuchet MS', sans-serif;">Be aware that I'm going to use a lot of new and scary programmer terminology in this post, like statements, declarations, and initialization. Don't be afraid, as I give a link to the definition of words when I first use them. Read the links and make sure you understand what I'm referring to.</span><br />
<br />
<span class="Apple-style-span" style="font-family: 'Trebuchet MS', sans-serif;">The programming in C that I'll be teaching you, as an absolute beginner, will be of the following steps:</span><br />
<ul>
<li><span class="Apple-style-span" style="font-family: 'Trebuchet MS', sans-serif;">Write code</span></li>
<li><span class="Apple-style-span" style="font-family: 'Trebuchet MS', sans-serif;">Compile code into an executable</span></li>
</ul>
<span class="Apple-style-span" style="font-family: 'Trebuchet MS', sans-serif;">An executable is a .exe file that your computer can run, and when this executable file is run your computer will actually follow the steps you wrote in your code, thus running your code as a program. Compiling your code is actually a step that a <a href="http://en.wikipedia.org/wiki/Compiler">compiler</a> does for you, in which it translates your C code into machine code. Machine code can be viewed as a lot of very hard to read 1's and 0's, also known as binary. The reason people don't code directly in machine code is because it's so hard to read. C is a nice translation of machine code for people to work with. If you want to learn more about how computers work on a very low level, I suggest reading <a href="http://www.amazon.com/Code-Language-Computer-Hardware-Software/dp/0735611319">Code: The Hidden Language of Computer Hardware and Software</a> by Charles Petzhold.</span><br />
<br />
<span class="Apple-style-span" style="font-family: 'Trebuchet MS', sans-serif;">You can write your C code in any text editor you like. You can just simply use notepad (to open hit windows key+r and type notepad, then hit enter), though I recommend using the <a href="http://en.wikipedia.org/wiki/Integrated_development_environment">IDE</a> apart of Visual Studio. Once you write some C code, save your file as a .c file and then use a compiler to turn it into a .exe file.</span><br />
<span style="font-family: 'Trebuchet MS', sans-serif;"><br /></span><br />
<span style="font-family: 'Trebuchet MS', sans-serif;">Now what about this compiler business. You might have already googled for a C compiler by now and noticed that there is a multitude of compilers out there. Luckily I have one to recommend to you! Download and install </span><a href="http://www.microsoft.com/visualstudio/en-us/products/2010-editions/visual-cpp-express" style="font-family: 'Trebuchet MS', sans-serif;">Visual Studio 2010 Express</a><span style="font-family: 'Trebuchet MS', sans-serif;">.</span><br />
<br />
<span class="Apple-style-span" style="font-family: 'Trebuchet MS', sans-serif;">When installing you'll be ask if you have a CD. Just say no and download the installation from online. Once you see this screen (mine is reinstalling however):</span><br />
<div class="separator" style="clear: both; text-align: center;">
</div>
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg2aNJLz4cs-AJRg8sdHmL-hSsQlnGfZjo-qmgj91WbSsaB_fjOA7EVEgRW9NMxzxc8HjRHr8CY0g1FnbulQfNFUpBWpfdZRLb19U5lYsaoGjQMUDUMJBQk1sjXeL_WLT-bTvDjYS4hlIA/s1600/Capture.PNG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="287" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg2aNJLz4cs-AJRg8sdHmL-hSsQlnGfZjo-qmgj91WbSsaB_fjOA7EVEgRW9NMxzxc8HjRHr8CY0g1FnbulQfNFUpBWpfdZRLb19U5lYsaoGjQMUDUMJBQk1sjXeL_WLT-bTvDjYS4hlIA/s320/Capture.PNG" width="320" /></a></div>
<br />
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
<span class="Apple-style-span" style="font-family: 'Trebuchet MS', sans-serif;">Be prepared to restart your computer in the middle of the installation. For some reason this installation took a long time, so be patient! After you restart, at the end of the installation it says: requires a key. Go ahead and hit the button to acquire one; you'll need a microsoft address from something like live.com. Once you fill out this lame questionnaire with fake answers copy/paste your key into the box and continue. You're now ready to code your C programs, and compile them.</span><br />
<br />
<span class="Apple-style-span" style="font-family: 'Trebuchet MS', sans-serif;">Now Visual C++ is called Visual C++, but in actuality you'll only be writing C code for now as I recommend avoiding C++ until you're proficient with C. The reasons for this are simple: if you're proficient with C, you understand its limitations. Once you understand C's limitations and hardships, you can better utilize C++.</span><br />
<br />
<span class="Apple-style-span" style="font-family: 'Trebuchet MS', sans-serif;">Now for the fun part, writing some code! I'm simply going to just give you some code to copy and paste into a .c file. Before this you need to create a .c file, however. Go to, in Visual C++, File >> New >>Project. Select Win32 Console Application -this means your application will run in a Windows console. Enter a name and a solution name (probably use the same thing for both), you can call it Test. Hit ok. This part is important, when you see this screen</span><span style="font-family: 'Trebuchet MS', sans-serif;">:</span><br />
<span style="font-family: 'Trebuchet MS', sans-serif;"><br /></span><br />
<div class="separator" style="clear: both; text-align: center;">
</div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjv7iS93yPbh-kvZjSZEBiDLddbkrzzthxqQ3ZL-6jFSZB8DFX8zBgdL7ch4epiWTPESAR8JX9YhxckYLt9FcC7DjQkY_HqSv8h3Molwyqxyj-6jKk-3XcbntwJN5cgC_NtTpA7ar1q8O4/s1600/Capture.PNG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjv7iS93yPbh-kvZjSZEBiDLddbkrzzthxqQ3ZL-6jFSZB8DFX8zBgdL7ch4epiWTPESAR8JX9YhxckYLt9FcC7DjQkY_HqSv8h3Molwyqxyj-6jKk-3XcbntwJN5cgC_NtTpA7ar1q8O4/s1600/Capture.PNG" /></a></div>
<span style="font-family: 'Trebuchet MS', sans-serif;"><br /></span><br />
<span style="font-family: 'Trebuchet MS', sans-serif;">Be sure to hit the next button! We need to disable the precompiled header. Hitting next will take you to this screen:</span><br />
<span style="font-family: 'Trebuchet MS', sans-serif;"><br /></span><br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi2rq9evS2xb4LrG-RwV3doGxymDjaJ0CaqL5TJnwbmQHC8L10Lb0Vd7icXA1IOuQvQaQ6ceqtyYmc7MDlUY0W62cdXSQed_Amjchgi_t_DdSzeuZ0lKGQA2pCtzUrQkAY8w2AN_zpAfpY/s1600/Capture.PNG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi2rq9evS2xb4LrG-RwV3doGxymDjaJ0CaqL5TJnwbmQHC8L10Lb0Vd7icXA1IOuQvQaQ6ceqtyYmc7MDlUY0W62cdXSQed_Amjchgi_t_DdSzeuZ0lKGQA2pCtzUrQkAY8w2AN_zpAfpY/s1600/Capture.PNG" /></a></div>
<span style="font-family: 'Trebuchet MS', sans-serif;"><br /></span><br />
<span style="font-family: 'Trebuchet MS', sans-serif;">You need to check mark the Empty Project box under Additional options, and uncheck the Precompiled header option. Hit finish! Now you'll see some folders on to your left:</span><br />
<span style="font-family: 'Trebuchet MS', sans-serif;"><br /></span><br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjNWMITlI0NmCvJMSB73Wwqe145eSNJDcuH4V6Su7CArnG3GMWox6lPgVGLZCUWTgxVZbTo9n9tQHCHaEKDS3l4M2eZBGmRy2fJWOepa5iNcMMBTtbLCv9RTC3RwodNYhb6eIytiqe-_44/s1600/Capture.PNG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjNWMITlI0NmCvJMSB73Wwqe145eSNJDcuH4V6Su7CArnG3GMWox6lPgVGLZCUWTgxVZbTo9n9tQHCHaEKDS3l4M2eZBGmRy2fJWOepa5iNcMMBTtbLCv9RTC3RwodNYhb6eIytiqe-_44/s1600/Capture.PNG" /></a></div>
<span style="font-family: 'Trebuchet MS', sans-serif;"><br /></span><br />
<span style="font-family: 'Trebuchet MS', sans-serif;">Right click on the Source Files folder (they are actually called filters not folders) and go to Add >> New Item. Click on the C++ file button, enter a filename in the Enter_Name box. Enter in "main.c" without quotes and hit Add. The added .c file should open up! Even though you specified a C++ file, since you named it a .c file it will be for C code. Now lets get to coding! Copy/paste this little bit into your main.c file:</span><br />
<br />
<div class="code">
<code>int main(void)<br />
{<br /> return 0;<br />
}</code></div>
<div>
<span class="Apple-style-span" style="font-family: 'Trebuchet MS', sans-serif;"><br />
</span></div>
<div>
<span class="Apple-style-span" style="font-family: 'Trebuchet MS', sans-serif;">This code is the minimum requirement for any C program to be able to run. Basically it starts, and then ends. In order to compile this code into an exe, hit Debug >> Build Solution (or F7). You'll see some output form from the compiler in a little box at the bottom of the window It should read:</span><br />
<span class="Apple-style-span" style="font-family: 'Trebuchet MS', sans-serif;"><br /></span><br />
<span style="font-family: 'Courier New', Courier, monospace;">1>------ Build started: Project: Test2, Configuration: Debug Win32 ------</span><br />
<span style="font-family: 'Courier New', Courier, monospace;">1> main.cpp</span><br />
<span style="font-family: 'Courier New', Courier, monospace;">1> Test2.vcxproj -> c:\users\cecil\documents\visual studio 2010\Projects\Test2\Debug\Test2.exe</span><br />
<span style="font-family: 'Courier New', Courier, monospace;">========== Build: 1 succeeded, 0 failed, 0 up-to-date, 0 skipped ==========</span><br />
<span class="Apple-style-span" style="font-family: 'Trebuchet MS', sans-serif;"><br /></span><br />
<span class="Apple-style-span" style="font-family: 'Trebuchet MS', sans-serif;">There you go! You've compiled your program. To run it open up the folder your solution is in. To do this you can copy paste the path to the file from your compiler output, as shown in the text above. Once you find your Test.exe (in the debug folder of your solution folder) try double clicking on it. A black box should open and then quickly close. This code starts, and then <b>ends</b>. I'll teach you how to make your program pause until you hit enter later, but for now lets get into the basics of C code <a href="http://en.wikipedia.org/wiki/Syntax_(programming_languages)">syntax</a>.</span></div>
<div>
<span class="Apple-style-span" style="font-family: 'Trebuchet MS', sans-serif;"><br />
</span></div>
<div>
<span class="Apple-style-span" style="font-family: 'Trebuchet MS', sans-serif;">In C whenever you write lines of code those lines of code are going to be turned into actions that a computer will follow. Whenever you write a <a href="http://en.wikipedia.org/wiki/Statement_(computer_science)">statement</a> it must end with a semi-colon ;. The ; is letting the computer know that it has reached the end of a statement. This is important, otherwise the computer running your code could perhaps mix two statements together as a single statement, which would result in strange behavior.</span></div>
<div>
<span class="Apple-style-span" style="font-family: 'Trebuchet MS', sans-serif;"><br />
</span></div>
<div>
<span class="Apple-style-span" style="font-family: 'Trebuchet MS', sans-serif;">Take a look back at your code you copy/pasted and lets check out what these different lines of code do. int main(void) is setting up the part of your code the program starts at. Every single time any program is ever started that was written in C, it starts at the line with main in it. This line is actually creating what is called the main function. I won't go into detail on exactly what a function is, as all you need to know for now is that this is the first code that is run when your program is started, and then the next line below it will be read then executed, and so on. The open curly bracket { is beginning of the main function, and the } is the end of the main function. For now you're going to write all your code within these two brackets. It's standard C syntax that code within two curly brackets is one tab farther to the right than the code outside of those two curly brackets, which is why the return 0; line is indented. The last thing to explain is this return 0; business. The return 0; line is actually the line of code that ends your program. Once your code is run and this line is executed, your program ends immediately. The 0 is actually a value returned to your operating system letting it know that the program ended successfully. If this sounds confusing, then don't worry about it - all you need to know is that when this line is reached your program ends.</span></div>
<div>
<span class="Apple-style-span" style="font-family: 'Trebuchet MS', sans-serif;"><br />
</span></div>
<div>
<span class="Apple-style-span" style="font-family: 'Trebuchet MS', sans-serif;">A variable in C is a place in <a href="http://en.wikipedia.org/wiki/Computer_memory">memory</a> that stores a value. There are different types of values that can be stored, and so there are different types of variables to hold those different types of values. I'd like to talk about Integers. For a more complete list of the different types of variables available in C, check out <a href="http://en.wikipedia.org/wiki/C_data_types">this link</a> on Wikipedia.</span></div>
<div>
<span class="Apple-style-span" style="font-family: 'Trebuchet MS', sans-serif;"><br />
</span></div>
<div>
<span class="Apple-style-span" style="font-family: 'Trebuchet MS', sans-serif;">Lets start with integers. An integer in C is a whole number value ranging from −2,147,483,648 to 2,147,483,647. In order to create a variable in C of the type integer, you would write:</span></div>
<div>
<span class="Apple-style-span" style="font-family: 'Trebuchet MS', sans-serif;"><br />
</span></div>
<div class="code">
<code>int myInteger;</code></div>
<div>
<span class="Apple-style-span" style="font-family: 'Trebuchet MS', sans-serif;"><br />
</span></div>
<div>
<span class="Apple-style-span" style="font-family: 'Trebuchet MS', sans-serif;">This code <a href="http://en.wikipedia.org/wiki/Declaration_(computer_programming)">declares</a> a variable with the name myInteger, and specifies it's type as an integer with the word int. Don't forget your semi-colon to end the statement! Now what is the value of myInteger? Well currently it would have an undefined value since you have not <a href="http://en.wikipedia.org/wiki/Initialization_(programming)">initialized</a> it yet. To initialize myInteger with a value, you can write:</span></div>
<div>
<span class="Apple-style-span" style="font-family: 'Trebuchet MS', sans-serif;"><br />
</span></div>
<div class="code">
<code>myInteger = 10;</code></div>
<div>
<span class="Apple-style-span" style="font-family: 'Trebuchet MS', sans-serif;"><br />
</span></div>
<div>
<span class="Apple-style-span" style="font-family: 'Trebuchet MS', sans-serif;">The above code will place the value of 10 into myInteger. Now you can type the word myInteger somewhere in your code, and it will refer to the value inside of it, which is currently 10. The equal sign is actually an <a href="http://en.wikipedia.org/wiki/Operator_(programming)">operator</a>. An operator in C takes a value and operates on it somehow. The equal sign, called the assignment operator, takes whatever is to its right and places the value of it into whatever is on its left. This means that the following code is invalid:</span></div>
<div>
<span class="Apple-style-span" style="font-family: 'Trebuchet MS', sans-serif;"><br />
</span></div>
<div class="code">
<code>10 = myInteger;</code></div>
<div>
<span class="Apple-style-span" style="font-family: 'Trebuchet MS', sans-serif;"><br />
</span></div>
<div>
<span class="Apple-style-span" style="font-family: 'Trebuchet MS', sans-serif;">The above code is invalid because it would be trying to place the value inside of the variable myInteger into 10, which is simply a constant value. Some other operators you can use to manipulate values are: - + * / %. Here is what each one does:</span></div>
<div>
<span class="Apple-style-span" style="font-family: 'Trebuchet MS', sans-serif;"><br />
</span></div>
<div>
<ul>
<li><span class="Apple-style-span" style="font-family: 'Trebuchet MS', sans-serif;">- The subtraction operator. Finds the difference between two values.</span></li>
<li><span class="Apple-style-span" style="font-family: 'Trebuchet MS', sans-serif;">+ The addition operator. Finds the sum of two values.</span></li>
<li><span class="Apple-style-span" style="font-family: 'Trebuchet MS', sans-serif;">* The multiplication operator. Finds the product of two values.</span></li>
<li><span class="Apple-style-span" style="font-family: 'Trebuchet MS', sans-serif;">/ The division operator. Finds the quotient of two values..</span></li>
<li><span class="Apple-style-span" style="font-family: 'Trebuchet MS', sans-serif;">% The modulo operator. Finds the remainder of two divided values.</span></li>
</ul>
</div>
<div>
<span class="Apple-style-span" style="font-family: 'Trebuchet MS', sans-serif;"><br />
</span></div>
<div>
<span class="Apple-style-span" style="font-family: 'Trebuchet MS', sans-serif;">What do you think the following code does:</span></div>
<div>
<span class="Apple-style-span" style="font-family: 'Trebuchet MS', sans-serif;"><br />
</span></div>
<div class="code">
<code>int val;<br />
val = 5;<br />
val = val + 5;</code></div>
<div>
<span class="Apple-style-span" style="font-family: 'Trebuchet MS', sans-serif;"><br />
</span></div>
<div>
<span class="Apple-style-span" style="font-family: 'Trebuchet MS', sans-serif;">The above code creates an integer variable called val, and then assigns the value of 5 to it in the next line. The last line then assigns the value of val + 5 to val. You can also do the following:</span></div>
<div>
<span style="font-family: 'Trebuchet MS', sans-serif;"><br /></span></div>
<div class="code">
<code>int val1, val2, val3;</code><br />
<code>val1 = 2;</code><br />
<code>
val2 = 5;<br />
val3 = val1 + val2;<br />
</code></div>
<div>
<span class="Apple-style-span" style="font-family: 'Trebuchet MS', sans-serif;"><br />
</span></div>
<div>
<span class="Apple-style-span" style="font-family: 'Trebuchet MS', sans-serif;">The above code creates three variables all at once within a single line. All three variables var1, var2, and var3 are all of the type integer, as denoted by the int <a href="http://en.wikipedia.org/wiki/Keyword_(computer_programming)">keyword</a>. val1 and val2 are initialized as 2 and 5 respectively, then val3 is assigned the value of the sum of val1 and val2, which is 7. Note that val1 and val2 remain unchanged, as the assignment operator doesn't change anything to the right side of it; it only assigns the value of what is on the right, to whatever is on its left.</span></div>
<div>
<span class="Apple-style-span" style="font-family: 'Trebuchet MS', sans-serif;"><br />
</span></div>
<div>
<span class="Apple-style-span" style="font-family: 'Trebuchet MS', sans-serif;">Now what if you want to actually see the value inside of a variable? Well then you need to modify your program slightly. Take a look at the following code:</span></div>
<div>
<span class="Apple-style-span" style="font-family: 'Trebuchet MS', sans-serif;"><br />
</span></div>
<div>
<div class="code">
<code>#include <stdio.h><stdio .h=".h"><br />
<br />
int main(void)<br />
{<br /> printf("This is a string!");<br />
<br /> return 0;<br />
}<br />
</stdio></code></div>
<div style="font-family: 'Trebuchet MS', sans-serif;">
<br /></div>
</div>
<div style="font-family: 'Trebuchet MS', sans-serif;">
The above code introduces a couple new things. printf is a line of code that is apart of the C standard library (a bunch of features for you to use as a coder), and it prints a string onto the screen. For now, just know that anything within C code that is within double quotes "" is a string. So if you place text within double quotes, within a printf statement like above, it will be considered a string and printf will place it onto the screen when you run your program. The other new thing is the #include <stdio.h> line. This line of code actually is telling the compiler to include a portion of the C standard library into your .C file, specifically the portion with the name stdio.h. stdio stands for Standard In Out, which is referring to input and output, which is why we need it to output a string onto the screen.</div>
<div style="font-family: 'Trebuchet MS', sans-serif;">
<br /></div>
<div style="font-family: 'Trebuchet MS', sans-serif;">
Try compiling and running this code. Sadly, your program opened and then closed very quickly. This is because your program prints the message "This is a string!" and then abruptly reaches the return 0; line and ends. To fix this, modify your code to look like so:</div>
<div>
<br />
<div class="code">
<code>#include <stdio .h=".h"><stdio.h><br />
<br />
int main(void)<br />
{<br /> printf("This is a string!");<br /> getchar();<br />
<br /> return 0;<br />
}<br />
</stdio></code></div>
<div style="font-family: 'Trebuchet MS', sans-serif;">
<span class="Apple-style-span" style="font-family: 'Trebuchet MS', sans-serif;"><br />
</span></div>
<div style="font-family: 'Trebuchet MS', sans-serif;">
<span class="Apple-style-span" style="font-family: 'Trebuchet MS', sans-serif;">The line getchar(); is a function from the C standard library in stdio.h. I won't go into the details, as that's out of the scope of this post, but just know that this line waits for the user to hit enter before executing the next line of code, thus letting you read what you output to the screen.</span></div>
<div style="font-family: 'Trebuchet MS', sans-serif;">
<span class="Apple-style-span" style="font-family: 'Trebuchet MS', sans-serif;"><br />
</span></div>
<div style="font-family: 'Trebuchet MS', sans-serif;">
<span class="Apple-style-span" style="font-family: 'Trebuchet MS', sans-serif;">In order to have your value show up on the screen, you need to modify your code slightly:</span></div>
<div style="font-family: 'Trebuchet MS', sans-serif;">
<br /></div>
<div>
<div class="code">
<code>#include <stdio .h=".h"><stdio.h><br />
<br />
int main(void)<br />
{<br /> int i;<br />
<br /> i = 5;<br /> printf("%d", i);<br />
<br /> getchar();<br /> return 0;<br />
}<br />
</stdio></code></div>
<span class="Apple-style-span" style="font-family: 'Trebuchet MS', sans-serif;"><br /></span><br />
<div style="font-family: 'Trebuchet MS', sans-serif;">
<span class="Apple-style-span" style="font-family: 'Trebuchet MS', sans-serif;">This new version of the code uses a special character within the string in the printf statement. The %d line is actually saying to place the variable i into the spot in the string where %d is located. %d basically means "insert variable of type integer into this location". You can place more characters before and after the %d, but not in between the percent sign and the d character. This will let you see the value of the integer i on the screen! You can now try more fancy things, here's an example program to calculate the product of two variables and print it to the screen:</span></div>
<span class="Apple-style-span" style="font-family: 'Trebuchet MS', sans-serif;"><br /></span><br />
<div>
<div class="code">
<code>#include <stdio.h><stdio .h=".h"><br />
<br />
int main(void)<br />
{<br /> int i, j, k;<br />
<br /> i = 5;<br /> j = 10;<br /> k = i * j;<br /> printf("%d", k);<br />
<br /> getchar();<br /> return 0;<br />
}<br />
</stdio></code></div>
<div style="font-family: 'Trebuchet MS', sans-serif;">
<br /></div>
</div>
<div style="font-family: 'Trebuchet MS', sans-serif;">
<span class="Apple-style-span" style="font-family: 'Trebuchet MS', sans-serif;">And there you have it! You've now learned how to write a simple program to do mathematical calculations on integers and display a single integer on the screen. Congradulations!</span></div>
</div>
</div>CecilSunkurehttp://www.blogger.com/profile/16129986119923492789noreply@blogger.com7