-
Notifications
You must be signed in to change notification settings - Fork 40
Chapter 1. Getting Started
HSM, short for Hierarchical State Machine, is an open-source C++ framework library that can be used to simplify the organization of state-driven code. The implementation is partially inspired by the UML State Machine (aka UML Statechart) standards, as well as by the UnrealScript state system in Unreal Engine 3.
Most state-driven code can benefit from using any type of state machine library; however, HSM provides the following specific benefits:
- Simple to use: making use of HSM is fairly straightforward;
- Easy to understand: reading HSM code and understanding how it works is often much simpler than in similar systems mainly due to how transition logic is implemented in-line rather than in a table;
- Easy to debug: similarly, since there are no transition table lookups, debugging the state machine is simple. Plus HSM includes a useful tracing feature, as well as a state machine plotting tool;
- Scalable: although its main purpose is to provide a method for nesting states, HSM can also be used for single-layer, or flat, state machines with very little overhead;
- Performance: HSM has been written with performance in mind.
HSM is particularly well suited to games, or any environment where state changes are made frequently based on complex conditions. However, this does not preclude its use in any other type of software.
HSM is an open-source library distributed under the MIT License. In a nutshell, it is a permissive license that allows users to modify the source, and does not force users to distribute the source code with the executable. Of course, although not necessary, if you do decide to use HSM, some form of acknowledgement would certainly be appreciated.
Please see the license file for more details.
The library is made up of a few header files and a single cpp file: statemachine.cpp
. To make use of it, you are expected to build the cpp file as part of your compilation step, and make the headers available for inclusion.
-
Download a release of the source code (or clone from the master branch).
-
Assuming the root directory is named "hsm", add "hsm/include" to your compiler's INCLUDE path. This is recommended so that including hsm headers with take the form:
#include "hsm/statemachine.h"
. -
Add
hsm/src/statemachine.cpp
to your compilation step. -
Modify
hsm/include/hsm/config.h
to match your environment and project-specific settings (more on this below) .
By default, HSM is configured to be compatible with standard C++ projects, making use of certain STL types, default operator new and operator delete, etc. However, many projects do not make use of the standard types, or provide their own types optimized for their target platform. Thus, the library provides a single header file, hsm/config.h, with macros and typedefs used by the library. This file can be modified to configure HSM to better suit the code environment it's being used in.
Most of the contents of config.h are self-explanatory; but here are a couple of notes for some of the configurable types and definitions:
- HSM_STD_VECTOR and HSM_STD_STRING are expected to define types that provide a subset of the std::vector and std::string functionality, respectively. Some code bases avoid using the STL, and define their own types, which are not necessarily compatible with the STL in terms of interface. In this case, one solution would be to provide a wrapper that implements the functionality subset of the STL types to your own types. If this proves too difficult, it may be simpler to replace HSM code that makes use of these types with your own.
HSM requires run-time type information (RTTI) for certain features to work. If standard C++ RTTI is enabled in your compiler settings, HSM will use it, and you don't have to worry about it. However, if standard C++ RTTI is explicitly disabled, HSM will enable its custom RTTI, which requires that you add the macro DEFINE_HSM_STATE to each state that you define, for example:
struct Alive : BaseState
{
DEFINE_HSM_STATE(Alive)
virtual Transition GetTransition()
{
return InnerEntryTransition<Stand>();
}
};
The DEFINE_HSM_STATE macro adds functions used by the custom RTTI system. Note that if you like, you can always add this macro to your states, whether you're using custom RTTI or not, as it is defined to nothing in the latter case.
If standard RTTI is enabled for your project, but you wish to force HSM to use its custom RTTI for whatever reason, you can set the HSM_FORCE_CUSTOM_RTTI to 1 in config.h.
Useful tools can be found in the hsm/tools
directory. This section describes these tools.
Large state machines can be difficult to understand by simply reading code, especially when they have deep hierarchies. The python script hsm/tools/plotHsm.py
can be used to parse cpp files containing a state machine implementation, and will render an image and open it.
For instance, if we run the following command:
python plotHsm.py drawing_hsms.cpp
This would produce and open an image like this:
The script works by running the hsmToDot.py script to produce a GraphViz "dot" file, then uses GraphViz to render it to an image, and finally opens the image in the default image viewer.
To use this tool, you must install the following:
- Python 2.7 (http://www.python.org)
- GraphViz 2.18 (Windows: http://www.graphviz.org/pub/graphviz/stable/windows/graphviz-2.18.exe)
Make sure that both python.exe
and dot.exe
are accessible by adding the relevant paths to the PATH environment variable.
All examples code listings, save a few, that are presented in this book can be found in the hsm/samples/hsm_book_samples/
directory. Each sample is a single cpp file for simplicity, and each code listing in this book provides the sample file name as the first comment of the listing. For instance, the first code listing in Chapter 2 starts like this:
// simplest_state_machine.cpp
So the code for this sample can be found here: hsm/samples/hsm_wiki_samples/source/ch2/simplest_state_machine.cpp
.
To build the samples, you will need to install CMake and run cmake .
in the hsm_book_samples
directory. This will generate the makefile/workspace/solution for the target platform and compilation environment. On Windows, for example, CMake may generate a Visual Studio solution and projects that you can open and build.
Although not required, it can be helpful to build the samples so that you can experiment with them as you read through the book.