Du bist hier: Snippet-Verzeichnis » C/C++ (495)
Sprache:

2 Dimensional Terrain Generation Program

Sprache: English
Programmiersprache: C++
Veröffentlicht von: november [nicht registriert]
Letzte Änderung: 15.05.2006
Aufrufe: 1146


Beschreibung

For those who want to generate 2 dimensional terrains for overhead maps, etc.

Code

1 /* 2 * This program is free software; you can redistribute it and/or modify 3 * it under the terms of the GNU General Public License as published by 4 * the Free Software Foundation; either version 2 of the License, or 5 * (at your option) any later version. 6 * 7 * This program is distributed in the hope that it will be useful, 8 * but WITHOUT ANY WARRANTY; without even the implied warranty of 9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 10 * GNU Library General Public License for more details. 11 * 12 * You should have received a copy of the GNU General Public License 13 * along with this program; if not, write to the Free Software 14 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 15 * 16 * jbaird Wed Jul 18 03:52:41 PM CDT 2001 17 * Author: Jayson Baird 18 * E-Mail: jbaird@ncsa.uiuc.edu 19 * 20 * If you make any changes to this, drop me a line, patch, etc. 21 * I'm curious to seen what improvements can be made. 22 */ 23 24 #include <stdio.h> 25 #include <stdlib.h> 26 #include <signal.h> 27 #include <time.h> 28 #include <unistd.h> 29 #include <math.h> 30 31 /** this is the class that holds our pixel type. Arbitrary to say the least. **/ 32 #include "MapSquare.cc" 33 34 /** 35 catch SIGINT and deal with it... 36 **/ 37 void signal_handler(int signum) 38 { 39 switch(signum) { 40 case SIGINT: 41 printf("\nRecieved interrupt signal. Exiting.\n"); 42 exit(0); 43 default: 44 printf("\nUnknown signal recieved. Ignoring.\n"); 45 } 46 } 47 48 /** 49 a random number generator that generates a double between 0.0 and 1.0 50 **/ 51 double doubleNoise(double x, double y) 52 { 53 int n = 0; 54 n = int(x) + int(y) * (57 * rand()); 55 int nShift = n << 13; 56 n = nShift ^ n; 57 return (1.0 - ((int)(n * (n * n * 15731 + 789221) + 1376312589) & 0xffffff) / 1073741824.0); 58 } 59 60 /** 61 interpolate the points v0 and v1 with relation to x 62 **/ 63 double cosineInterpolation(double v0, double v1, double x) 64 { 65 double ft = x * M_PI; 66 double f = (1 - cos(ft)) * 0.5; 67 68 return v0 * (1 - f) + (v1 * f); 69 } 70 71 /** 72 smooth the points based on the grid specifics 73 **/ 74 double smoothNoise(double x, double y) 75 { 76 x = int(x); 77 y = int(y); 78 double corners = (doubleNoise(x-1, y-1) + doubleNoise(x+1, y-1) + doubleNoise(x-1, y+1) + 79 doubleNoise(x+1, y+1)) / 16; 80 double sides = (doubleNoise(x-1, y) + doubleNoise(x+1, y) + doubleNoise(x, y-1) + 81 doubleNoise(x, y+1)) / 8; 82 double center = doubleNoise(x, y) / 4; 83 84 return corners + sides + center; 85 } 86 87 /** 88 create the noise, smooth it and return the interpolated point. 89 **/ 90 double InterpolateNoise(double x, double y) 91 { 92 int intX = int(x); 93 double fracX = x - intX; 94 95 int intY = int(y); 96 double fracY = y - intY; 97 98 double v1, v2, v3, v4, i1, i2; 99 v1 = smoothNoise(intX, intY); 100 v2 = smoothNoise(intX + 1, intY); 101 v3 = smoothNoise(intX, intY + 1); 102 v4 = smoothNoise(intX + 1, intY + 1); 103 104 i1 = cosineInterpolation(v1, v2, fracX); 105 i2 = cosineInterpolation(v3, v4, fracX); 106 107 return cosineInterpolation(i1, i2, fracY); 108 } 109 110 /** 111 the function that generates the entire map with Perlin Noise. 112 try playing with the persistence and numOctaves variables or the 113 gridSize 114 **/ 115 double perlinNoise2D(double x, double y) 116 { 117 double persistence = 1/4; 118 int numOctaves = 4; 119 int gridSize = 20; 120 double total = 0.0; 121 for(int i = 0; i < numOctaves; i++) { 122 double frequency = pow(2, (double)i); 123 double amplitude = pow(persistence, (double)i); 124 total = total + InterpolateNoise((x / gridSize) * frequency, (y / gridSize) * amplitude) * amplitude; 125 } 126 127 return total; 128 } 129 130 /** 131 do it already... 132 **/ 133 int main(int argc, char *argv[]) 134 { 135 if(argc < 2) { 136 printf("Useage: %s <map size>\n", argv[0]); 137 exit(1); 138 } 139 140 signal(SIGINT, signal_handler); 141 142 int mapSize; 143 mapSize = atoi(argv[1]); 144 145 MapSquare *map[mapSize][mapSize]; 146 147 /* place holders for world building timing */ 148 time_t starttime, endtime; 149 150 /** 151 build the world 152 NOTE: this is extremely memory and computationally expensive, 153 but hey, it works. If you find any better way to do it, let 154 me know. 155 **/ 156 starttime = time(NULL); 157 for(int i = 0; i < mapSize; i++) { 158 for(int j = 0; j < mapSize; j++) { 159 /** 160 .9920 is an arbitrary threshold value that can be 161 changed to the users liking. I picked .9920... 162 **/ 163 if(perlinNoise2D((double)i, (double)j) < .9920) { 164 map[i][j] = new MapSquare(i, j, 'g'); 165 } else { 166 map[i][j] = new MapSquare(i, j, 'w'); 167 } 168 } 169 } 170 endtime = time(NULL); 171 172 /* report on the world building statistics ... */ 173 printf("World built in %d sec(s) using %d KB worth of memory.\n", (endtime - starttime), sizeof(map) / 1024); 174 175 //add here functions to save the map to a file, or display it with SDL, etc. 176 177 return 0; 178 }

Noch kein Kommentar vorhanden

Dieses Snippet kommentieren

Name *  

E-Mail (wird nicht angezeigt) *    

Website  

Kommentar *  

Sicherheitscode Sicherheitscode *    

RSS