粒子化的Everyinch
思路主要是:1. 创建一个512*512,背景色白色的BitmapData作为粒子的容器
2. 创建一个256*256,背景色黑色的BitmapData,由perlinNoise方法生成影响速度的BitmapData,粒子根据这张位图相应位置的颜色,觉得它的速度:
[code lang="as3"]p.vx += (velocityBytes[pos + 1] - 128) * 0.00088;
p.vy += (velocityBytes[pos + 2] - 128) * 0.00088;[/code]
3. 创建一个256*256,背景色黑色的BitmapData,将文本绘制其中,形成黑底白字的文字位图。粒子检测文字的颜色,快速弹动
[code lang="as3"]p.vx += (velocityBytes[pos + 1] - 128) * 0.0018;
p.vy += (velocityBytes[pos + 2] - 128) * 0.0018;
p.vx *= 0.5;
p.vy *= 0.5;[/code]
4. 粒子位置的计算,主要应用了BitmapData的getPixels方法
getPixles方法:从像素数据的矩形区域生成一个字节数组。参数是当前 BitmapData 对象中的一个矩形区域(Rectangle),返回给定矩形中的像素的 ByteArray。需要注意的是BitmapData中的像素由32无符号整数表示,即RGBA每个颜色通道一个字节,所以返回的ByteArray的长度为原始32无符号整数表示的4倍。例如,256*256的BitmapData,length为65536,返回的ByteArray的长度为65536*4 = 262144
效果如下:
[code lang="as3"]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);
}
}
}[/code]
查看完整版本: 粒子化的Everyinch
赞!粒子的效率效果都不错!Tags: