中点変位法 世界生成

#概要
こちらはRPGに出てくるようなマップを作成する記事です。

何か不備がありましたら指摘していただければ幸いです。

#コード
1秒おきにワールドマップが自動生成されるプログラムです。

```cpp:Main.cpp
#include "DxLib.h"

//横画面サイズ
#define MAP_X 480

//縦画面サイズ
#define MAP_Y 320

/*チャンク生成*/
void mapMake(int x, int y, int size, int t1, int t2, int t3, int t4, unsigned char map[][18])
{
	//再起の終了処理
	if (size < 1) return;

	//頂点の高さを決める
	int mapPlus = ((t1 + t2 + t3 + t4) >> 2) + GetRand(size);
	if (mapPlus >= 255) mapPlus = 255;
	map[x][y] = mapPlus;

	//四角形の2点同士の中点の高さを決定
	int s1 = ((t1 + t2) >> 1);
	int s2 = ((t1 + t3) >> 1);
	int s3 = ((t2 + t4) >> 1);
	int s4 = ((t3 + t4) >> 1);

	//4つの地点の座標を決める
	map[x + size][y] = s3;
	map[x - size][y] = s2;
	map[x][y + size] = s4;
	map[x][y - size] = s1;

	//分割サイズを半分にする
	size >>= 1;

	//4つに分割
	mapMake(x - size, y - size, size, t1, s1, s2, map[x][y], map);
	mapMake(x + size, y - size, size, s1, t2, map[x][y], s3, map);
	mapMake(x - size, y + size, size, s2, map[x][y], t3, s4, map);
	mapMake(x + size, y + size, size, map[x][y], s3, s4, t4, map);
}

/*チャンク生成の呼び出し*/
void mapSimple(unsigned char map[][18])
{
	//チャンク生成を実行
	mapMake(8, 8, 8, map[0][0], map[16][0], map[0][16], map[16][16], map);
}

/*ワールドマップ生成*/
void worldMake(unsigned char map[][18], int SEED, unsigned char WorldMap[][MAP_Y])
{
	for (int i = 0; i < MAP_X / 16; i++) {
		for (int j = 0; j < MAP_Y / 16; j++) {

			//四角形の4点の高さを決定
			SRand(SEED + i + j * 10000 + (i&j) * 100);
			map[0][0] = GetRand(255);
			SRand(SEED + i + 1 + j * 10000 + ((i + 1)&j) * 100);
			map[16][0] = GetRand(255);
			SRand(SEED + i + (j + 1) * 10000 + (i&(j + 1)) * 100);
			map[0][16] = GetRand(255);
			SRand(SEED + i + 1 + (j + 1) * 10000 + ((i + 1)&(j + 1)) * 100);
			map[16][16] = GetRand(255);

			//チャンク生成
			mapSimple(map);

			for (int i2 = 0; i2 < 16; i2++) {
				for (int j2 = 0; j2 < 16; j2++) {
					//生成したチャンクをワールドマップにコピペ
					WorldMap[i * 16 + i2][j * 16 + j2] = map[i2][j2];
				}
			}


		}
	}

	for (int i = 0; i < (MAP_X / 16) * 16; i++) {
		for (int j = 0; j < (MAP_Y / 16) * 16; j++) {

			//ワールドマップの線画
			if (WorldMap[i][j] <= 110 && WorldMap[i][j] > 50) {
				DrawPixel(i, j, GetColor(WorldMap[i][j], 165, WorldMap[i][j]));
			}
			else if (WorldMap[i][j] <= 50) {
				DrawPixel(i, j, GetColor(WorldMap[i][j], 125, WorldMap[i][j]));
			}
			else {
				DrawPixel(i, j, GetColor((255 - WorldMap[i][j]) / 3, (255 - WorldMap[i][j]) / 3, 240));
			}

		}
	}

	//文字列初期化
	clsDx();

	//SEED値を文字列線画
	printfDx("SEED:%d", SEED);
}


int WINAPI WinMain(HINSTANCE, HINSTANCE, LPSTR, int) {

	//log出力停止・ウィンドウモード変更・初期化・裏画面設定
	SetOutApplicationLogValidFlag(FALSE), ChangeWindowMode(TRUE), DxLib_Init(), SetDrawScreen(DX_SCREEN_BACK);

	//画面サイズの決定
	SetGraphMode(MAP_X, MAP_Y, 32);

	//チャンク生成用の配列
	unsigned char map[18][18] = { 255 };

	//SEED値
	int SEED = GetRand(65535);

	//ワールドマップ
	unsigned char WorldMap[MAP_X][MAP_Y] = { 255 };

	//時間
	int time = 0;

	//ワールドマップを生成する
	worldMake(map, SEED, WorldMap);

	while (ScreenFlip() == 0 && ProcessMessage() == 0) {
		//1秒おきにワールドマップを生成
		if (time == 60) {
			worldMake(map, GetRand(65535), WorldMap);
			time = 0;
		}

		//ESCキーで終了
		if (CheckHitKey(KEY_INPUT_ESCAPE)) break;

		//時間を増やす
		time++;
	}

	//DXライブラリの終了処理
	DxLib_End();
	return 0;
}
```

#結果
###実行してみたらこんな感じ
![map.png](https://qiita-image-store.s3.amazonaws.com/0/213065/674ed804-aee7-c935-be8e-ab4b7738c812.png)

RPGに使えそうなマップになりましたね。

![circleanimationmuvie](https://i.imgur.com/R5AhbdF.gif)

こんな感じにアニメーションします。

##ソースコードのライセンス

These codes are licensed under CC0.
[![CC0](https://mirrors.creativecommons.org/presskit/buttons/88x31/svg/cc-zero.svg "CC0")](http://creativecommons.org/publicdomain/zero/1.0/deed.ja)

ソースコードは自由に使用してください。


#参考
[ＤＸライブラリ　関数リファレンスページ](http://dxlib.o.oo7.jp/dxfunc.html)
[新・C言語 ～ゲームプログラミングの館](http://dixq.net/g/)
[フラクタル](https://ja.wikipedia.org/wiki/%E3%83%95%E3%83%A9%E3%82%AF%E3%82%BF%E3%83%AB)
[フラクタル地形自動生成](https://qiita.com/keny30827/items/f4e29a4a90779cf94da6)
[中点変位法を使用してマインクラフトのようなランダム地形を Unity で作ってみた](https://loumo.jp/wp/archive/20130526220501/)