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:

Aesthetics:

Media

Screenshots:

Spawn point destruction Battle example 1 Collecting a coin Battle example 2

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:

Completely unoriginal 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.

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:

Resources created specifically for HeroMan:

Reflections

Three Greatest Challenges:

  1. 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.
  2. 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.
  3. 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:

  1. 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.
  2. 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.
  3. The weapons in the game are interesting and fun. New weapons can be easily aded to the game.

Three things that went wrong:

  1. 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.
  2. 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.
  3. 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:

  1. 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.
  2. 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.
  3. 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.