Not logged in, Join Here! or Log In Below:  
 
News Articles Search    
 


Submitted by Luke Hodorowicz, posted on August 29, 2012




Image Description, by Luke Hodorowicz



This is a shot of a game I've been developing for the past year or so. The working title is Banished.

The game begins with a small group of people in the wilderness that have a few supplies left. As the player you guide them to survive, build homes, grow or hunt food, provide warmth, and eventually grow a city. Another focus of the game is on limited resources. A tree takes nearly the lifetime of a citizen to grow, so you can't just clear-cut the play area. Over fishing or hunting will dwindle the number of animals. Failure to rotate crops will result in poor soil.

Unlike most games of this type there are no build trees, no taxes, and no money involved. You can build anything at any time as long as you have the resources for them. Each citizen is individually simulated. They spend time at home, tend to crops, go fishing, hunt, visit the market, have families, and children their children grow up to do the same thing.

I've developed all the tech for the game using C++. No third party libraries are used for the final run time.

The code is written to be cross platform compatible, but currently only the PC is support. When finished I plan on supporting other platforms as well.

All assets are configured using text input files that match C++ class member declarations. Binary assets such as models, audio, or textures are loaded from thier source format and then cached for fast loading in a format that is ready to use by the system. Changes to source assets are automatically detected and then re-cached. The code has it's own RTTI system that can be used both for type safety and to serialize pointers to disk and reconnect them on load.

The entity system uses a component based model rather than a typical C++ polymorphic hierarchy. Entities are collections of simple components, such as a Model component - to display a mesh, or a Storage component - a place where resource can be stored, or a Growth component - which allows trees and plants to grow over time. This allows functionality to be shared between class types without having a heavy base class with common implementations. It also allows for strange combinations of entities, such as allowing people to live inside a tree - simply by configuring a new entity asset - no code changes required.

The graphics engine uses a simple scheme of a loose quad tree and hierarchical frustum culling. Any objects found in view are sorted by material and instance identifiers. Objects are then drawn many at a time using instancing. Different instances can have different parameters such as scale and color. When fully zoomed out the game can submit ~16,000 objects which is then submitted to the GPU with ~400 draw calls. The scene is typically drawn twice, once for a full scene shadow map that conforms to the view frustum and then again for the main scene. On a nVidia GTX280 and a single CPU thread the game runs at a solid 60 FPS. The game current runs using shader model 2.0, for widest possible support, but the graphics engine has scalability features built into it to decrease gpu load for slower GPUs.

The material system is very configurable. New materials can be generated without changing C++ code. Using just a few parameters from the game, the shaders in the game light the objects, and then apply seasonal effects. Leaves on trees turn brown and then are lost in autumn, and snow covers the ground and water turns an icy color in winter.

Skinned models and animations are supported and can be drawn instanced, as long as the models are sharing an animation. Animations blend between each other and can blend between instanced and non-instanced sequences. This allows characters in the game to share animations most of the time but gives the ability to play a unique animations. Shared animations also significantly reduce the CPU time for updating 100's of hierarchies.

Pathfinding is dynamic and accomplished using A* as well as node maps that determine areas that are accessible from one another. These node maps remove the worst case scenarios of A* and allow path finding queries to be very fast.

The UI is fairly simple but supports many widget types, such as backgrounds, buttons, check boxes, combo drop downs, images, tables, progress bars, text, drag and drop as well as localizable Unicode font support. The UI has its own implementations of these widgets for cross platform considerations.

Geez, I've written a lot of code this past year...

If you'd like to see progress on the game, follow me here: http://www.shiningrocksoftware.com/


[prev]
Image of the Day Gallery
www.flipcode.com

[next]

 
Message Center / Reader Comments: ( To Participate in the Discussion, Join the Community )
 
Max

September 11, 2012, 01:53 PM

This sounds like a really unique concept for a game. I'd love to hear more about the implementation of your component system.

 
CodingCat

September 11, 2012, 03:45 PM

Stunningly beautiful! Keep it up, this can only become awesome.

 
DirtyPunk

September 11, 2012, 10:25 PM

Yeah, the component system sounds very interesting. The market model is very pretty.

 
_1dt3k_

September 12, 2012, 03:44 AM

Stunning, just stunning.

 
pacificat0r

September 12, 2012, 03:46 AM

Nice looking game.
I don't really get the need of a growth component. Won't it be used only on trees?
Wasn't the point of having components the fact that they can be plugged into any entity object?
Can you have a growth component added on a house? If not why is it a component?

Do you have a tree like this:
Entity
ComponentList: MeshComponent(with a tree model), ResourceComponent ( specifies that wood can be gathered from here), GrowthComponent

Can't you have a
FoliageEntity: public Entity
ComponentList: MeshComponent, GatheringComponent
And just have the Growth logic in the FoliageEntity::Update?

Or maybe houses can have a growth component :).
Do people have a growth component? They have one but, they just age and don't regenerate so it wouldn't be the same functionality.

 
Luke

September 12, 2012, 09:09 AM

Max, DP, glad you're both still around. :)

Pacificat0r:

So the growth component is used by trees in the forest, trees in orchards, plants that grow in fields, and other collectible plants that are scattered around. The components can be plugged into any entity. If you added a growth component to a house, the house would scale from small to large over time, and optionally have a random chance to spawn some sort of other entity around it (this is how the forest self propagates). Then the house would 'die' after some set number of years. This doesn't make much sense for a house, but it would work.

People don't have a growth component - they're too different. People have two major components - one that handles everything a person can do - things that are mechanical - pathing, moving, updating age, health, etc. The other is the AI component which makes decisions and uses the other component to have the person perform actions. The separation is more for code clarity and cleanliness than anything else.

There's no derivation in entities, so you're example of 'FoliageEntity : public Entity' just doesn't exist. Why hide functionality that couldn't be shared because it's in a child class. That's exactly what I wanted to avoid with the component system. Certainly I do have components that are used only in one situation on one entity, but the way the data is configured and serialized it makes more sense for it to be a component than a derived type. Plus you never know when later on you can reuse that component in a different situation.

The entity class at its core is simply:

class Entity
{
// retrieve a component by type, binary search by type id.
template <typename T> ObjectPtr<T> GetComponent();

// runtime components
Array<ObjectPtr<Component>> _components;

// shared static data
ObjectPtr<EntityDescription> _description;
};

class EntityDescription : public ExternalResource
{
// shared static data and configuration for components - serialized from disc.
Array<ObjectPtr<Description>> _descriptions;
};

 
TheSatoshiChiba

September 13, 2012, 06:13 AM

Looks really good and sounds really interesting.

 
pacificat0r

September 13, 2012, 10:19 AM

@Luke

Oh ok makes sense, I miss-understood the role of the Growth Component.

 
stefan

December 01, 2012, 07:22 PM

So you declared evolution dead?

 
This thread contains 9 messages.
 

If you'd like to post a comment on this discussion thread, please log in or create an account.

 
 
Hosting by Solid Eight Studios, maker of PhotoTangler Collage Maker.