Last active
September 10, 2017 23:08
-
-
Save TheBuzzSaw/54e483de7dda291ab2b99d29118fd12f to your computer and use it in GitHub Desktop.
2D Terrain Generation Sample
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #include <iostream> | |
| #include <vector> | |
| #include <random> | |
| #include <string> | |
| #include <cstdint> | |
| #include <cstring> | |
| #include <ctime> | |
| #define STB_IMAGE_WRITE_IMPLEMENTATION | |
| #include "stb_image_write.h" | |
| using namespace std; | |
| static constexpr int PixelSize = 3; | |
| static mt19937 mt(time(nullptr)); | |
| void Paint(uint8_t* pixel, const uint8_t* color) | |
| { | |
| memcpy(pixel, color, PixelSize); | |
| } | |
| void GenerateWorldMap(int width, int height, const char* path) | |
| { | |
| if (width < 1 || height < 1) | |
| { | |
| cout << "invalid map size: (" << width << ")x(" << height << ")\n"; | |
| return; | |
| } | |
| int pixelCount = width * height; | |
| const uint8_t SkyBlue[] = {0x84, 0xaa, 0xf8, 0x00}; | |
| const uint8_t DirtBrown[] = {0x97, 0x6b, 0x4b, 0x00}; | |
| vector<double> elevations(width + 1); | |
| int w = width; | |
| double range = 1.0; | |
| while (w > 3) | |
| { | |
| int half = w / 2; | |
| uniform_real_distribution<double> distribution(-range, range); | |
| for (int i = 0; i < width; i += half) | |
| { | |
| auto delta = distribution(mt); | |
| double low = elevations[i]; | |
| double high = (elevations[i + half] += delta); | |
| double gap = high - low; | |
| for (int j = 1; j < half; ++j) | |
| { | |
| double t = double(j) / double(half - 1); | |
| elevations[i + j] = gap * t + low; | |
| } | |
| } | |
| range /= 2.0; | |
| w = half; | |
| } | |
| vector<uint8_t> bytes(width * height * PixelSize); | |
| auto data = bytes.data(); | |
| auto GetPixel = [=](int x, int y) | |
| { | |
| return data + (y * width + x) * PixelSize; | |
| }; | |
| int halfHeight = height / 2; | |
| for (int i = 0; i < width; ++i) | |
| { | |
| int elevation = halfHeight + int(elevations[i] * double(halfHeight)); | |
| for (int j = 0; j < height; ++j) | |
| { | |
| auto pixel = GetPixel(i, j); | |
| Paint(pixel, j > elevation ? DirtBrown : SkyBlue); | |
| } | |
| } | |
| int result = stbi_write_png( | |
| path, | |
| width, | |
| height, | |
| PixelSize, | |
| data, | |
| width * PixelSize); | |
| if (result == 0) | |
| { | |
| cout << "failed to write image to " << path << '\n'; | |
| } | |
| else | |
| { | |
| cout << "successfully wrote image to " << path << '\n'; | |
| } | |
| } | |
| int main(int argc, char** argv) | |
| { | |
| string path; | |
| for (int i = 0; i < 8; ++i) | |
| { | |
| path = "world"; | |
| path += to_string(i + 1); | |
| path += ".png"; | |
| GenerateWorldMap(1024, 256, path.data()); | |
| } | |
| return 0; | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment