见到这样排列的方格格,我们很容易想到二维数组,因为最起码要用双重循环才有可能将它们排列成这样。那么这种渐退的效果又是怎样形成的呢?我们给每个小格一个等待时间,按照点击到的方格的位置逐渐向外增加,离点击到的方格越远则等待时间就越长一些。
图中我们看到,方格 0 的位置,代表点击到的小方格,那么它的等待时间是 0,就是说点击后立即消失。然后向外围扩展,每向外一圈则等待时间就越长一些。我们用顺序的数字表示等待时间。这些数字并非真正的等待时间,可以作为等待时间的系数,这样就更加灵活了。
如何构造这样一个二维数组呢?我想了很多办法,最开始用的是数组操作,加入各种的判断,没能实现;后来又试用递归的方法,搞得越来越复杂。画过 N 张图表后,终于发现了规律,得出了一个简单得难以至信的算法。
OK,来看一下程序,大家可以直接复制到“动作-帧”当中,这里我们假设点击到的小格位于数组的 5,5 这个位置:
var Row:Number = 10;
var Colum:Number = 10;
// 10 行 10 列
var ci:uint = 5;
var cj:uint = 5;
// 点击到的数组位置 5,5
var a:Array = new Array();
for (var i:uint = 0; i < Row; i++) {
a[i] = new Array();
for (var j:uint = 0; j < Colum; j++) {
a[i][j] = Math.abs(i-ci) > Math.abs(j-cj) ? Math.abs(i-ci) : Math.abs(j-cj);
}
}
for (i = 0; i < Row; i++) {
trace(a[i]);
}
输出结果如下:
5,5,5,5,5,5,5,5,5,5
5,4,4,4,4,4,4,4,4,4
5,4,3,3,3,3,3,3,3,4
5,4,3,2,2,2,2,2,3,4
5,4,3,2,1,1,1,2,3,4
5,4,3,2,1,0,1,2,3,4
5,4,3,2,1,1,1,2,3,4
5,4,3,2,2,2,2,2,3,4
5,4,3,3,3,3,3,3,3,4
5,4,4,4,4,4,4,4,4,4
测试一下。核心语句,就这一句,OK,搞定,呼呼:
a[i][j] = Math.abs(i-ci) > Math.abs(j-cj) ? Math.abs(i-ci) : Math.abs(j-cj);
这句话可以理解为,当前数组小格的行和列(i 和 j)与点击到的方格的 i 和 j 相比较,找出这两个比较后哪个绝对值最大,就用这个绝对值最大的数填入当前的数组元素中。
OK,写到这里,这个程序的难点就介绍完了。骨架有了,下面开始填肉。
既然已经进入了 AS 3 时代,就不能想 AS 2 时候那么奔放了,不能够动态地加入属性或方法了。因为我们的类是密封类,无法在运行时添加其他属性和方法。密封类对象实例没有内部哈希表,从而提高内存使用效率和访问性能。所以说事物都是有两面性的,好处是提高了效率,那么缺点就是我们要多敲些代码了。解决办法就是创建自定义的类。
看过前面 Making Things Move 的朋友们应该很熟悉了吧。好了,不多说了,看这个 Box 类:
package {
import flash.display.Sprite;
public class Box extends Sprite {
public var BufTime:Number = 0;
public var ci:uint = 0;
public var cj:uint = 0;
public var Count:Number = 0;
public function Box(W:Number,H:Number) {
graphics.beginFill(0x66CCFF)
graphics.drawRect(0, 0, W, H)
graphics.endFill();
}
}
}
首先它是 Sprite 的子类。那么说是子类大还是父类大?按照辈分来讲当然是父类大。呵呵,不过在 OOP 世界里就不一样了,一般来讲,子类都是大于父类的,因为子类继承了父类的一切,并且在父类的基础上发展出了更多的功能(属性和方法),所以从功能上讲,子类要比父类大。
我们给 Box 影片,自定义几个成员变量(类变量),分别是:BufTime(存储等待时间),ci(该小格位于数组中的 i 下标),cj(该小格位于数组中的 j 下标),Count(用于计数时间)。通过构造函数给出 Box 的大小,例如:Box(40,40)。将 Box 类保存起来(Box.as)。
下面来看文档类 MainBox.as:
package {
import flash.display.Sprite;
import flash.events.Event;
import flash.events.MouseEvent;
public class MainBox extends Sprite {
// 方格的宽和高为 10 * 10
var Box_w:Number = 10;
var Box_h:Number = 10;
// 根据舞台大小和方格大小,求出可以放入多少行,多少列个小方格
var Colum:int = stage.stageWidth / Box_w;
var Row:int = stage.stageHeight / Box_h;
// boxAry 用于保存每个小方格的引用
var boxAry:Array = new Array();
public function MainBox() {
init();
}
function init():void {
for (var i = 0; i < Row; i++) {
for (var j = 0; j < Colum; j++) {
// 生成新的方格,保存每个的引用,码放好位置
var box:Box = new Box(Box_w, Box_h);
boxAry.push(box);
addChild(box);
box.x = j * (Box_w + 1);
box.y = i * (Box_h + 1);
// 保存方格对应数组中的行和列,并添加侦听
box.ci = i;
box.cj = j;
box.addEventListener(MouseEvent.MOUSE_DOWN,MouseDown);
}
}
}
function MouseDown(evt:MouseEvent):void {
// 根据点击的方格的数组下标,计算出二维数组
var ci = evt.target.ci;
var cj = evt.target.cj;
var a:Array = new Array();
for (var i:uint = 0; i < Row; i++) {
a[i] = new Array();
for (var j:uint = 0; j < Colum; j++) {
a[i][j] = Math.abs(i-ci) > Math.abs(j-cj) ? Math.abs(i-ci) : Math.abs(j-cj);
}
}
// 按照二维数组的顺序,为每个 box 设置等待时间
var count:uint = 0;
for (i = 0; i < Row; i++) {
for (j = 0; j < Colum; j++) {
var box:Box = boxAry[count] as Box;
// 设置等待时间
// + Math.random() * 4 可让时间有些差异
box.BufTime = a[i][j] + Math.random() * 4;
count++;
}
}
addEventListener(Event.ENTER_FRAME,EnterFrame);
}
function EnterFrame(evt:Event):void {
// 每帧每个 box 的 Count 加一,大于延迟时间后删除 box。
for (var i = boxAry.length-1; i >=0; i--) {
var box:Box = boxAry[i] as Box;
if (box.Count++ > box.BufTime) {
removeChild(box);
boxAry.splice(i,1);
}
}
}
}
}
这里使用的延迟方法,是在每帧都将变量加 1,加到 BufTime 为止。这种方法虽然有些不精确,但是要比使用 Timer 灵活许多。
如果可以把这些小方块制作当作遮罩,实现图片的转场效果也不错哟。
以下是源文件下载地址:
http://www.fs2you.com/files/40a8bf70-21ad-11dd-a2c5-00142218fc6e/
教程到此结束
QQ:147461195 (FL车在臣)