Thursday, December 17, 2009

TattooCapture Update



Here's the skinny on TattooCapture. I called myself out at Flash on the Beach, then Sheridan College, a FlashinTO user group meeting and finally Seneca College, for being a procrastinating chump (see my presentation 10 Best Excuses to NOT do Amazing Work)

Currently the site is still incomplete. I've spent quite a bit of time on it and have stricken plenty of items off my to do list but there are many many more items remaining.


image scaled roughly 50%

As you can see in the screengrab above I have a lot done. The design of the site is rough and will remain so until I can convince one of the many talented designers I know to make it pretty. But as Chris Pelsor has said "Get version 1 done and worry about the rest after".

What's working;
    Age verification
    Registration and account creation
    Login
    Account update (for facebook, twitter, etc)
    Avatar creation (using a webcam or uploaded image)
    Gallery creation
    Image creation (using a webcam or uploaded image)
    Adding images to a gallery
    Viewing galleries
    Viewing images
    A development notes window
    An instructions window


What isn't working (yet);
    Viewing updated user info
    Viewing specific users
    Search in any form
    The actual mechanism for a tattoocapture (take one image, put it on another, save)
    Add friend functionality
    Verify friend functionality
    Send in-site messages
    Ratings on images
    And much, much, sigh, much more


Anyway, I know the amount of egg on the face one wears when they commit to specific launch dates and can't make it. I'm relatively embarassed, but considering what's been accomplished so far, I can safely say I've done a lot.

Never fear, this is not the end. It's simply an update so you all know I didn't just stop. I'm really excited with the progress. If you want to play with the site as is, send me an email

Labels: , , ,

Wednesday, December 16, 2009

2010 Subaru Legacy

Firstly, I have to thank Tribal DDB Toronto for the opportunity to work on this project. Their timely assignment firmly planted me in my new freelance role.


Welcome to the 2010 Subaru Legacy

This project had some challenges. Not the least of which was the fact that when I was pitched it, the art director (the effervescent Missy Kelley) involved said they wanted PaperVision 3D. Although I took a workshop on PV3D with the inimitable John Grden, I can honestly say I still know next to nothing about how to implement this powerful class set. It's embarrassing to admit but I'll live.

At any rate, here comes the fun part; all the cool stuff I put to use. Either new to me or a finessing of things I already know.


Starting the audio experience

1. Audio triggering. I used flv video (f4v, actually) for the audio. The audio is in binaural format. Meaning if you happen to be wearing headphones, the audio will wrap your head in true surround sound. It's wicked cool. They want the image sets to appear based off timing in the audio. eg. the narrator is talking about the radio, the radio image ought to be front and center and the set that image is in ought to be the focus. To accomplish this, I used XML and a type of closed captioning. When using closed captioning, you can either set an event within the audio export or you can use XML with timecodes in it and look for these. I opted for the latter. A. because I couldn't be sure the audio wasn't going to change and I didn't want to have to input all the new events in the audio. B. because I'm really familiar with XML.


No PaperVision 3D? No problem. Sort of.

2. Fake 3D. Since I didn't know PV3D, I could use the 2.5D implemented in Flash 10 to allow for skewing and perspective. Therefore, when placing the images in their sets, I'd use a center point (locally, the 0,0 of the set) and randomly place the images around that point. Their distance from the center dictated the amount of perspective they would have. When that image becomes focused it swaps it's perspective on the vertical axis. It's a fairly good effect and easily set up.


Highlighting a feature.

3. Call outs. Now, having worked with auto minisites for pretty much my entire career, I know the four pinnacles of the industry; power, performance, comfort, safety. It never changes. Call it what you will, but those things are paramount. I think you can probably add cost in there now, but whatev. I used the image sets and XML to control callouts. If the callout existed (in the XML of an image) it popped open when that image was the focus.

4. swfObject loading issues. I blogged about this. Suffice it to say, thanks to Chris Pelsor and Stacey Mulcahy, this got sorted out.


Soundboard with downloadable MP3s

5. Downloading of files. There is a soundboard in this piece and the request to be able to download the MP3s came from on high. I'd never done that before, but it was fun to make happen.


En francais, s'il vous plait.

6. Localization. The request from a Canadian client was of course that this needed to be in french and english. I wanted to be able to easily access this portion by simply swapping a variable. eg. ?lang=fr (see french in action)

So that's Subaru Legacy in a nutshell. I'm pretty proud of this piece. Thanks again to the crew at Tribal DDB Toronto for the opportunity!


That's all she wrote

Labels: , , ,

Friday, September 18, 2009

Estée Lauder win

Update September 25 Turns out Estée won in the "Beauty and Cosmetics" category at the OMMA Awards a few days ago! This thing is a monster.

I've found out the site I worked on, Estée Lauder, has won;

two WebAward awards (Outstanding Website, Best Fashion Website)
one Internet Advertising Award (Outstanding Achievement In Internet Advertising)

It's also an entry at Cannes! (Cosmetics, Beauty & Toiletries)

More after the jump;


Managing a team of five Flash developers and co-ordinating remotely with the New York office was a true test of my managerial abilities. The site went down to the wire, but in all, I was really pleased with the efforts of my team. Todd Fraser and Stephan Tanguay, especially.

Not to mention, it was my very first AS3 project. I've learned a ton since then in implementing AS3, but I cut my teeth with this project. My favourite self-built classes, TextFormatter and MainImporter were first coded for Estée Lauder. I owe Organic, a debt of thanks for being able to work on this project.

My focus, beyond management, was the Skin Care Diagnostic Tool




Honestly, what better way to start the day than to find out work you've done won awards?

In case I forget, FOTB, here I come!

Labels: , , , , ,

Wednesday, September 02, 2009

Facts about Fees

I forgot to blog about the re-release of Fee & Processes on Bank of America. Now known as Facts about Fees.



This had several fun challenges. The flash was loaded and reloaded by the html wrapper every time the user changed sections, so I made extensive use of the SharedObject to store visits. This way, the user gets a different experience from the video on the first visit and subsequent visits. Quite fun.

There were some alterations to my base once I left Organic, but it's still functioning and I'm quite pleased with the site on the whole. Take note of the Asked & Answered windows with their cross-linking and the control you have over the video, muting, volume, etc.




Plus, I incorporated pre-existing AS2 demos from the original site and brand new demos from the InfoCenter engine. This piece is rife with yummy hugh goodness.

Labels: , ,

Thursday, August 20, 2009

FoTB 30 days away!

Things are really motoring. I've moved http://tattoocapture.com over to my friend John Breton's server. John is a .NET guy and knows his junk, lemmetellya.

I have never done so much using webservices. Registration, login, updating, uploading, friending, messages, world locations, etc, etc. I have exclusively been using Carlo Alducente's WebService class. It's been invaluable and I don't know where I'd be without it.

Soon enough I'll be making use of Senocular's Transform Tool.

Interested in being a beta-tester (or as I like to call it, Better Tester)? send me an email. I hope to be ready for full-scale testing in about a week. Many hands make light work, as they say. Many eyes make amazing work, I say.

The end goal for this is to be finished by Flash on the Beach where I am presenting my session The 10 Best Excuses to NOT do Amazing Work. I hope to see you there! I did say I would light a monkey on fire to compete with Quasimondo's presentation happening at the same time as mine.

I've been updates about TattooCapture.com development on Twitter : tattoocapture

Labels: , , , , ,

Tuesday, February 24, 2009

Keyboard Events

There was a comment by Muaad for help on how to capture Keyboard Events in AS 3.0. I figured instead of filling up a comment box I'd just go ahead and do a little post on it.

Keyboard Events and capturing them has been around for a long time. I'm going to assume Flash 4 days since I'd built a little animated typer in Flash 4 and can't recall doing it Flash 3.

Like everything else in AS 3.0, you need to import the appropriate class(es);

For capturing Keyboard Events, you'll need;

import flash.events.KeyboardEvent;
Add an eventListener to the stage for whatever you want to capture KEY_DOWN, KEY_UP, etc etc.
stage.addEventListener(KeyboardEvent.KEY_DOWN,checkKey);

List of Key Codes on Adobe

Source files


There you go, Muaad.

Labels: ,

Tuesday, January 06, 2009

Aspect Ratio

I've been working on a little something and wanted to maintain a 16:9 aspect ratio no matter what size the browser window was.

Essentially, the calculation is this;
multiplier = 16/9 = 1.7777778

In my test, I used the multiplier on the stageHeight and stageWidth to find out

private function maintainAspectRatio(event:Event):void
{
   width16x9 = stage.stageHeight*multiplier16x9
   height16x9 = stage.stageWidth/multiplier16x9
   if(width16x9 < stage.stageWidth){
      height16x9 = width16x9/multiplier16x9;
   }else{
      width16x9 = height16x9*multiplier16x9;
   }
}


So using an EventListener on the stage I can monitor the current stage size.

stage.addEventListener(Event.RESIZE, maintainAspectRatio);

And there you go.

Here's the test.

Labels: , ,

Tuesday, December 23, 2008

Seasons' Greetings from wheniwas19!

While planning our little trip to see family for Christmas, I thought about a little something something to have for anyone who reads this blog.

Because the build is randomly generated, it takes a while to get to something coherent, so here's a screenshot.

*Edit*
Thanks to a few phrases from my father-in-law, I had to crack this open to make some changes;
1. There's an initial navigation to choose the animated build over just splashing the page randomly with specific numbers of iterations.
2. You can go back and start over.
3. I used setTint instead of Greensock's TweenLite to save on processor cycle(s).

Thanks, John. I hate thinking I haven't done enough. Mind you, there are a few more things I'd like to do but I might save that for another project.




If you do have time on your hands and want to see it in action, click here.

So, Merry Christmas and Happy New Years.

*Edit*
I noticed some weirdness with this thing. Like when it finished it's loop, it would remove the last item(s) and not add them to the Bitmap Object. Looked into it and discovered I ignore the last set of items and just snapshot the ones before them. Fixed that.

Just to explain what's going on under the hood;
Step 1. place an MC on the stage. In this case, MERRY *LOGO* CHRISTMAS. Change it's visibility to false
Step 2. randomly locate a pixel on the stage and sample the color of that pixel.
Step 3. place a random MC on the stage at that location and tint it to the color of the pixel.
Step 4. after 10 iterations, draw those clips to a bitmap and remove them (the clips). Increment a second iteration counter.
Step 5. after 10 iteration on the second counter, draw the bitmaps to an overall bitmap and trash them (the bitmaps)
Step 6. rinse and repeat.

Labels: ,

Friday, December 12, 2008

The Art of John Wall

Announcing the launch of The Art of John Wall.

Sometime in May, a friend of mine contacted me asking if I'd be willing to work on his site. "No rush," he said.

Now unfortunately, I don't do well with no timelines. So when he followed in June and July with "How's it going, man?" I would respond with, "Ah, crap. Sorry."

It's not intentional, I just need a deadline to motivate me. So when he called in August and I prepared to apologize once again for not working on his site, he asked, "No, no, I was wondering if you might want to work on a second site?"

Usually when I've screwed the pooch for so long, a client would be inclined to fire me. Not this guy. To his credit, I think he got it. "This one has to be live by the end of November."

Sweet mother of pearl. A deadline?!?

I was given a lot of creative license with this site, so I packed it full of things I've wanted to try in AS3 but couldn't seem to talk Organic into trying;

Full-window, liquid layout.
A self-centering content box.
All content in one spot. Text, images, doesn't matter. One GD spot.
Navigation that goes away when it isn't needed. Fewer items on the screen, less clutter.



Yes, in essence it's just another portfolio site. And yes, the concept of next previous buttons in an image isn't new, but it's a good idea, so why not do it?

I'm just glad to have been given the opportunity to build something for someone so talented.

Labels: , ,

Tuesday, December 02, 2008

Using External Libraries with Flash and Flex

Over the past couple of years, I've really been trying to embrace my inner OOP-ness. There's been figuring things out slowly but surely and my latest wish was to externalize my libraries from my project(s).

I have a few classes here and there that it would be simpler if they were in one spot. Theoretically, if I make an update to one class it's universally updated across the board. I might need to go into older projects and add an argument here or there if that project needs an update itself, but my classes would never need to move.

Deciding where I'd like these classes to reside is a stressful thing. Forever is a long time, after all. I've been using Flex for almost a year now and I don't know why I was so reluctant to use it. Probably because I heard so many people saying "Oh, you HAVE to use Flex. You HAVE to." I alway get all obstinate when someone tells me I must do something. I'm crotchety. I tried Flex, and I never looked back.

Anyway, here are the steps. I am sure they're outlined efficiently elsewhere, but since it's new to me, it must be new to someone else and I want to save them the effort of looking. As a caveat, I never say this is THE WAY to do things. This is MY WAY to do things.

step 1. create a new project in Flex. Do whatever you do, name it whatever you name it, put it wherever you put it. Don't hit Finish yet.



step 2. hit Next. Notice the Source Path tab with a big window underneath it? To the right of the window is an Add Folder… button. Click Add Folder… and find your code folder. When you click OK, that library will be added to your project.





step 3. Hit Finish.



Your project will be set up by flex. You'll see your project folder and inside it is [source path] yourLibrary. In my case, it's com

That's not all though. There is a little housecleaning in Flex I find I still need to do. Right-click on your project and choose Properties.



In ActionScript Compiler, deselect Copy non-embedded files to output folder and Generate HTML wrapper file BTW, this is a personal choice. I don't like them, so I dump them. It's up to you.



Finally, create a new Flash file and save it to your new src folder. Now we move to;

step 4. Open the Properties panel and under Document Class: enter in the main class. In my case, this is "Temporary_Project".



step 5. Now, under Settings in the Properties panel, click the Formats tab and change the output location of your swf to ../bin/fileName.swf fileName being the name of your file.



step 6. This is the big final set of steps that made the difference between Flash finding my class files and not. Under Flash, choose Preferences….



step 7. In Categories, choose ActionScript. Click ActionScript 3.0 Settings….



step 8. Click the bullseye and locate your code folder. Once you choose it, the path to your folder will appear in your ClassPath: window.




And that's it. Flex will auto-complete your paths as normal, the classes will be available to your project and Flash will know where your classes are. It's a lot of screenshots, I know, but I spent 5 minutes trying to figure this out and was flummoxed at the very end when I neglected to add the Classpath to Flash.

Hope this helps.

Labels: , ,

Friday, November 07, 2008

Text Selection Discovery

I was wracking my brain on and off for about a week trying to get a field to select all the text in it when it achieves focus. This happens automatically when you tab to it, but when you click in it, it sets the caret wherever you're clicked.

Initially I was convinced that FocusEvent.FOCUS_IN should do the trick. In fact, I'm still convinced it is, but it doesn't work.

var tmp:TextField = new TextField();
tmp.addEventListener(FocusEvent.FOCUS_IN,focusText);
tmp.htmlText = "test text";
tmp.autoSize = "left";
tmp.selectable = true;
tmp.type = "input";
tmp.border = true;
tmp.x = 50;
tmp.y = 50;
addChild(tmp);
function focusText(_fevt:FocusEvent):void{
trace(_fevt.target.text);
var tf:TextField = TextField(_fevt.target);
tf.setSelection(0,tf.length);
}

This doesn't work. Such a shame.

Anyway, Todd Fraser over here at Organic gave me one of those, "wait, MouseEvent.CLICK didn't work?" with one eyebrow raised. And although I had to admit I hadn't even bothered with MouseEvent.CLICK because I assumed FocusEvent.FOCUS_IN should work. Don't discount what you might consider "ol' timey" ways of doing things.

var tmp:TextField = new TextField();
tmp.addEventListener(MouseEvent.CLICK,focusText);
tmp.htmlText = "test text";
tmp.autoSize = "left";
tmp.selectable = true;
tmp.type = "input";
tmp.border = true;
tmp.x = 50;
tmp.y = 50;
addChild(tmp);
function focusText(_fevt:MouseEvent):void{
trace(_fevt.target.text);
var tf:TextField = TextField(_fevt.target);
tf.setSelection(0,tf.length);
}

Shoot, dawg.

Labels: , ,

Thursday, September 11, 2008

MainImporter Class

This is the second custom class used in the Bullet Class, MainImporter.

During the same project that prompted TextFormatter it dawned on me I had no real useful Load this class. There are a lot of nice phat loaders around, BulkLoader is a great example. However, it's kind of overkill for what I wanted.

So I put together MainImporter. It handles Bitmaps, SWFs and XML nicely and I've used it extensively for pretty much every project since.

package com.utils{
import com.events.LoaderEvent;
import flash.display.Loader;
import flash.events.Event;
import flash.events.EventDispatcher;
import flash.events.IOErrorEvent;
import flash.events.ProgressEvent;
import flash.net.URLLoader;
import flash.net.URLRequest;
public class MainImporter extends EventDispatcher{
public static const ITEMLOADED:String = "item loaded";
private var itemURL:String;
public var loader:Loader;
public var loaderXML:URLLoader;
private var fileEnder:String;
public var loadedCurrent:Number;
public var loadedTotal:Number;
public function MainImporter(_url:String){
itemURL = _url;
var tmpArray:Array = itemURL.split(".");
fileEnder = tmpArray[tmpArray.length-1];
loadItem();
}
private function loadItem():void{
var urlRequest: URLRequest = new URLRequest(itemURL);
if(fileEnder == "xml"){
loaderXML = new URLLoader();
loaderXML.addEventListener(IOErrorEvent.IO_ERROR,loadError);
loaderXML.addEventListener(ProgressEvent.PROGRESS,progressListener);
loaderXML.addEventListener(Event.COMPLETE,completeLoad);
loaderXML.addEventListener(Event.INIT,initListener);
loaderXML.load(urlRequest);
}else{
loader = new Loader();
loader.contentLoaderInfo.addEventListener(IOErrorEvent.IO_ERROR,loadError);
loader.contentLoaderInfo.addEventListener(ProgressEvent.PROGRESS,progressListener);
loader.contentLoaderInfo.addEventListener(Event.COMPLETE,completeLoad);
loader.contentLoaderInfo.addEventListener(Event.INIT,initListener);
loader.load(urlRequest);
}
}
private function initListener(evt:Event):void{
//trace("init");
}
private function progressListener(evt:ProgressEvent):void{
loadedCurrent = Math.floor(evt.bytesLoaded/1024);
loadedTotal = Math.floor(evt.bytesTotal/1024);
dispatchEvent(new LoaderEvent(LoaderEvent.UPDATELOADER,loadedCurrent,loadedTotal,true));
}
private function loadError(evt:IOErrorEvent):void{
trace("IOErrorEvent : " + evt);
}
private function completeLoad(evt:Event):void{
dispatchEvent(new Event(MainImporter.ITEMLOADED));
}
}
}


This is a work in progress, so do what you want with it.
MainImporter.as

Labels: , , ,

TextFormatter Class

I just posted on BulletBuilder. I realized there are two other classes I set up a while ago for another project that I use regularly that could use some explanation.

First is TextFormatter. We'd started a project and needed a quick way to implement some basic textfields across the project that could react to some supplied variables; font, color, size, leading

To circumvent some massive discussion about Stylesheets or whatever, I set up TextFormatter and it's done the job pretty adequately and I've used it since for anything non-complex in a textfield.

To use TextFormatter, just import the class and create a textfield then instantiate TextFormatter. Of course, also import the TextField class. You'll want to set the width of the textfield as well.
var tf:TextField = new TextField;
tf.width = 300;
new TextFormatter(tf,0x000000,12,"Flash ain't so bad","Arial");
addChild(tf);

Now in TextFormatter all the pseudo-heavy lifting can begin.
package com.utils {
import flash.text.TextField;
import flash.text.TextFieldAutoSize;
import flash.text.TextFormat;
import flash.text.AntiAliasType;
public class TextFormatter {
public function TextFormatter(src:TextField,fcolor:uint,fsize:Number,str:String,ffont:String="FranklinGothicEF-Demi", leading:Number=0)
{
src.autoSize = TextFieldAutoSize.LEFT;
src.background = false;
src.border = false;
src.embedFonts = true;
src.selectable = false;
src.antiAliasType = AntiAliasType.ADVANCED;
var format:TextFormat = new TextFormat;
format.font = ffont;
format.color = fcolor;
format.size = fsize;
format.leading = leading;
src.defaultTextFormat = format;
src.htmlText = str;
}
}
}


TextFormatter.as

Labels: , , ,

Bullet Class

A little while ago, I was working a little project that had several lists of bullets. I couldn't find any suitable solutions that gave the designer what he craved; a list of bullets with well-wrapped text.

Sample xml;
<SAMPLE_TEXT>• Bullet item one.
• Bullet item two. Long enough to wrap because I've typed a little bit too much and it definitely is too long to fit in one line.
• Bullet item three. There's nothing like seeing text wrapping to make you realize that bullets are the bane of your existence. Nothing, I say.
• Bullet item four.</SAMPLE_TEXT>


Here's what you get when you just set up a normal textfield and do what you normally do.

var tf:TextField = new TextField;
tf.width = 300;
tf.multiline = true;
tf.wordWrap = true;
tf.text = SAMPLE_TEXT;
addChild(tf);




As you can see, the text wraps under the bullet because flash only sees it as a block of text.

I realized that the best solution, for me anyway, was to separate the bullet and the line, make two textfields and line them up. This way the copy aligns as it should and doesn't wrap under the bullet. So I set up a little class to take care of it for me.

The XML had to change to accomodate TextFormatter, but only a little;
<SAMPLE_TEXT bulletString="•" ffont="Arial" fsize="18" fcolor="0x000000">• Bullet item one.
• Bullet item two. Long enough to wrap because I've typed a little bit too much and it definitely is too long to fit in one line.
• Bullet item three. There's nothing like seeing text wrapping to make you realize that bullets are the bane of your existence. Nothing, I say.
• Bullet item four.</SAMPLE_TEXT>

package com.display
{
import flash.display.Sprite;
import com.utils.TextFormatter;
import flash.text.TextField;
public class BulletBuilder extends Sprite
{
private var content:Sprite;
private var bulletCharacter:String;
private var bulletArr:Array;
private var contentArray:Array;
private var bullet:TextField;
private var copy:TextField;
private var bulletHeight:Number = 0;
private var fieldWidth:Number;
/*====================
provide the constructor with;
the xml node
what character to look for
the width of the end field
sample;
var bulletBuilder:BulletBuilder = new BulletBuilder(sampleNode,"•",415);
addChild(bulletBuilder);
=====================*/
public function BulletBuilder(_copy:XML,_bulletCharacter:String,_fieldWidth:Number)
{
content = new Sprite;
bulletCharacter = _bulletCharacter;
fieldWidth = _fieldWidth;
bulletArr = _copy.toString().split(bulletCharacter+" ");
setBulletFields(_copy);
}
/*=====================
setBulletFields separates the copy
into an array based on the provided bullet character.
it then uses two textfields; one for the bullet character, one for the copy.
places the copy at the same y position as the bullet
and moving it to the right of the bullet
it then adds the two fields to the sprite and updates the y position for the next bullet
finally, the function adds the content sprite
========================*/
private function setBulletFields(_copy:XML):void{
contentArray = []
for(var i:int = 1;i<bulletArr.length;i++){
contentArray[i] = new Sprite;
bullet = new TextField;
copy = new TextField;
copy.width = fieldWidth;
copy.multiline = true;
copy.wordWrap = true;
new TextFormatter(bullet,_copy.@fcolor,_copy.@fsize,bulletCharacter,_copy.@ffont);
new TextFormatter(copy,_copy.@fcolor,_copy.@fsize,bulletArr[i],_copy.@ffont);
copy.x = bullet.width;
contentArray[i].addChild(bullet);
contentArray[i].addChild(copy);
contentArray[i].y = bulletHeight;
bulletHeight +=contentArray[i].height;
content.addChild(contentArray[i]);
}
addChild(content);
}
}
}



Here's sample with the package(s)

Labels: , , ,

Monday, June 02, 2008

Happy June

Things are busy as usual and that means not posting. That's not to say I'm not doing anything and just to prove it...

I ran into a problem in a recent project where I had a series of buttons and I wanted to one to be active right off the bat. ie, like a gallery where the first image is the triggered from the first thumbnail.

There are two ways I found;

1. When your button isn't actually sending any information along with it you can change your callback function to accept a null parameter.

ex.
button.addEventListener(MouseEvent.CLICK, onClick);

private function onClick(mevt:MouseEvent=null):void
{
//do whatever here
}

now I can just call the onClick function like any regular ol' function

onClick();

However, if you want to actually click the button because you need to know something that button has;

//using the same code as above

button.dispatchEvent(new MouseEvent(MouseEvent.CLICK));

TADA!

Now tell me I haven't been doing anything.

Labels: , ,

Monday, April 28, 2008

Bit-101's Three Useful Methods

Keith Peters posted on his blog last week three useful methods.

I've added a couple of extra methods that I'm finding I use more often than not and might as well shove into this class. Shove is an inelegant word, but I'm an inelegant guy.

//thanks, Keith.

public static function distanceCalculation(x1:Number, y1:Number, x2:Number, y2:Number):Number
{
var dx:Number = x1 - x2;
var dy:Number = y1 - y2;
return Math.sqrt(dx * dx + dy * dy);
}

//I mixed something up here. Fixed the randomRange value return. Thanks again, Keith.

public static function randomRange(start:Number, end:Number):Number
{
return Math.floor(start + Math.random() * (end - start));
}
It's fair to note that I didn't create these methods. They were found at various times in various locations. I just keep misplacing them and looking for them again. Good to know that it's last time I'll do it.

It's nice to be spurred on to centralizing this stuff. Thanks, Keith!

Labels: ,

Thursday, February 07, 2008

BulkLoader

This nifty library gives you the power (that's right, I said "power") to load multiple items easily.

Very nice.

Labels: ,