• Advertisement
  • entries
  • comments
  • views

Building a large procedurally generated world with no load screens: How caveman 3.0 works.

Sign in to follow this  


Building a large procedurally genrated world with no load screens:
How caveman 3.0 works.


1. the world map
the world map is stored in a 500x500 array of structs.
each map square is 5 miles across.

terrain chunks and collisions maps are generated from the world map data.

assets are loaded once at program start. asset reuse is maximized.
load times are on the order of 20 seconds or so for EVERYTHING! : )

if required, paging of assets could be implemented.

the map structs hold info about elevation (heightmap used), vegetation
(what plants to draw, what ground texture tile set to use), water
(what water to draw), and miscellaneous terrain features, such as rock
outcroppings, fruit trees, berry bushes, tar pits, etc (more stuff to

the world map is randomly generated at game start, updated (changes)
once per game day, and is included in a save game.

2. pattern maps:
so the world map tells us more or less what to draw, but not necessarily
where exactly to draw stuff.

enter "pattern maps".

a pattern map is a 2d array, either a true 2d array, or implemented as
a sparse matrix (a list).

so you have a pattern maps to tell you where to draw trees, rocks, etc.
pattern maps are then repeatedly tiled over a map square to place trees,
etc. The size of a pattern map should be big enough that no moiarre'
patterns are discernible within viewing range. this usually works out to
a size of two times visible range.

multiple pattern maps are used for different things so rocks and trees
for example don't all appear at the same locations.

pattern maps can contain more information that just location, they can
also include things like type information for determining drawing info,
or even render and physics info like scale, bbox dimensions, etc.

ground coverage plants can simply be draw every x number of feet with
type based on "location mod ".

caveman uses 5 pattern maps: one for trees, one for rocks, one for berry
bushes, one for fruit trees, and a generic pattern map for tall grass,
canyon heightmaps, and a few other things.

pattern maps are randomly generated at game start, and are included
in a save game.

3. The CRH list:
the CRH list is a list of all the caves, rock shelters, and huts in the
game (IE all buildings in essence). an index is used to speed searches.
the index is a 2d array the size of the world map. for each map square,
the index holds a list of the CRH's in that map square
(IE their indexes in the CRH list).
the CRH list is randomly generated at game start, is updated once per
game day, and is included in a save game.

4. The world objects list:
this is a list of all the immobile objects the player has built in the
game world such as shelters, huts, landmarks, traps, bedding, etc.
it also includes all inventory objects the player has dropped. dropped
objects are only persistent inside player owned CRH's, otherwise they
are removed from the simulation when the player is no longer nearby.
so its ok to store them here without running out of room.

when it comes time to render, the game determines the terrain chunks
in visible range, and draws each one. if a chunk is not in the cache
its generated on the fly. chunks are also generated in the background.

a terrain chunk is basically a pre-generated render queue list of all
the meshes in the chunk to be drawn, ready for sort on distance
(if desired), frustum cull and rendering.

a chunk is generated by clearing the cache slot, then adding meshes, then
setting the slot to active for use by the renderer.

the coverage and miscellaneous terrain features in a map square
determines what to draw, and the pattern maps are used to place items
such as trees, rocks, and plants.

the world map, pattern map, and world objects list determine the meshes
added to the chunk. once the meshes are added, the chunk is marked as
active for use by the renderer.

the optimal size for a chunk appears to be whatever visual range is.

ground mesh generation:
ground meshes are generated as follows:
pre-allocated static buffers are used.
the ground is composed of four interleaved meshes, one for each of the
four texture tiles used. a pattern map determines the texture used
by a quad. all quads using a texture are heightmapped and added to the
static buffers (VB and IB) for that mesh. the four meshes draw together
form one continuous ground mesh with tiled textures that still follows
the game's mantra of "one texture per mesh" for speed.

the elevation in a map square determines the heightmap used by the
ground meshes. elevations can vary from map square to map sqaure.
a "heightmap seam fixer" is used at map square edges. the ground
texture pattern map determines which texture a ground quad uses.

collision maps:
collision maps are generated on the fly, in a manner similar to terrain chunks,
and stored in a collision map cache.
the maps are 2d arrays of ints, with different values indicating different types
of obstacles: 0=none 1=rock 2=tree, etc.
collision maps are the same size as terrain chunks.
when a collision check is made, the location is translated to a collision map
and coordinates in the map. if the map indicates something there, true is returned
for the collision check.
if a collision map is not in the cache, its generated on the fly.
a maps is generated by clearing it, then adding trees, rocks, buildings, etc.
as specified by the world map, pattern maps, and world objects list. collision map
generation is faster than terrain chunk generation because it only sets a few ints
instead of adding a drawinfo struct to a database with a 2d index. so background
generation is unnecessary.

overall results:
as the player moves across the world, terrain chunks and collision maps are generated
as needed. right now there is a slight delay when a large number terrain chunks must be
generated in the foreground on the fly, but its too short to even display a
"generating area..." message. as i fine tune the background chunk generation to run
faster with more passes of less stuff per pass, and increase terrain chunk cache size,
and perhaps increase the background generator's look ahead range, i hope to eliminate
the slight delay entirely.

this approach gives you a procedurally generated random persistent modifiable game world
with no load screens.
Sign in to follow this  


Recommended Comments

There are no comments to display.

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

  • Advertisement