Random 2D Terrain

BlitzMax Forums/BlitzMax Beginners Area/Random 2D Terrain

MattC(Posted 2005) [#1]
I'd like to try my hand at a couple of ideas but my first attempt was mediocre at best.
Both games (think Lunar Lander and Scorched Earth) require a random 2D landscape viewed from the side.

I know the originals used different techniques but I'd like the lander game to have similar functionality to Scorch, ie destructibility and scrolling support.

So really I need a scrollable (and maybe zoomable) Scorched Earth style terrain which can be modified. When a crater is formed, or new lumps of earth are created, the terrain should 'landslide' when steepness exceeds a certain value. I'd also need to be able to create flat areas in specific positions, and if possible, pass hilliness/steepness values to the generator in order to have some control over the kind of terrain created.

From my first attempt I think this will be difficult to achieve, maybe someone can give a few pointers or the name of a technique I can google?


ImaginaryHuman(Posted 2005) [#2]
Hey, somebody after my own heart. Scorched Earth type games are cool and I eventually hope to make one myself. The very best of luck to you and since this is an area that particularly interests me, I'm gunna help you with some basic ideas.

One idea you might want to consider for landscape generation is to use a simple subdivision technique. This should give you some control over what kind of terrain is created. What you want to do is start off with several points with lines drawn between them which is a very approximate idea of what kind of shape the terrain will be, in general. The distance that you space these points apart will determine how cliff-like or steep the hills will likely end up being. Also how much randomness you give to each Y coordinate will termine how variagated the hills are (and steep). You may want to either consider an absolute random Y value for each point within a certain range, or you might want to make it relative to the previous point. It might look something like this to begin with if you were to render it by drawing lines between the points .. quick mockup...

Note: These images are stored on geocities so if they're not available try again later.


Then you go through in another pass and divide each of the x segments by 2 (or something else if you want more control) and add another set of points (ie twice as many)



Then again



And then when you have done this enough times that you are either down to individual pixels width or want to stop, you know what height each column of pixels needs to be. Kinda like...



You can decide what resolution you want the first iteration to be - you'll notice that the final landscape is still *basically* the same shape as you started with, just with more `fractal` detail and variagation. You can also decide whether to subdivide by two each time or by some other value to create different kind of shapes.

In order to subdivide you simple find the difference between the Y coord of the current point and Y coord of the next point, divide it by 2, and then add some kind of random amount. And you may want it so that for each iteration of the routine you decrease how much the randomizing is so that as you are defining the smaller and smaller features of the landscape the details get smaller. Otherwise (if you want) it would produce a very spiky terrain. Might be another option for you. You could perhaps also decide to give each subdivided point a movement in the X direction, although you'd then be in danger of making overhanging land, which would require a whole different kind of algorithm to handle land falling and detection.

So basically you come up with a very approximate shape for the overall land, not accurate, just a genearal outline with lots of space between points. Then you divide all those spaces and add more points, and keep going until you are satisfied. If you want to stop before you get down to the pixel level you would later need to perhaps draw polygons or lines or otherwise interpolate between adjacent points to produce a curve or a connected outline. You might also want to get fancy and use the points as handles for a long spline - you could then stop subdividing at a certain level and let the spline handle the rest. Either you could draw as you go along or create an array of heights for each pixel colum or whatever you decide is best for you.

You could get fancy and then explore adding `layers` of earth like strata levels, where you could take your new land shape, move it down by a certain number of Y pixels, and variagate it further a little, then draw in a different color or using some kind of texture. How you render the actual graphic is up to you to experiment with. It's been done in a lot of different ways. Some people use gradients (scorched tanks), some use solid color, some use textures, some use varying textures for depths of earth, some use splined to create a smooth landscape, etc.

Also you may want to consider that since we're creating a fractal subdivided landscape here you could apply a `smoothing` routine to the land shape either at each stop or afterwards, which reduces the difference between each point to produce a smoother graduation. Also you can experiment with adjusting the amount of random values that are added to each point to produce different kinds of landscape.

This is one way of doing it. There are of course others. Worms for example lets you draw the land using a simple paintbrush attached to the mouse pointer which is then uses to turn into a landscape made of textures and images. You could also load in a graphic from a file. You could also use any other methods to generate a landscape - maybe it'd be fun to let the number of subdivision iterations be controlled too so that you can create a pointy landscape with smooth slopes - though you'd then either have to draw polygons between the points or interpolate from one point to the next. Interpolate means - draw the slope between the two.

---------------

You asked about how to create flat parts in a specific area. Presumably this is where you want your tank or whatever to start off? This is simple enough. At the start of the above routine, decide where in x coordinates you want to have these flat areas. You might want to make them as wide as the space between each point on the first version of the terrain. Just manually set two adjacenet points to have the same Y value. This will create a `flat`. Then each time that you do another iteration of subdivision, check to see if you are currently at the points which need to stay flat and don't subdivide them further - or just set them to the same Y value as the flat area. This should allow the rest of the land to continue being random rugged while the flat part stays flat. You can of course have more than one flat area and they can be different widths - different number of adjacent points that stay fixed. How you code this is up to you, whether you use multiple arrays or a multidimensional array or some kind of type with flags for whether a point should stay fixed or not. Hey, you could even get adventurous and give each point in the first version of the land its own randomizing values to use for all the subdivisions that are between it and the next point - this would produce some parts of the land that are for example cliffs, while other parts are hilly, while other parts are flatish, or while other parts are rough, etc. No need to always have just one type of land accross the board.

--------------

You also asked about letting the land slide to a certain degree of steepness when it changes as the result of some explosion or mining or whatever. Well, you need to turn all the pixels above the explosion site into individual particles and then on an individual basis, as you drop the particles and a particle lands directly on top of another, you need to check whether there is a particle below and to the left and below and to the right. If there isn't, that particle can move down to the left or down to the right (ie if there is a particle already on the left side, roll to the right, and vice versa). That would give you a 45 degree slope. If you want a steeper slope you can check the pixels two below and one across, which would give you a 22.5 degree slope? I guess. Not a lot of control over that without getting into something more sophisticated. In the game `pocket tanks` on the Mac there is a dirt slinger weapon which throws up a pile of mud, which then falls and does a landslide like this. I'm fairly sure it just does the 45 degree slope detection as described here since the slopes end up being a perfect diagonal. Incidentally the slope also pushes a tank aside if it's at the base of the slope, something to consider.

If you want to landslide existing land that isn't above an explosion but to the sides of it, then you'll need to turn those pixels into particles - ie grab them with a slope, and move then similarly. Something to bear in mind is that if you are going to have land that landslides at 45 degrees, then it doesn't make sense that you would start out with a landscape with all kinds of cliffs with much steeper slopes - why didn't they landslide already. Doesn't make sense, so be careful with consistency.
------------

Regarding scrolling and zooming, well, that's something I haven't tried to implement in BlitzMax quite yet but I have some ideas. Using a superbitmap is a bit more tricky than using a tile based engine but you can break the superbitmap into tiles and just move updated tiles from the pixmap to an Image. You'll have to get creative in that area, I'm not giving away all my ideas ;-) Zooming is pretty simple, just use SetScale ;-)

Good luck. And create some original features, original weapons and original menu's and heads-up display - almost all games like this are so similar ;-) Don't just make another scorched earth remake, it already exists, go play it on a pc if you want to play it. Get some originality in there, different landscape designs, cool sound effects, nice explosions and stuff, decent looking tanks (or whatever else, something original? I know tanks have been done, castles, turrets, gorillas, people, worms, etc... get original).


MattC(Posted 2005) [#3]
Thanks, you've obviously put a lot of thought into that. It turns out that I wasn't too far off with my initial hill generator... I was originally filling a 1D array with random values and then smoothing them, and using them for altitude values. I'll try to implement something like your subdivision suggestion, it does seem like a better way of doing things, and I can see a couple of ways to influence the output and add plateaus. It might take some time...

I hadn't thought about converting the data to a bitmap or tiles. Which would explain the slowness - I was using Blitz3D and filling the screen pixel by pixel. If I generate the terrain on a pixmap or image I can keep it independant of the background for collisions and landslides etc. I'll have to learn more about pixmaps.

Biggest thanks for the particles idea! I was totally at a loss as to how to achieve landslides. Particles are fairly simple and more importantly, within my abilities :) Again it'll take a little while to get something but I'll post if and when I have something reasonable to show. I'd like to apply fairly realistic physics to the particles (acting like gravel?) but we'll have to see what happens when half the screen needs to be processed on a per-pixel level :\

I think scrolling and zooming, as you said, is trivial with BMX's transform commands. The Lander engine is underway already and I've had no performance problems with sprite rotation, but it's early days yet.

Anyway, with regards to actual game design, no solid ideas yet. The Lander game will be fairly standard, but I wanted to add the twist of wind and fixed gun emplacements on the ground just to spice things up.
For my Scorch clone, I've played Worms, Sheep and Dwarves and they all feel the same. Personally I prefer tanks. It's something to dwell on... Maybe I can inject some originality in other areas like features (air strikes), systems (targeting, shields) or play modes.

I'll show some progress in err.... about 12 years? lol

Thanks again


ImaginaryHuman(Posted 2005) [#4]
Good luck with it, let us know how you're getting on.


Booticus(Posted 2005) [#5]
Damned! Thanks both of you MattC for asking the question and AngelDaniel for answering the question nin awesome, explicit detail! This one goed into the files fo' SHO!!


ImaginaryHuman(Posted 2005) [#6]
Ya welcome. Actually I found most of the above techniques for fractal land on a website someplace, I would've pointed you there but I couldn't find it, maybe it's been taken down since. I'm glad you got some use from it.


ImaginaryHuman(Posted 2005) [#7]
How is this project coming along, MattC?


MattC(Posted 2005) [#8]
Hi AngelDaniel!

There was a slight hiccup, shortly after I started this thread I suffered a spontaneous pneumothorax and spent a lot of time in hospital. It was months before they let me out :(

I re-read your initial response and settled down to start from scratch this evening. So to answer your question, I've just finished the outline of a landscape generator.

Based on your advice, it begins with a set of random values and subdivides down to produce a randomly rugged surface. I'm happy with the shape, but haven't done any work on filling it. If you ever saw a game called Howitzer in early 90's, that's the look I'm aiming for.
The number of initial heights, subdivision levels and random factor can be adjusted, and I can generate a fair variety of land types from flat plains to steep mountains.
Once the terrain is finalised I think the rest should be plain sailing, but I think I'm going to reverse course slightly in order to set up a scrolling playfield.

So in the ten months since asking the question, I have 79 lines of code :)


deps(Posted 2005) [#9]
Welcome back MattC, and good luck with the game!


ImaginaryHuman(Posted 2005) [#10]
Cool, good luck to you and I hope you're doing better now.

We look forward to seeing the fruits of your labour. :-)


MattC(Posted 2005) [#11]
I'm pretty much repaired now, thanks. I'm also happy to seem BM has matured a bit, it was still in beta last time I was here.


Diordna(Posted 2005) [#12]
About your "make a crater and fill it with earth," you could use those particle thingies. Just spawn them randomly above the crater and have them fall, and they'll make it uneven.


MattC(Posted 2005) [#13]
Heh, particles are one thing I do know how to do! I'm hoping to do some particle effects in realtime but it seems to mean learning opengl first...


ImaginaryHuman(Posted 2006) [#14]
How's this project coming along?