如何实现中点位移

时间:2014-01-03 04:04:46

标签: c++ algorithm procedural-generation

我正在尝试在游戏中实现程序生成。我想真正掌握并理解所有算法,而不是简单地复制/粘贴现有​​代码。为了做到这一点,我试图自己实现1D中点位移。我已经使用信息here来编写和指导我的代码。下面是我完成的代码,它不会抛出错误,但结果看起来不正确。

srand(time(NULL));

const int lineLength = 65;
float range = 1.0;
float displacedLine[lineLength];

for (int i = 0; i < lineLength; i++)
{
    displacedLine[i] = 0.0;
}

for (int p = 0; p < 100; p++)
{
    int segments = 1;
    for (int i = 0; i < (lineLength / pow(2, 2)); i++)
    {
        int segs = segments;
        for (int j = 0; j < segs; j++)
        {
            int x = floor(lineLength / segs);
            int start = (j * x) + 1;
            int end = start + x;
            if (i == 0)
            {
                end--;
            }
            float lo = -range;
            float hi = +range;
            float change = lo + static_cast <float> (rand()) / (static_cast <float> (RAND_MAX / (hi - lo)));

            int center = ((end - start) / 2) + start;
            displacedLine[center - 1] += change;
            segments++;
        }
        range /= 2;
    }
}

我究竟在哪里犯错,我怎么纠正错误?

我得到的结果如下:

My Results

但我期待这样的结果:

Expected Results

2 个答案:

答案 0 :(得分:1)

答案非常简单,顺便说一下,我给你留下了深刻的印象,你设法调试代码中所有潜在的错误。以下行错误:

displacedLine[center - 1] += change;

您正确计算了中心索引并更改了金额,但您错过了该更改应该应用于高度方面的中点。那就是:

displacedLine[center - 1] = (displacedLine[start] + displacedLine[end]) / 2;
displacedLine[center - 1] += change;

我相信你明白了。

答案 1 :(得分:0)

问题似乎是你只改变每个线段的中点,而不是改变线段的其余部分与它从每个端点到中点的距离成比例。以下代码似乎为您提供了更多您喜欢的内容:

#include <iostream>
#include <cstdlib>
#include <math.h>
#include <algorithm>

using namespace std;

void displaceMidPt (float dline[], int len, float disp) {
    int midPt = len/2;
    float fmidPt = float(midPt);
    for (int i = 1; i <= midPt; i++) {
        float ptDisp = disp * float(i)/fmidPt;
        dline[i] += ptDisp;
        dline[len-i] += ptDisp;
    }
}

void displace (float displacedLine[], int lineLength, float range) {
    for (int p = 0; p < 100; p++) {
        int segs = pow(p, 2);
        for (int j = 0; j < segs; j++) {
            float lo = -range;
            float hi = +range;
            float change = lo + static_cast <float> (rand()) / (static_cast <float> (RAND_MAX / (hi - lo)));
            int start = int(float(j)/float(segs)*float(lineLength));
            int end = int(float(j+1)/float(segs)*float(lineLength));
            displaceMidPt (displacedLine+start,end-start,change);
            }
        range /= 2;
    }
}

void plot1D (float x[], int len, int ht = 10) {
    float minX = *min_element(x,x+len);
    float maxX = *max_element(x,x+len);
    int xi[len];
    for (int i = 0; i < len; i++) {
        xi[i] = int(ht*(x[i] - minX)/(maxX - minX) + 0.5);
    }
    char s[len+1];
    s[len] = '\0';
    for (int j = ht; j >= 0; j--) {
        for (int i = 0; i < len; i++) {
            if (xi[i] == j) {
                s[i] = '*';
            } else {
                s[i] = ' ';
            }
        }
        cout << s << endl;
    }
}

int main () {
    srand(time(NULL));

    const int lineLength = 65;
    float range = 1.0;
    float displacedLine[lineLength];

    for (int i = 0; i < lineLength; i++) {
        displacedLine[i] = 0.0;
    }

    displace (displacedLine,lineLength,range);
    plot1D (displacedLine,lineLength);
    return 0;
}

以这种方式运行时,会产生以下结果:

$ c++ -lm displace.cpp
$ ./a
                                  *
                              *       *
                                 * ***
                             * *       *             *
                         * **            ****       * **
      * ***  ****  *   *                *    **         *
     * *   **    ** ***   *     *                * *
   **                                          **        *
  *                     *                         *       ***
**                                                            ***
                                                             *