Actionscript 3 - as3 Lightning / Thunderbolt / Electric discharge Class

BitmapData, Math, actionscript 3, algorithms, classes, fun, morphing, perlinNoise, simulation

Finally here we come!

Yup, sry for the delay, I’ve had a lot of work recently.

I have prepared three demos and a publishable (but far from perfect and not yet documented) class. The demos are FLA based… you can find the timeline code to assemble the demos at the bottom of the post. I’ll publish some documentation in the next days, so until then just look at the demos’ code to unserstand the basic of the class usage.

Download Lightning classes

Demo N°1:
This demo shows the two different behaviours the class can mimic: Electric discharge/beam or lightning. Drag the ball near or far to the coil to see different behaviors.


Click to start

Demo N°2:
This demos show the maxLength and maxLengthVary properties in action.
Bring the fingers near to the plug to have continuos electricity. Bringing the hand far from the plug lowers the discharge probability. Reaching the max distance simply disables it.


Click to start

Demo N°3:
This demo is a good reason for the publishing delay :P

A nice sandbox to play with (some of) the properties.
The class is recursive to create children so many properties have also a decay twin property which rule how the property is passed to children.
As instance if you set a childrenMaxCount = 6 to the main Lightning instance it will have a maximum of 6 direct children. Its children will have a childrenMaxCount value which depends on the main instance childrenMaxCount and childrenMaxCountDecay.
So if you set childrenMaxCount = 6 and childrenMaxCountDecay = .5 the children of the main instance will have childrenMaxCount = 3.
If you set childrenMaxCount = 6 and childrenMaxCountDecay = 0 the children of the main instance will have childrenMaxCount = 6 (no decay).

This value can be very useful to optimize the speed of execution cause smaller branches don’t need many children or many steps of detail.


Click to start

Ok, I’m too tired to write more. I’ll publish some documentation in the next days.
Feel free to ask everything question you can have in the comments, and as usual if you like this stuff scream it in the comments!

Demos’ code after the break.

Demos code is just timeline code to instance and pilot the lightning class… and very untidy! Please don’t blame it :D

Demo N°1:

import com.oaxoa.fx.Lightning;
import com.oaxoa.fx.LightningFadeType;
 
const cx:uint=360;
const cy:uint=320;
 
var color:uint=0xffffff;
var ll:Lightning=new Lightning(color, 2);
ll.blendMode=BlendMode.ADD;
ll.childrenDetachedEnd=true;
ll.childrenLifeSpanMin=.1;
ll.childrenLifeSpanMax=2;
ll.childrenMaxCount=4;
ll.childrenMaxCountDecay=.5;
ll.steps=150;
ll.alphaFadeType=LightningFadeType.TIP_TO_END;
 
ball.useHandCursor=ball.buttonMode=true;
dot1.mouseEnabled=dot2.mouseEnabled=false;
dot1.alpha=.75;
 
var glow:GlowFilter=new GlowFilter();
glow.color=color;
glow.strength=3.5;
glow.quality=3;
glow.blurX=glow.blurY=10;
ll.filters=dot1.filters=dot2.filters=[glow];
addChild(ll);
 
ll.childrenProbability=.3;
 
var p:Point=new Point();
randomizePoint();
function randomizePoint():void {
	var angle:Number=-Math.random()*Math.PI;
	var dist:Number=160+Math.random()*180;
	p.x=cx+Math.cos(angle)*dist;
	p.y=cy+Math.sin(angle)*dist;
}
 
addEventListener(Event.ENTER_FRAME, onframe);
function onframe(event:Event):void {
 
	var rnd:Number=Math.random();
	if(rnd<.05) randomizePoint();
	var dx:Number=cx-ball.x;
	var dy:Number=cy-ball.y;
	var d:Number=Math.sqrt(dx*dx+dy*dy);
	if(d<310) {
		dot2.visible=true;
		if(ll.childrenDetachedEnd) {
			ll.childrenDetachedEnd=false;
			ll.alphaFadeType=LightningFadeType.GENERATION;
			ll.killAllChildren();
		}
 
		ll.endX=dot2.x=ball.x;
		ll.endY=dot2.y=ball.y;
	} else {
		dot2.visible=false;
		if(!ll.childrenDetachedEnd) {
			ll.childrenDetachedEnd=true;
			ll.alphaFadeType=LightningFadeType.TIP_TO_END;
			ll.killAllChildren();
		}
		ll.endX=p.x;
		ll.endY=p.y;
	}
	var ddx:Number=cx-ll.endX;
	var ddy:Number=cy-ll.endY;
	var aangle:Number=Math.atan2(ddy, ddx);
	ll.startX=cx-Math.cos(aangle)*80;
	dot1.scaleX=Math.sin(aangle);
	ll.startY=cy;
	dot1.x=ll.startX;
	dot1.y=ll.startY;
	ll.update();
}
 
ball.addEventListener(MouseEvent.MOUSE_DOWN, onmdown);
function onmdown(event:MouseEvent):void {
	ball.startDrag();
}
ball.addEventListener(MouseEvent.MOUSE_UP, onmup);
function onmup(event:MouseEvent):void {
	ball.stopDrag();
}

Demo N°2:

import com.oaxoa.fx.Lightning;
import com.oaxoa.fx.LightningFadeType;
 
setChildIndex(fingers, 2);
 
var iy:Number=fingers.y;
addEventListener(MouseEvent.MOUSE_MOVE, onmove);
 
fingers.x=fingers.y/2.5-10;
 
function updatePositions():void {
	ll.endX=fingers.x+fingers.dot1.x;
	ll.endY=fingers.y+fingers.dot1.y;
	ll2.endX=fingers.x+fingers.dot2.x;
	ll2.endY=fingers.y+fingers.dot2.y;
}
 
function onmove(event:MouseEvent):void {
	fingers.y=mouseY-150;
	if(fingers.y<iy) fingers.y=iy;
	if(fingers.y>320) fingers.y=320;
	fingers.x=fingers.y/2.5-10;
	updatePositions();
	event.updateAfterEvent();
}
addEventListener(Event.ENTER_FRAME, onframe);
function onframe(event:Event):void {
	ll.update();
	ll2.update();
}
 
var color:uint=0xddeeff;
var ll:Lightning=new Lightning(color, 2);
var ll2:Lightning=new Lightning(color, 2);
ll.blendMode=ll2.blendMode=BlendMode.ADD;
ll.childrenProbability=ll2.childrenProbability=.5;
ll.childrenLifeSpanMin=ll2.childrenLifeSpanMin=.1;
ll.childrenLifeSpanMax=ll2.childrenLifeSpanMax=2;
ll.maxLength=ll2.maxLength=50;
ll.maxLengthVary=ll2.maxLengthVary=200;
 
ll.startX=dot3.x;
ll.startY=dot3.y;
ll2.startX=dot4.x;
ll2.startY=dot4.y;
 
var glow:GlowFilter=new GlowFilter();
glow.color=color;
glow.strength=3.5;
glow.quality=3;
glow.blurX=glow.blurY=10;
ll.filters=ll2.filters=[glow];
addChild(ll);
addChild(ll2);
 
updatePositions();

Demo N°3:
(The ugliest bunch of random code lines ever written :D)

import com.oaxoa.fx.Lightning;
import com.oaxoa.fx.LightningFadeType;
import com.oaxoa.components.ToolTip;
import fl.controls.Button;
import fl.data.DataProvider;
 
import fl.events.SliderEvent;
var color:uint=0xffffff;
var ll:Lightning=new Lightning(color, 2);
ll.blendMode=BlendMode.ADD;
 
var glow:GlowFilter=new GlowFilter();
glow.color=color;
glow.strength=4;
glow.quality=3;
glow.blurX=glow.blurY=10;
ll.filters=[glow];
addChild(ll);
ll.startX=cross1.x;
ll.startY=cross1.y;
 
ll.endX=cross2.x;
ll.endY=cross2.y;
 
setChildIndex(ll,0);
 
ll.childrenMaxGenerations=3;
ll.childrenMaxCountDecay=.5;
 
addEventListener(Event.ENTER_FRAME, onframe);
function onframe(event:Event):void {
	ll.startX=cross1.x;
	ll.startY=cross1.y;
 
	ll.endX=cross2.x;
	ll.endY=cross2.y;
	ll.update();
	updateCircles();
}
 
import com.oaxoa.components.FrameRater;
var fr:FrameRater=new FrameRater(0xffffff, true);
addChild(fr);
 
var ttip:ToolTip=new ToolTip();
addChild(ttip);
 
var tfmt:TextFormat=new TextFormat("_sans", 11, 0xffffff);
 
cb0.addItem({label:"Choose a preset", value:0});
cb0.addItem({label:"Fast discharge", value:1});
cb0.addItem({label:"Fast discharge (Max length + max length variation)", value:2});
cb0.addItem({label:"Fast discharge (slow-motion)", value:3});
cb0.addItem({label:"Moving Thunderbolt", value:4});
cb0.addItem({label:"Moving Thunderbolt (Max length + max length variation)", value:5});
cb0.selectedIndex=0;
cb0.addEventListener(Event.CHANGE, oncb);
cb0.textField.setStyle("textFormat", tfmt);
cb0.dropdown.setRendererStyle("textFormat", tfmt);
 
cb1.addItem({label:"Discharge", value:false});
cb1.addItem({label:"Lightning (detached end)", value:true});
cb1.selectedIndex=1;
cb1.addEventListener(Event.CHANGE, oncb);
cb1.textField.setStyle("textFormat", tfmt);
cb1.dropdown.setRendererStyle("textFormat", tfmt);
 
cb2.addItem({label:"None", value:LightningFadeType.NONE});
cb2.addItem({label:"Generation", value:LightningFadeType.GENERATION});
cb2.addItem({label:"Tip to end", value:LightningFadeType.TIP_TO_END});
cb2.selectedIndex=2;
cb2.addEventListener(Event.CHANGE, oncb);
cb2.textField.setStyle("textFormat", tfmt);
cb2.dropdown.setRendererStyle("textFormat", tfmt);
 
cb3.addItem({label:"None", value:LightningFadeType.NONE});
cb3.addItem({label:"Generation", value:LightningFadeType.GENERATION});
cb3.addItem({label:"Tip to end", value:LightningFadeType.TIP_TO_END});
cb3.selectedIndex=2;
cb3.addEventListener(Event.CHANGE, oncb);
cb3.textField.setStyle("textFormat", tfmt);
cb3.dropdown.setRendererStyle("textFormat", tfmt);
 
function oncb(event:Event):void {
	var t:ComboBox=event.currentTarget as ComboBox;
	switch(t) {
		case cb0:
			setPreset(t.selectedItem.value);
			break;
		case cb1:
			ll.childrenDetachedEnd=t.selectedItem.value;
			ll.killAllChildren();
			break;
		case cb2:
			ll.alphaFadeType=t.selectedItem.value;
			ll.killAllChildren();
			break;
		case cb3:
			ll.thicknessFadeType=t.selectedItem.value;
			ll.killAllChildren();
			break;
	}
}
 
 
slider.addEventListener(SliderEvent.CHANGE, onslider);
slider2.addEventListener(SliderEvent.CHANGE, onslider);
slider3.addEventListener(SliderEvent.CHANGE, onslider);
slider4.addEventListener(SliderEvent.CHANGE, onslider);
slider5.addEventListener(SliderEvent.CHANGE, onslider);
slider6.addEventListener(SliderEvent.CHANGE, onslider);
slider7.addEventListener(SliderEvent.CHANGE, onslider);
slider8.addEventListener(SliderEvent.CHANGE, onslider);
slider9.addEventListener(SliderEvent.CHANGE, onslider);
slider10.addEventListener(SliderEvent.CHANGE, onslider);
slider11.addEventListener(SliderEvent.CHANGE, onslider);
slider12.addEventListener(SliderEvent.CHANGE, onslider);
slider13.addEventListener(SliderEvent.CHANGE, onslider);
function onslider(event:SliderEvent):void {
	var t:Slider=event.currentTarget as Slider;
	ttip.show(t.value.toString());
	ttip.y=t.y-30;
	switch(t) {
		case slider:
			ll.smoothPercentage=t.value;
			break;
		case slider2:
			ll.childrenAngleVariation=t.value;
			break;
		case slider3:
			ll.childrenMaxCount=t.value;
			break;
		case slider4:
			ll.wavelength=t.value;
			break;
		case slider5:
			ll.amplitude=t.value;
			break;
		case slider6:
			ll.speed=t.value;
			break;
		case slider7:
			ll.thickness=t.value;
			ll.killAllChildren();
			break;
		case slider8:
			ll.maxLength=t.value;
			break;
		case slider9:
			ll.maxLengthVary=t.value;
			break;
		case slider10:
			ll.childrenProbability=t.value;
			ll.killAllChildren();
			break;
		case slider11:
			ll.childrenLifeSpanMin=t.value;
			ll.killAllChildren();
			if(t.value>slider12.value) slider12.value=t.value;
			break;
		case slider12:
			ll.childrenLifeSpanMax=t.value;
			ll.killAllChildren();
			slider11.visible=t.value!=0;
			break;
		case slider13:
			ll.steps=t.value;
			ll.killAllChildren();
			break;
	}
	ll.render();
}
 
function setPreset(n:uint):void {
	switch(n) {
		// fast discharge
		case 1:
			ll.childrenLifeSpanMin=1;
			ll.childrenLifeSpanMax=3;
			ll.childrenProbability=1;
			ll.childrenMaxGenerations=3;
			ll.childrenMaxCount=4;
			ll.childrenAngleVariation=110;
			ll.thickness=2;
			ll.steps=100;
 
			ll.smoothPercentage=50;
			ll.wavelength=.3;
			ll.amplitude=.5;
			ll.speed=.7;
			ll.maxLength=0;
			ll.maxLengthVary=0;
 
			ll.childrenDetachedEnd=false;
			cb1.selectedIndex=0;
			ll.alphaFadeType=LightningFadeType.GENERATION;
			cb2.selectedIndex=1;
			ll.thicknessFadeType=LightningFadeType.NONE;
			cb3.selectedIndex=0;
 
			break;
		// fast discharge (with max length+variation)
		case 2:
			ll.childrenLifeSpanMin=1;
			ll.childrenLifeSpanMax=3;
			ll.childrenProbability=1;
			ll.childrenMaxGenerations=3;
			ll.childrenMaxCount=4;
			ll.childrenAngleVariation=110;
			ll.thickness=2;
			ll.steps=100;
 
			ll.smoothPercentage=50;
			ll.wavelength=.3;
			ll.amplitude=.5;
			ll.speed=.7;
			ll.maxLength=440;
			ll.maxLengthVary=75;
 
			ll.childrenDetachedEnd=false;
			cb1.selectedIndex=0;
			ll.alphaFadeType=LightningFadeType.GENERATION;
			cb2.selectedIndex=1;
			ll.thicknessFadeType=LightningFadeType.NONE;
			cb3.selectedIndex=0;
 
			break;
		// fast discharge slowmo
		case 3:
			ll.childrenLifeSpanMin=1;
			ll.childrenLifeSpanMax=3;
			ll.childrenProbability=1;
			ll.childrenMaxGenerations=3;
			ll.childrenMaxCount=4;
			ll.childrenAngleVariation=110;
			ll.thickness=2;
			ll.steps=100;
 
			ll.smoothPercentage=50;
			ll.wavelength=.3;
			ll.amplitude=.5;
			ll.speed=.1;
			ll.maxLength=0;
			ll.maxLengthVary=0;
 
			ll.childrenDetachedEnd=false;
			cb1.selectedIndex=0;
			ll.alphaFadeType=LightningFadeType.GENERATION;
			cb2.selectedIndex=1;
			ll.thicknessFadeType=LightningFadeType.NONE;
			cb3.selectedIndex=0;
 
			break;
		// moving thumnder
		case 4:
			ll.childrenLifeSpanMin=.1;
			ll.childrenLifeSpanMax=2;
			ll.childrenProbability=1;
			ll.childrenMaxGenerations=3;
			ll.childrenMaxCount=4;
			ll.childrenAngleVariation=130;
			ll.thickness=3;
			ll.steps=100;
 
			ll.smoothPercentage=50;
			ll.wavelength=.3;
			ll.amplitude=.5;
			ll.speed=1;
			ll.maxLength=0;
			ll.maxLengthVary=0;
 
			ll.childrenDetachedEnd=true;
			cb1.selectedIndex=1;
			ll.alphaFadeType=LightningFadeType.TIP_TO_END;
			cb2.selectedIndex=2;
			ll.thicknessFadeType=LightningFadeType.GENERATION;
			cb3.selectedIndex=1;
 
			break;
		case 5:
			ll.childrenLifeSpanMin=.1;
			ll.childrenLifeSpanMax=2;
			ll.childrenProbability=1;
			ll.childrenMaxGenerations=3;
			ll.childrenMaxCount=4;
			ll.childrenAngleVariation=130;
			ll.thickness=3;
			ll.steps=100;
 
			ll.smoothPercentage=50;
			ll.wavelength=.3;
			ll.amplitude=.5;
			ll.speed=1;
			ll.maxLength=440;
			ll.maxLengthVary=75;
 
			ll.childrenDetachedEnd=true;
			cb1.selectedIndex=1;
			ll.alphaFadeType=LightningFadeType.TIP_TO_END;
			cb2.selectedIndex=2;
			ll.thicknessFadeType=LightningFadeType.GENERATION;
			cb3.selectedIndex=1;
 
			break;
	}
	ll.killAllChildren();
	updateSliders();
}
function updateSliders():void {
	slider.value=ll.smoothPercentage;
	slider2.value=ll.childrenAngleVariation;
	slider3.value=ll.childrenMaxCount;
	slider4.value=ll.wavelength;
	slider5.value=ll.amplitude;
	slider6.value=ll.speed;
	slider7.value=ll.thickness;
	slider8.value=ll.maxLength;
	slider9.value=ll.maxLengthVary;
	slider10.value=ll.childrenProbability;
	slider11.value=ll.childrenLifeSpanMin;
	slider12.value=ll.childrenLifeSpanMax;
	slider13.value=ll.steps;
}
///////////////////
 
var tf:TextFormat=new TextFormat();
tf.color=0xffffff;
 
cross1.addEventListener(MouseEvent.MOUSE_UP, onup);
cross1.addEventListener(MouseEvent.MOUSE_DOWN, ondown);
cross2.addEventListener(MouseEvent.MOUSE_UP, onup);
cross2.addEventListener(MouseEvent.MOUSE_DOWN, ondown);
cross1.buttonMode=cross2.buttonMode=cross1.useHandCursor=cross2.useHandCursor=true;
 
function ondown(event:MouseEvent):void {
	event.currentTarget.alpha=.2;
	event.currentTarget.startDrag();
}
function onup(event:MouseEvent):void {
	event.currentTarget.alpha=1;
	event.currentTarget.stopDrag();
}
var circles:Shape=new Shape();
addChildAt(circles, 0);
 
function updateCircles():void {
	circles.graphics.clear();
	if(ll.maxLength>0) {
		circles.graphics.lineStyle(6, 0xffffff, .3);
		circles.graphics.drawCircle(cross1.x, cross1.y, ll.maxLength);
		circles.graphics.lineStyle(2, 0xffffff, .4);
		circles.graphics.drawCircle(cross1.x, cross1.y, ll.maxLength+ll.maxLengthVary);
		var steps:uint=5;
		for(var i:uint=1; i<steps; i++) {
			circles.graphics.lineStyle(1, 0xffffff, .2);
			circles.graphics.beginFill(0xffffff, .025);
			circles.graphics.drawCircle(cross1.x, cross1.y, ll.maxLength+(ll.maxLengthVary/steps)*i);
			circles.graphics.endFill();
		}
	}
}
 
 
setPreset(1);

52 Responses

  1. ethan  •  July 28, 2009 @2:16 am

    hey! that looks like the kind of code i write!

    impressive work though Pierluigi

  2. katopz  •  July 28, 2009 @5:31 am

    thx! it’s coooooooooooool ever! i love it :D

  3. localToGlobal  •  July 28, 2009 @8:53 am

    really awesome! i like it…

  4. Yugi  •  July 28, 2009 @4:54 pm

    Very cool. Thanks for sharing the code :)

  5. Og2t  •  July 28, 2009 @5:56 pm

    Wow, it’s great, I loved the example with fingers :) Would be nice to add some synchronised sound fx (generated as well), wondering how difficult it would be?

  6. Badger Manufacture  •  July 29, 2009 @12:59 am

    Amazing effect!! It has way more features than I’d been guessing about too. Really good Panta, I can’t wait to experiement with your well organised code. :)

  7. Winney  •  July 30, 2009 @3:45 am

    Best lightning effect ever!! Many thanks!

  8. Vlad  •  July 31, 2009 @6:31 pm

    Very well done. I downloaded the classes and I’ll give it a very good look, but before I do it, I have a question: are you drawing it to a BitmapData object?

  9. Maha  •  July 31, 2009 @6:54 pm

    Wow…great to see an awesome AS3 blog! Loved the lightning!

  10. Denis_s  •  August 10, 2009 @7:17 pm

    Sweet lightning!!! Came in perfect for a project I’m working on.
    I’ll send a link once it’s working.

  11. Og2t  •  August 17, 2009 @3:42 pm

    Looks like someone had used your class already :)

    http://www.hellofromearth.net (adverts)

  12. Pierluigi Pesenti  •  August 17, 2009 @3:58 pm

    WOA! Super cool!!! :)

  13. [...] View Tutorial // [...]

  14. Ruwan  •  August 21, 2009 @5:28 am

    Nice effect. Thank you for sharing.

  15. Jonno  •  August 21, 2009 @11:29 am

    Anyone have some good sound for this?

  16. Deepin3000  •  August 21, 2009 @4:04 pm

    wonderful. it’s a great work!

  17. TS  •  August 25, 2009 @5:54 pm

    omg it’s damn cool, thanks for sharing!

  18. David5  •  August 25, 2009 @10:24 pm

    Cool effect!

  19. Denis_s  •  September 3, 2009 @4:18 pm

    I used it here. go to ’song list creator’ and you’ll see it in step 2
    http://www.gogurt.com

    thank you for sharing your source code!

  20. Pierluigi Pesenti  •  September 3, 2009 @6:44 pm

    Wow! Very nice application, and nice implementation too!! ;-)

  21. hai  •  September 10, 2009 @11:28 am

    so cool.

  22. paul  •  September 10, 2009 @5:51 pm

    hi, looks amazing!!
    but i cant get the demo’s to work..
    could you share your fla’s? please
    i would love to use this for my next short movie.
    thanks !

  23. Pierluigi Pesenti  •  September 11, 2009 @7:18 am

    hi Paul, it’s not about the fla. It contains only the code snippet I posted to import and instance the main class. Did you download and imported the class?
    Could you post any error you receive from the compiler?
    Bye

  24. paul  •  September 11, 2009 @12:24 pm

    ok. for example demo 2. i make a fla, add a document class, copy your demo code in there. i make fingers, dot1, dot2 movieclip symbols. add them to the stage even.
    then i run it. and i get errors regarding events and filters, so i import those. but then i get other errors. just one hopeless mess i get myself in.
    i must be missing something silly. you probably have an easy way to do it. but i cant figure it out.

    thanks for taking your time to help, much appreciated

  25. Pierluigi Pesenti  •  September 11, 2009 @1:50 pm

    No problem at all. Could you up your fla somewhere to let me have a look?
    Cheers

  26. paul  •  September 11, 2009 @5:42 pm

    finally i did get it to work. ^^ this is my code (stripped down to a minimum) in the document class.
    sorry to spam your blog with it.
    but i’m still wondering how you do it. it should be possible to copy/paste your demo-code and have it workable, right?


    package {
    import com.oaxoa.fx.Lightning;
    import com.oaxoa.fx.LightningFadeType;
    import flash.events.*;
    import flash.display.*;
    public class LightningFX2 extends MovieClip {
    var ll:Lightning;
    public function LightningFX2(){
    stage.addEventListener(MouseEvent.MOUSE_MOVE, onmove);
    addEventListener(Event.ENTER_FRAME, onframe);
    ll = new Lightning(0xFF6677, 2);
    addChild(ll);
    updatePositions();
    }
    function updatePositions():void {
    ll.endX = mouseX;
    ll.endY = mouseY;
    }
    function onmove(event:MouseEvent):void {
    updatePositions();
    }
    function onframe(event:Event):void {
    ll.update();
    }
    };
    };

  27. magno  •  September 18, 2009 @1:04 pm

    how did you do that can you publish a tutorial step by step please i just need it.

  28. Pierluigi Pesenti  •  September 18, 2009 @1:30 pm

    hey mango, there’s a full downloadable class, there are 3 examples with the relative source code, there are two previous posts explaining the logic behind this… I think I couldn’t explain it more :)

  29. lianrb  •  September 21, 2009 @1:44 am

    cool………

  30. Raghuanth  •  September 21, 2009 @8:59 am

    ok

  31. oliwen  •  September 27, 2009 @8:44 am

    Thanks!Cool effect!

  32. icefirefdp  •  October 14, 2009 @11:36 am

    awesome that’s very cool, it make me excited.i had copied your codes to flex builder and run it certainly change code littlely, i am researching your code,but i don’t understand some logic,please comment its logic the following is i dont understand, thank your for sharing your code.
    soff=(sbd.getPixel(i, 0)-0×808080)/0xffffff*len*multi2;
    soffx=Math.sin(angle)*soff;
    soffy=Math.cos(angle)*soff;

    boff=(bbd.getPixel(i, 0)-0×808080)/0xffffff*len*amplitude;
    boffx=Math.sin(angle)*boff;
    boffy=Math.cos(angle)*boff;

    tx=startX+dx/(steps-1)*i+soffx+boffx;
    ty=startY+dy/(steps-1)*i-soffy-boffy;

    thank you for writing back mail: icefirefdp@163.com

  33. Pierluigi Pesenti  •  October 14, 2009 @11:56 am

    There are two displacements to achieve the effect a small one (every var beginning with “s” and a big one “b”).

    /* small offset is calculated by getting pixel value from the small perlinNoise bitmapData (sbd) - medium grey (0×808080) so the value doesn’t range from 0 to 0xffffff but from -0×808080 to +0×808080 the normalized to -1 to +1 (dividing by 0xffffff) and multiplied for the length of the lightning (so is always proportioned when scaling it) and multiplied for the (fixed) multiplier (multi2).
    So all this is just to have a numeric value taken from the perlinNoised bitmapData*/
    soff=(sbd.getPixel(i, 0)-0×808080)/0xffffff*len*multi2;
    // the x offset is calculated upon the sin of the angle of the lightning * the small offset
    soffx=Math.sin(angle)*soff;
    // the same for the y using cosin
    soffy=Math.cos(angle)*soff;

    // do the same with the big offset except from that the big one is ruled by the amplitude parameter and not fixed.
    boff=(bbd.getPixel(i, 0)-0×808080)/0xffffff*len*amplitude;
    boffx=Math.sin(angle)*boff;
    boffy=Math.cos(angle)*boff;

    // finally the target X of the segment to draw is calculated starting from the beginning (startX) + the step length (dx/(steps-1) * i (and this would lead to a straight very normal line) the the small X offset and the big X offset are added to make the actual lightning.
    tx=startX+dx/(steps-1)*i+soffx+boffx;

    // same for the Y
    ty=startY+dy/(steps-1)*i-soffy-boffy;

    hope this helped :)

  34. tommy  •  October 20, 2009 @3:53 am

    Woo..It’s so cool

  35. facebook application development  •  October 26, 2009 @3:24 pm

    awesome, it may be copy to use after some editing.
    Thanks for your sharing.

  36. Pierluigi Pesenti  •  October 26, 2009 @3:55 pm

    You can use it freely, as every piece of code I share here :-)

  37. swfDude  •  October 27, 2009 @9:43 pm

    1st worked great…cool, 2nd notWork…argh, error says:
    TypeError: Error #1010: A term is undefined and has no properties.
    at lightning2_fla::MainTimeline/updatePositions()
    at lightning2_fla::MainTimeline/onmove()

    thanx for code/ and any hep

  38. Meeeesta  •  October 30, 2009 @11:52 am

    Wow. Totally blown away.

    I was looking for a way to create a background animation that consists of morphing lines that didn’t hammer a viewer’s CPU. This looks the part. The effect I’m after is here, but without the macro variations, you’ve probably seen it before in abstract vector backgrounds (http://www.shutterstock.com/results.mhtml#photo_id=39720274 for example), almost parallel lines that bend and move like a ribbon.

    Without waffling on, what book’s would you recommend as reference for this kind of work? Are there any that you’d recommend? Especially for a Maths monkey. I’m going to try and pick at this to get the solution I want (before I have a mental break down and do another tween animation lol).

    Most all thanks for the inspiration, it’s a real find when you discover someone with massive talent willing to share their knowledge and experiences.

  39. Pierluigi Pesenti  •  October 30, 2009 @1:16 pm

    If it is a background animation, and you don’t want to hammer the CPU, you should move a single line with the kin of smooth movement you want, and draw it to a bitmap at everyframe, then darken the bitmap a little at every frame so the old lines progressively disappears. For the movement I could suggest to have a 1px*height px bitmapdata with a slowly moving perlinNoise. Then you should read all the pixels (or better get the vector) and use those values to draw your line.

    About the book, I am sorry since I an not the one who reads a lot of books, I learned by dashing my head against the wall until it works :-P, sometimes I look for some math articles online (understanding a very small percentage of them :D).

    However try this: http://www.bit-101.com/blog/?p=2425
    I just bought it yesterday super discounted, not looked yet, but it seems promising.

    Thanks a lot for your appreciations.
    p.s.: You cannot come out with this… come back next week, since it’s quite interesting and we could try to do it together and then publish an article here ;)

  40. Meeeesta  •  October 30, 2009 @2:43 pm

    When I’m done unpicking what you’ve created and (if) I manage to get anything up and running (before I’m taken away by men in white coats) I’ll definitely drop you a line.

  41. Greg  •  November 5, 2009 @3:23 am

    SCREEEEEEEEEEEEEEEEAMING! *two thumbs up*
    How many walls did you broke with your head while making this? ;P

  42. [...] 项目地址猛击这里 [...]

  43. Milan  •  November 10, 2009 @5:18 am

    hey mate,
    just wondering in the first demo how i would go by setting the lightning to go between two mc’s, i cant figure out how to change the coordinates, it just seems to drag my mc up into the corner, i managed to connect one (mindmc) but the other (powMc2) will connect but be dragged up into the top of the stage? i just wanted the lightning effect to join 2 motionless mc’s
    heres ur code hacked up
    [CODE]
    import com.oaxoa.fx.Lightning;
    import com.oaxoa.fx.LightningFadeType;

    const cx:uint=660;
    const cy:uint=320;

    var color:uint=0xffffff;
    var ll:Lightning=new Lightning(color, 2);
    ll.blendMode=BlendMode.ADD;
    ll.childrenDetachedEnd=true;
    ll.childrenLifeSpanMin=.1;
    ll.childrenLifeSpanMax=2;
    ll.childrenMaxCount=4;
    ll.childrenMaxCountDecay=.5;
    ll.steps=150;
    ll.alphaFadeType=LightningFadeType.TIP_TO_END;

    var glow:GlowFilter=new GlowFilter();
    glow.color=color;
    glow.strength=5;
    glow.quality=3;
    glow.blurX=glow.blurY=10;
    ll.filters=powMc1.filters=powMc2.filters=[glow];
    addChild(ll);

    ll.childrenProbability=.3;

    addEventListener(Event.ENTER_FRAME, onframe);
    function onframe(event:Event):void {

    var rnd:Number=Math.random();
    var dx:Number=cx-mindmc.x;
    var dy:Number=cy-mindmc.y;
    var d:Number=Math.sqrt(dx*dx+dy*dy);
    if(d<280) {
    powMc2.visible=true;
    if(ll.childrenDetachedEnd) {
    ll.childrenDetachedEnd=false;
    ll.alphaFadeType=LightningFadeType.GENERATION;
    ll.killAllChildren();
    }
    ll.endX=powMc2.x=mindmc.x;
    ll.endY=powMc2.y=mindmc.y;
    } else {
    powMc2.visible=false;
    if(!ll.childrenDetachedEnd) {
    ll.childrenDetachedEnd=true;
    ll.killAllChildren();
    }

    }
    var ddx:Number=cx-ll.endX;
    var ddy:Number=cy-ll.endY;
    powMc2.x=ll.startX;
    powMc2.y=ll.startY;
    ll.update();
    }
    [/CODE]

    please help meeee!

  44. Jimmy  •  November 27, 2009 @7:58 am

    Can you sent me you Demo2 Fla file
    thank you very much!!!

    my Email:jimmy.light@gmail.com

  45. takopus  •  December 1, 2009 @3:59 am

    Perfect! Just perfect! Thank you!

  46. aDoubleSo  •  December 1, 2009 @1:36 pm

    hi,
    this is great…
    i tried to convert this to flex 3, but i can’t add the Lightning-Objekt to the stage.
    when i try “Application.application.addChild(l1);” i get an UIComponent-exception.
    can anybody help me please!?

    thanks
    aDouble

  47. Pierluigi Pesenti  •  December 1, 2009 @1:47 pm

    You cannot simply add a Sprite to the stage, wrap it into a UIComponent.

  48. aDoubleSo  •  December 1, 2009 @1:53 pm

    thanks, i tried this first, but now it works … first time i get an null-pointer-exception. mayby i forgot to init the UIComponent…

    thanks

  49. Yan  •  December 19, 2009 @6:27 pm

    Thanks for share your code,They’re really cool,and this’s a piece of news come form Chinese friend.I hope we will be a good friend.
    My msn account is yanxingyang@hotmail.com

  50. tenchiwang  •  January 21, 2010 @10:08 am

    Lightning is useful~
    Good to share with the ~ thanks ~ ^ ^

  51. _mark  •  January 26, 2010 @11:08 pm

    dood, awesome job on this lightning effect! i’ll definitely let you know if i use the class! now watching ur blog :D

Leave a Reply

Allowed tags: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>