HeroMan
Abstract
Game Title: HeroMan
Development Team Members:
Game Genre: Co-op Dungeon Crawl
Brief Description:
Up to four players play cooperatively to crawl through a dungeon
environment and fight monsters.
Overview
Game Story / Objective:
Up to four players crawl through a dungeon with one goal in mind:
Find the jukebox hidden within the map and put on some different music!
Several obstacles stand in their way. First and foremost, the party
of adventurers must find the coins necessary to operate the jukebox.
But more pressingly, the dungeon is populated with monsters that
don't take kindly to your presence.
The adventurers are aided in their quest by a suite of super advanced
guns that will help them get past the monsters. Within the dungeon,
players will find power shards that they can collect to upgrade these
guns. Each increased power level gives access to a new and unique
weapon!
Game Mechanics + Controls:
Technology:
- DevIL image loading library
- FMOD Audio
- OpenGL graphics; designed to run fine on low-end graphics hardware (e.g. GMA 950)
-
ODE Physics library for collision detection and response. For example,
power up items (dropped by monsters and some objects) such as chairs can
be tossed and pushed around the map.
- SDL input
- Cooperative multiplayer available by connecting several XBox360
controllers to the PC. Up to four players are supported.
-
Levels may contain moving platforms activated by some comination of
switches. The combination of switches necessary for activation is
defined by an s-expression embedded in the level data file.
- Entity/Component system, described in detail in the next section
Aesthetics:
- Not being artists, James and Andrew opted to scavenge what art assets
they could from previous game projects. Obviously, this limited our
choices for game aesthetics. Monster models and the player models were
chosen form a limited selection of articulated MD3s available. The player
model was chosen because 4 versions exist, each with a different color
shirt. These different models are used for each different player.
-
Many events in the game are accompanied by sound effects. Characters
make sounds when they die. Guns make sounds when they are fired.
Projectiles and explosions make sounds when they collide with a target or
obstacle. Etc.
-
Weapon and explosion effects use aesthetically pleasing particle effects.
-
Character damage effects uses an aesthetically pleasing flashing effect.
This is intended to be reminiscent of effects used on old SNES and arcade
games.
-
Objects are at points in the game highlighted using a nifty stencil buffer
effect.
Media
Screenshots:
Documents:
Milestone 1 Presentation (PDF)
Final Project Presentation (PDF)
Download:
Download HeroMan
Download Source Code
Development Summary
Code
I'm not really sure where to start. The game is based on Andrew Fox's
project 2 code, which was in turn based on source code from Andrew's game
Abarlith 2. A quick diff
of the source code demonstrates that almost none of the original code remains.
Now since I'm not sure how to handle this section of the post-mortem, I've
decided to cover the highlights. There are many more original pieces of code
than are described here and I may have missed some unimportant snippets that
remained unchanged since Arbarlith 2. The important, large pieces of
code are covered below.
Code not completely scrapped from Arbarlith 2:
-
The XML parser from Arbarlith 2 was not completely scrapped,
but ended up being modified heavily and bears little resemblence to the
parser used in the original engine.
-
The MD3 loader is a modified version of the MD3 loader used in
Arbarlith 2. The code used for storing, animating, and rendering
models was almost completely rewritten for project 1.
-
Much of the GUI code from Arbarlith 2 was stripped out of the
engine, but the code that remains has not been changed much.
-
Utility code such as the vec2, vec3, vec4, and mat3, mat4 have remained
from Arbarlith 2. This code works; why change it?
Completely unoriginal code:
-
Stackwalker code in StackWalker.cpp/.h was originally found
at
http://www.codeproject.com/threads/StackWalker.asp
-
PropertyBag.h/.cpp was originally based on code from
McCuskey, Mason. "Game Programming Tricks of the Trade".
"Trick 15: Serialization Using XML Property Bags".
Premier Press. 2002.
-
Frustum.h/.cpp defines a simple class for dealing with frustum objects
and is able to perform frustum intersection tests.
Original Author:
Ben Humphrey (DigiBen)
E-Mail: mailto:DigiBen@GameTutorials.com
Co-Web Host of www.GameTutorials.com
Extensively modified over the years. Some resemblence to the original
code can still be seen in the Frustum::set method.
-
anorms.h defines encoded MD2 normals. This table was taken from the
Quake 2 source code.
Game Loop
The game loop is based around a game state machine class with each
game state being implemented in a separate state object. This allows the
easy creation of new game states and state transitions. Additionally, each
pane of the game menu is implemented as a separate game state.
Game World
The game world is contained in the World object which resides within the
GameStateRun object. The world takes care to create the map and all actors,
manages the physics engine, and is called to render and update the game world.
Entity/Component system
Game objects are composed of an aggregate of components, each
of which implements a single aspect of the object. In effect,
each component implements a discrete feature of a game object.
This allows a more agile and flexible approach, as new game
objects can be created by rearranging components and creating
new aggregate collections of components without having to
recompile the game or edit source code.
Unfortunately, the downside of the component system is a
greater initial investment in the system itself and the
message passing system that is necessary to allow components
to effectively communicate.
The component/entity system is powerful and flexible, but
it can be improved in future projects. Unfortunately,
there wasn't enough time in this half-semester project
to research and experiment with these additional features.
Room for improvement in future projects:
-
The component system can be extended in future projects to
allow network multiplayer by serializing messages across
the network.
-
Also, the component system can be extended in future projects
to take advantage of multithreading. Very often, the exact
order in which messages are processed is unimportant and the
messages themselves contain all information necessary to
perform the required computations.
Resources:
Physics Engine
ODE is used under the hood for physics and collision detection. For the most
part, ODE handles this without any interference from the rest of the engine.
However, there are a few components that connect game entities to the physics
engine and provide access to the position and orientation of the rigid body.
See ComponentPhysics.cpp/.h ; ComponentPhysicsGeom.cpp/.h ;
ComponentPhysicsBody.cpp/.h ; and PhysicsEngine.cpp/.h for the source code
involved.
Models and Animation
MD3 and MD2 animations are supported. Also, OBJ models are supported and can
be animated by stringing together several OBJ models, each acting as a keyframe
in the animation. Once loaded, the format of the model doesn't matter to the
animation subsystem anymore.
See Material.cpp/.h ; Mesh.cpp/.h ; KeyFrame.cpp/.h ; AnimationSequence.cpp/.h
; AnimationController.cpp/.h ; ResourceBuffer.cpp/.h
Particle Engine
The particle engine handles all particle systems. Particles are implemented
using batches of billboard quads. The graphical fidelity gained by
sorting these quads properly by z-order was more than offset by the
performance penalty of being unable to batch quads by texture state changes.
See ParticleElement.cpp/.h ; ParticleEmitter.cpp/.h ; ParticleEngine.cpp/.h ;
ParticleSystem.cpp/.h
Sound System
Simple wrapper for the FMOD 3.7.5 API
See SoundSystem.cpp/.h
Input System
Wraps SDL input but adds a layer of functionality by allowing arbitrary
boost::function objects to be bound to specific input events. This allows
input event callbacks to be defined easily and flexibly.
It should be noted that while this class shares the same name and essential
purpose as one written by Tom Cauchois for Parasomnia, and used again
for Arbarlith 2, this class uses none of Tom's code.
See SDLinput.cpp/.h
Weapons
The WeaponItem class defines the interface for interacting with the various
weapons in the game. Sub-classes of weapons implement specific behaviors.
See WeaponItem.cpp/.h ; WeaponItem_*.cpp/.h
Special Abilities
Like the WeaponItem class, the SpecialAbility class defines the interface for
interacting with the various special abilities in the game. Due to time
constraints, only one specific special ability was written for the game.
See SpecialAbility.cpp/.h ; SpecialAbility_SpeedUp.cpp/.h
S-Expressions
S-Expressions provide crude scripting capabilities to the game engine. For
example, the logic necessary to determine when it is appropriate for a
door (aka Gate) to open and close is written in a pair of s-expressions.
See sexpr.cpp/.h
Content
Unless otherwise noted, resources have been graciously donated by the
following skilled artists. Many of these assets were originally created for
GCS projects in previous semesters:
- Sky Box - Johannes Schloerb of www.schloerb.com
- Textures - John Nesky
- 3D models - John Nesky
- Sound effects - Chris DeLeon
- Music - Rachel Berkowitz
Resources created specifically for HeroMan:
- Closet model - James Huff
- Shard model - Andrew Fox
- Heart model - Andrew Fox
- Font images - Generated via script by Andrew Fox
- Ability Defs - James Huff
- Weapon Defs - Andrew Fox
- Actor Defs - both Andrew Fox and James Huff
- Level 1 - Andrew Fox
- Level 2 - Andrew Fox and James Huff
- Level 3 - James Huff
Reflections
Three Greatest Challenges:
-
As described above, the infrastructure necessary for the component/entity
system was quite substantial. This challenge was nearly insurmountable,
but the gains given by the experimental system did pay off near the last
third of the project, which helped us to make significant
advances. On the bright side, future projects using this engine
will be able to get off the ground nearly immediately.
-
James and Andrew are not artists in any sense of the word.
Careful scavenging of existing assets from previous projects
did help to create a somewhat coherent visual aesthetic.
-
ODE is a great physics engine, but it does have a number of
annoying drawbacks. James and Andrew encountered a number of
bizarre physics bugs that could only be solved through careful
and thoughtful debugging sessions.
Three things that went right:
-
The component/entity system (described in depth above) is very flexible
and did allow a very agile approach to creating game objects. Its really
quite beautiful to be able to create entirely unique game objects without
a single extra line of code.
-
The particle effects system is particularly satisfying. Particle effects
are defined in a flexible data file that allows quite a bit of variety in
the effects that are possible.
-
The weapons in the game are interesting and fun. New weapons can be
easily aded to the game.
Three things that went wrong:
-
The player control scheme and camera controls changed several times during
development. Several iterations of each were written and tested, which
did ultimately lead to a better, more playable final game, but the time
spent experimenting with control schemes was sorely needed on other,
equally important portions of the game.
-
Not enough time was spent on monster behavior (i.e. AI). It was
prioritized below other features, which led to certain AI features such
as A* path finding being cut late in the project. This certainly led
to a less impressive final product.
-
Too much time was spent working to resolve problems with ODE. These
issues included collision geometry that failed to work correctly on
certain computers, seemingly random bNormalizationErrors, odd issues
with physics joints used for character movement, and strange system
stability issues when the game was allowed to run at fast framerates
(>60fps). These issues were not insurmountable, but did consume valuable
time that could have been devoted to more important issues such as monster
AI and additional weapons.
Other final thoughts:
-
Early on, decision was made to avoid writing a level editor. Instead,
levels were written by hand as XML data files. In hindsight, this was
time-consuming and tedious. The initial investment of a level editor
might have been worthwhile.
-
The XML parser is heavily modifed version of a piece of XML parser code
found in a book. This is one of the few pieces of code that remain from
the original code base. However, it may have been worthwhile to use
an XML parser library like libxml or switch to a different, simpler, data
format such as YAML or JSON.
-
Perhaps a more stylized visual aesthetic could have reduced the number
of problems related to scavenging art assets. Bossmen demonstrated
that a bloom effect and some spiffy effects can go a long way to make a
simple model look wonderful.