Home Tutorials Forums Articles Blogs Movies Library Employment Press
Old 10-08-2007, 06:26 AM   #1
Advocate
eye heart ay ess three
 
Join Date: Feb 2005
Posts: 38
Default Dripping Blood Effect - BitmapData fun

I was planning on playing around with the BitmapData object during christmas time (snow) to familiarize myself with its awesomeness, but I got impatient and decided to do dripping blood for halloween.

The way it will work is I am going to compile this effect into a transparent windowless movie, and run it inside of a div tag that completely covers a webpage. The desired effect will be blood dripping over the usual website's content.

Here's the source, feel free to use or improve upon. I'm sure there are performance improvements that can be made. It fades to a sort of gray before it disappears, and I would have liked a browner black, but eh, close enough.

BloodEffect.as
Code:
package
{
	import flash.display.*;
	import flash.events.*;
	import flash.utils.*;
	import flash.geom.*;
	import flash.filters.ColorMatrixFilter;
	
	public class BloodEffect extends Sprite
	{
		private var timer:Timer;
		private var fadeTimer:Timer;
		private var drops:Array;
		private var bmd:BitmapData;
		private var bitmap:Bitmap;
		private var dropPath:Sprite;
		private var fadeColorMatrix:ColorMatrixFilter;
		private var clearBmd:BitmapData;
		private var clearBitmap:Bitmap;
		
		public function BloodEffect()
		{	
			// define the fading color matrix - reduce Red, subtract Alpha
			var matrix:Array = new Array();
			matrix = matrix.concat([.96, 0, 0, 0, 0]);
			matrix = matrix.concat([0, 1, 0, 0, 0]);
			matrix = matrix.concat([0, 0, 1, 0, 0]);
			matrix = matrix.concat([0, 0, 0, 1, -5]);
			
			fadeColorMatrix = new ColorMatrixFilter(matrix);
			
			// init the droplets
			drops = new Array();
			
			for (var i:Number = 0; i < 10; i++)
			{
				var s:Sprite = new Sprite();
				drops.push(s);
			}
			
			// create the BitmapData and Bitmap objects - made for 1280x1024 res
			bmd = new BitmapData(1280, 1024, true, 0x000000);
			bitmap = new Bitmap(bmd);
			addChild(bitmap);
			
			addEventListener(Event.ADDED_TO_STAGE, addedToStage);
		}
		
		public function addedToStage(e:Event):void
		{
			// draw the droplet path graphic
			dropPath = new Sprite();
			dropPath.graphics.beginFill(0xAA0000, 0.4)
			dropPath.graphics.drawCircle(0, 0, 5);
			dropPath.graphics.endFill();
			dropPath.graphics.beginFill(0xFFFFFF, .8);
			dropPath.graphics.drawCircle(-2, 0, 1.5);
			
			// draw blood droplets
			for each (var s:Sprite in drops)
			{
				s.graphics.beginFill(0xAA0000);
				s.graphics.drawCircle(0, 0, 7);
				s.graphics.endFill();
				s.graphics.beginFill(0xAA0000);
				s.graphics.moveTo(-7, 0);
				s.graphics.curveTo(-8, -8, -4, -16);
				s.graphics.curveTo(0, -20, 4, -16);
				s.graphics.curveTo(8, -8, 7, 0);
				s.graphics.endFill();
				
				var flare:Sprite = new Sprite();
				flare.graphics.beginGradientFill(GradientType.RADIAL, [0xCC0000, 0xCC0000], [1, 0], [0, 15]);
				flare.x = -3;
				flare.y = -4;
				flare.graphics.drawCircle(0, 0, 8);
				flare.graphics.endFill();
				s.addChild(flare);
			
				s.x = stage.stageWidth * Math.random();
				s.y = -80 * Math.random();
				addChild(s);
			}
			
			// init motion timer - fired every 50ms
			timer = new Timer(50);
			timer.addEventListener(TimerEvent.TIMER, onTick);
			timer.start();
			
			// init fade timer - fired every 1000ms
			fadeTimer = new Timer(1000);
			fadeTimer.addEventListener(TimerEvent.TIMER, onFadeTick);
			fadeTimer.start();
		}
		
		public function onTick(e:TimerEvent):void
		{
			for each (var s:Sprite in drops)
			{
				// move the droplet down 2px
				s.y += 2;
				
				// copy the path graphic to the BitmapData
				bmd.draw(dropPath, s.transform.matrix);
				
				// send the droplet back to the top if its off the screen
				if (s.y > stage.stageHeight + 30)
				{
					s.x = stage.stageWidth * Math.random();
					s.y = -80 * Math.random();
				}
			}
		}
		
		public function onFadeTick(e:TimerEvent):void
		{
			// apply the color matrix filter
			bmd.applyFilter(bmd, new Rectangle(0, 0, 1280, 1024), new Point(0, 0), fadeColorMatrix);
		}
	}
}
Advocate is offline   Reply With Quote
Old 10-08-2007, 12:46 PM   #2
janeos
Registered User
 
Join Date: Aug 2007
Posts: 2
Default Bloos.as

Hi advocate,
how do u implement this as into a movie clip.
thanks
janeos is offline   Reply With Quote
Old 10-08-2007, 02:38 PM   #3
nikefido
Registered User
 
Join Date: Sep 2007
Posts: 215
Default

Quote:
Originally Posted by janeos View Post
Hi advocate,
how do u implement this as into a movie clip.
thanks
I imagine in your document class file you do something like this:
ActionScript Code:
var myBlood:BloodEffect = new BloodEffect(); addChild(myBlood)



tried it out myself, it works. cool stuff.

Last edited by nikefido; 10-08-2007 at 02:45 PM.
nikefido is offline   Reply With Quote
Old 10-08-2007, 04:30 PM   #4
Advocate
eye heart ay ess three
 
Join Date: Feb 2005
Posts: 38
Default

nikefidos right on.

One thing I did not expect is that I can't click hyperlinks beneath the effect unfortunately (as the whole view is an bitmap image, though its transparent).

Anyone know a way around this? or am I going to have to get tricky with only having bitmap objects existing where the droplets' paths are.
Advocate is offline   Reply With Quote
Old 10-11-2007, 12:58 AM   #5
Advocate
eye heart ay ess three
 
Join Date: Feb 2005
Posts: 38
Default

Ok, I solved my problem by turning 1 huge bitmap into a smaller bitmap for each dripping blood path. This allows the user to click on stuff underneath the flash (mostly, more on this below...). It is also much faster and uses less CPU. For times sake, I got a little hacky so it may not be totally clear what its doing.

Code:
package
{
	import flash.display.*;
	import flash.events.*;
	import flash.utils.*;
	import flash.geom.*;
	import flash.filters.ColorMatrixFilter;
	
	public class BloodEffect extends Sprite
	{
		private var timer:Timer;
		private var fadeTimer:Timer;
		private var drops:Array;
		private var oldPaths:Array;
		private var bmd:BitmapData;
		private var bitmap:Bitmap;
		private var dropPath:Sprite;
		private var fadeColorMatrix:ColorMatrixFilter;
		
		private var dropPathRect:Rectangle = new Rectangle(0, 0, 10, 1024);
		private var dropPathPoint:Point = new Point(0, 0);
		
		private var transBD:BitmapData = new BitmapData(10, 1024, true, 0x000000);
		
		public function BloodEffect()
		{	
			// define the fading color matrix - reduce Red, subtract Alpha
			var matrix:Array = new Array();
			matrix = matrix.concat([.96, 0, 0, 0, 0]);
			matrix = matrix.concat([0, 1, 0, 0, 0]);
			matrix = matrix.concat([0, 0, 1, 0, 0]);
			matrix = matrix.concat([0, 0, 0, 1, -5]);
			
			fadeColorMatrix = new ColorMatrixFilter(matrix);
			
			// init the droplets
			drops = new Array();
			
			for (var i:Number = 0; i < 10; i++)
			{
				var s:Sprite = new Sprite();
				var bd:BitmapData = new BitmapData(10, 1024, true, 0x000000);
				var b:Bitmap = new Bitmap(bd);

				drops.push([s, bd, b]);
			}
			
			oldPaths = new Array();
			
			addEventListener(Event.ADDED_TO_STAGE, addedToStage);
		}
		
		public function addedToStage(e:Event):void
		{
			// draw the droplet path graphic
			dropPath = new Sprite();
			dropPath.graphics.beginFill(0xAA0000, 0.4)
			dropPath.graphics.drawCircle(0, 0, 5);
			dropPath.graphics.endFill();
			dropPath.graphics.beginFill(0xFFFFFF, .8);
			dropPath.graphics.drawCircle(-2, 0, 1.5);
			
			// draw blood droplets
			for each (var array:Array in drops)
			{
				var s:Sprite = array[0] as Sprite;
				var bd:BitmapData = array[1] as BitmapData;
				var b:Bitmap = array[2] as Bitmap;
				
				s.graphics.beginFill(0xAA0000);
				s.graphics.drawCircle(0, 0, 7);
				s.graphics.endFill();
				s.graphics.beginFill(0xAA0000);
				s.graphics.moveTo(-7, 0);
				s.graphics.curveTo(-8, -8, -4, -16);
				s.graphics.curveTo(0, -20, 4, -16);
				s.graphics.curveTo(8, -8, 7, 0);
				s.graphics.endFill();
				
				var flare:Sprite = new Sprite();
				flare.graphics.beginGradientFill(GradientType.RADIAL, [0xCC0000, 0xCC0000], [1, 0], [0, 15]);
				flare.x = -3;
				flare.y = -4;
				flare.graphics.drawCircle(0, 0, 8);
				flare.graphics.endFill();
				s.addChild(flare);
			
				s.x = stage.stageWidth * Math.random();
				s.y = -80 * Math.random();
				addChild(s);
				
				b.x = s.x - 5;
				addChildAt(b, this.getChildIndex(s));
			}
			
			// init motion timer - fired every 50ms
			timer = new Timer(50);
			timer.addEventListener(TimerEvent.TIMER, onTick);
			timer.start();
			
			// init fade timer - fired every 1000ms
			fadeTimer = new Timer(1000);
			fadeTimer.addEventListener(TimerEvent.TIMER, onFadeTick);
			fadeTimer.start();
		}
		
		public function onTick(e:TimerEvent):void
		{
			for each (var array:Array in drops)
			{
				var s:Sprite = array[0] as Sprite;
				var bd:BitmapData = array[1] as BitmapData;
				// move the droplet down 2px
				s.y += 2;
				
				var matrix:Matrix = new Matrix(1, 0, 0, 1, 5, s.y);
				
				// copy the path graphic to this BitmapData obj
				bd.draw(dropPath, matrix);
				
				// send the droplet back to the top if its off the screen
				if (s.y > stage.stageHeight + 30)
				{
					s.x = stage.stageWidth * Math.random();
					s.y = -80 * Math.random();
					makeNewPath(array);
				}
			}
		}
		
		public function makeNewPath(array:Array):void
		{
			var s:Sprite = array[0] as Sprite;
			var bd:BitmapData = array[1] as BitmapData;
			var b:Bitmap = array[2] as Bitmap;
			
			
			// send the drop back to the top layer
			setChildIndex(s, numChildren - 1);
			
			// push the path to the 'old paths' list
			oldPaths.push([bd, b, 0]);
			
			
			// make a fresh path BitmapData and Bitmap obj
			var bd2:BitmapData = new BitmapData(10, 1024, true, 0x000000);
			var b2:Bitmap = new Bitmap(bd2);
			
			// replace the old BitmapData and Bitmap objs (path graphics) with the new ones
			b2.x = s.x - 5;
			addChildAt(b2, this.getChildIndex(s) - 1);
			array[1] = bd2;
			array[2] = b2;
		}
		
		public function onFadeTick(e:TimerEvent):void
		{
			// apply the color matrix filter
			for each (var array:Array in drops)
			{
				var s:Sprite = array[0] as Sprite;
				var bd:BitmapData = array[1] as BitmapData;
				bd.applyFilter(bd, dropPathRect, dropPathPoint, fadeColorMatrix);
			}
			
			// decay the old paths for some time, and cleanup - super hacky
			for (var i:Number = 0; i < oldPaths.length; i++)
			{
				var bd2:BitmapData = oldPaths[i][0] as BitmapData;
				var b2:Bitmap = oldPaths[i][1] as Bitmap;
				var t:Number = oldPaths[i][2] as Number;
				
				if (t > 30)
				{
					removeChild(b2);
					bd2.dispose();
					oldPaths.splice(i, 1);
				}
				else
				{
					bd2.applyFilter(bd2, dropPathRect, dropPathPoint, fadeColorMatrix);
					oldPaths[i][2]++;
				}
			}
		}
	}
}
Again, I think this serves as a good example of BitmapData finagling.

HOWEVER, The trick with a 100%x100% div tag on top of a web page only seems to work correctly in IE. The effect does not work in Firefox or Safari (Even though there is nothing in a region in the movie, the user can not click on the webpage content beneath the div). Everyone proclaims the awesomeness of Firefox from their rooftops, but it doesn't really seem to do anything I want it to do when it comes to embedding flash in a page (resizing a 'No Scale' movie, using div z-depth layering in this case, etc...).

Anyone know how to get Firefox to work in this regard?
Advocate is offline   Reply With Quote
Reply


Thread Tools
Display Modes Rate This Thread
Rate This Thread:

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off

Forum Jump

Similar Threads
Thread Thread Starter Forum Replies Last Post
Fade to White Picture Gallery effect smegedd Animation and Effects 8 07-31-2009 10:35 AM
BitmapData fire effect abeall Flash 8 General Questions 0 12-15-2006 12:57 AM
blood effect gregsmith ActionScript 2.0 2 03-08-2005 03:55 PM
Wormhole tunnel effect? binar ActionScript 1.0 (and below) 4 08-07-2002 08:33 AM


All times are GMT. The time now is 12:21 PM.

///
Follow actionscriptorg on Twitter

 


Powered by vBulletin® Version 3.8.5
Copyright ©2000 - 2014, Jelsoft Enterprises Ltd.
Ad Management plugin by RedTyger
Copyright 2000-2013 ActionScript.org. All Rights Reserved.
Your use of this site is subject to our Privacy Policy and Terms of Use.