代码改变世界

点阵土

2009-10-13 23:11  宝宝合凤凰  阅读(374)  评论(0编辑  收藏  举报

根据输入的内容,利用bitmap的象素值判断文字所占用的区域,生成对应的点阵图

http://www.sanag.com.cn/html/teach/flash/2009/0629/1011.html
 

 

代码如下:
 

///bitmap的高和宽
var b = 200;
var b2 = 550;
//区域大小
var size = 4;
//
var s:Shape = new Shape();
s.y = b;
addChild(s);
//
cau(null);
stage.focus = t;
//
t.addEventListener(’change’,cau);
//计算并绘制
function cau(e) {
 var bmd:BitmapData = new BitmapData(b2,b);
 bmd.draw(root);
 s.graphics.clear();
 for (var i=0; i<b2; i+=2*size) {
  for (var j=0; j<b; j+=2*size) {
   if (isB(i,j,bmd)) {
    s.graphics.beginFill(int(Math.random()*0xffff00),1);
    s.graphics.drawCircle(i,j,size/2);
    s.graphics.endFill();
   }
  }
 }
}
//计算当前区域是否需要画点,条件是在size*size的区域内有5个象素不是空白
function isB(a,b,bmd)
{
 var c = 0;
 for(var i=0;i<size;i++)
 for (var j=0; j<size; j++)
 {
  if(bmd.getPixel(a+i,b+j)==0)c++;
 }
 if(c>5)return true;
 return false;
}

///

源文件(flash cs3格式):

点阵图.rar

别一个http://blog.sina.com.cn/s/blog_3ecb9b1101000e5n.html

第一次在fanflash上看到这个实例,感觉很不可思议

仔细研究一下发现,作者的构思还是很巧妙的,今天拿来与大家分享一下

这个实例可以说结合了BitmapData类的技术与Tween类的动感。

 

思路:

1.用AS创建一个空文本框,存储欲显示的字;

2.把这个文本框看成一个位图,并存储其位图数据;

3.逐行扫描这个位图数据,把有文字信息的像素点都存储到数组中;

4.最后根据数组复制出"点",并使每个"点"移动到相应的位置。

步骤1:

    绘制10*10的圆点,保存为影片剪辑,连接—>导出—>标志符"dot"

步骤2:

加入AS代码:

import flash.display.BitmapData;
import mx.transitions.Tween;
import mx.transitions.easing.*;
//导入BitmapData及Tween类
_root.createTextField("txt", -1, -100, -100, 0, 0);
txt.autoSize = true;
txt.text = "输入要显示的文字";
//创建一个空的文本框,存储输入的文本
var bm:BitmapData = new BitmapData(txt._width,txt._height, false, 0xffffff);
bm.draw(txt);
//把txt看成位图,并把txt位图信息存入mb
var DotArray:Array = new Array();
//申请一个数组用于存储mb位图信息
var w:Number = 4;
var h:Number = 4;
//w,h分别为点间宽度和高度
for (y=0; y<txt._height; y++) {
 for (x=0; x<txt._width; x++) {
  if (bm.getPixel(x, y) != 0xffffff) {
   DotArray.push({x:x*w, y:y*h});
   //逐行逐列取像素,把有字的像素位置存入数组并乘上w,h以扩展距离
  }
 }
}
_root.createEmptyMovieClip("MC", -1);
MC._x = 10;
MC._y = 150;
//============根据数组复制"点"===============
for (var i = 0; i<DotArray.length; i++) {
 var p = MC.attachMovie("dot", "dot"+i, i);

 p.cacheAsBitmap = true;

 //将"点"进行位图缓存
 p._x = Math.random()*Stage.width;
 p._y = Math.random()*Stage.height;
 //给每个"点"一个随机的起点
 p.tox = DotArray[i].x;
 p.toy = DotArray[i].y;
 //tox,toy是每个点要移动到的终点

 var speed = Math.random()*4

new Tween(p, "_x", Back.easeOut, p._x, p.tox, speed, true);
new Tween(p, "_y", Back.easeOut, p._y, p.toy, speed, true);
 //利用Tween类,让每个"点"移动到他们的终点坐标
}

 

Flash充电:MovieClip.cacheAsBitmap 属性

1.作用:如果设置为 true,则 Flash Player 将缓存影片剪辑的内部位图表示。这可以提高包含复杂矢量内容的影片剪辑的性能。

2.原理:矢量图体积小,但比较消耗计算资源;位图则比较消耗内存资源,但对计算资源消耗小。

3.简单地说:cacheAsBitmap就是把矢量图转化成位图;节省CPU,但消耗内存,可以提高对于矢量图的运算速度。

4.注意:cacheAsBitmap最适用于包含大量静态内容,并不需要频繁scale和旋转的MC里。

5.默认:当你添加filter(滤镜)到MC上,cacheAsBitmap自动设置为true,这点即使你强行让cacheAsBitmap=false也改变不了。只有当你去掉filter,cacheAsBitmap将返回最新被设置的逻辑值。


本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/octverve/archive/2008/02/12/2088991.aspx

=====================================================================

文字点阵和TweenMax的应用以及对象的深度排序

http://www.cnblogs.com/niuniuzhu/archive/2008/08/08/1263343.html

首先说声不好意思,本人太懒,借Roxik大师的头像用一下

 

首先从文本输入框获得bitmapData

 


var bitmapData:BitmapData = new BitmapData(text.textWidth + 3, text.textHeight + 3); //预留3个象素,以避免文字绘制不全
bitmapData.draw(text);
new DataMap(bitmapData, mainCnt.width, mainCnt.height);

 

这里涉及到一个DataMap类。这个类用来处理放大bitmaoData,并且用一个数组保存所有坐标。

 


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的操作。

 


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方法,但这个角色被添加到容器后,就开始移动了。我们看看里面的东西。

 


        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里面的东西

 


            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 (++== 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走到指定位置后,才进行一次排序。先看一下排序的代码。

 


            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:

Tag标签: as3,flex,Actionscript

 ===============================================================

3D粒子的排列和分散
2008/08/25 10:56

在这里先介绍一个十分好用的loader类—BulkLoader,这是它的API文档。它能把管理所有需要加载的文件,并支持多种加载类型,加载后可以直接从类中得到各类型的实例,十分方便。这里有官方的一个使用例子。

 
  1. import br.com.stimuli.loading.BulkLoader;
  2.  
  3.     / /instantiate a BulkLoader with a name : a way to reference this instance from another classes without having to set a expolicit reference onon many places
  4.     var bulkLoader : BulkLoader = new BulkLoader("main loading");
  5.     // add items to be loaded
  6.     bulkLoader.add("my_xml_file.xml");
  7.     bulkLoader.add("main.swf");
  8.     // you can also use a URLRequest object
  9.     var backgroundURL : URLRequest = new URLRequest("background.jpg");
  10.     bulkLoader.add(backgroundURL);
  11.  
  12.     // add event listeners for the loader itself :
  13.     // event fired when all items have been loaded
  14.     bulkLoader.addEventListener(BulkLoader.COMPLETE, onCompleteHandler);
  15.     // event fired when loading progress has been made:
  16.     bulkLoader.addEventListener(BulkLoader.PROGRESS, _onProgressHandler);
  17.  
  18.     // start loading all items
  19.     bulkLoader.start();
  20.  
  21.     function _onProgressHandler(evt : ProgressEvent) : void{
  22.         trace("Loaded" , evt.bytesLoaded," of ",  evt.bytesTotal);
  23.     }
  24.  
  25.     function onCompleteHandler(evt : ProgressEvent) : void{
  26.             trace("All items are loaeded and ready to consume");
  27.             // grab the main movie clip:
  28.             var mainMovie : MovieClip = bulkLoader.getMovieClip("main.swf");
  29.             // Get the xml object:
  30.             var mXML : XML = bulkLoader.getXML("my_xml_file.xml");
  31.             // grab the bitmap for the background image by a string:
  32.             var myBitmap : Bitmap = bulkLoader.getBitmap("background.jpg");
  33.             // grab the bitmap for the background image using the url rquest object:
  34.             var myBitmap : Bitmap = bulkLoader.getBitmap(backgroundURL);
  35.     }
  36.  
  37.     // In any other class you can access those assets without having to pass around references to the bulkLoader instance.
  38.     // In another class  you get get a reference to the "main loading" bulkLoader:
  39.     var mainLoader : BulkLoader = BulkLoader.getLoader("main loading");
  40.     // now grab the xml:
  41.     var mXML : XML = mainLoader.getXML("my_xml_file.xml");
  42.     // or shorter:
  43.     var mXML : XML = BulkLoader.getLoader("main loading").getXML("my_xml_file.xml");

回到正题,我们看看如何实现粒子的散落效果。首先我们在3D场景添加一块地板

 
  1. var cm:ColorMaterial = new ColorMaterial(0x212121, 1);
  2. floor = new Plane(cm, 1100, 1100, 1, 1);
  3. floor.rotationX = 90;
  4. floor.y = -550;
  5. scene.addChild(floor);

然后添加粒子阵,damp属性为碰撞后质量损失的值

 
  1. pixels = new MotionPixels(bfx, floor);
  2. pixels.damp = 0.4;
  3. scene.addChild(pixels);

在这个粒子阵里添加粒子

 
  1. var offsetX:int = int(bmd.width * .5 * intervalIn / intervalOut);
  2.            var offsetY:int = int(bmd.height * .5 * intervalIn / intervalOut);
  3.            var m:int = 0, n:int = 0;
  4.            for (var i:int = bmd.height; i > 0; i -= intervalOut)
  5.            {
  6.                for (var j:int = 0; j < bmd.width; j += intervalOut)
  7.                {
  8.                    var color:uint = bmd.getPixel32(j, i);
  9.                    if (color > 0) pixels.addPixel3D(new MotionPixel(color, n - offsetX, m - offsetY, 0));
  10.                    n += intervalIn;
  11.                }
  12.                n = 0;
  13.                m += intervalIn;
  14.            }

我们看看这个MotionPixel类

 
  1. public function MotionPixel(color:uintx:Number=0, y:Number=0, z:Number=0)
  2.         {
  3.             super(colorxy, z);
  4.             
  5.             weight = int(Math.random() * 35 + 5);
  6.             
  7.             radomXYZ();
  8.             
  9.             sx = x;
  10.             sy = y;
  11.             sz = z;
  12.         }
  13.         
  14.         public function radomXYZ():void
  15.         {
  16.             vx = int(Math.random() * 60 - 30);
  17.             vy = 0;
  18.             vz = int(Math.random() * 60 - 30);
  19.         }

在构造函数里,每个粒子都拥有初始位置,初始速度和重量。设置X和Z的初始速度目的为了有“分散”的效果,总不能让粒子都落在一条直线上吧。而重量则是决定在粒子Y方向速度的因素。

我们看看最重要的一个类MotionPixels类。里面包括了所有粒子的分散和聚合算法。有深入了解PV3D的朋友都知道所有继承了DisplayObject3D类的子类都可以override project方法。这个方法是pv3d里面重要的渲染方法之一。我们在这里面加上两个函数,让粒子在渲染到屏幕之前进行排列。

 
  1. if (isBreaking) startBreakUp(p);
  2. if (isGrouping) startGroup(p);

我大概说一下算法的原理,由于粒子拥有初速度vx0,vy0,vz0,其中vx0,vz0我们不用改变,它们是粒子能够分散到四周的重要条件。看看vy0,初速度我为0,假设粒子和地板之间的距离为d,有这样一个公式vy -= dy * p.weight * .004,当距离越远,加速度就越大,这个不难理解。当粒子和地板发生碰撞,也就是d=0的时候,vy改变方向:vy *= -1。并且vx,vy,vz都会损失速度vx *= _damp,vy *= _damp;vz *= _damp;。直到vx=vy=vz=0,粒子停止运动。当所有粒子停止运动后,获得下一张图片的象素位置和颜色,改变现有粒子的初始位置和颜色一致。然后从现在的位置返回到初始位置组成了一个新的图案。

如何你有任何意见和建议,欢迎和本人交流。

Preview:http://niuniuzhu.cn/p/PixelsRank