粒子化的Everyinch

二维粒子 everyinch 4773℃ 0评论

思路主要是:
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

喜欢 (0)
发表我的评论
取消评论

表情

Hi,您需要填写昵称和邮箱!

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址
(1)个小伙伴在吐槽
  1. 赞!粒子的效率效果都不错!
    tartiflop2014-01-08 09:18 回复
'; } if( dopt('d_footcode_b') ) echo dopt('d_footcode'); ?>