Monday, 27 July 2009

Sliding-Page Effect - Navigation in Flash

The other thing that http://www.fuelfugitives.com/ got me interested in was the way the navigation works. The wonder of Flash is that you don't load a new "page" when you click a "link" (or button). In fact anything can happen - make a noise, play a video, basically anything you can imagine and code. This means we are not constrained to the traditional ideas of navigation transitions from "page" to "page".

Fuel Fugitives utilises a nice idea I have seen a few times. Instead of simply changing to another "page" or screen, you slide gracefully from one place to another, as though all the "pages" are actually on the same sheet, you just change which part of the sheet you are looking at.

Well, unable to resist the challenge I decided to work out a way of getting the same effect myself, using Flash and AS2.

Let's get started







1. Create a new Actionscript 2 document and set the frame rate to 30fps.

2. Create an object on the stage, hit F8 and convert it into a MovieClip, with the registration set to the middle.

3. Create 3 more instances of the MovieClip (for a total of 4), space them out, and give them the instance names object1_mc, object2_mc, object3_mc, and object4_mc.

4. Select (using SHIFT) all of the instances of the MovieClip on the stage, then hit F8 and convert the group into a MovieClip with the registration set to the top left. This new MovieClip should contain all the other clips on the stage. Give this new MovieClip the instance name objholder_mc.

Once that's done it's time for the Actionscript.

The Actionscript

/* First we set a variable called currobj. This will store the name (or in this case number) of the movieclip we want centred on the stage. We will use it later to centre that movieclip if it is not already centred. */

var currobj = 1;


/* Now we need some easing to give the slide animation a bit of style */
var easing = 6;

/* Then we set variables to define the centrepoint we want to centre movieclips to. */

var hmiddle = Stage.width/2;
var vmiddle = Stage.height/2;

/* Then we create the function that moves the current movieclip (defined by currobj) to the centre (defined by hmiddle and vmiddle). */

onEnterFrame = function () {

/* Finding the difference between the object holder x and y and the centre x and y */
objh_v = _root.objholder_mc._y;
objh_h = _root.objholder_mc._x;
vdiff = vmiddle-objh_v;
hdiff = hmiddle-objh_h;

/* Finding the object x and y within object holder. By using the ["object"+currobj+"_mc"] the code works for every object, all we need to do is update the value of the currobj variable. This means that we can keep our code small and reusable. */

obj_h = _root.objholder_mc["object"+currobj+"_mc"]._x;
obj_v = _root.objholder_mc["object"+currobj+"_mc"]._y;

/* Finding the difference between the current object (currobj) x and y and the centre x and y */

finalvdiff = vdiff-obj_v;
finalhdiff = hdiff-obj_h;

/* Finally we get onto the animation. This basically tells the objholder x and y to move so that the currobj MovieClip inside objholder is centred. All the calculations up to now allowed us to find out exactly where objholder needed to move to for this to happen. So that we get the easing effect on the animation, objholder only moves just under half the actual distance to its destination on each frame (this is controlled by the easing variable). */

_root.objholder_mc._y += finalvdiff/easing;
_root.objholder_mc._x += finalhdiff/easing;
};

/* Making the objects act as links to the next object. I am working on a way to write this code only once for any number of objects, on the basis of telling Flash the total number of objects, but not there yet. meanwhile we need a function for each object manually telling it to go to the next by setting the currobj value to the next object. */

_root.objholder_mc.object1_mc.onPress = function () {
currobj = 2;
};
_root.objholder_mc.object2_mc.onPress = function () {
currobj = 3;
};
_root.objholder_mc.object3_mc.onPress = function () {
currobj = 4;
};
_root.objholder_mc.object4_mc.onPress = function () {
currobj = 1;
};

Over to you...

As you can see, the code is fairly straightforward (hopefully the comments explain how it works). But so far all we have is the mechanics, to be really effective you need to have good graphics to go with it. A good idea!

That's what Fuel Fugitives has, now over to you.

Controling Flash Navigation through the URL

Just came across this site http://www.fuelfugitives.co.uk/ which uses the URL in a really interesting way to allow you to access different parts of a Flash Movie depending on the URL. Even though it is the same Flash Movie, not different pages.

This is useful because it means you can bookmark or "add to favourites" a specific part of the Flash Movie. It also means you can use your browser back button to return to a previous part of the same movie (normally with Flash this would result in you leaving the page containing the embedded movie).

So how did they do it?

I'm still looking into that, but a quick view of the source code indicates that some cool javascript is the answer. Will investigate more later... meanwhile - gardening.

Having cleared nigh on 168 square feet of garden (and finding bricks, carpet, bags of clothes and all manner of rubbish buried there by previous owners) with the help of a brother, I have come back to find the answer, and after a bit of searching found if not the solution, a solution...

And the answer is...

http://www.asual.com/swfaddress/

To quote the website:

SWFAddress is a small, but powerful library that provides deep linking for
Flash and Ajax. It's a developer tool, allowing creation of unique virtual URLs
that can point to a website section or an application state. SWFAddress enables
a number of important capabilities which are missing in today's rich web
technologies including:

  • Bookmarking in a browser or social website
  • Sending links via email or instant messenger
  • Finding specific content with the major search engines
  • Utilizing browser history and reload buttons

There are some cool little demos too so you can see it in action, and sure enough, seems to be pretty much what I saw on http://www.fuelfugitives.co.uk/, the site that started me looking in the first place.

So that seems to be it. One more thing to add to my todo list, but I fully intend to put this to good use this holiday. I hope you find it useful as well.

Friday, 24 July 2009

Drag n' Drop (with momentum) in Flash



A few weeks ago I had the opportunity to attend a JISC e-learning event. A fair number of educational technology vendors were present promoting their latest products and services, but for a brief moment one thing caught my eye. The SMART Technologies SMART Table.

It wasn't so much the idea of the SMART Table that intrigued me but the interactivity it offered. The e-learning game running on the table at the time was a diagram of the human body on which the students would have to correctly identify the different body parts by dragging labels onto them from the edge of the screen. As they were dragged the labels would turn as though being pulled by little strings, then when released would continue on to a gentle stop as though they had their own momentum.

I thought that idea of dragging and dropping labels that had weight and momentum was really cool, and I immediately realised that you could do a similar thing using flash.

Well, now that the first evening of my holiday is here I have begun work and have a basic solution for the momentum part of it (I will add the turning and following part another day when that is done).

So here it is, drag and drop, with momentum, in Flash:

Here's it is







If you are not yet an AS3 whizz or using an older version of Flash, don't worry, this one uses AS2.

Let's get going.

1. Create a new AS2 document.

2. Create a shape on the stage, select it and hit F8, then turn it into a MovieClip

3. Give the new MovieClip the instance name of object_mc in the Properties panel.

And that's the easy bit done. Now for the ActionScript.

4. Create a new layer in the timeline and give it the name Actions.

5. Select the first frame of the Actions layer, then hit F9 to open the Actions panel.

5. Input the following code into the Actions panel (hopefully my comments will explain everything, if not, leave a comment):

/* set some variables we will use later */

var posBh = 0;
var posBv = 0;
var posAh = 0;
var posAv = 0;
var trajh = 0;
var trajv = 0;
var drag = 0;


/* sets the level of friction, the higher the number, the more friction.*/

var friction = 1.35;

/*We make the object draggable, and set the drag value to 1*/


object_mc.onPress = function() {
this.startDrag();
drag = 1;
};


/*We stop dragging and set the drag value to 0*/

object_mc.onRelease = function() {
this.stopDrag();
drag = 0;
};


/*This part controls the momentum of the drag on stopDrag()*/

onEnterFrame = function () {

/*If we are dragging the object (and we can tell we are because drag == 1) then we gather information on the trajectory of the drag for ready for when we stop drag. We do this by comparing the X and Y position of the object between frames and so finding out its X and Y velocity. This is stored in the variables trajh and trajv.*/

if (drag == 1) {

/* Calculate Y trajectory/velocity*/

posBv = posAv;
posAv = _ymouse;
trajv = posBv-posAv;


/* Calculate X trajectory/velocity*/

posBh = posAh;
posAh = _xmouse;
trajh = posBh-posAh;
}


/*If the object has stopped being dragged (and we can tell because drag == 0) we then apply some momentum so the object keeps moving after it is let go. We do this by telling the X and Y position of the object to keep moving each frame with the value of the X and Y velocity as stored in the variables trajh and trajv. However we also apply some friction by reducing the value of trajh and trajv a little on each frame. We do this by dividing the variables trajh and trajv by the friction value on every frame and then setting trajh and trajv to have this new value.*/

if (drag == 0) {
trajh = (trajh/friction);
trajv = (trajv/friction);
_root.object_mc._x -= (trajh);
_root.object_mc._y -= (trajv);
}
};


And that's your lot.

CTRL ENTER to test your movie. You will find you can click and drag the object on the stage and if you let go while moving it will carry on with momentum but come to a gradual halt.

You can increase or reduce the amount of friction the object encounters on release by changing the value of the friction variable. Remember, the more friction the quick it slows, the less friction further it travels (like on ice). Have fun experimenting.

Summary

Although this was inspired by my experience of the SMART Table, it won't ever be that versatile because while the SMART table can handle several kids all working at once, Flash will always be limited by the number of "mouse" type inputs your computer supports at once. Usually one.

But we interactive media types don't care for such trifling limitations. Inspiration is one thing, and application is another. I don't have to make a SMART Table clone.

I can still use my flash experiment in a variety of ways to spice up my interactive applications, so the inspiration and the experiment was worth it.