Generative Landscapes

Initially designed for a side scroller game, this project took a life of its own. I don't know why landscapes are easy on the eyes. The vastness of space or the immensity of mountains. I'd been playing around with randomness and organicness in code before, but these landscapes were my first implementation.

The hardest part to figure out was harmony of the colors. I wanted each peace to be a surprise but random colors make bad art. I'm quite happy with the results.

Almost all variables are parametrized. Color range, flora density, mountain density and elevation. This was coded with Java on Processing. It takes about 1 second to generate each image.







//generative landscapes program/*chapter oneSKYbase colorsranges*/
void setup() 
{
	
	//sky-------------------
	weightage= new float [3];
	rate= new float [3][2];
	randomStarterSky= new float [3][2];
	randomStarterMountain= new float [3][2];

	//mountain
	mountainRecorder= new int[1000];

	size(1000, 1000);
	background(100);
	frameRate(1000);

	

	
	
	

}

int mouseclicker=1;

void mouseReleased() {
	mouseclicker=1;
}

void draw() 
{

	if(mouseclicker==1)
	{
		generateSkyConstraints();
	
	drawSky();
	drawMountainS();
	////saveFrame("C:/Users/Akhil/Documents/Processing/sketches2/trees/images13/img-######.png");
	mouseclicker=1;
	}
	
	
	
}

//grass//--------------------------------//mountains//--------------------------------float density;
void drawMountainS()
{
	bright/=1.5;
	density=random(10,30);
	int ranges=(int)random(10,30);
	int mountainBrightnesslevel=(int)random(255-bright);
	int level=(int)random(200,300);
	int levelRemaining=700-level;
	float percentageMultiplier=(100/ranges)*0.01;
	int multiplier=(int)random(200,600);
	int multiplierRemaining=600-multiplier;
	float rate=random(0.0005,0.01);
	float rateRemaining= rate-0.0005;



	for (int i = 1; i <= ranges; ++i) {

		drawMountain((int)(bright + (255-bright- mountainBrightnesslevel )*i*(percentageMultiplier)) ,
			(int)(level+levelRemaining*i*percentageMultiplier),
			(int)(multiplier-multiplierRemaining*i*percentageMultiplier),
			rate-rateRemaining*i*percentageMultiplier,
			ranges-i);

	
		
	}
	
	//void drawMountains(int mbright, int level, int multiplier, float rate)

}

color mountainColor;
int[] mountainRecorder;

void drawMountain(int mbright, int level, int multiplier, float ratemnt,int last)
{
	
	stroke(255,50);

	fill(mbright+random(0,255-mbright),mbright+random(0,255-mbright),mbright+random(0,255-mbright));
	mountainColor=color( (weightage[0]*map(  (noise(level*rate[0][0],multiplier*rate[0][1]))  , 0, 1, 0, 255-mbright)) +mbright,
		(weightage[1]*map(  (noise(level*rate[1][0],multiplier*rate[1][1]))  , 0, 1, 0, 255-mbright)) +mbright,
		(weightage[2]*map(  (noise(level*rate[2][0],multiplier*rate[2][1]))  , 0, 1, 0, 255-mbright)) +mbright);

	fill(mountainColor,50);
	//noFill();fill( (weightage[0]*map(  (noise(level*rate[0][0],multiplier*rate[0][1]))  , 0, 1, 0, 255-mbright)) +mbright, (weightage[1]*map(  (noise(level*rate[1][0],multiplier*rate[1][1]))  , 0, 1, 0, 255-mbright)) +mbright, (weightage[2]*map(  (noise(level*rate[2][0],multiplier*rate[2][1]))  , 0, 1, 0, 255-mbright)) +mbright);
	int flag=(int)random(100);
	int j=0;

	beginShape();

	for (int i = 0; i < 1000; ++i) {

		if(j<980);
		j=(int)(level+noise(i*ratemnt+flag)*multiplier);
		vertex(i,j);
		mountainRecorder[i]=j;
		
		
	}

	
	

	if(last ==0)
	{

		raiseGrass=5;
		for (int i = 0; i < 1000; ++i) {

			drawgrass(i,mountainRecorder[i]);

			if (random(1000)< density*5)
				printShrub(i,mountainRecorder[i] );

			if (random(1000)< density)
				printTree(i,mountainRecorder[i] , 0);

		}
	}
	else {

		raiseGrass=0;
		
	}

	vertex(1000,1000);
	vertex(0, 1000);
	endShape(CLOSE);

	

	
	renderMountain2();


}

int raiseGrass;
void drawgrass(int i, float j)
{
	float ht=random(5)+map(noise(i*0.01),0,1,0,30);
	noStroke();
	fill(mountainColor);
	//noFill();int randvalgrass=(int)random(10);
	for (float k=0; k<ht; k+=0.2) 
	{
		ellipse(i+(map(noise(i+0.03*k), 0, 1, -1, 1))*k,randvalgrass+ j-k, 3-(map(k, 0, ht, 0, 3)), 3-(map(k, 0, ht, 0, 3)));
	}
}

void printShrub(int i, int j)
{
	int ht=(int)random(5, 30);
	fill(color(red(mountainColor)+(int)random(-50,0)-40,green(mountainColor)+(int)random(-50,0)-40,blue(mountainColor)+(int)random(-50,0)-40));
	for (int k=0; k<ht; k+=3)
	{

		for (float l=0; l<ht; l+=1) 
		{

			ellipse(i+(map(noise(i+00.2*k*l), 0, 1, -k*0.6, k*0.6)), j-l, 3-(map(l, 0, ht, 0, 3)), 3-(map(l, 0, ht, 0, 3)));
		}
	}
}

void printTree(int i, int j, float size)
{
	ellipseMode(CENTER);
	float ht=random(50, 300);
	//j=(int)(random(j,1000));//color treeclr=(get((int)random(500,1000),(int)random(500,1000)));color c = color(red(mountainColor)+(int)random(-50,0)-20,green(mountainColor)+(int)random(-50,0)-20,blue(mountainColor)+(int)random(-50,0)-20);
	float girth=map(ht,50,300,5,30);
	for (float k=size; k<ht; k+=2) 
	{


		//ellipse(i+(map(noise(i+0.006*k), 0, 1, -k*0.2, k*0.2)), j-k, 10-(map(k, 0, ht, 0, 10)), 10-(map(k, 0, ht, 0, 10)));fill(random(50,150));
		ellipse(i+(map(noise(i+0.006*k), 0, 1, -k*0.2, k*0.2))-1, j-k, girth-(map(k, 0, ht, 0, girth)), girth-(map(k, 0, ht, 0, girth)));
		fill(c,50);
		ellipse(i+(map(noise(i+0.006*k), 0, 1, -k*0.2, k*0.2)), j-k, girth-(map(k, 0, ht, 0, girth)), girth-(map(k, 0, ht, 0, girth)));


	}

	renderCanopy(i,(int)(j-ht),(int)ht);
  //make canopy

}

void renderCanopy(int x, int y, int ht)
{
	//color c=color(random(bright,bright*2),random(bright,bright*2),random(bright,bright*2));color c=color(red(mountainColor)+(int)random(-20,40),green(mountainColor)+(int)random(-20,40),blue(mountainColor)+(int)random(-20,20));
	translate(x, y+40);
	float rotator=random(-0.3,0.3);
	rotate(rotator);
	float max=random(map(ht,50,300,20,60),map(ht,50,300,60,90));
	float maxcopy =max;
	float min=random(map(ht,50,300,10,60),map(ht,50,300,60,90));


	randomStarterSky[0][1]=(int)random(100);
	randomStarterSky[0][1]=(int)random(100);
	randomStarterSky[1][1]=(int)random(100);
	randomStarterSky[1][0]=(int)random(100);

	rate[0][0]=random(0.005,0.1);
	rate[0][1]=random(0.005,0.1);
	rate[1][0]=random(0.005,0.1);
	rate[1][1]=random(0.005,0.1);
	
	for (int i = -200; i < 200; ++i) {

		for (int j = -200; j < 200; ++j) {

			if(j>0)
				{max=maxcopy-j+noise(i*0.1,j*0.1)*20;}
			else {

				max=maxcopy;
				
			}
			float f = map(noise(randomStarterSky[1][0]+i*0.06,randomStarterSky[1][1]+j*0.06),0,1,0,3);
			if(((((i)*(i))/((min)*(min)))+(((j)*(j))/((max)*(max))))<1+f)
			{
				

				
				
				if(noise(
					randomStarterSky[0][1]+ i* map(noise(randomStarterSky[1][1]+1+i*rate[0][0],randomStarterSky[1][1]+2+j*rate[0][1]),0,1,0.01,0.3),
					randomStarterSky[0][0]+ j* map(noise(randomStarterSky[1][0]+1+i*rate[1][0],randomStarterSky[1][1]+2+j*rate[1][1]),0,1,0.01,0.3))
					>0.4
				   )
				{
					fill(c,200);
					rect(i, j, 1, 1);
				}

				else  {

					fill(c,100);
					rect(i, j, 1, 1);
					
				}

				

				if(noise(random(100)+i*0.05,random(100)+j*0.05)>0.4)
				{
					
					if(noise(randomStarterSky[0][1]+ i*0.05,randomStarterSky[0][0]+j*0.05)>0.4)
					{
					fill(bright,100);
					rect(i, j, 1, 1);
					}
				}



			}

			else if (((((i)*(i))/((min)*(min)))+(((j)*(j))/((max)*(max))))<1+f+0.2) {

				fill(bright,200);
					rect(i, j, 1, 1);
				
			}
			
		}
		
	}
	rotate(-rotator);
	translate(-x, -y-40);
}






void renderMountain2()
{
	int fallDecider=(int)random(5,20);
	for (int k = 0; k < 50; ++k) {

		int  randval=(int)random(100);

		fill(bright,5);
		//noStroke();stroke(150, 15);
		beginShape();
		for (int i = 0; i < 1000; ++i) {
			float mountainrate=map(noise((randval+1)+i*0.005),0,1,0,0.1);
			mountainRecorder[i]+=map(noise(randval+i*mountainrate),0,1,-1,fallDecider)+raiseGrass;
			vertex(i,mountainRecorder[i]);
			
			
		}
		vertex(1000,1000);
		vertex(0, 1000);
		endShape(CLOSE);
		
		
		
	}
	
}

//try forthriple noise rendering float[][] randomStarterMountain;




//sky //--------------------------------int bright;
float[] weightage;
float[][] rate;
float[][] randomStarterSky;

void generateSkyConstraints()
{
	bright=(int)random(0, 200); //minimum val of each color
	weightage[0]=random(0.2, 1);
	weightage[1]=random(0.1, 0.7);
	weightage[2]=random(0.2, 1);

	//r
	rate[0][0]=random(0,0.01);
	rate[0][1]=random(0,0.01);
	//g
	rate[1][0]=random(0,0.01);
	rate[1][1]=random(0,0.01);
	//b
	rate[2][0]=random(0,0.01);
	rate[2][1]=random(0,0.01);

	randomStarterSky[0][0]=random(100);
	randomStarterSky[0][1]=random(0100);
	//g
	randomStarterSky[1][0]=random(100);
	randomStarterSky[1][1]=random(0100);
	//b
	randomStarterSky[2][0]=random(100);
	randomStarterSky[2][1]=random(0100);

	

}

void drawSky()
{
	loadPixels();
	float noisevalr=0;
	float noisevalg=0;
	float noisevalb=0;
	for (int i = 0; i < 1000; ++i) {

		for (int j = 0; j < 1000; ++j) {

			
			noisevalr=weightage[0]*map(  (noise(randomStarterSky[0][0]+i*rate[0][0],randomStarterSky[0][1]+j*rate[0][1]))  , 0, 1, 0, 255-bright);
			noisevalg=weightage[1]*map(  (noise(randomStarterSky[1][0]+i*rate[1][0],randomStarterSky[1][1]+j*rate[1][1]))  , 0, 1, 0, 255-bright);
			noisevalb=weightage[2]*map(  (noise(randomStarterSky[2][0]+i*rate[2][0],randomStarterSky[2][1]+j*rate[2][1]))  , 0, 1, 0, 255-bright);


			pixels[i*1000+j]=color(noisevalr+bright,noisevalg+bright,noisevalb+bright);

			
		}
		
	}
	updatePixels();



	

	


}

//----------------------------------------