思路主要是:
1. 创建一个512*512,背景色白色的BitmapData作为粒子的容器
2. 创建一个256*256,背景色黑色的BitmapData,由perlinNoise方法生成影响速度的BitmapData,粒子根据这张位图相应位置的颜色,觉得它的速度:
p.vx += (velocityBytes[pos + 1] - 128) * 0.00088; p.vy += (velocityBytes[pos + 2] - 128) * 0.00088;
3. 创建一个256*256,背景色黑色的BitmapData,将文本绘制其中,形成黑底白字的文字位图。粒子检测文字的颜色,快速弹动
p.vx += (velocityBytes[pos + 1] - 128) * 0.0018; p.vy += (velocityBytes[pos + 2] - 128) * 0.0018; p.vx *= 0.5; p.vy *= 0.5;
4. 粒子位置的计算,主要应用了BitmapData的getPixels方法
getPixles方法:从像素数据的矩形区域生成一个字节数组。参数是当前 BitmapData 对象中的一个矩形区域(Rectangle),返回给定矩形中的像素的 ByteArray。需要注意的是BitmapData中的像素由32无符号整数表示,即RGBA每个颜色通道一个字节,所以返回的ByteArray的长度为原始32无符号整数表示的4倍。例如,256*256的BitmapData,length为65536,返回的ByteArray的长度为65536*4 = 262144
效果如下:
package { import flash.display.Bitmap; import flash.display.BitmapData; import flash.display.Sprite; import flash.display.StageAlign; import flash.display.StageQuality; import flash.display.StageScaleMode; import flash.events.Event; import flash.geom.Matrix; import flash.geom.Point; import flash.text.TextField; import flash.text.TextFieldAutoSize; import flash.text.TextFormat; import flash.utils.ByteArray; import com.particles.BasicBitmapParticle; [SWF(width="512",height="512",frameRate="64")] public class BitmapParticleTest8 extends Sprite{ private var bmpd:BitmapData; private var vec:Vector.; private var velocityBmpd:BitmapData; private var textBmpd:BitmapData; private var particle:BasicBitmapParticle = new BasicBitmapParticle(); private var text:String = "Everyinch"; private var count:int = 51111; private var tf:TextField; private var matrix:Matrix = new Matrix(); private var point:Point = new Point(); private var seed:int = 8888; private var speed:int; private var velocityBytes : ByteArray; private var textBytes:ByteArray; private var character:uint; function BitmapParticleTest8(){ stage.align = StageAlign.TOP_LEFT; stage.scaleMode = StageScaleMode.NO_SCALE; stage.quality = StageQuality.LOW; // 位图粒子的容器Bitmap var bmp : Bitmap = new Bitmap(bmpd = new BitmapData(512, 512, false, 0xFFFFFF)); addChild(bmp); vec = new Vector.(bmpd.width * bmpd.height, true); // 由像素颜色来生成粒子的运动,由perlinNoise方式来生成 velocityBmpd = new BitmapData(256, 256, false, 0x000000); // 黑底白字的字母BitmapData textBmpd = new BitmapData(256, 256, false, 0x000000); tf = new TextField(); tf.defaultTextFormat = new TextFormat("Verdana", 200, 0xFFFFFF, true); tf.autoSize = TextFieldAutoSize.LEFT; // 初始化粒子 var p:BasicBitmapParticle = particle = new BasicBitmapParticle(); while (count-- != 0){ p.x = Math.random()*512; p.y = Math.random()*512; p.vx = p.vy = 0.0; p = p.next = new BasicBitmapParticle(); } stage.addEventListener(Event.ENTER_FRAME, onEnterframe); } private function onEnterframe(e:Event):void{ speed++; // 每个字符保持的时间 if ((speed & 127) == 1){ // 使用perlinNoise生成速度的BitmapData seed = (((seed & 1) - 1) & 0xF00FC7C8) ^ (seed >> 1); velocityBmpd.perlinNoise(32, 32, 8, seed, false, true, 3, false); // getPixels 根据位图的Rectangle生成ByteArray,每个pixel包含RGBA,所以是4个Bytes velocityBytes = velocityBmpd.getPixels(velocityBmpd.rect); // 生成单个字符的BitmapData tf.text = text.charAt(character & 15); // 使用第1-15个字符 //tf.text = "Everyinch"; matrix.tx = (256 - tf.width) / 2; matrix.ty = ((256 - tf.height) / 2); textBmpd.fillRect(textBmpd.rect, 0x000000); textBmpd.draw(tf, matrix); textBytes = textBmpd.getPixels(textBmpd.rect); character++; } var pos:uint = vec.length - 1; while (pos > 1){ pos--; vec[pos] = 0xFFFFFF; } var p:BasicBitmapParticle = particle; while (p != null){ /* 将512*512的数组形式,转换为256*256的串形式 由于BitmapData的每个pixel包含4个Bytes,所以ByteArray的长度为原始长度的4倍 位运算的方式: pos = (((p.y >> 1) << 8) + (p.x >> 1)) << 2; */ pos = (int(p.y/2)*256 + int(p.x/2))*4; if (textBytes[pos + 1] > 128){ p.vx += (velocityBytes[pos + 1] - 128) * 0.0018; p.vy += (velocityBytes[pos + 2] - 128) * 0.0018; p.vx *= 0.5; p.vy *= 0.5; } else{ p.vx += (velocityBytes[pos + 1] - 128) * 0.00088; p.vy += (velocityBytes[pos + 2] - 128) * 0.00088; } p.x -= p.vx; p.y -= p.vy; if (p.x < 0) p.x = 511; else if (p.x > 511) p.x = 1; if (p.y < 0) p.y = 511; else if (p.y > 511) p.y = 1; /* 将最终位置转换为 512*512的串形式 位运算形式:pos = ((p.x >> 0) & 511) + (((p.y >> 0) & 511) << 9); */ pos = int(p.x)+int(p.y)*512; var c:uint = vec[pos]; c -= 0x0F0F0F; if (c > 0xFFFFFF) c = 0xf1e4b9; vec[pos] = c; p = p.next; } bmpd.setVector(bmpd.rect, vec); } } }
转载请注明:陈童的博客 » 粒子化的Everyinch