Cloud background

Hi,

Wanting to add some cloud backgrounds to my game, clouds would be made up of tiles of size 32x32 so can hve quite a large scrolling region of them.

Do you just add another camera up for the cloud background and render to same spritebatch as other layers?

Thanks for advice,

Steve

I’m stumped as what you want. Do you want a parallax cloud background with clouds that move as the player moves while they also move themselves, or just a static background of clouds?

First of all like MrPork said your question isn’t very clear.

  1. If you want just normal clouds, simply render them.

  2. If you want the clouds to scroll automatically, something like this can be done


cloud.x += velX; // assuming you want it to scroll left, so velX = -1 or -ve something

if (cloud.x + cloud.width < 0) cloud.x = SCREEN_WIDTH; // so that if it goes out, it'll come from the right side

Hi, yes sorry about the question, not very clear.

Just want clouds to scroll slowly in the background and wrap back round.

I have a camera for my landscape (tiled landscape) a camera for my HUD, was wondering if I also needed
one for the clouds so they don’t scroll with the tiled landscape (this is in Libgdx).

Thanks again

You don’t need a new camera if that’s all you want. All you really need is to draw the clouds in a Spritebatch that hasn’t set it’s projection matrix to the camera’s combined whatever thing. Which means the clouds won’t be drawn relative to the cameras position, instead it just uses the normal screens x and y position. Sorry if I’m not explaining this well, hopefully someone will come along and explain it better if you don’t understand this. Also for the wrapping, just use the above or google something like “Pacman wrapping java” and it should spew out a few equations that should facilitate this.

Hi,

Something like this:


	Matrix4 uiMatrix = backgroundCamera.combined.cpy();
		uiMatrix.setToOrtho2D(0, 0, SCREENWIDTH, SCREENHEIGHT);
		batch.setProjectionMatrix(uiMatrix);
		backGroundCamera.update();

		batch.begin();

// draw clouds here

                batch.end();


Thanks

I’m not sure if you can use it like this, but it should hopefully work:

batch.begin();

// draw clouds 

batch.end();


batch.setProjectionMatrix(camera.combined);
batch.begin();

// Draw all other stuff relative to canera

batch.end();

I’m doing all this from an iphone, so I can’t properly test it. If it does work please tell me! I would love to learn something new.

Another way of doing this is by using the setWrap method for a texture, for example.

cloudTexture.setWrap(TextureWrap.Repeat, TextureWrap.Repeat);

inside your assets class

Then, inside your render loop you can have a timer that sets the texture U and U2 coords depending on what the value is. Something like this:



timer += Gdx.Graphics.getDeltaTime * 0.2f; // Plus the timer and then * by 0.2f to slow it down. You can change the value depending on the speed you want
		
		if(timer > 1.0f){
			timer = 0f;
		}
		
		Assets.cloudTexture.setU(timer);    // Scrolls using the float values of 0-1f and sets it to the U text coords
		Assets.cloudTexture.setU2(timer-1); 

EDIT: I shoud add that this means you need an image that is at least and width/height of your camera (So it looks good). So sadly no random cloud placement

Well is suggest he make random cloud placement and just not wrap it. Eventually players will start to notice the wrapping.

A lot of games use wrap backgrounds :smiley: He could even have a huge image that was 20x larger than the screen width if he liked and get the same effect.

However, for random cloud placements I would simply use another spritebatch.

I’m not sure if this would work but could you not do the following: Use the same spritebatch BUT store all the clouds inside an arraylist and then use camera.project() to draw them to the screen?

Hi,

Got this working, got the cloud background into a different spritebatch and render first, then the tiles second.

Used a OrthographicCamera for the cloud camera, very simple in the end.

Now to look at creating caves…is cellular automata the way to go for this?

Thanks

I’ve talked about caves a lot recently so I’m just going to dump a previous post here.

I did some basic terrain generation a while ago using OpenSimplex noise. It turned out pretty good:

The steps went a bit like this:


float hillCoeff = 8f;
		float terrainLimit = hillCoeff + (sizey / 8);
		int dirtLimit = Math.round(hillCoeff + (sizey / 8));
		int caveStart = dirtLimit - (sizey / 32);
        
                // generate the hills
		for (int i = 0; i < sizex; i++) {
			float noise = (float) noiseGen.eval(i * 0.15f, -1 * 0.15f);
			int actualHeight = Math.round(noise * hillCoeff);

			int topOfDirt = actualHeight + (sizey / 16);
			int endOfDirt = actualHeight + (sizey / 8);
			for (int y = endOfDirt; y >= topOfDirt; y--) {
				setBlock(Blocks.instance().getBlock("dirt"), i, y);
			}
			setBlock(Blocks.instance().getBlock("grass"), i, actualHeight + (sizey / 16));

			for (int y = endOfDirt; y < sizey; y++) {
				setBlock(Blocks.instance().getBlock("stone"), i, y);
			}

			// long cave under surface to cover up noise's abrupt end
			for (int y = caveStart - Math.round(4 * noise) - 6; y < caveStart
					+ Math.round(3 * noise) + 3; y++) {
				setBlock(Blocks.instance().getBlock("empty"), i, y);
			}
		}

		/* NOTES
		 * Terrain upper limit is essentially 1 * hillCoeff + (sizey / 8)
		 * dirt ends at around hillCoeff + (sizey / 8)
		 * noise ends at dirtLimit - (sizey / 32)
		 * caves start at dirtLimit - (sizey / 32)
		 * 
		 */
                
                // generate the caves
		float caveStartThreshold = 0.56f;
		float caveEndThreshold = 0.825f;
		for (int x = 0; x < sizex; x++) {
			for (int y = caveStart; y < sizey; y++) {
				float noise = (float) noiseGen.eval(x * 0.1f, y * 0.1f);
				noise = (noise + 1) / 2f;
				if (noise >= caveStartThreshold && noise <= caveEndThreshold) {
					setBlock(Blocks.instance().getBlock("empty"), x, y);
				}
			}
		}

Github code here.

The code generated the hills using 1D noise (that’s actually 2D, but the Y dimension is always -1), and added a cave at the bottom that’s a bit like the inverse of the hill heights. This is to cover up the cave generation stub.

Caves are generated with 2D noise and a min-max value. If the noise function returns a value (which is changed to 0-1 for ease) that is between the min and max it will set the block to air. Likewise, you could do the same thing except for ore deposits or different types of stone, etc. before cave generation.

I hope that helps! If you need me to explain more I can!

I believe this is what the original question was, I feel ignored :confused:

Thanks for that and to PocketCrafter7 for original answer :wink:

I do feel cellular automata seems the way to go to generate some smooth caves, although yours does look good - do you have
a screenshot of the game not zoomed out?

Thanks

Which game are you talking about ?

EDIT
Oh, I think that message was meant for chrislo27.

The problem with my current generation is that it’s very rough in proportion to the game size (blocks are really big). But here’s a screenshot nonetheless. My code is also scaleable for different world types.

As you can see it’s very rough. One way to fix this would be to either raise the threshold of the caves or make all the noise coefficients smaller.

Still looks good.

I’ve used cellular automata. I’ve created a class for it which uses a char array, this needs to be changed to whatever you use for your map array (anybody out there
convert this to a generic class?)


import java.util.Random;

public class CellularAutomata {

	private char[][] map = null;
	private char[][] newMap = null;

	private Random r = new Random();

	private int chanceToStartAlive, w, h, death, life;

	public CellularAutomata(int w, int h, int chanceToStartAlive, int death,
			int life) {
		this.w = w;
		this.h = h;
		this.chanceToStartAlive = chanceToStartAlive;
		this.death = death;
		this.life = life;
	}

	public void initialiseMap() {
		map = new char[w][h];
		for (int x = 0; x < map.length; x++)
			for (int y = 0; y < map[0].length; y++)
				map[x][y] = r.nextInt(100) > chanceToStartAlive ? '#' : '.';

	}

	public void displayMap() {
		if (map != null) {
			for (int x = 0; x < map.length; x++, System.out.println())
				for (int y = 0; y < map[0].length; y++)
					System.out.print(map[x][y]);
		}
	}

	public char[][] doSimulationStep() {
		newMap = new char[w][h];
		for (int x = 0; x < map.length; x++) {
			for (int y = 0; y < map[0].length; y++) {
				int nbs = countAliveNeighbours(map, x, y);
				if (map[x][y] == '#')
					newMap[x][y] = nbs <= life ? '.' : '#';
				else
					newMap[x][y] = nbs > death ? '#' : '.';
			}
		}
		map = newMap;
		return newMap;
	}

	private int countAliveNeighbours(char[][] map, int x, int y) {
		int count = 0;
		for (int i = -1; i < 2; i++) {
			for (int j = -1; j < 2; j++) {
				int neighbour_x = x + i;
				int neighbour_y = y + j;
				if (i == 0 && j == 0) { // do nothing as this is us!
				} else if (neighbour_x < 0 || neighbour_y < 0
						|| neighbour_x >= map.length
						|| neighbour_y >= map[0].length) {
					count++;
				} else if (map[neighbour_x][neighbour_y] == '#')
					count++;
			}
		}
		return count;
	}
}

and to use:


caves.initialiseMap();
		System.out.println("\nFirst generation:");
		caves.displayMap();
		caves.doSimulationStep();
		System.out.println("\nSecond generation:");
		caves.displayMap();
		System.out.println("\nThird generation:");
		caves.doSimulationStep();
		caves.displayMap();
		System.out.println("\nFourth generation:");
		caves.doSimulationStep();
		caves.displayMap();


Of course, you don’t need to call displayMap when put into your world array.