Randomly generating maps like in minicraft

Hey guys. As a quick background, I’ve been coding Java for quite a while now but wanted to mess around with game programming for fun. I’ve been reading up on using the LWJGL library.

Anyways, I was wondering how/what the logic is to create a dynamic map in a 2D world (of course 3D world would also be interesting to know!). Notch did this in his live stream of Minicraft and I was wondering for an explanation of how to do it and maybe some code snippets. This is my first post on here so I hope this is the right section.

Thanks to any answers and/or advice!

This is a method from ‘THECH3RN0’ off of youtube, he used this in exactly what you want…
(Mentioned Notch alot during his video, saying that these methods are not ‘‘exactly’’ the same as his, but it’s a Distant Graphic algorithm of some type.
Basicly using nothing but pixels, creating a 3D looking envionment/movement, while using no Graphics2D.

Code Snippet: (randomly generating 8x8 walls)


		Level level = game.level;
		int size = 10;
		for (int xBlock = -size; xBlock <= size; xBlock++) {
			for (int zBlock = -size; zBlock <= size; zBlock++) {
				Block block = level.create(xBlock, zBlock);
				Block east = level.create(xBlock + 1, zBlock);
				Block south = level.create(xBlock, zBlock + 1);
				if (block.solid) {
					if (!east.solid) {
						renderWall(xBlock + 1, xBlock + 1, zBlock, zBlock + 1,
								0);
					}
					if (!south.solid) {
						renderWall(xBlock + 1, xBlock, zBlock + 1, zBlock + 1,
								0);
					}
				} else {
					if (east.solid) {
						renderWall(xBlock + 1, xBlock + 1, zBlock + 1, zBlock,
								0);
					}
					if (south.solid) {
						renderWall(xBlock, xBlock + 1, zBlock + 1, zBlock + 1,
								0);
					}
				}
			}

The Level class:


public class Level {

	public final int width, height;
	public Block[] blocks;

	public Level(int width, int height) {
		this.width = width;
		this.height = height;
		blocks = new Block[width * height];
		Random random = new Random();
		for (int y = 0; y < height; y++) {
			for (int x = 0; x < width; x++) {
				Block block = null;
				if (random.nextInt(4) == 0) {
					block = new SolidBlock();
				} else {
					block = new Block();
				}
				blocks[x + y * width] = block;
			}
		}
	}

	public Block create(int x, int y) {
		if (x < 0 || y < 0 || x >= width || y >= height) {
			return Block.solidWall;
		}
		return blocks[x + y * width];
	}

}

Now…
I really didn’t want to post this next snippet after looking at it because it’s so large…
But here’s the method renderWall():
(TONS of fun math XD)


/** NOTE: Reason this method is so chunky is due to all bugs being patched. */
	public void renderWall(double xLeft, double xRight, double zDistanceLeft,
			double zDistanceRight, double yHeight) {

		double upCorrect = 0.0625;
		double rightCorrect = 0.0625;
		double forwardCorrect = 0.0625;
		double walkCorrect = -0.0625;

		double xcLeft = ((xLeft / 2) - (right * rightCorrect)) * 2;
		double zcLeft = ((zDistanceLeft / 2) - (forward * forwardCorrect)) * 2;

		double rotLeftSideX = xcLeft * cosine - zcLeft * sine;
		double yCornerTL = ((-yHeight) - (-up * upCorrect + (walking * walkCorrect))) * 2;
		double yCornerBL = ((+0.5 - yHeight) - (-up * upCorrect + (walking * walkCorrect))) * 2;
		double rotLeftSideZ = zcLeft * cosine + xcLeft * sine;
		double xcRight = ((xRight / 2) - (right * rightCorrect)) * 2;
		double zcRight = ((zDistanceRight / 2) - (forward * forwardCorrect)) * 2;
		double rotRightSideX = xcRight * cosine - zcRight * sine;
		double yCornerTR = ((-yHeight) - (-up * upCorrect + (walking * walkCorrect))) * 2;
		double yCornerBR = ((+0.5 - yHeight) - (-up * upCorrect + (walking * walkCorrect))) * 2;
		double rotRightSideZ = zcRight * cosine + xcRight * sine;
		double tex30 = 0;
		double tex40 = 8;
		double clip = 0.5;

		if (rotLeftSideZ < clip && rotRightSideZ < clip) {
			return;
		}
		if (rotLeftSideZ < clip) {
			double clip0 = (clip - rotLeftSideZ)
					/ (rotRightSideZ - rotLeftSideZ);
			rotLeftSideZ = rotLeftSideZ + (rotRightSideZ - rotLeftSideZ)
					* clip0;
			rotLeftSideX = rotLeftSideX + (rotRightSideX - rotLeftSideX)
					* clip0;
			tex30 = tex30 + (tex40 - tex30) * clip0;
		}

		if (rotRightSideZ < clip) {
			double clip0 = (clip - rotLeftSideZ)
					/ (rotRightSideZ - rotLeftSideZ);
			rotRightSideZ = rotLeftSideZ + (rotRightSideZ - rotLeftSideZ)
					* clip0;
			rotRightSideX = rotLeftSideX + (rotRightSideX - rotLeftSideX)
					* clip0;
			tex40 = tex30 + (tex40 - tex30) * clip0;
		}

		double xPixelLeft = (rotLeftSideX / rotLeftSideZ * height + width / 2);
		double xPixelRight = (rotRightSideX / rotRightSideZ * height + width / 2);
		/* boundary issue */
		if (xPixelLeft >= xPixelRight) {
			return;
		}

		int xPixelLeftInt = (int) (xPixelLeft);
		int xPixelRightInt = (int) (xPixelRight);

		if (xPixelLeftInt < 0) {
			xPixelLeftInt = 0;
		}

		if (xPixelRightInt > width) {
			xPixelRightInt = width;
		}

		/* 4 corner pins */
		/* y corner divided by left side, multiplied by height + height / 2 */
		double yPixelLeftTop = yCornerTL / rotLeftSideZ * height + height / 2.0;
		double yPixelLeftBottom = yCornerBL / rotLeftSideZ * height + height
				/ 2.0;
		double yPixelRightTop = yCornerTR / rotRightSideZ * height + height
				/ 2.0;
		double yPixelRightBottom = yCornerBR / rotRightSideZ * height + height
				/ 2.0;

		/* TEXTURE MODIFIERS */
		double tex1 = 1 / rotLeftSideZ;
		double tex2 = 1 / rotRightSideZ;
		double tex3 = tex30 / rotLeftSideZ;
		double tex4 = tex40 / rotRightSideZ - tex3;
		for (int x = xPixelLeftInt; x < xPixelRightInt; x++) {
			/* left = left, if less than right, keep rendering (if no inversion) */
			double pixelRotation = (x - xPixelLeft)
					/ (xPixelRight - xPixelLeft);
			double zWall = (tex1 + (tex2 - tex1) * pixelRotation);
			if (zBufferWall[x] > zWall) {
				continue;
			}
			zBufferWall[x] = zWall;
			int xTexture = (int) ((tex3 + tex4 * pixelRotation) / zWall);
			double yPixelTop = yPixelLeftTop + (yPixelRightTop - yPixelLeftTop)
					* pixelRotation;
			double yPixelBottom = yPixelLeftBottom
					+ (yPixelRightBottom - yPixelLeftBottom) * pixelRotation;
			/* top & bottom */
			int yPixelTopInt = (int) (yPixelTop);
			int yPixelBottomInt = (int) (yPixelBottom);

			if (yPixelTopInt < 0) {
				yPixelTopInt = 0;
			}
			if (yPixelBottomInt > height) {
				yPixelBottomInt = height;
			}
			for (int y = yPixelTopInt; y < yPixelBottomInt; y++) {
				double pixelRotationY = (y - yPixelTop)
						/ (yPixelBottom - yPixelTop);
				int yTexture = (int) (8 * pixelRotationY);
				// pixels[x + y * width] = xTexture * 100 + yTexture * 100 *
				// 256;
				pixels[x + y * width] = Texture.fill.pixels[(xTexture & 7)
						+ (yTexture & 7) * 8];
				zBuffer[x + y * width] = 1 / (tex1 + (tex2 - tex1)
						* pixelRotation) * 8;
			}
		}
	}

Hope it helps you out some mate.

Hey thanks for the quick reply!

Funny enough I actually just went through his a lot of his videos on youtube. The math in this is definitely hard to grasp via the code. I think I’ll have to watch this video more closely on YouTube and see if he offers decent explanations. I only watched through his creating the floor and ceiling. One thing I’ve found difficult about getting into the game development is that a lot of tutorials and online videos skim over what a lot of the things do. A lot of hand waving if you will.

I mentioned the Notch stuff since in Minicraft he seemed to create maps by what resembles a “render clouds” filter in Photoshop. Pretty neat! :slight_smile:

You’re thinking of perlin noise and generating height maps i think.

lol, he said it took him about 4 hours to think up how to explain to us what that method does exactly (to learn+play with).

Can you drop the link to the video?

Here’s Episode 17: http://www.youtube.com/watch?v=WkBMoCbbgO0&feature=bf_prev&list=UUQ-W1KE9EYfdxhL6S4twUNw&lf=plcp
you could of course surf your way back to the beginning.
Still coming out, last one was… march sixth this year?