LoginSignup
7
5

More than 3 years have passed since last update.

中点変位法 世界生成

Last updated at Posted at 2017-12-05

概要

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

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

コード

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 で作ってみた

7
5
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
7
5