SimBlob. This is the project that got me interested in tile games, hex maps,
pathfinding, road drawing, economic simulation, AI, and procedural map
generation. Those of you who have been following me for a long time
know that these are topics I'm especially fond of. This project was a
huge influence on me and my game programming site. It ended 15 summers ago.
SimBlob was the simulation game engine / project that I was going to
use for a building game called BlobCity, but I also wanted to use it for other games. As typical for people who work on a game engine
first, I didn't finish. But that's ok. I was writing the game in order
to learn and experiment, not learning and experimenting in order to write
a game.
More screenshots from 1995-1998
Playing the game
The reason I'm going through this code is that I'm porting it to run
on modern systems; the next blog post will describe that process. (I'm not planning to work on it beyond the port.) Once
I got it running, I spent some time playing the game. The UI feels
clunky today but it followed the standard "paint program" paradigm
that I saw in games like Pinball Construction Set and SimCity.
I only had 8-bit graphics back then, so I used lots of dithering. The
dithering on ground textures looks terrible to me today, but it
probably looked ok on fuzzy CRTs. Some of the placeholder art is
terrible, but I'm quite happy with roads and walls. There are some
neat patterns you can make. Putting them together in a triangle or
hexagon forms some nicely curved shapes, not because these shapes were
specifically implemented, but because the way I made the individual
tiles, these shapes came out automatically:
I spent way too much time on simulation, both water and economic. A
lot of this stuff just isn't visible to the player. A simpler version
would've worked just as well. I also tuned the difficulty for
myself. Since I knew how the simulation algorithms worked, I knew what
to look for and could play the game reasonably, but I think the
simulation might be too difficult to understand for anyone who hasn't
understood the code.
Looking through the code
I've not looked at this code for a very long time. I've learned a lot
since then. Some aspects of my coding and design style are different
now. But other aspects are still the same, which tells me I have so
much more yet to learn.
There's plenty of extra complexity that never paid off:
- There are two separate class hierarchies for windowing:
Windowworks with OS/2 windows. The main map, minimap, toolbar,
statusbar, and menus are all using this level.Glyphis another window hierarchy, independent of OS/2
windows. The design was inspired by the InterViews GUI toolkit,
which had quite an impact on my impressionable yound mind. The
buttons, statusbar items, tabbed information area, and a few other
things fit into this hierarchy.
- There are multiple event processing systems. There's the OS/2 native
one,WndProc, then one for my Window hierarchy, and another one
for my Glyph hierarchy. - The widget libraries include things I never used, like state cycling
buttons and radio buttons. - The layout manager was complete overkill, but something I wanted to
experiment with. I had vertical layouts, horizontal layouts,
overlapping layouts, and toggleable panels. It supported centering,
stretching, and spacers. The original idea was that SimBlob was a
simulation game engine that would support multiple games, and
therefore would need an easy way to build UIs. In practice, I only
ever partially wrote one game, and I could have manually placed the
elements.
My main goal with the project was to learn things by trying things
out. It's a good thing my main goal wasn't to finish a game. I learned
a lot from all of these experiments, but I didn't finish the game.
I'm reasonably happy with the way the code looks. The main thing I
don't like is that the modules don't cleanly map onto files. This was
fine back when I was working on it, since I had the mapping in my
head, but when I try to navigate the code now, it takes more
effort. It's a good thing there are code navigation tools available.
Algorithms - environmental
I spent a huge amount of time playing with procedural map generation:
fractal terrain, mountains and valleys, ridges and canyons, soil
erosion, continental uplift, water erosion, volcanos, floods, forests,
river channels. I followed the standard model of: try something out,
run it, see if I like it. This was a huge time sink. At the very
least I should have automated some of the testing. When I work on map
projects today, I try to avoid this time sink by instead working
backwards, building maps based on the game's requirements instead of
trying to make a realistic simulation.
Programming the map generator and environment simulator led me to
learn a lot about geology, hydrology, and other fun subjects.
The environment simulation was largely about water. Water flows
downhill from springs. There are seasonal floods and droughts. Water
moistens the soil (which affects farms and trees). It evaporates. It
is absorbed by plants. It destroys towns. Flowing water picks up
sediment and deposits it in other places, creating erosion
patterns. Add simulation of energy and momentum, and I got some really
interesting patterns. For example, water picks up sediment on the
straight parts of a river then deposits it on the inner bank of a
curve, creating meandering rivers and oxbow lakes.
For gameplay, I wanted a continually changing surface. In SimBlob,
continental uplift followed by soil erosion happens not only during
map generation but also while the game is being played. Soil erosion
rates vary by area; it's higher on mountains and near towns and lower
in deserts and on river banks.
Vegetation was modeled in two ways: plants and trees. Plants are
entirely based on elevation. Low elevation gets plants; high elevation
does not. Trees are much more interesting. Trees would grow over
time, and older trees would spread seeds to nearby tiles. Seeds
sprouted if the soil was moist. Fires spread across the landscape,
damaging forests.
Volcanos would spread lava, which flowed downhill and then hardened
into new land. Lava also set fire to any nearby trees. Volcanos are
part of the map generator but can also be triggered in the game by the
player.
Algorithms - economic
Writing the economic system led me to learn about economic geography,
including location theory, central place theory, and economic rent. The model is: Farms generate food; Houses generate labor;
and Markets bring them together. Farms need to be near water and
roads. Houses want to be near other houses, but also like
water. Markets need to be near roads but away from other
markets. Markets and houses are more valuable near the city
center. The first economic system automatically built roads where
transportation was needed; it generated neat fractal-like patterns. My
later economic system required the player to build roads, as I was
moving away from pure simulation and towards having a playable game.
The simulation was based on a resource flow model. Resources flow from
sources to sinks along roads. Food flows from the market to houses. If
there's excess food, blobs move into houses; if there's a lack of
food, blobs move out of houses. Labor flows from houses to farms, and
houses to markets to farms. The more laborthere is, the more food is
produced.
The intended effect was for land near the town center to be more
valuable to markets than to farms. At a medium radius from the center,
houses are more valuable than farms, and there are just a few
markets. On the outskirts of town are the farms. As the town grows,
tiles near the center would switch from farms to houses to
markets. It's a nice simple model that leads to pleasant towns.
The job system for builders was rather bad. Each builder blob would
accept up to 6 nearby jobs, but this greedy algorithm wouldn't
consider cases where another builder was better suited for the
job. The code is messy. It worked fine for a single builder but worked
poorly when there were multiple builders. If I were approaching it
today, I'd look at algorithms for the Assignment Problem.
The original implementation of firefighter blobs used an influence map
to "follow the heat". I was a big fan of influence maps. However, it
didn't work that well, because after a fire was put out, it took too
long to propagate. Also, all firefighters would end up going to the
same place (I hear this is a problem in some other games too). I
changed it to an algorithm that divides the map into regions, and
chooses regions based on the number of fires and firefighters already
there. That worked much better.
I have a lot more notes written up here.
If you want to try out the game, I've made it run in a web browser.
Conclusions
Working on SimBlob was great for me. I learned a lot about science,
economics, simulation, and programming. I learned that finishing a
game wasn't as interesting to me as understanding a topic and writing
about it. So that's my site's "origin story": SimBlob is the project
that led to the original game programming topics covered on my site.
Không có nhận xét nào:
Đăng nhận xét