Preview:http://niuniuzhu.cn/p/ActiveWord/Main.html在用户输入文本并提交后,在容器里还存在上一次的MC,该如何处理?我们必须让他们按照原来的路径返回到起点,然后removeChild。回来上面提到的addList列表,当用户点击按钮后,我们先把addList里面的东西,复制到removeList列表,然后清空addList列表(说一个题外话,清空Array用array.length = 0是最高效率的 - -!)。然后再调用一次Character类的startRender方法。看到上面startRender的if(pathList),由于上一次移动后,路径并没有被清空,所以当这个列表不为null,表明这个M
首先说声不好意思,本人太懒,借Roxik大师的头像用一下。
首先从文本输入框获得bitmapData
Code
var bitmapData:BitmapData = new BitmapData(text.textWidth + 3, text.textHeight + 3); //预留3个象素,以避免文字绘制不全
bitmapData.draw(text);
new DataMap(bitmapData, mainCnt.width, mainCnt.height);
这里涉及到一个DataMap类。这个类用来处理放大bitmaoData,并且用一个数组保存所有坐标。
Code
for (var i:int = 0; i < resW; i ++)
{
for (var j:int = 0; j < resH; j ++)
{
if (bitmapDataText.getPixel(i, j) < 0x111111)
dataMap.push({x:i * scale, y:j * scale}); }
}
在完成了以上工作后,开始addChild的操作。
Code
for (var i:int = 0 ; i < dataMap.length; i ++)
{
var mc:MovieClip = loading.mc;
var c:Character = new Character();
c.ID = i;
c.mc = mc;
c.x0 = mc.x;
c.y0 = mc.y;
c.x1 = dataMap[i].x;
c.y1 = dataMap[i].y;
addChild(mc);
addList.push(c);
c.startRender();
}
我们创建dataMap.lenght个MC,并添加到容器。Character是存放每个角色信息的类,包括了ID、开始坐标、结束坐标。注意,最后把这个类放进一个addList的数组,作用下面会说明。最后,我调用了Character类的startRender方法,但这个角色被添加到容器后,就开始移动了。我们看看里面的东西。
Code
public function startRender():void
{
if (pathList)
{
pathList.reverse();
mc.addEventListener(Event.ENTER_FRAME, onRendering);
}
else
{
pathList = [];
trail = {x:x0, y:y0};
var trailList:Array = [{x:x0 + (x1 - x0) * Math.random(), y:-100}];
TweenMax.to(trail, ID * .025 + 2, {x:x1, y:y1, bezier:trailList, onUpdate:onTweenUpdate, ease:Linear.easeIn});
TweenMax.delayedCall(.3, function():void { mc.addEventListener(Event.ENTER_FRAME, onRendering); });
}
}
private function onTweenUpdate():void
{
pathList.push({x:Number(trail.x).toFixed(2), y:Number(trail.y).toFixed(2)});
}
先看else,新建一个trail对象,利用tweenMax,把这个对象从MC的开始坐标,移动到结束坐标。第二个tweenMax作用是延时0.3秒执行MC的移动,延时是为了不让MC“追上"了trail,让MC跟着trail的轨迹走。到这里,可能你会提出一个问题,为什么直接让MC tween呢?因为在这个MC里,定义了13个方向,我们需要知道它现在需要面向的方向,也就是需要知道往后的坐标值。因此必须用一个对象作为"导航"。
再来看看onRendering里面的东西
Code
if (c % 3 == 0)
{
var cc:int = c + 3, l:int = pathList.length - 1;
cc = cc > l ? l : cc;
getDirection(pathList[cc].x, pathList[cc].y);
}
mc.x = pathList[c].x;
mc.y = pathList[c].y;
if (++c == pathList.length)
{
c = 0;
if (mc.scaleX < 0)
mc.scaleX *= -1;
mc.gotoAndStop("yaoshou");
mc.removeEventListener(Event.ENTER_FRAME, onRendering);
mc.dispatchEvent(new Event(MC_END_MOVING));
}
为了减少CPU的负荷,我设了每3步取一次方向,每次以3步后的坐标值来决定现在的方向。然后开始按照trail的轨迹来走。如果走到了最后,向外抛出事件。
在用户输入文本并提交后,在容器里还存在上一次的MC,该如何处理?我们必须让他们按照原来的路径返回到起点,然后removeChild。回来上面提到的addList列表,当用户点击按钮后,我们先把addList里面的东西,复制到removeList列表,然后清空addList列表(说一个题外话,清空Array用array.length = 0是最高效率的 - -!)。然后再调用一次Character类的startRender方法。看到上面startRender的if(pathList),由于上一次移动后,路径并没有被清空,所以当这个列表不为null,表明这个MC需要被移走了。然后把这个列表倒置一下,按照刚才所说的方法移动MC,那么在容器里的MC就按照原路径返回了。
这里做一个小效果,当旧MC在移走的过程中,新的MC就在指定时间后开始创建并移动。我们还是利用TweenLite的delayCall方法,延时指定时间后,开始创建新的MC,并添加到addList(注意,之前addList已经被清空了)。这就开始了新的一轮跑动了。就这样周而复始吧。
最后说一下对象的深度排序问题。其实并不复杂。在这个例子里,为了减少CPU的负荷,我并没有在EnterFrame里面采用排序,我只选择了当MC走到指定位置后,才进行一次排序。先看一下排序的代码。
Code
var dep_arr:Array = [];
for (var i:int = 0; i < addList.length; i ++)
{
dep_arr.push({mc:getChildAt(i), l:MovieClip(getChildAt(i)).y});
}
dep_arr.sortOn("l", Array.NUMERIC);
for (i = 0; i < dep_arr.length; i ++)
{
var mc:MovieClip = dep_arr[i].mc;
setChildIndex(mc, i);
}
这里不作说明了,简单易懂。
如果你有更好的想法、算法和意见,可以和本人联系,或共同讨论。
Preview:http://niuniuzhu.cn/p/ActiveWord/Main.html
Capture: