1
\$\begingroup\$

I am trying to implement moving random hills in SDL. I am using midpoint displacement algorithm to create some random terrain and I have also accomplished to move the terrain too. But the problem is that the terrain repeats itself after certain period of time. Why is that exactly happening and how to rectify it. Here is my source code.

#include <SDL2/SDL.h>
#include <iostream>
#include <cstdlib>
#include <cmath>
using namespace std;
const int SCREEN_WIDTH = 640;
const int SCREEN_HEIGHT = 480;
SDL_Window* gWindow = NULL;
SDL_Renderer* gRenderer = NULL;
int arr_size = pow(2.0,11.0) + 1;
int terrain_array[10000];
float roughness = 0.5;
int intial_displacement = 150;
int count = 0;
bool init()
{
    bool success = true;
    if( SDL_Init( SDL_INIT_VIDEO ) < 0 )
    {
        cout << "SDL could not initialize. SDL_Error: " << SDL_GetError() << endl;
        success = false;
    }
    else
    {
        if( !SDL_SetHint( SDL_HINT_RENDER_SCALE_QUALITY, "1" ) )
        {
            cout << "Linear texture filtering not enabled.\n";
        }
        gWindow = SDL_CreateWindow( "Midpoint_Displacement_Algortihm", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, SCREEN_WIDTH, SCREEN_HEIGHT, SDL_WINDOW_SHOWN );
        if( gWindow == NULL )
        {
            cout << "Window could not be created. SDL_Error: " << SDL_GetError() << endl;
            success = false;
        }
        else
        {
            gRenderer = SDL_CreateRenderer( gWindow, -1, SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC );
            if( gRenderer == NULL )
            {
                cout << "Renderer could not be created. SDL_Error: " << SDL_GetError() << endl;
                success = false;
            }
            else
            {
                SDL_SetRenderDrawColor( gRenderer, 96, 96, 96, 96 );
            }
        }
    }
    return success;
}
void close()
{
    SDL_DestroyRenderer( gRenderer );
    SDL_DestroyWindow( gWindow );
    gWindow = NULL;
    gRenderer = NULL;
    SDL_Quit();
}
void initializeArray()
{
    for(int i = 0; i < arr_size; i++)
    {
        terrain_array[i] = 0;
    }
}
void generateTerrain(int leftindex, int rightindex, int displacement)
{
    if((leftindex + 1) == rightindex)
        return;
    int midindex = floor((leftindex + rightindex) / 2);
    int change = ((rand()%1) * 5 - 1) * displacement;
    terrain_array[midindex] = (terrain_array[leftindex] + terrain_array[rightindex]) / 2 + change;
    displacement = displacement * roughness;
    generateTerrain(leftindex, midindex, displacement);
    generateTerrain(midindex, rightindex, displacement);
}
void drawTerrain()
{
    int start_point = 1;
    int i;
    SDL_SetRenderDrawColor( gRenderer, 96, 96, 255, 255 );
    for(i = 1; i < arr_size; i++)
    {
        SDL_RenderDrawLine( gRenderer, start_point, SCREEN_HEIGHT, i, (terrain_array[(count + i)%arr_size] + 3 * intial_displacement));
        start_point = i;
    }
    count++;
}
int main()
{
    initializeArray();
    if( !init() )
    {
        cout << "Failed to initialize\n";
    }
    else
    {
        bool quit = false;
        SDL_Event event;
        while( !quit )
        {
            while( SDL_PollEvent( &event ) != 0)
            {
                if( event.type == SDL_QUIT )
                {
                    quit = true;
                }
            }
            generateTerrain(0, arr_size - 1, intial_displacement);
            SDL_SetRenderDrawColor( gRenderer, 96, 96, 96, 96 );
            SDL_RenderClear( gRenderer );
            drawTerrain();
            SDL_RenderPresent( gRenderer );
        }
    }
    close();
    return 0;
}

I am new to this stuff and trying to learn. This is what it looks like.

enter image description here

\$\endgroup\$
  • 1
    \$\begingroup\$ You should post the relevant code in the question, because links can stop working. \$\endgroup\$ – SurvivalMachine Jun 6 '16 at 15:48
  • \$\begingroup\$ @SurvivalMachine In the future, feel free to submit an edit instead of commenting if you have the time. \$\endgroup\$ – Dan Jun 7 '16 at 16:05
1
\$\begingroup\$

You are generating a random number incorrectly.

int change = ((rand()%1) * 5 - 1) * displacement;

Change will always be (-1 * displacement), because anything modulus 1 is always zero.

Try this for a range of [-5, 5]:

//rand() % 11 returns range [0, 10], subtract 5 makes range [-5, 5]
int change = ((rand() % 11) - 5) * displacement;

I also recommend you seed rand with the system time. Otherwise the application will generate the same terrain every time (though this behavior is often useful for testing):

#include <time.h>

//Call this once at program start, before the first call to rand()
srand(time(NULL));

http://www.cplusplus.com/reference/cstdlib/rand/

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.