Pinguinpanic
JGO n00b  Posts: 17 Medals: 1
|
 |
«
on:
2012-01-03 19:02:26 » |
|
Hello there, I'm new here, and thought I'd share something isntead of only being here to ask annoying questions. I'm working on some random map generation for a game I am working on, and I was thinking that some sharing of thoughs on map generation would be nice, since my stuff so far is far from perfect. What I am doing at the moment, is rather simple, and would be best described in a snippet of code: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| for(int i=0;i<laketimes;i++) { pointX=genValue(WIDTH); pointY=genValue(HEIGHT); for(int x=0;x<WIDTH;x+=1) { for(int y=0;y<HEIGHT;y+=1) { int t=distance(x,y,pointX,pointY); value[x][y]+=(int)(100.0*Math.cos(t/10+90)); } } } |
I also added in a bit of white noise over the whole thing, and afterwards I smooth it out, by for every x,y assigning the average of the surrounding values. I do this two times but I guess that is all down to flavor, here's a pic of my method:  As you can see, everything seems to be a bit circling arround the lakes. So anyone have past experience with generating maps?
|
|
|
|
|
SimonH
JGO Strike Force    Posts: 896 Medals: 14
|
 |
«
Reply #1 on:
2012-01-03 19:50:56 » |
|
If you use regular functions like cos then you're going to get regular results... A simple solution would be to add multiple cos functions at different resolutions.Try; 1
| value[x][y]+=(int)(100.0*Math.cos(t/10+90)+50*Math.cos(t/5+45)); |
for example. A more advanced solution would be Perlin Noise.
|
|
|
|
theagentd
JGO Wizard     Posts: 1392 Medals: 88
|
 |
«
Reply #2 on:
2012-01-03 20:07:08 » |
|
As you can see, everything seems to be a bit circling arround the lakes.
You mean like IRL? >_> I think that map looks awesome...
|
There is no god.
|
|
|
Games published by our own members! Go get 'em!
|
|
Roquen
JGO Strike Force    Posts: 827 Medals: 25
|
 |
«
Reply #3 on:
2012-01-03 21:53:49 » |
|
I wish Hugo would edit this page. This is "value" noise and not Perlin. The concepts are fine, the noise function is not. There are various noise implementations in various thread here which can be searched for.
|
|
|
|
|
SwampChicken
Full Member   Posts: 199 Medals: 1
|
 |
«
Reply #4 on:
2012-01-03 22:18:25 » |
|
Nice. How many tiles across is that?
|
|
|
|
|
Shazer2
Jr. Member   Posts: 66 Medals: 3
|
 |
«
Reply #5 on:
2012-01-04 01:15:09 » |
|
This is very interesting and cool. Hopefully one day I can do stuff like this.
~Shazer2
|
"When you want to be successful as bad as you want to breathe, then you will be successful." - Eric Thomas
|
|
|
Swattkidd7
Full Member   Posts: 203
|
 |
«
Reply #6 on:
2012-01-04 02:07:09 » |
|
I see how you are storing the values into the 2D array of "values" but what exactly do you do with those values? How do you render the map?
Anyway, the map looks really nice, good work and thanks!
|
|
|
|
|
princec
« League of Dukes » JGO Kernel      Posts: 8089 Medals: 96
Eh? Who? What? ... Me?
|
 |
«
Reply #7 on:
2012-01-04 05:31:58 » |
|
I really like that map - it has a "real" look to it. Cas 
|
|
|
|
Pinguinpanic
JGO n00b  Posts: 17 Medals: 1
|
 |
«
Reply #8 on:
2012-01-04 06:17:13 » |
|
If you use regular functions like cos then you're going to get regular results... A simple solution would be to add multiple cos functions at different resolutions.Try; 1
| value[x][y]+=(int)(100.0*Math.cos(t/10+90)+50*Math.cos(t/5+45)); |
for example. A more advanced solution would be Perlin Noise. Thanks for that tip, I was actually aiming for Perlin noise, but my math skills are pretty meh, so I just left it at cos(blah), but that link is really helpfull. I got the idea of taking points and aplying a "formula" from the distance from this link: http://www.noisemachine.com/talk1/, it's from one of the guys who did 3d graphics for the Tron movie, apparently all of that stuff was just algorithms, no prefabs. It's quite an interesting read, if anyone's interested. Nice. How many tiles across is that?
It's 200x200, I'm using a tilesize of 8x4, but the tiles I'm drawing are atcually 16x8  , so if you zoomed in, it would look awkard. Just doing it for testing sake, the real tiles are 64x32. This is very interesting and cool. Hopefully one day I can do stuff like this.
~Shazer2
It's nothing very fancy, I just have a 2D array storing what tile to draw at a position, and one of my friends made me a nice tileset. What part of this looks difficult? I might be able to give you a pointer in the right direction. I see how you are storing the values into the 2D array of "values" but what exactly do you do with those values? How do you render the map?
Anyway, the map looks really nice, good work and thanks!
I have a set of tiles stored in an array "tilesheet[]" of which 1 is Water, 2 is Sand, 3 is Grass, 4 is elevated Grass, 5 is more elevated grass and 6 is most elevated grass. To determine the tile for every tile I use the value[][] that I calculate with my mapgenerating algorithm, the script looks like this: 1 2 3 4 5 6 7 8 9 10
| public int getTile(int x, int y) { int ret=value[x][y]; if(ret<35) return 1; if(ret<45) return 2; if(ret<75) return 3; if(ret<90) return 4; if(ret<95) return 5; return 6; } |
I just fiddled with these numbers untill it looked nice, I'm not a very organized programmer, I ussually just mess arround untill it looks good/works. Thanks for all the positive feedback (: does anyone have ideas on how you could create a method that also works with an expandable world? The weakness of my method is that, if you want the expand the world, the "seeds" that you used will all be really close, while the rest of the world is far away, resulting in simply circles arround your original part of the map:  The north quarter of the map was the original map in this image.
|
|
|
|
|
roland
Full Member   Posts: 235 Medals: 6
|
 |
«
Reply #9 on:
2012-01-04 06:31:04 » |
|
You draw every tile, one at a time? and you just draw textured cubes? like for (int x = 0; x < numTilesX; x++) { for (int z = 0; z < numTilesZ; z++) { //draw the highest(y value) block here and ignore the lower ones? } }
Edit: this is 2d?
|
|
|
|
Games published by our own members! Go get 'em!
|
|
Pinguinpanic
JGO n00b  Posts: 17 Medals: 1
|
 |
«
Reply #10 on:
2012-01-04 06:43:24 » |
|
You draw every tile, one at a time? and you just draw textured cubes? like for (int x = 0; x < numTilesX; x++) { for (int z = 0; z < numTilesZ; z++) { //draw the highest(y value) block here and ignore the lower ones? } }
Edit: this is 2d?
It's 2d, my tileset kind of has the height in it, like this:  Then I just draw them one by one, starting from the top to make sure the front ones are in front of the back ones.
|
|
|
|
|
SimonH
JGO Strike Force    Posts: 896 Medals: 14
|
 |
«
Reply #11 on:
2012-01-04 07:04:05 » |
|
I was actually aiming for Perlin noise, but my math skills are pretty meh, so I just left it at cos(blah) Forgot to say, you might find this useful.
|
|
|
|
Mickelukas
JGO Ninja    Posts: 731 Medals: 25
Java guru wanabee
|
 |
«
Reply #12 on:
2012-01-04 07:36:37 » |
|
The north quarter of the map was the original map in this image.
Right, here the circle look is very visible indeed and it looks less good. Other than that, nice looking rendering!  Mike
|
|
|
|
tackman
JGO n00b  Posts: 14
|
 |
«
Reply #13 on:
2012-01-04 07:40:59 » |
|
The Cos function is a cyclic function, meaning - statistically - it will bear similar results over time. Maybe your circling behavior can be accounted to the use of the Cos function?
Try spicing it up, either by adding another Cos function with a different argument, or modifying the argument of the Cos function by a random multiplier. Not sure if these would work, but they are at least worth a try.
|
|
|
|
|
Riven
« League of Dukes » JGO Kernel      Posts: 5870 Medals: 255
Hand over your head.
|
 |
«
Reply #14 on:
2012-01-04 13:44:16 » |
|
The weakness of my method is that, if you want the expand the world, the "seeds" that you used will all be really close, while the rest of the world is far away, resulting in simply circles arround your original part of the map:
Then make the seeds not so close to eachother... spread them evenly across you larger world. It would probably a good idea too to fade the influence of a 'seed' with distance.
|
Hi, appreciate more people! Σ ♥ = ¾ Learn how to award medals... and work your way up the social rankings
|
|
|
Pinguinpanic
JGO n00b  Posts: 17 Medals: 1
|
 |
«
Reply #15 on:
2012-01-05 03:35:10 » |
|
The weakness of my method is that, if you want the expand the world, the "seeds" that you used will all be really close, while the rest of the world is far away, resulting in simply circles arround your original part of the map:
Then make the seeds not so close to eachother... spread them evenly across you larger world. It would probably a good idea too to fade the influence of a 'seed' with distance. Problem is, if I add a piece of map, with a seed on it, it will have to have an effect on the previously generated map, unless I make it fade somehow at the edges. Maybe I could just choose my "seeds" somewhere outside of my current map I just realized, there's no reason for the calculation to require the seeds to be within the array, so I could try that and see how it looks.
|
|
|
|
|
Roquen
JGO Strike Force    Posts: 827 Medals: 25
|
 |
«
Reply #16 on:
2012-01-05 04:53:46 » |
|
What you're (in effect) attempting to do is fake noise, so unless you're having fun, just change to using some noise function.
|
|
|
|
|
Damocles
Sr. Member   Posts: 264 Medals: 14
|
 |
«
Reply #17 on:
2012-01-05 05:33:54 » |
|
Here a simple mapgenerator, not fancy, but it will create the hightmap of some island type landscape  1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146
| import java.applet.Applet; import java.awt.image.BufferedImage; import java.awt.image.DataBufferInt; import java.util.Random;
public class MapGen extends Applet implements Runnable {
static int wide = 1000; static int high = 800;
public void start() { new Thread(this).start(); }
public void run() { while (!this.isActive()) Thread.yield(); setSize(wide,high); Random ran = new Random();
BufferedImage image = new BufferedImage(wide, high, BufferedImage.TYPE_INT_RGB); int[] pixels = ((DataBufferInt) image.getRaster().getDataBuffer()).getData();
double[][] map = new double[wide][high];
int iterator=1; int stepsize=wide/16; do { for (int y = stepsize; y <= high-stepsize*2; y+=stepsize) { for (int x = stepsize; x <= wide-stepsize*2; x+=stepsize) { int val=ran.nextInt(40+iterator*2)-20 - iterator*1; int valFirst=50+ran.nextInt(200); for (int yy = 0; yy < stepsize; yy++) { for (int xx = 0; xx < stepsize; xx++) { if(iterator==1) map[x+xx][y+yy] =valFirst; else { map[x+xx][y+yy] += val; map[x+xx][y+yy]= (map[x+xx][y+yy]*2 + map[x+stepsize+xx][y+yy] + map[x-stepsize+xx][y+yy] + map[x+xx][y+yy+stepsize] + map[x+xx][y+yy-stepsize] + map[x+stepsize+xx][y+yy+stepsize] + map[x+stepsize+xx][y+yy-stepsize]+ map[x-stepsize+xx][y+yy+stepsize] + map[x-stepsize+xx][y+yy-stepsize] ) / 10 ; } if(map[x+xx][y+yy]>255) map[x+xx][y+yy]=255; if(map[x+xx][y+yy]<0) map[x+xx][y+yy]=0; } } } } iterator++; stepsize/=2; } while(stepsize>0); for(int passes=0;passes<10;passes++) { for (int y = 1; y < high-1; y++) { for (int x = 1; x < wide-1; x++) { map[x][y]= ( map[x][y]*2 + map[x+1][y] + map[x-1][y] + map[x][y+1] + map[x][y-1] + map[x+1][y+1] + map[x+1][y-1]+ map[x-1][y+1] + map[x-1][y-1] ) / 10; } } } for (int i = 0; i < pixels.length; i++) { pixels[i]=0x40A0FF; int mv= (int)map[i % wide][i / wide]; int mvRB= (int)(map[i % wide][i / wide]*0.5); if(mvRB>255) mvRB=255; if(mv>140) { pixels[i] = (mvRB << 16) | (mv <<8) | mvRB; if(mv<152)pixels[i] = 0xE0D090; } }
while (isActive()) { this.getGraphics().drawImage(image, 0, 0, null); Thread.yield(); } }
} |
|
|
|
|
Damocles
Sr. Member   Posts: 264 Medals: 14
|
 |
«
Reply #18 on:
2012-01-05 09:54:56 » |
|
There are many parameters that can be tweaked. Especially how much noise is applies for each step, and how much it should be smoothed.
|
|
|
|
Roquen
JGO Strike Force    Posts: 827 Medals: 25
|
 |
«
Reply #19 on:
2012-01-05 10:02:38 » |
|
This is basically value noise broken into a two step (and significantly more expensive) processes...why bother? Just use an existing noise function rather than re-inventing the wheel.
|
|
|
|
|
Pinguinpanic
JGO n00b  Posts: 17 Medals: 1
|
 |
«
Reply #20 on:
2012-01-05 11:47:06 » |
|
1 2 3 4
| [quote author=Damocles link=topic=25442.msg219354#msg219354 date=1325759634]
|
[/quote] That is basicly just "noise" applied to increasingly smaller segments? That's a pretty nifty idea as well. Looks good, that would be like 10 passes for an 1024x1024 field right? (2^10), +10 for smoothing would be about 20 passes. I think mine has about as many passes, but yours is probably better if you want to expand the map. This is basically value noise broken into a two step (and significantly more expensive) processes...why bother? Just use an existing noise function rather than re-inventing the wheel.
What you're (in effect) attempting to do is fake noise, so unless you're having fun, just change to using some noise function.
Sorry, but I'm still a beginning programmer, just finding out about all this stuff. Where do you guys aquire this knowledge? Is it something that builds up over time, or are there sites/books that are bundles with usefull information like this? I'm currently reading into the "Value Noise" you talked about, and I think that would be usefull for terrain generation.
|
|
|
|
|
Roquen
JGO Strike Force    Posts: 827 Medals: 25
|
 |
«
Reply #21 on:
2012-01-05 11:53:50 » |
|
IMHO: Value noise isn't of great interest. You'd probably should use Perlin gradient noise.
|
|
|
|
|
Riven
« League of Dukes » JGO Kernel      Posts: 5870 Medals: 255
Hand over your head.
|
 |
«
Reply #22 on:
2012-01-05 11:58:45 » |
|
What you're (in effect) attempting to do is fake noise, so unless you're having fun, just change to using some noise function.
You have got to agree his terrain has a unique feel. Value noise and perlin noise typically look rather boring and unnatural, unless it's finetuned into oblivion.
|
Hi, appreciate more people! Σ ♥ = ¾ Learn how to award medals... and work your way up the social rankings
|
|
|
Damocles
Sr. Member   Posts: 264 Medals: 14
|
 |
«
Reply #23 on:
2012-01-05 12:10:00 » |
|
In the end what counts is how the result looks like. No need for academic discussions on that.
BTW: how can terraingeneration be inperformant, that not a realtime application, the performce does not matter there. Be it 1 or 3 seconds at initial worldgeneration, noone cares.
|
|
|
|
Pinguinpanic
JGO n00b  Posts: 17 Medals: 1
|
 |
«
Reply #24 on:
2012-01-05 12:47:14 » |
|
In the end what counts is how the result looks like. No need for academic discussions on that.
BTW: how can terraingeneration be inperformant, that not a realtime application, the performce does not matter there. Be it 1 or 3 seconds at initial worldgeneration, noone cares.
Well, I want to add new terrain in real time, but I guess if I'd for example add chuncks of like 32x32 at a time, that that should be still very doable in real time. So well yes, it doesn't matter at all haha  . Sometimes I just have no idea where I'm going
|
|
|
|
|
Damocles
Sr. Member   Posts: 264 Medals: 14
|
 |
«
Reply #25 on:
2012-01-05 13:30:47 » |
|
no was directed at Roquen's post.
Anyhow, there are many good tutorials online. And since your voxel-cube rendering looks good already, you should be able to make a nice terrain in no time.
The circular terrain still looks good. Maybe you can leave it in to be applied at some parts of your world.
|
|
|
|
Pinguinpanic
JGO n00b  Posts: 17 Medals: 1
|
 |
«
Reply #26 on:
2012-01-05 13:57:40 » |
|
no was directed at Roquen's post.
Anyhow, there are many good tutorials online. And since your voxel-cube rendering looks good already, you should be able to make a nice terrain in no time.
The circular terrain still looks good. Maybe you can leave it in to be applied at some parts of your world.
I'm not drawing voxel-cubes or anything, it's just images. Here's an image of the world upclose, that was just a version of the game with smaller images:  Currently breaking my head on building a system to load tile variations from a file so that I can just change a text file for different graphics instead of code. It's ussually the basic stuff that gets me stuck, Java always mock me like that, with stuff like LOL YOU LOADED AN IMAGE, AND I CAN DISPLAY THE WIDTH OF THAT IMAGE FOR TESTING PURPOSE, BUT THERE'S NO WAY I AM GOING TO DRAW THAT ON SCREEN. Sorry for the rambling, after I have the system done, I will get back to terrain generation, and I can share with you my silly ideas of treeplanting, and rockplacing on the map. That is, if anyone is interested.
|
|
|
|
|
ra4king
JGO Kernel      Posts: 3160 Medals: 196
I'm the King!
|
 |
«
Reply #27 on:
2012-01-05 16:32:21 » |
|
Oooh I'm interested! Keep sharing your silly ideas because I love them  I've been quietly lurking this thread because random map generation has always amazed and baffled me 
|
|
|
|
Pinguinpanic
JGO n00b  Posts: 17 Medals: 1
|
 |
«
Reply #28 on:
2012-01-05 17:31:47 » |
|
Hey, I'm back with some more not-really related stuff. But while making this I was thinking IT'S KIND OF BORING TO HAVE THE SAME GRASS TILE ALL THE TIME. So I said to my spritedrawing friend DO THOSE SPRITES AGAIN BUT NOW WITH FLOWERS AND LITTLE POOLS OF MUD. And he did (Thanks  ), so then I had to make some way to get the flowers in game, which COULD mean I would have to hardcore all the sprites and blah blah, but I thought that would not be very good for development of the game later on, so instead I create this sytem, where the only thing I have to do to get a tile ingame, with a couple of variations, is this: [Code]tType[3]=new TileResource("Grass"); [/Code] So you might be thinking, but how does it load all it's information? Well, I simply have a file grass.props, that has this text: 1 2 3 4 5 6 7 8 9 10 11 12 13
| Name=Grass Height=0 Images=5 Image1=Grass.png Image1Freq=800 Image2=Grasshole.png Image2Freq=5 Image3=Grasshole2.png Image3Freq=5 Image4=Grasshorseflower.png Image4Freq=100 Image5=Grasshorseflower2.png Image5Freq=100 |
So from that I just load the props, and images, this way instead of having to think and try how many percent of my grass I want all happy with flowers, I can just tell my graphic designing friend, to do that stuff. Tl;dr: I am lazy and post stuff not related to Map Generation to a map generation thread, here's a pretty picture of my work: 
|
|
|
|
|
sproingie
JGO Strike Force    Posts: 899 Medals: 55
|
 |
«
Reply #29 on:
2012-01-05 17:33:38 » |
|
Nice. Just need a bit of texture splatting and you're all set.
|
|
|
|
|
|