引言
还是随机地图的问题,除了细胞自动机的生成方式以外,一般3D游戏中的地形大部分是使用某个噪音原图,这个原图大部分是由perlin噪音产生的(perlin noise),perlin噪音的主要作用可参考Perlin噪音。
Perlin噪音的实现方式有点复杂,一时间不是很好看懂,我个人理解的是,噪音不太可能是完全随机的,自然界的很多东西虽然看起来是随机的,但是随机中间又蕴藏着很多规则,这些规则导致出现随机实际上是有些规则的,不可能出现类似电视雪花点的噪音。
所以为了用计算机图形来更好的描述自然界的这一随机现象,perlin创造了perlin噪音这么个自然随机算法。perlin噪音包含了平滑差值及八阶分形的内容,有点复杂,不好在这里展开。
实现思路
通过perlin噪音生成随机的灰度(即只有黑白的)噪音图,然后一定比率的颜色变成可通行区域颜色,一定比例的成为障碍物颜色。如0~100为陆地,101~255为障碍物。然后,神奇的一幕发生了。
效果
PerlinNoiseRandomMap.swf
高清无码
PerlinNoiseRandomMap1.swf
像不像地球呢?
源码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
|
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();
}
}
}
|
参考文献