Skip to content

Posts from the ‘Flash Platform’ Category

25
Jul
2007

Web Spinner Revealed

As promised, you can now download the code used for my web spinning projects. There is one fla, and four classes.

I made some modifications to Grant Skinner’s grid based proximity manager to take advantage of an IProximityDetectable interface. For a full explanation on how grid based proximity management works, check out Grant’s original post on the subject. The IProximityDetectable interface has only two methods:

interface IProximityDetectable {
public function getPosX():Number;
public function getPosY():Number;
}

As might be assumed, they retrieve the ‘x’ and ‘y’ position of an object. Why implement this? Well, the original ProximityManager used the _x and _y values of a MovieClip, but my spider web particles don’t actually have any MovieClips. Its just adjusting x and y values of an object in memory, and drawing lines to the new distance. The ProximityManager is used for drawing the lines between particles based on how close they are to each other.

So how do the particles move? Each onEnterFrame the ParticleManager calls the tick function for each particle.

public function tick():Void {
canvas.moveTo(x,y);
x += xVel;
y += yVel;

xVel *= drag;
yVel *= drag;

yVel += yGravity;
xVel += xGravity;

var f:Number = Math.abs(xVel) + Math.abs(yVel);
alpha -= f/__lifeSpan;
canvas.lineStyle(2, rgb, alpha);
canvas.lineTo(x,y);

if(alpha <= 0){
manager.removeSpark(this);
}

var n:Array = pm.getNeighbours(this);
var l:Number = n.length;
for(var i:Number = 0; i < l; i++){
canvas.lineStyle(1, rgb, alpha);
canvas.moveTo(x, y);
canvas.lineTo(n[i].getPosX(), n[i].getPosY());
}
}

Each particle starts out with random velocities for x and y. These velocities are added to the x and y position of the particle. Drag is applied to the velocities to slow them down. The drag is set to such a small value in this particular instance that it really doesn’t have much of an effect. Gravity along the x and y axis is then applied to the particle The gravity values are generated randomly when the particle is first created and unlike the velocities, has no baring on its parents value (in the instance of a branched particle). Since gravity is random, it may pull particles up, down, left or right. After all moving is done, the particle uses asks who its neighbors are and draws lines to them.

Speaking of branching, the ParticleManager does a probability calculation for each particle during the onEnterFrame which determines if a particle will branch. Each particle has a chance to branch, so growth can occur exponentially. To keep particles from branching too much, this calculation is ignored if the maximum number of particles has been reached (default to 40).

Once each particle has been moved and had its connections drawn, the entire image is drawn to a Bitmap and color/alpha adjusted to fade away slowly. All and all a pretty neat little effect.

I’d like to move this to AS3 eventually to see if I get crazy speed increases! I’ve put one last experiment below which allows you some control over different variables in the spider webs. Be careful when making adjustments… You can easily give your computer a heart attack.

No Comments
13
Jul
2007

Web Spinning Goodness II

Made a few small technical changes… May not be noticeable to most. In the previous example, each particle received a random Y axis based gravity. When gravity was negative, it forced the particle up, and positive gravity made it go down. I’ve also added an X axis based gravity to this example, increasing the curvature and randomness of the webs.

Read moreRead more

One Comment
12
Jul
2007

Web Spinning Goodness

Made this today at work. Click and hold to spin mad crazy webs.

Read moreRead more

No Comments
11
Jul
2007

BitmapData + Particles = Fireworks

Made this little app today while working with particles and bitmap data. It combines some of the work from Seb’s particle system, with Grant’s bitmap data used in Varicose-g. I’ll get to posting code examples as soon as I clean it up. Each click makes about a 100 particles, so if its running a bit slow, let me know. Enjoy!

No Comments
23
Jun
2007

Cartoon Smoke Using Particle Systems

Earlier this week I had the pleasure of attending my first FlashBelt conference and had a great time! If you ever get the opportunity to attend, FlashBelt is definitely worth it!

Seb Lee-Delisle gave a great presentation on Particles for the Non-Physicist. I have worked a bit with particles on my own, but never really understood the possibilities of what a particle system could do. Seb pointed out all the spots on the Plug-in Media website that have particles – way more systems going on there than I expected.

I had a chance to speak with Seb after the session as to how he made the merging borders around the cartoon smoke effects and dripping ooze (from the Plug-in Media main page). He said you needed to have multiple layers of particles. So, when I got home, I downloaded the demonstration files and got to work. Below you can see the results. Its a really cool effect.

The important thing when creating the two layers of particles, is that each layers of particles must have matching properties – only the linked movieclip is changed. You can see that the background particle is darker and larger than the foreground, but they move and grow in unison. This allows the background particle to be the border around the lighter front particles and merge together seamlessly.

My next step is to figure out how to use a particle system to make a MovieClip appear on fire. If you’ve seen my fire effect code, it uses a computationally-heavy method of duplicating, distorting, coloring and fading the MovieClip. I think the particle-system effects could be used to create the fire instead.

One Comment
2
Apr
2007

Flickr & Flex

As I said in my previous post, I’ve started working in Flex! So far I have been very impressed! Creating dynamic content and application designs is much more natural and faster. Although I miss the timeline, I question whether a pseudo-designer type such as myself would need Flash at all.
That being said, I’ll divulge some of the details of my first Flex component. For this project I was asked to create a Flex component using AS#, and quickly! I had a few neat ideas but decided to kill two birds with one stone and design a lightbox/gallery type component I could use on my art website.

I’ve never been great at designing databases, and don’t reinvent the wheel when I don’t have to. Yahoo’s Flickr service provided all the tools I needed for managing a gallery: tags, dating, sets, and automatic resizing to multiple formats. Yahoo is also kind enough to give access to their Flickr API services so you can access image data from webservice calls which return XML.

Thanks to ActionScript 3′s new E4X extension, XML is easy. If you have ever tried parsing XML in AS2, you will be very happy with this addition!

The section of this project that I’m going to focus on for this post is the Flickr package I’ve been working on. I will admit that there are probably plenty of other AS3 classes that connect to Flickr, but part of the purpose of this project was to challenge myself and get some experience using webservicee (something we don’t get a to use a lot in e-Learning!).

The Flickr Package currently consists of four classes: FlickrImage, FlickrImageData, FlickrUserData and FlickrUserPhotosData. Each of these correlate to one or more Flickr webservice calls. For example, FlickrImageData takes in a picture id and returns almost all the information that is needed for that image, including title, date, user and the paths to the image sizes. I combined the two webservices because I honestly couldn’t see very many times when one wouldn’t need all the data.

Now one question I’m going to pose to the blogsphere is whether or not it is necessary, good or bad to recreate the variables passed in from the XML. For example, in the FlickrUserData class I have this bit of code:

private function onInfoXMLDataLoaded(event:Event):void {
var data:XML = XML(_urlLoaderInfo.data);
_userName = data.person.username;
_realName = data.person.realname;
_location = data.person.location;
_photosUrl = data.person.photosurl;
_profileUrl = data.person.profileurl;
_photosCount = data.person.photos.count;
_isLoadedInfo = true;
dispatchEvent(new Event(FlickrUserData.LOADED, true, true));
}

I’m just taking all the attributes and variables passed in from the XML and attaching them to hardcoded variables. Is this a good practice or does it waste memory and efficency? I would think that one could create getter methods that access the loaded XML directly, but how would these objects work when passed around? Or if one were to create a clone() function? I like creating the actual variables because its what I’m used to and makes sense, but am open to any discussion saying otherwise.

You’ll notice that the FlickrImageData contains just that, all the data, but doesn’t actually show anything to the user. The FlickrImageData class is simply a model class. The FlickrImage class extends the mx:Image class and is the View for the FlickrImageData. You could potentially use a FlickrImage component anywhere you would create a normal image. You simply pass it the Flickr Image ID and a size (if desired, it defaults to Original) and the FlickrImage class will grab all the necessary data and display the image! This is an example of the most popular design pattern in application development today, the Model View Control (MVC) design pattern.

No Comments
26
Mar
2007

Flexing My Flex Muscles

Now, for those who actually come and read my blog (I get a whopping 20 hits a day!) you may be wondering why the delay in posts… Don’t worry, this isn’t going to be one of those blogs that gets a few updates in the first few weeks then disappears into oblivion. I’ve been coding like crazy in Flex and trying to write my first component! Ok… make that components, because the main one I’m trying to create actually involves quite a few mini-components and classes built into it.

I’m trying to make an image viewer that connects to a users Flickr account, grabs 100 images or so, and displays them in a rotating circle, with the one selected displaying in the middle. The image selected will also magnify slightly, as well as the ones next to it (in a sort of Fish-Eye view but not quite that advanced at the moment). Well, I’ve gotten a good start, and having some 600+ lines of code written! It may not look like much, but you can see the of it start here.

A few things I’m having issues with… I can hear a COMPLETE event when the image is loaded, but for some reason the width/height/x/y values aren’t initalized yet. When the image is done loading, I want to move the Images so their registration point is actually in the center of the clip, not the top left corner, but without those values initialized when the image loads I’m at a loss! If anyone has suggestions on what I’m doing wrong, I’d love to hear them!

One Comment
14
Mar
2007

Writing the PreloadQueue

The e-Learning applications we develop at work are often used by employees out in the field. Not all of these employees have broadband connections, so figuring out ways to lessen the wait time for course distribution has been an on going battle. As our courses become more advanced, the file sizes often increase as well. This led me to develop the PreloadQueue (PQ) class which continues to pull content to the users computer while viewing other sections of the course.

The requirements of the PQ class where as follows:

  • It had to sort the Preloads based on priority
  • It had to be able to be cleared on request
  • Preloads must be able to be interrupted/stopped
  • Preloads must be able to ‘force’ load immediately – bypassing the queue
  • Preloads must be able to specify a target MovieClip in which to load

As a rule, I like to have only one item loading at a time. I also wanted the PQ to be accessed by any part of the application and make sure that everything was adding to the same queue. Making the PQ a Singleton object was the natural solution to all of these issues.

The PQ is tightly coupled with the PreloadItem, which stores all the information about the preload. It takes four parameters. The first parameter is the path to the SWF you want to load. The second is the target MovieClip in which to display upon completing the load. Next is the priority – the lower the number, the sooner the SWF will load. The final parameter is a special object I called the linkage (I realize now that this is probably a bad name for the variable as ‘linkage’ is associated with other parts of Flash development). The linkage is used to pass extra information from the events dispatched by the PQ. For example, we organize our courses into Volumes, Chapters and Pages. We sometimes want the first page of a volume to appear on the screen differently than subsequent pages. So to do this, our new PreloadItem would look something like this:

new PreloadItem("http://www.path.com/aSwf.swf", holder_mc, 0, {volume:"firstSwf"})

Now I would set my eventlisteners to check for the eventObject.preloadItem.linkage.volume variable and act accordingly.

Most of the time your preloaded items won’t need to display on the screen. Simply downloading in the background to the users computer is sufficient (caching). When this is the case, you need only pass the PreloadItem a path in the constructor. There is a chance that the users computer will delete the cached SWF before it is actually needed, but in any case the SWF will simply load again. In any case, you haven’t cost the user any time since had you not used the PQ to begin with, they would have had to sit through it anyways.
Since most content displayed on screen is placed into the same holder MovieClip, I didn’t want that MovieClip to disappear while loading the next item. So, rather than force the developer to create another holder MovieClip, you pass the Stage (or a suitable MovieClip) in the getInstance function. The PQ will then use this MovieClip to create ‘dummy clips’ to load background information into.

After instantiating the PQ, developers can add preloads to it by using a method like below:

__preloadQueue.addPreload(new PreloadItem("http://www.path.com/aSwf.swf", holder_mc);

This will add the PreloadItem and give it a default priority of 0. If the PQ is running (which by default it is), it will automatically start to load the item at the top of the queue (which was just added). Combining this technique with the use of a for loop or an XML file, you can easily have it preload an entire site.

But what if the user clicks a link in my site and I need to load a SWF immediately? You use the loadNow function. When the loadNow function is called, the PQ will check to see if something is already in the process of loading, stop it, and re-add it to the queue. (note that depending on the priority number of the preload, it may not be the next item to loaded if there are other items with the same priority number).

But what if the item currently be loading is the same SWF asking to loadNow? If that is the case the PQ will switch it to be treated as if it was originally called from a loadNow function. That way you don’t need to start the content downloading over again.

SWFs technically get loaded twice, once via the PQ and once by the PreloadItem. When the request is made to load it in the PreloadItem script, it will have already been cached on the users computer and will load instantly into the target MovieClip. Using a hookback, the PreloadItem then tells the PQ to dispatch events for download complete and init. This allows the developer to only listen to events from the PQ (which dispatches separate events for background preload items and preloadNows).

You can download all the files needed for the PreloadQueue from the downloads section. **Update 10/24/2010: Downloading PreloadQueue no longer available.**

No Comments
7
Mar
2007

Function Overloading & MovieClip Dimensions

Today at work I wrote a nifty little piece of code that I couldn’t believe we hadn’t written before… To center a MovieClip on a point regardless of its registration point. Until now we had never really needed a MovieClip to center like this, and always justified things to 0,0. I’m creating an application that creates a group of movieclips in a spiral formation from the center of 0,0. This meant that I would have to figure out a way to center it to its absolute center, not just to 0,0. I added the following function to my AdvancedMovieClip class (which I’ll upload eventually).

public function absoluteCenterTo(p1:Object, p2:Object):Object{
var xCenter:Number;
var yCenter:Number;
if(p1 instanceof MovieClip){
xCenter = p1._x;
yCenter = p1._y
} else {
xCenter = Number(p1);
yCenter = Number(p2);
}

var bounds:Object = getBounds(this);

var newXPosition:Number = xCenter - (((bounds.xMin + bounds.xMax)/2)*this._xscale)/100;
var newYPosition:Number = yCenter - (((bounds.yMin + bounds.yMax)/2)*this._yscale)/100;
if(isNaN(newXPosition) or isNaN(newYPosition)){
throw new Error("ERROR: Parameter does not result in a valid number");
} else {
var returnObj:Object = {x:newXPosition, y:newYPosition};
}
return returnObj;
}

If the function looks weird to you, its becuase I’ve used (a somewhat hack version of) function overloading. What this means, is you can pass different types of parameters into the same function (although in other languages like Java you actually have multiple functions with the same name) and the program will treat the function differently based on those parameters. I’ll admit, I only did this to see if I could, and it will be a lot better with AS3 because of the is keyword which works simlar to instanceof but can detect primatives such as String, Number and Boolean.

As it is though, its kind of handy because you tell the function to center the clip over a specific location via centerTo(100,100) or tell it to center to the desired MovieClip’s registration, centerTo(myMovieClip_mc). It doesn’t center the MovieClip automatically, but instead returns an object that has the new coordinates to center it. You can then pass these into your tweening function, or directly. I of course recommend my EasyTween class! :)   **Update 102/24/2010:  EasyTween no longer available for download. **

The function uses getBounds() to calculate what the actual center of the MovieClip, not just where the registration point is. One of the most frustrating things I find when resizing MovieClips is the at _width, _height are based on the MovieClips fullsize dimensions – not what it is actually scaled to when called. So when trying to figure out the actual width and height of a MovieClip you must first multiply it by its respective scale value and divide that by 100 to get a useable value.

2 Comments
6
Mar
2007

DelegatePlus: Delegate Plus Parameters!

DelegatePlus is a class which is almost exactly like the Delegate class except you can pass parameters with the function.

The Delegate class helps you manage scope when calling functions from with other functions, classes or events. Take the example code below:

import mx.utils.Delegate;

function traceThis(){
trace("Tracing!");
}
var myInt = setInterval(Delegate.create(this, traceThis), 1000);

A very simple class that just outputs “Tracing!” over and over again. But what if you wanted to pass it a string for the function to trace out? You can’t do it with the original delegate class! Now lets use DelegatePlus to pass parameters to the function.

import com.dcholth.utils.DelegatePlus;

function traceThis(aString:String){
trace("Tracing: " + aString);
}
var myInt = setInterval(DelegatePlus.create(this, traceThis, "http://blog.dcholth.com"), 1000);

The code will now trace “Tracing: http://blog.dcholth.com” indefinetly! No scope errors, no limit to the amount of parameters you want to specify. It runs the function exactly as if it were called within the original class.

This works by using the ‘arguments’ array which is passed with every function call regardless of the parameters used. The first two parameters in the ‘argument’ array are the scope object, and the second is the function being called. The rest of the array are the parameters passed, in order. The full delegate class can be seen below with commenting. You may notice it is very similar to the orginal Delegate class written by Mike Chambers.

/**

*/
//	****************************************************
//	DelegatePlus
//	****************************************************
//	By: Daniel Holth
//	eMail: dan [at] dcholth.com
//	web: http://blog.dcholth.com
//
//	The DelegatePlus class creates a function wrapper to let you
//	run a function in the context of the original object,
//	rather than in the context of the second object, when
//	you pass a function from one object to another.
//	The DelegatePlus class works exactly like Delegate but allows you
//	to pass parameters. (Its basically the same code!)
//
//	****************************************************
//	Last Modified 3/06/2007
//	****************************************************
//
/////////////////////////////////////////////
class com.dcholth.utils.DelegatePlus extends Object
{
/**
Creates a functions wrapper for the original function so that it runs
in the provided context.
@parameter obj Context in which to run the function.
@paramater func Function to run.
*/
static function create(obj:Object, func:Function):Function {
// Creates an array of the parameters that were also passed
                // with the create code.
                var parameters:Array = new Array();
// Using the arguments variable fill the array with the
                // parameters passed.  Start i at 2 because obj and func
                // use the first to positions in the arguments array
                for(var i:Number = 2; i < arguments.length; i++) {
parameters[i - 2] = arguments[i];
}

var f = function() {
// set the target scope and function
                        var target = arguments.callee.target;
var func = arguments.callee.func;
// use concat to link all the arguments together
                        var newArguments = arguments.concat(parameters);
//apply the function to the target with the arguments
                        return func.apply(target, newArguments);
};

f.target = obj;
f.func = func;
// using the return value from f will return the
                // result of the original function designated
                return f;
}

function DelegatePlus(f:Function){
func = f;
}

private var func:Function;

function createDelegatePlus(obj:Object):Function{
return create(obj, func);
}
}
3 Comments