Skip to content

Instantly share code, notes, and snippets.

@TheBuzzSaw
Last active September 10, 2017 23:08
Show Gist options
  • Select an option

  • Save TheBuzzSaw/54e483de7dda291ab2b99d29118fd12f to your computer and use it in GitHub Desktop.

Select an option

Save TheBuzzSaw/54e483de7dda291ab2b99d29118fd12f to your computer and use it in GitHub Desktop.
2D Terrain Generation Sample
#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