Falling Sand Game
I just spent 3 hours playing with this.
The chronicle of one man's quest for a video game development hobby.
So I set out last night to continue working on the "feature painting" design, then got really sidetracked into the wonderful world of random number generation.
This is the class diagram I was messing around with. The original idea was to use this as an opportunity to experiment with generics, so I started with an abstract, generic RandomGenerator<T> class that would, conceptually, serve as a top-level class for producing random things. To create random numbers, I'd implement a RandomGenerator<int> or RandomGenerator<float>. But I also wanted to create random tiles or features as well. In fact, I'll eventually want to be able to randomize virtually any property of the game.
I just had an idea. Just now.
Anyway, I said to myself, "OK, this is good kind of class to have. Making it generic will serve to benefit me later if I build other generics that accept RandomGenerators." But then I started to realize that numbers, tiles, features, etc. don't all fit into the same classification of selectable things...
While I was thinking about implementing RandomGenerators for int and float types, it occured to me that I will probably want the ability to define, at runtime, a strategy by which the RandomGenerator chooses what numbers to output. That got me investigating probability distributions, and I learned plenty of fascinating things about discrete and continuous distributions and how greek they are. But the fact remained that, at least when choosing numbers, I'd like to be able to affect the selection by somehow instructing the RandomGenerator to use a uniform, logarithmic, Poisson — whatever — distribution.
But how to you apply such distributions to collections of tiles or features? Does it make semantic sense to say, "choose from among these objects using a uniform distribution?" Yes, in that case every object in the set has an identical probability of being selected. But I can't make semantic sense out of "choose from among these objects using a logarithmic distribution." To me, with my earthworm-like understanding of probability, such an action requires a sorted list. But how do you sort a list of tiles?
It occured to me that when selecting from a list of objects like tiles or features, the list in question will likely be a collection of object/probability pairs, not just object references. Each entry in the collection (Dictionary<Type, float>?) would identify a thing (unique to the set) and a probability that that thing will be chosen if something is selecting things from the set. This seems like a good idea, but I still can't wrap the idea of a logarithmic distribution around it. In this case, it seems like accomplishing a logarithmic distribution would be a matter of defining the pairs' probabilities according to a logarithmic curve. That makes defining the probabilities my responsibility, and as I'm sure you all know I don't like to work when I can get a computer to do it for me.
So I'm stuck on this: how do I come up with the RandomGenerator<T> class I seek? How do I make it so simple that all the user (me now or plugin developers later) has to do is implement (or if I make the class concrete, instantiate) RandomGenerator<WHATEVER> and get something useful out of that?
The diagram above is a fractured representation of my thoughts last night. I was trying to create an abstraction above the idea of a set and a continuum, and have that abstraction (a "source") serve as the pool from which a RandomGenerator selects its output. But ultimately I ran into this wall: a generator of random numbers is fundamentally a different engine that a random selector of things from a set. But I'm not sure they should be. I'm trying to get over this wall at the moment.
Faced with this problem, I decided to take a step back and regroup my thoughts. I could spend the next several months coming up with a really cool random generation framework, but I'm still itching to have a tech demo of a map generator. These are the thoughts I had. Clearly I couldn't completely tear myself away from the problem.
I'm obsessive like that.
By the way, here's the link to the page I mentioned describing various maze algorithms: http://www.astrolog.org/labyrnth/algrithm.htm.
Spotted this set of tutorials on Digg today: http://www.rdxgames.net/projects/wrathlands/index.html. These tutorials discuss the creation of a text-based RPG created in C++.
Had an interesting thought while watching King Kong this evening. In the spirit of Super Mario Bros., why not have Vyde randomly insert sub-caves within the map? These would likely appear as open or unlockable doors — discoverable by happenstance or by uncovering them — that the player would press Up to enter, and contain some kind of bonus room or other interesting feature.
So here's the plan. What I want to do for my first piece of code is create a rudimentary random cave generator whose results can be rendered to a simple bitmap. I want to be able to create an image (2 colors probably -- black and brown) that resembles the tunnels you might find in an ant farm.
To that end, the diagrams you saw in the last post represent my first approach toward the objects that I'm thinking about for implementing this project. I'm a big believer in designing complex even if results are simple, 'cause that usually makes for the most reusable code, which leads to quicker development over the long term.
The composable tiles thing could be tricky. By having every tile in the game potentially comprised of other tiles, and every tile itself potentially a member of a greater tile, I hope to have a tile / map architecture that allows the following features:
This will be a fun little experiment. I found a great page on maze generation algorithms and am anxious to discover the best framework that will make not only random generation possible, but also the inclusion of prefab elements. For example, I'd like the ability to create a church room (say, a screen big) with specific decorations and whatnot, then register that room with the engine in a way that causes the engine to insert my hand-made church in the otherwise randomly-generated map if some condition is met.
Here are the sub-tasks for this project:
Here's a reasonable question: have I designed enough of the game (gameplay, story, etc.) to go this far in implementation? Probably not. Knowing exactly what features I want in the game -- having an itemized list of gameplay elements -- that would be the best blueprint for building code. But here's the thing. This is a hobby, and I (along with ZMan, apparently :) am itching to see something that actually does something.
My philosophy is this: Vyde as a game is far too big to design all in one go. I set out on this journey with every intention of letting the project grow organically. To that end, this map generator is a prototype. It's a proof-of-concept tech demo that I believe will serve to give me a better idea of what my limits are and tune me to a more focused direction later on.
Let the game begin!
I asked my brother to draw some concept art for Vyde for my Christmas present. He asked me to come up with a list of some things I wanted. So here's a list of some things. It's up to you which ones you do, bro.
Merry Christmas. :)