最近在设计一个游戏,游戏中需要随机生成森林树木,如何让树木显得随机自然确实是个难题。一个是树木的大小需要随机,然后是树木的位置需要随机,这两个是关键,其它诸如颜色、形状等等属性的变化则不是大问题。
至于将不同大小的树木种植到平地上的问题其实可以简化为在一个平面上摆放互不重叠的随机大小的圆。
具体实现思路:
1. 建立一个n,n的矩阵作为树木可能出现的坐标地图。
2. 随机生成树木半径尺寸和坐标位置。
3. 尝试将树木放入矩阵对应坐标位置。
4. 检测该位置周边一个小范围框内是否有别的树木,两个树木间是否会发生碰撞,如果碰撞则放弃,如果不碰撞则直接植入这个树。
这一步是最关键最复杂的。由于树木尺寸有个最大限定,所以可以确定每次只需要检测周边最大树木尺寸和当前树木尺寸之和范围内树木是否碰撞即可,无需每次和已经植入的所有树木全部检测碰撞,于是可以大大节约计算量。
<!DOCTYPE html>
<HTML>
<HEAD>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,target-densitydpi=high-dpi,initial-scale=1.0,minimum-scale=1.0,maximum-scale=1.0, user-scalable=no"/>
<TITLE></TITLE>
<STYLE TYPE="TEXT/CSS">
body{
margin:0px;
padding:0px;
overflow:hidden;
}
div{
position:absolute;
margin:0px;
padding:0px;
background-color:rgba(255,0,0,0.5);
}
</STYLE>
<SCRIPT TYPE="TEXT/JAVASCRIPT">
function init(){
//初始化布局数组
var position=new Array();
for(var i=0;i<100;i++){
position[i]=new Array();
for(var j=0;j<100;j++){
position[i][j]={radius:0,isPlanted:0,isSet:0};
}
}
//随机种植树木
var treeCount=1000;
//树木最大半径
var treeRadiusMax=3;
for(var i=0;i<treeCount;i++){
//随机选择一个位置来种植一棵树
var treeX=Math.floor(Math.random()*100);
var treeY=Math.floor(Math.random()*100);
if(position[treeX][treeY].isSet==1){
//如果该位置已经植入树木则跳过后续操作
continue;
}
//树木直径随机
var treeRadius=treeRadiusMax*Math.random();
treeRadius=Math.max(0.5,treeRadius);
//初始设定为可以种植
position[treeX][treeY].radius=treeRadius;
position[treeX][treeY].isPlanted=1;
checkStartX=Math.max(treeX-Math.ceil(treeRadius)-treeRadiusMax,0);
checkStartY=Math.max(treeY-Math.ceil(treeRadius)-treeRadiusMax,0);
checkEndX=Math.min(treeX+Math.ceil(treeRadius)+treeRadiusMax,99);
checkEndY=Math.min(treeY+Math.ceil(treeRadius)+treeRadiusMax,99);
for(var x=checkStartX;x<=checkEndX;x++){
for(var y=checkStartY;y<