from: http://bbs.9ria.com/thread-77302-1-1.html
演示程序
http://www.adamatomic.com/canabalt/
http://www.flixel.org/mode/
Flixel横板游戏制作教程(四)— RandomLevels
本教程是接着Flixel横板游戏制作教程(三)— AddingWeapons来做的。
现在我们来给游戏加入 随机的平台,由于本次教程的重点是随机平台的算法,所以对算法不太明白的同学大可以不去理会,喜欢研究的就看看算法吧。后面的教程会介绍一个专门配合flixel 的地图编辑器,非常好用,所以本次教程属于 娱乐向。。。看看就好,不比深究。
那么开始了,看到 GameState 类:
package
{
import org.flixel.FlxG;
import org.flixel.FlxGroup;
import org.flixel.FlxState;
import org.flixel.FlxTileblock;
import org.flixel.FlxU;
/**
* ...
* @author zb
*/
public class GameState extends FlxState
{
/*********** 前面已有的声明 *************/
//地图制作用
//地图宽度
static public const MAP_WIDTH:Number = 640;
//地图高度
static public const MAP_HEIGHT:Number = 480;
//素材中每个小砖块的宽度
static private const TILE_BLOCK_WIDTH:Number = 8;
//随机地图中一个矩形平台一个方向(水平方向或垂直方向)的最大的砖块数量
//比如 最大的一个平台的砖块数 是 4*4=16
static private const MAX_TILE_BLOCK_NUM:uint = 4;
///随机地图中一个矩形平台一个方向(水平方向或垂直方向)的最大的砖块数量
static private const MIN_TILE_BLOCK_NUM:uint = 2;
//每次进行随机平台生成的时候,重复的次数,用法见下面算法中解释
static private const RANDOM_LOOP_COUNT:int = 5;
//我们用一个 flxGroup来储存 生成的 随机平台
protected var levels:FlxGroup;
override public function create():void
{
//*********已有的内容**********/
//这里不需要上一节的 地板了,注释掉吧
//addGround();
//*********已有的内容**********/
//加入随机地图
addRandomMap();
}
//************已有的 方法**************//
private function addRandomMap():void
{
levels = new FlxGroup();
//生成地图边界
var tile:FlxTileblock;
//地图的左边界
tile = new FlxTileblock(0, 0, 8, MAP_HEIGHT);
tile.loadTiles(tileImg);
levels.add(tile);
//地图的下边界
tile = new FlxTileblock(0, MAP_HEIGHT-8, MAP_WIDTH, 8);
tile.loadTiles(tileImg);
levels.add(tile);
//地图的右边界
tile = new FlxTileblock(MAP_WIDTH-8, 0, 8, MAP_HEIGHT);
tile.loadTiles(tileImg);
levels.add(tile);
//地图的上边界
tile = new FlxTileblock(0, 0, MAP_WIDTH, 8);
tile.loadTiles(tileImg);
levels.add(tile);
//将levels 组加入到显示列表中
//注意,只要 flxGroup 被添加进入了 显示列表,
//后面 再 加入组的 object 也会自动加入显示列表中
add(levels);
//下面就是生成随机平台了,这里生成 150 个平台
for (var i:int = 0; i < 150; i++)
{
addRandomTile();
}
}
private function addRandomTile():void
{
//随机矩形平台的实例
var newTile:FlxTileblock;
//随机矩形平台的宽度
var blockWidth:Number;
//随机矩形平台的高度
var blockHeight:Number;
//随机平台的 x 坐标
var blockX:Number;
//随机平台的 y 坐标
var blockY:Number;
//这个是用来判断 这次新生成的 平台,是否与 之前的平台 重叠
var newTileIsOverlapOthers:Boolean = false;
//重新生成随机平台的重复次数,用在 当与之前的 平台重叠时
//取消并重新生成一个新的平台,再进行 重叠判断
//当 重复次数 超过规定的 最大重复 次数时,则取消本次 随机平台的生成
var loopCount:int = 0;
//进行本次随机平台的生成与重叠判断循环
do {
//计算随机平台的宽度
// int(Math.random() * (MAX_TILE_BLOCK_NUM - MIN_TILE_BLOCK_NUM) + MIN_TILE_BLOCK_NUM)
// 上面这个是 水平方向的 砖块数量
// * TILE_BLOCK_WIDTH ,然后 砖块数量 乘上 砖块的 宽度,
//就是平台的宽度了
blockWidth = int(Math.random() * (MAX_TILE_BLOCK_NUM - MIN_TILE_BLOCK_NUM) + MIN_TILE_BLOCK_NUM) * TILE_BLOCK_WIDTH;
//计算随机平台的高度
//因为 这里素材中 砖块的高度和宽度 都是 8,所以就不再额外加入 高度的静态值了
blockHeight = int(Math.random() * (MAX_TILE_BLOCK_NUM - MIN_TILE_BLOCK_NUM) + MIN_TILE_BLOCK_NUM) * TILE_BLOCK_WIDTH;
//计算平台的 x 坐标位置
//MAP_WIDTH / TILE_BLOCK_WIDTH,这个是先计算出 地图的宽度 相当于多少个小砖块的数量
//使用 random ,得到一个 砖块数的 随机值
// - MAX_TILE_BLOCK_NUM,接着减去一个 每个随机平台的 最大数量,
//就可以保证 平台的位置 不会超过 地图边界
// * TILE_BLOCK_WIDTH,最后乘上小砖块的宽度,算出平台的 x 坐标
blockX = int(Math.random() * MAP_WIDTH / TILE_BLOCK_WIDTH - MAX_TILE_BLOCK_NUM) * TILE_BLOCK_WIDTH;
//同样算出 y 坐标
blockY = int(Math.random() * MAP_HEIGHT / TILE_BLOCK_WIDTH - MAX_TILE_BLOCK_NUM) * TILE_BLOCK_WIDTH;
//这里就生成一个 随机的砖块了
newTile = new FlxTileblock(blockX, blockY, blockWidth, blockHeight);
newTile.loadTiles(tileImg);
//遍历levels 组中的 平台
for each (var existTile:FlxTileblock in levels.members)
{
//当 新生成的 平台 与 之前的平台 重叠的话
//就会返回 true
//overlaps方法,判断 本object 是否与 参数中的 object 重叠
newTileIsOverlapOthers = newTile.overlaps(existTile);
//如果 发生重叠了 ,就停止遍历
if (newTileIsOverlapOthers)
{
break;
}
}
//重复次数 增加 1
++loopCount;
//当 发现 重叠 并且 重复次数 小于 最大重复次数时
//回到循环,并重新 生成一个新的 随机平台
//再与 之前 的平台 进行 重叠 判断
//最大重复 次数 为 RANDOM_LOOP_COUNT
//如果 不重叠,或者 重复次数 超过 最大重复次数
//结束循环
}while (newTileIsOverlapOthers && loopCount < RANDOM_LOOP_COUNT)
//不管 本次生成的 随机平台 是否与之前的 重叠
//都会加入到 平台 组中
//由于 有 一定的 重复机会
//所以 不重叠的 概率 也有 一定保证
levels.add(newTile);
}
override public function update():void
{
//由于前面的地板方法被注释掉了,这个也跟着注释吧!
//FlxU.collide(player, groundTile);
//同上,注释掉吧
//FlxU.collide(bullets, groundTile);
//加入 子弹 与 现在 的 levels 碰撞检测
FlxU.collide(bullets, levels);
//人物与 levels 碰撞检测
FlxU.collide(player, levels);
//还是要提醒下,别忘了加上。。。
super.update();
}
}
}
看看运行效果吧,每次进入游戏都不一样哦~