使用perlin噪音生成随机地图

引言

还是随机地图的问题,除了细胞自动机的生成方式以外,一般3D游戏中的地形大部分是使用某个噪音原图,这个原图大部分是由perlin噪音产生的(perlin noise),perlin噪音的主要作用可参考Perlin噪音

Perlin噪音的实现方式有点复杂,一时间不是很好看懂,我个人理解的是,噪音不太可能是完全随机的,自然界的很多东西虽然看起来是随机的,但是随机中间又蕴藏着很多规则,这些规则导致出现随机实际上是有些规则的,不可能出现类似电视雪花点的噪音。

所以为了用计算机图形来更好的描述自然界的这一随机现象,perlin创造了perlin噪音这么个自然随机算法。perlin噪音包含了平滑差值及八阶分形的内容,有点复杂,不好在这里展开。

实现思路

通过perlin噪音生成随机的灰度(即只有黑白的)噪音图,然后一定比率的颜色变成可通行区域颜色,一定比例的成为障碍物颜色。如0~100为陆地,101~255为障碍物。然后,神奇的一幕发生了。

效果

Get Adobe Flash player

高清无码

Get Adobe Flash player

像不像地球呢?

源码

package {
	import flash.display.BitmapData;
	import flash.display.Bitmap;
	import flash.geom.Rectangle;
	import flash.geom.Point;
	import flash.events.Event;
	import flash.display.Sprite;
	import flash.events.MouseEvent;

	public class PerlinNoiseRandomMap extends Sprite {
		protected var bmTerrain:Bitmap;
		protected var bmpTerrain:BitmapData;
		protected var freq:Number = 0.5;
		protected var octs:Number = 8;
		protected var seed:Number = 12;
		protected var stitch:Boolean = true;
		protected var fractal:Boolean = true;
		protected var channels:Number = 7;
		protected var gray:Boolean = true;
		protected var red:Array = new Array(256);
		protected var green:Array = new Array(256);
		protected var blue:Array = new Array(256);
		protected var land:Number = 0xff00ff00;
		protected var water:Number = 0xff0000ff;

		public function PerlinNoiseRandomMap() {
			init();
			stage.addEventListener(MouseEvent.CLICK, reset);
		}

		public function init():void {
			for (var i:Number = 0; i < 128; i++) {
				red[i]=green[i]=blue[i]=land;
			}
			for (i = 128; i < 256; i++) {
				red[i]=green[i]=blue[i]=water;
			}
			bmpTerrain = new BitmapData(800,600);
            // perlin噪音
			bmpTerrain.perlinNoise(bmpTerrain.width * freq,bmpTerrain.height * freq, octs, seed, stitch, fractal, channels, gray);
            // 以红色通道举例,0-128的红色值重新映射到red[0]到red[128]的数组值
			bmpTerrain.paletteMap(bmpTerrain,new Rectangle(0,0,bmpTerrain.width,bmpTerrain.height),new Point(0,0),red,green,blue);
			bmTerrain = new Bitmap(bmpTerrain);
			bmTerrain.width = stage.stageWidth;
			bmTerrain.height = stage.stageHeight;
			addChild(bmTerrain);
		}

		public function destroy():void {
			removeChild(bmTerrain);
			bmTerrain = null;
			bmpTerrain = null;
		}

		public function reset(e:MouseEvent):void {
			destroy();
			seed = Math.random();
			init();
		}

	}
}

参考文献

发表评论

电子邮件地址不会被公开。 必填项已用*标注