C++
アルゴリズム
ゲーム制作
フラクタル
DungeonGeneration

中点変位法によるワールドマップ自動生成

概要

こんにちは、がっちょ( ¨̮ )です。

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

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

また、疑問点や質問等がございましたら、この投稿のコメント欄または「がっちょ( ¨̮ ) Twitter」にてお申し付けください。
内容に関する質問、いつでもウェルカムです。

コード

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

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

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

circleanimationmuvie

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

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

These codes are licensed under CC0.
CC0

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

参考

DXライブラリ 関数リファレンスページ
新・C言語 ~ゲームプログラミングの館
フラクタル
フラクタル地形自動生成
中点変位法を使用してマインクラフトのようなランダム地形を Unity で作ってみた