Collaboration

I’d already seen some billboards around advertising that T-Mobile and Orange are now using each others signals…..then I saw these neato tandem ads on Yahoo…

T-Mobile and Orange Banner

T-Mobile and Orange Banner

Countdown Timer

Well, here is my Countdown Timer. It is an Adobe Air desktop application that you can use to count down time until an event. You’ll need to make sure you have Adobe Air installed first, then all you have to do is download the Countdown zip file, extract application file then run it on your computer.

Download Timer

Get Adobe Air

Features

It’s quite a simple little application – here’s a some of the things you can do with it.

Start your countdown

Use the settings panel to name your event and set the date and time. You can specify it up to 15 minute intervals.

Countdown Settings

Counting down

Watch your timer count down to your event. It will countdown up to milliseconds. You can reset the timer to begin again, minimise it to the taskbar, view the mini countdown version, or just close it.

Countdown Counter

The mini view

This mini view of the countdown allows you to keep your countdown open without taking up too much of your desktop space.

Mini Countdown

Download the Adobe Air application package

Download Timer

Get Adobe Air

My first Adobe Air Application

To help improve my AS3 skills I thought a good starting project would be to challenge myself to create an Adobe Air desktop application, and after working on a Christmas countdown, I decided it would be rather nice to make a Countdown timer.

This article runs through a few things I had to learn in AS3 to create it.

Getting Adobe Air working

First thing I needed to do was ensure that Adobe Air was installed and that everything working.

  • Install Adobe Air
  • Ensure Flash is updated, and install all the available updates. For Flash CS4 they are here.
  • Get the Adobe AIR SDK. Once downloaded this needs to be copied into the AIK folder in the Flash program folder – i.e. C:\Program Files\Adobe\Adobe  Flash  CS4\AIK.

Phew! Now creating the application…

First step was to get an accurate countdown mechanism. I found this Countdown example which was a good starting point to create a Countdown class in AS3. The basic idea is that it takes the current date and the specified event date then works out the difference.

Creating the event date input

I used Flash UI components for the drop down menus, but controlled their content using my Countdown class. To style the UI combo box component you can edit it in the FLA file, but to change the font you need create a TextFormat variable, then apply it to the component.

var comboFont : TextFormat = new TextFormat ();
comboFont.font = "Calvert MT Light";
comboFont.color = 0x333333;
comboFont.size = 12;
eventDayCombo.textField.setStyle ("embedFonts", true);
eventDayCombo.textField.setStyle ("textFormat", comboFont);
eventDayCombo.dropdown.setRendererStyle ("embedFonts", true);
eventDayCombo.dropdown.setRendererStyle ("textFormat", comboFont);

I then added data to the combo box. It is important to add this data dynamically to ensure that the Countdown is always up to date.

eventDayCombo.addItem ({label: dayStr, data: day})

Reading, saving and using XML data

Check if the data exists

Every time the application opens it checks to see if the user has already set an event date. The first thing it does is specify the name of the file, then where this file should be located. In my Countdown example the application creates an XML file called CountdownPrefs in the user’s My Documents folder.

var prefs:String = "CountdownPrefs.xml";
var prefsFile:File = File.documentsDirectory.resolvePath (prefs);

To check if a file exists on the system you can use prefsFile.exists; this will give a true or false result.

if (prefsFile.exists){

AS3 uses file streams to manipulate data; this makes the process much simpler than in AS2. It opens a file stream and reads the data. When it has completed reading the data the event listener calls the function processXMLData.

readStream = new FileStream ();
readStream.addEventListener (Event.COMPLETE, processXMLData);
readStream.openAsync (prefsFile, FileMode.READ);
}

Processing the data

So, to process the XML data I just use the function to specify the data then close the file stream. Now I can set my event date from the data in the XML file.

function processXMLData (event : Event) : void {
var prefsXML: XML = XML (readStream.readUTFBytes (readStream.bytesAvailable));
readStream.close ();
TITLE = prefsXML.child ("title");
YEAR = prefsXML.child ("year");
MONTH = prefsXML.child ("month");
DAY = prefsXML.child ("day");
HOUR = prefsXML.child ("hour");
MINUTE = prefsXML.child ("minute");
startCountdown ();
}

Saving new data

When the user sets their event date in the application it creates an XML file. First I defined what the content of the XML should be.

var dateStr:String = "<?xml version=\"1.0\" encoding=\"utf-8\"?><countdown><title>" + TITLE + "</title><year>" + YEAR + "</year><month>" + MONTH + "</month><day>" + DAY + "</day><hour>" + HOUR + "</hour><minute>" + MINUTE + "</minute></countdown>";

It then opens a file stream and writes the data to the location specified previously using the string variable to construct the XML content.

var newStream:FileStream = new FileStream();
newStream = new FileStream();
newStream.open(prefsFile, FileMode.WRITE);
newStream.writeUTFBytes(dateStr);
newStream.close();

Delete the data

To reset the countdown application all you need to do is simply delete the XML file then I called my reset function to restart the application.

if (prefsFile.exists){
prefsFile.deleteFile ();
resetCountdown ();
}

Using the Timer Class

So my Countdown function returns an object with the years, months, days, hours, minutes, seconds and milliseconds, then to update my countdown display I need to repeat the call every millisecond.   I can use the Timer class to repeat the function call and get the updated countdown object.

timerObject:Timer = new Timer (delay, repeatCount );
timerObject.addEventListener (TimerEvent.TIMER, updateCountdown);
timerObject.start ();

The finishing touches

Creating a custom chrome

To make the application visually nicer I added my own chrome to it with minimise and close buttons, here is how: http://www.adobe.com/devnet/air/flash/articles/custom_chrome_app.html

Creating an application icon

This is very simple. All you need to do is create little image files in the sizes: 128×128, 48×48,32×32, 16×16 then on the publish settings you can add the icon images.

Publishing the application

All you have to do then is publish the application and it’s ready to go. Look out for my next post if you want to download the application and try it out.

Creating Buttons with ActionScript 3.0

This is a quick guide on how to create and set up a button in AS3.

Set up the movie clip as a button

To make sure that your movie clip will act like a button you need to set the buttonMode and also set the movie clip to have a hand cursor.

bttn.buttonMode = true;
bttn.useHandCursor = true;

Ensure that you won’t interact with the child movie clips

When you rollover a movie clip in AS3, then the mouse cursor will recognise child clips within your button movie clip. To ensure that this doesn’t happen you can set the mouseChildren to false.

bttn.mouseChildren = false;

Making the button do stuff

Create a event listeners to call a function when the you interact with the movie clip.

bttn.addEventListener (MouseEvent.MOUSE_DOWN, doStuff);
bttn.addEventListener (MouseEvent.MOUSE_OVER, overBttn);
bttn.addEventListener (MouseEvent.MOUSE_OUT, outBttn);

Using mouse events

Here is a sample of how you use the mouse events. This function will trace the movie clip that you have clicked on.
function doStuff (evt : MouseEvent) : void
{
trace(evt.target)
}

Nice banner from Auto Trader

I was just doing some browsing on IMDB this afternoon and saw this banner. I don’t normally even want to click on interactive banners, but was rather intrigued…

Frame 1 – Draw a car you’d like to sell

Banner - First frame

Frame 1 – My wonderful drawing

Yes – my car actually does look like that – isn’t it lovely. Erm…
Banner - Second Frame

Frame 2 – Cheeky robot

Hard to believe this was actually my fourth or fifth attempt at drawing a decent looking car. He actually had a few different cheeky messages. He even fell over laughing once.
Banner - Third Frame

Frame 3 – Are you done?

Cute little jumping up and down animation on the Drive button. I liked the call to action on this too, made me want to click on it.

Banner - Fourth Frame

Frame 4 – Interact a wee bit more

I dislike when interactive banners want you to something, but it does actually seem connected to the rest of the banner. This is a nice way to make you feel like drawing the car actually had a point.
Banner - Fifth Frame

Frame 5 – Aw, he’s actually going to drive it away

So off he goes in to the distance, and I get taken to the landing page: http://www.autotrader.co.uk/CARS/selling/selling_a_car.jsp?platform=DFA
Banner - Sixth Frame

Well, cute little banner that I liked. Fun to use, nice touches…and maybe when I am selling my car I’ll even go to Auto Trader.

Dipping my toes into Flash CS4 and AS3

Well, I downloaded the Flash CS4 trial and have been experimenting with it for a day or so.

Overall I’m positive about what I’ll be able to do with the AS3, but a little disappointed in Flash CS4. I’ve never been that excited about the fancy new features in it, although I’m sure I will end up finding them useful. What my problem is, is that there was a few things about the interface and set up that I’d hope they would have improved.

The main one is the colour palette. You still can’t save swatches or custom colours. How annoying! It is also irritating that the ‘Free Transform’ and ‘Gradient Transform’ tools are together – it does get frustrating having to click between them when you are doing a lot of resizing and colour shading.

I have struggled a little today with AS3, but I think a good sit down reading ‘Learning ActionScript 3.0′ will probably let me understand better how it’s structured, then it will be a lot easier to make the transition from AS2 – I’m already am quite fond of the event listener.

ActionScript Naming Conventions

Well, in the midst of the Flash interactive feature I’ve been working on, I decided it really was about time I set myself a naming convention to follow when writing Actionscript code. I’ve always been a bit haphazard about how I name things, which in the long run will make it difficult for someone else to understand or to re-use. I also need to remember to use descriptive names for things. This will make it much easier for someone else reading the code to understand what each thing is or what it is doing.

Anyway, this is probably a work in progress, but at least I’ve gotten started!

Read more here: Abobe ActionScript 2.0 Best Practices – Naming Conventions

So, here it is:

Classes

  • Start with Uppercase
  • Concatenate words, using mixed cases

class MyClass

Functions & Objects

  • Start with lowercase
  • Concatenate words, using mixed cases

function myFunction

Movie Clips

  • Prefix with ‘mc’
  • After prefix start with Uppercase
  • Concatenate words, using mixed cases

mcMyMovieClip

Constants

  • All uppercase
  • Separate words should contain underscores
  • MY_CONSTANT

Number variables

  • Prefix with ‘num’
  • After prefix start with Uppercase
  • Concatenate words, using mixed cases

numMyNumber

String variables

  • Prefix with ‘str’
  • After prefix start with Uppercase
  • Concatenate words, using mixed cases

strMyString

Arrays

  • Prefix with ‘arr’
  • After prefix start with Uppercase
  • Concatenate words, using mixed cases

arrMyArray

Boolean expressions

  • Prefix with ‘is’
  • After prefix start with Uppercase
  • Concatenate words, using mixed cases

isThisOn

Flash Tutorial – Arranging a scene (Part Two) using hitTest

In the first tutorial (Arranging a scene using depths & scale) I created a scene that gives the impression that a character can move around scenery using the _y property. This tutorial explains how to stop the character moving through the scenery using hitTest.

First, create the file from the first tutorial.

In the Scene

Create a new movie clip and add a rectangular shape in it. Place this movie clip in each of your character and scenery movie clips, re-sizing it to the width of the item and the height to represent the “depth” – see diagram. Name each of the rectangular movie clips “testarea” and set the alpha to 0%.

Flash tutorial diagram

Initial Variables

Add this below the intial variables in the Actions frame.

moveAllowed = true;

Additional Code

In the mouseListener function, replace the code

_root.Character._x = _root._xmouse;
_root.Character._y = _root._ymouse;

with this code

if (_root.moveAllowed) {
_root.Character._y = _root._ymouse;
_root.Character._x = _root._xmouse;
} else {
_root.Character._x = _root._xmouse;
}
for (i=0; i<DepthArray.length; i++) {
if (_root.DepthArray[i].mcname != "Character") {
if (_root.Character.testarea.hitTest(_root[DepthArray[i].mcname].testarea)) {
_root.moveAllowed = false;
break;
} else {
_root.moveAllowed = true;
}
}
}

And so…

Here are the results

okay, it’s December, I can do Christmasy posts now

Way back on November the something-th (I think when they were putting the Christmas lights on) there were actually reindeer on Buchanan Street, yes – real reindeer – I’m sure you’re as excited as I was! Anyway – I (along with all the other losers) took a picture on my phone…

REINDEER!!!!!!!!

And, while I’m on the subject, a few years ago I created a little reindeer Christmas game to teach myself more ActionScript. It’s a bit silly, but I’ve cleared the hi-scoreboard anyway if you want to have a wee go.

Christmas Reindeer Game

Flash Tutorial – Arranging a scene using depths & scale

This tutorial explains how to use ActionScript to update depths and scales to give the impression that a character can move around scenery using the _y property.

First of all create your graphics and place them where you want them on the scene, giving them individual names. Ensure that the registration point is set to the bottom of the movie clip, this is especially important if your movie clips are different heights.

Next, create a new layer. This is where all the actions will go.

Initial variables

The first actions will hide the mouse cursor and state the initial variables; these will set the increments of the scale and y position.

Mouse.hide();
MinScale = 50;
MaxScale = 100;
ScaleIncrements = (MaxScale-MinScale)/100;
MinPos = 10;
MaxPos = 250;
PosIncrements = (MaxPos-MinPos)/100;

Setting the scene

Then, create an array to store all depth and height information on all the movie clips on the scene. This is a multidimensional array that stores the movie clip name, it’s _y position and the current depth.

var DepthArray:Array = new Array();
DepthArray.push({mcname:"Scenery_1", mcposition:Scenery_1._y, mcdepth:Scenery_1.getDepth()});
DepthArray.push({mcname:"Scenery_2", mcposition:Scenery_2._y, mcdepth:Scenery_2.getDepth()});
DepthArray.push({mcname:"Scenery_3", mcposition:Scenery_3._y, mcdepth:Scenery_3.getDepth()});
DepthArray.push({mcname:"Character", mcposition:Character._y, mcdepth:Character.getDepth()});

Next, the array should be sorted based on the y position. The property “Array.NUMERIC” is used to ensure the sort is ordering the array as a number rather than a string.


DepthArray.sortOn(["mcposition"], Array.NUMERIC);

Then the movie clips on the scene should be updated. This uses a for loop which will go through all the items in the array, and update the movie depth according to the order they have been placed into within the array, then scale the movie clips according to their y position so the movie clips that are higher will be smaller. This uses the variables that have been set at the beginning.


for (i=0; i<DepthArray.length; i++) {
// sort initial depths
DepthArray[i].mcdepth = i;
_root[DepthArray[i].mcname].swapDepths(DepthArray[i].mcdepth);
// set inital scales
CurrentPosition = (_root[DepthArray[i].mcname]._y-MinPos);
CurrentPositionPerc = CurrentPosition/PosIncrements;
_root[DepthArray[i].mcname]._xscale = _root[DepthArray[i].mcname]._yscale=MinScale+((CurrentPositionPerc)*ScaleIncrements);
}

Time to get moving

So now a mouse listener is added to allow the scene to be updated you move the character around.


var mouseListener:Object = new Object();
mouseListener.onMouseMove = function() {

The mouse cursor has already been hidden as part of the initial actions, so now the character must be set to follow the x and y positions of the mouse.


_root.Character._x = _root._xmouse;
_root.Character._y = _root._ymouse;

The array must be updated to set the character at the right depth, and then the scene is updated according to this.


for (i=0; i<DepthArray.length; i++) {
DepthArray[i].mcposition = _root[DepthArray[i].mcname]._y;
}
DepthArray.sortOn(["mcposition"], Array.NUMERIC);
for (i=0; i<DepthArray.length; i++) {
DepthArray[i].mcdepth = i;
_root[DepthArray[i].mcname].swapDepths(DepthArray[i].mcdepth);
}

Now the correct scale for the character is set.


CurrentPosition = (_root.Character._y-MinPos);
CurrentPositionPerc = CurrentPosition/PosIncrements;
_root.Character._xscale = _root.Character._yscale=MinScale+((CurrentPositionPerc)*ScaleIncrements);
};

Finally you just activate the listener


Mouse.addListener(mouseListener);

And so…

So, now just take a look at the final results.

Previous Older Entries