I am using perlin noise to generate a map for my game. This is then being drawn using marching squares. The values That are being input for the perlin noise function are relative to a 0,0 coordinate and then this is converted to a position on screen that can then be drawn to.
The problem is that when the player moves the image that is drawn to the screen is slightly different at the edges of the mesh this causes a flickering effect when the player is moving.
asteroids_in_range(player.x-WIDTH/2,player.x+WIDTH/2,player.y-HEIGHT/2,player.y+HEIGHT/2,16);
int get_asteroid_case(float x, float y, float box_size)
{
/*get the case for the box with the bottom left corner
at location x,y and size of box_size*/
int count = 0;
if(perlin.GetValue(x, y, 0.1) > THRESHHOLD)
{
count += 8;
}
if(perlin.GetValue(x+box_size, y, 0.1) > THRESHHOLD)
{
count += 4;
}
if(perlin.GetValue(x+box_size, y+box_size, 0.1) > THRESHHOLD)
{
count += 2;
}
if(perlin.GetValue(x, y+box_size, 0.1) > THRESHHOLD)
{
count += 1;
}
return count;
}
void asteroids_in_range(float xmin, float xmax, float ymin, float ymax, float grid_size)
{
int num;
for(float x = xmin; x <= xmax; x+=grid_size)
{
for(float y = ymin; y <= ymax; y+=grid_size)
{
num = get_asteroid_case(x, y, grid_size);
if(num != 0 && num != 15)
render_asteroids(num,x,y, 1);
}
}
}
Images with the player one pixel apart as can be seen, there are subtle differences on the fringes of the generated meshes.
Your problem is you are getting different noise values because you are getting the noise at different points. Don't do that. Make it the same points - the ones on the grid.
Let's say grid_size is 10 (pixels) and WIDTH is 100 (pixels) and the player is at 0,0. You are getting the noise at -50,-50, and -40,-50, and -30,-50, and so on.
Now say the player moves 3 pixels right. You are getting the noise at -47,-50, and -37,-50, and -27,-50, and so on. Obviously you get different noise values, because you asked for different noise values!
Instead you should round the noise coordinates to the grid - to multiples of grid_size. Your code can easily be adapted by rounding xmin and xmax and ymin and ymax before the grid rendering - for example:
xmin = floor(xmin / grid_size) * grid_size;
xmax = ceil(xmax / grid_size) * grid_size;
// same for y
The min coordinate is rounded down, and the max coordinate is rounded up, to make sure the entire screen is still inside the rendered coordinates.