Friday, 10 October 2008
Switches and Key Listeners for Game Controls
Rather than dive straight into graphics I followed the best practice and began making the code work first. What follows is the simple beginnings of a game control script that uses a key listener object to check what key the player is using. Then, instead of using if else as I might usually be tempted to do I decided to use a switch to check which key is being pressed and change the direction of acceleration accordingly. For this to work for you, all you need to do it dump a movieclip onto the stage with the instance name "ship_MC", then copy the following code into your first key frame:
/*Up, down, left and right keys control direction. Space is the emergency brake.*/
/*Set initial values for direction and speed, and the rate of acceleration */
xspeed = 0;
yspeed = 0;
accelerate = 1;
/*Create the key listerner object*/
var myControlKeyListener:Object = new Object();
/*Set up a conditional response to the key press that changes the value of xspeed and yspeed depending on which key is being pressed and for how long.*/
myControlKeyListener.onKeyDown = function() {
switch (Key.getCode()) {
case Key.SPACE :
trace("space");
xspeed = 0;
yspeed = 0;
break;
case Key.LEFT :
trace("left");
xspeed -= accelerate;
break;
case Key.UP :
trace("up");
yspeed -= accelerate;
break;
case Key.RIGHT :
trace("right");
xspeed += accelerate;
break;
case Key.DOWN :
trace("down");
yspeed += accelerate;
break;
}
};
/*Add the key listener*/
Key.addListener(myControlKeyListener);
/*Animate the direction and velocity of the ship_MC movie clip according to the value of xspeed and yspeed */
onEnterFrame = function () {
this.ship_MC._x += xspeed;
this.ship_MC._y += yspeed;
};
The comments between the /* */ in the code above explain how it works. If you have not used switch before, and tend to stick to if else you will find in some cases that switch is much easier to work out the logic for and takes less typing.
Demo SWF
Monday, 1 September 2008
Flash Projects - #4 - Custom Video Player Dynamic Menu
Having programmed a custom FLV player in Flash, I wasn't satisfied with hard coded video selection menu. This would mean that whenever I want to add another video would I need to edit the source file, add another button, add the actionscript for the button, recompile the movie and re-upload the movie - with all the attendant cacheing issues. Not a great approach.
Better would be to have the video selection menu generate itself dynamically from data in an XML file. This way I would only have to compile the video player once, but could update the menu by uploading a new XML file.
I hunted down some code on the web (I forgot the URL or I would link to it), it didn't work but with a minor tweak I was left with the following:
xStart = 0;
yStart = 0;
bWidth = 101;
bHeight = 35;
menuXml = new XML();
menuXml.ignoreWhite = true;
menuXml.onLoad = loadVidData;
menuXml.load("menu.xml");
function loadVidData() {
for (var i = 0; i<this.firstchild.childnodes.length; i++) {
var bn = this.firstChild.childNodes[i].attributes.buttonName;
var b = _root.menuHolder_mc.attachMovie("button", bn, i);
b._x = xStart;
b._y = yStart+(bHeight*i);
b.txt = bn;
b.onPress = function() {
//trace(this.txt);
_root.video_ns.play(this.txt+".flv");
currentvid = this.txt+".flv";
_root.heading = this.txt;
};
}
}
Essentially it sets a few variables to start with - the starting co-ordinates of the menu when it builds (xstart and ystart), and the dimensions of the buttons that make up the menu (bWidth and bHeight). You can set your own values for these to suite your design.
Then it creates an XML object and loads an XML file called "menu.xml". If you choose to name your XML file differently, make sure you change it in the Actionscript too.
The next part builds the menu based on the content of the XML file by attaching a copy of the button library item (more about this later) for each entry in the XML file. It positions each button one below the other based on the bHeight value you set earlier.
The text on each button is also taken from the XML file variable txt.
Then we have the Actionscript that tells the button what to do when clicked. In this case it tells the video_ns netstream object to play a file with the name defined by the XML variable txt. (The Actionscript adds the file extension .flv to the end of the value defined in the XML variable txt).
We also set the currentvid variable (purpose explained in the other tutorial).
Finally we set a variable called heading to have the same value as the XML variable txt. This is used to display the title of the video in a dynamic text box.
Putting It All Together
The Menu
First create a movie clip to be used in your menu as a button. This will be repeated vertically for each video file in the XML file. The button needs to have a dynamic text box on it to display the name of the video that will be shown when it is clicked. The variable name of the dynamic text box should be txt.
Right click the button in the library and select "linkage". Set the movie clip to export for Actionscript and give it the identifier "button".
Then create an empty movie clip on the stage, and give it the name menuHolder_mc. The script above will actually fill this empty movie clip with the menu, this makes it possible to adjust the position of the menu visually, by moving the positio of the menuHolder_mc movie clip. (It will also allow us to animate the movie clip in a future tutorial).
The Title
Create a dynamic text box with the variable name heading. Put it where you want it on the screen.
The XML File
Now the flash movie is done we need to format an XML file in such a way that the Flash movie will be able to parse it to make our menu. Sample XML code follows:
<?xml version="1.0" encoding="iso-8859-1"?>
<menu>
<menu buttonName = "Vid 1"/>
<menu buttonName = "Vid 2"/>
<menu buttonName = "Vid 3"/>
<menu buttonName = "Vid 4"/>
<menu buttonName = "Vid 5"/>
<menu buttonName = "Vid 6"/>
</menu>
You can enter as many <menu buttonName = "video file name without file extension goes here"/> lines as you like. Just make sure you put the exact file name, minus file extension. If, for instance, your file name is "Summer Holiday.flv" you put "Summer Holiday".
The Flash movie can cope with spaces in the filename, and don't forget, it is the filename that is being used to label the buttons, so I recommend you name your files with the title of the films and with spaces.
Let's face it, "Summer Holiday" reads a lot better than "holiday_video_001" on the video select menu.
Finishing Off
All you need to do is make sure the XML file, the Flash movie video player, and the FLV files listed in the XML file are all in the same folder. Then it should just work.
Anyway, as I said, it is pretty late (01:30am) for me, so I know the above is not as clear as it could be. I will rewrite in a few days.
Friday, 29 August 2008
Well that didn't take long - Carrara 5 Pro - free on a magazine again!
I'm not saying I was right, but it is pretty well timed. Only a couple of posts ago I was speculating that Caligari's give away of TrueSpace 7.2 might be their answer to Daz giving away Carrara 5 Pro on 3D World magazine, and we should expect the next move from Daz.
Guess what! Daz is giving Carrara 5 Pro away again - this time on Computer Shopper (sold in the UK for the princely sum of £4.99) - a magazine with a massive distribution. They might as well let people download it from the Daz website now, anyone in the UK who ever planned on buying Carrara 5 will just buy Computer Shopper instead. But I suppose there is the bandwidth issue, the download would be so popular it would seriously slow up their servers so this is just another way of getting market penetration.
Read about it on the Computer Shopper website here (Note, the content of the linked page will change next month) >
Meanwhile, where can we expect the next move? I think it's about time Maxon gave something away. I've not seen any offerings from them since Cinema 4D 6SE way back in about 2002. Can they feel their market share shrinking around them? Free is a hard price the compete with, and let's face it, Carrara 5 Pro and TrueSpace 7.2 are both pretty able programs. The workflow, or habit, (or even snobbery) that keeps some users loyal to ridiculously high priced software can only stand up to so much.
As software like Carrara keeps increasing its power it is only a matter of time before the devoted Max user begins to wonder what extra they are getting by paying $3495.00 for their license instead of the $549.00 they could pay for Carrara 6.
I predict that for most users, the added extras that come with Max are of a very niche nature, and lots of people could switch to Carrara and still produce what they want at the end of the day. Blender is in the running too, at an even lower price of free, but its unusual interface would make a quick switch too jarring for most users.
This developing situation reminds me of Quark Xpress. Originally a one product company that dominated the print publication industry as the "standard", sold for a high price and according to an old lecturer of mine didn't offer much of an academic discount. So Adobe launches InDesign with seamless integration with the other Adobe products the designers are already using, at a much lower price, and they practically gave it away for educational purposes. Even little Serif kept building their PagePlus until even that was hailed by industry journals as being a professional level DTP package at a budget price.
The result? Quark gave away a full copy of their Xpress software on a magazine for the first time ever around a year ago (it happened to be Quark Xpress 5). Were they feeling the pinch of shrinking market share? I reckon so. It would be interesting to look at their pricing structure now to see if they charge as much as they did back in their heyday of the mid 1990s.
I use this as an example that, no matter how "industry standard" a product is today, a new product is being developed right now that is just as good, just as powerful for every common application, and it is being sold at a fraction of the price (and in some cases given away).
One day many users will wake up and find that they can use this cheaper product for everything they need, and wonder why they should pay 6 times as much for the niche gizmos they never used anyway. And this is how market share is eroded.
Let the battle continue.
Friday, 22 August 2008
Online Developer Tutorials from .NET
I have long since been a fan of the tutorials provided by Computer Arts. But only today did I learn that .NET magazine also has some seriously useful tutorials too.
Ranging from CSS to Flash they are well worth adding to your browser favourites. Check out their repository here:
http://www.netmag.co.uk/zine/develop
Saturday, 16 August 2008
TrueSpace 7.6 FREE?
Occasionally, as I look around at free software for creative purposes, I am genuinely suprised by some amazing give-aways. Usually these freebies come with one of the well known digital design journals like Computer Arts, 3D World or DigitalArts (formerly Digit).
This time though, it is well known 3D Software developer Caligari that is giving away their hard developed wares, and not even limiting it to magazine readers. This time you can download Truespace 7.6, their latest version, absolutely free. All you need to do is click the link on the home page, and set up a free membership account if you don't already have one.
What are you waiting for? Download it now >
Caligari have given away TrueSpace before. V1 and V3 have both been available for a while, but this is the first time they appear to have given away their latest version, and by the looks of things it is pretty powerful.
See how it compares with more well known competitor products:
I actually found out about this amazing offering when reading on the Computer Arts website, what the content of the new 3D World issue was going to be, then promptly zoomed over to Caligari to see for myself.
The reasons for this daring move by Caligari are to be discussed in the new issue of 3D World (which I don't have yet), but I can't help wondering if this has something to do with Daz 3D's move to give away Carrara 5 Pro on a magazine a few months ago. If so, watch Daz, because that is where the next move may be.
Whatever the reason, high competition in the 3D software industry has to be a factor, and so a good thing in the short term. The problem with this type of competition is that there are likely to be casualties, and that may hurt if you have developed a workflow around software from a company that goes under, or stops developing that title.
But while that is largely out of the control of most of us, make hay while the sun shines and download TrueSpace 7.6 today, free.
Thursday, 14 August 2008
Flash Projects - #3 - Custom FLV Player
Although both programs are fine, FLV is much the up-to-date way of showing video in Flash so I hope you find this useful. feel free to leave comments or questions.
Getting Started
To keep things organised I like wherever possible to keep all my code in one place. All the ActionScript in this tutorial should be attached to the first key frame in your movie.
Unlike the version of the video player that played SWF movies, we cannot use loadmovie to simply show a movie within a movie. FLV files require us to use NetConnection and then NetStream to stream the FLV file from its location.
First off then we need to create a new NetConnection called "myConnection_nc":
var myConnection_nc:NetConnection = new NetConnection();
myConnection_nc.connect(null);
Now we need to create a NetStream called "video_ns" that will stream through the NetConnection you made above:
var video_ns:NetStream = new NetStream(myConnection_nc);
Now we have created a NetConnection and a NetStream through which we will stream the FLV file, we need to create a video object on the stage through which the FLV will be displayed.
First, you need to create a new Embedded Video object in the library. To do this, click the little menu in the corner at the top of the Library and select the "New Video" option. It should appear in the Library as "Embedded Video 1". Then drag an instance of the Embedded Video 1 onto the stage and give it the instance name of "my_video".
Now we are ready to attach the NetStream created above to the video object you just placed on the stage called "my_video":
my_video.attachVideo(video_ns);
Now we need to do two things. First, we need to find out how long the FLV file is (its duration), second we need to set the value of the duration variable equal to the property of the duration object. This will allow us to control the playback of the FLV later on.
To do this we first use prototype.OnMetaData to find the duration of the video - this only works with FLV 1.1 files and later, earlier versions do not include duration in metadata.
Unfortunately there is no other way of finding the duration of an FLV file (you can't use the _totalframes method like you can in SWF files).
Then we can set the value of the duration variable to be equal to the duration property of the FLV file as defined in the FLV's MetaData. Here goes:
NetStream.prototype.onMetaData = function(obj){
var duration = obj.duration;
}
Video Selector
Now for the playback controls. The simplest control is the video selector. This allows the user to choose which video they want to watch.
First create a button in the Library, then drag two instances of the button onto the stage. Give the buttons the following instance names - "m1_btn" and "m2_btn".
Because we are playing FLV files and not SWF files, we cannot use the loadMovie method. Instead we need to tell the NetStream object we created earlier, to play and tell it which FLV file to play. We create code for each of the buttons we created earlier, so that when each is clicked, the NetStream object we created streams a different FLV file to the video object:
_root.m1_btn.onRelease = function () {
video_ns.play("video2.flv");
currentvid = "video2.flv";
}
_root.m2_btn.onRelease = function () {
video_ns.play("video1.flv");
currentvid = "video1.flv";
}
The code above does two things when the button is released. First, it tells the NetStream object called "video_ns" to play a specified FLV file. Secondly it sets the value of a variable called currentvid to be the same as the name of the FLV file - this helps us later on when we are programming the playback controls.
Rewind Button
Dead easy. Create a button in the Library that looks like a rewind icon. Drag an instance of the button onto the stage and give it the instance name of "rw_btn". Then add the following code to the first key frame with the rest:
_root.rw_btn.onRelease = function () {
playpos = video_ns.time;
if (playpos > 10)
{
video_ns.seek(playpos-10);
}
else
{
video_ns.seek(0);
}
}
The code above makes the video jump back 10 seconds when the rewind button is clicked. It might seem pretty complex considering that all we want to do is rewind a bit. What it actually does first is check how far into the video we have progressed and the reason for this is that we don't want to jump back to a point before the video starts, that would be impossible. Depending on how far the video has played the code then does one of two things. If the video has played more than 10 seconds, then it tells the NetStream object to jump back 10 seconds in the FLV, if the video has not yet been playing for more than 10 seconds it tells the NetStream object to go back to the beginning of the FLV.
I found that in practice, with large FLV files, the rewind is not always reliable, and can get "stuck" at points, refusing to rewind past them. I suspect this is something to do with the FLV itself, rather than the coding - however, I have also included the option of clicking on the progress bar to jump to any point in the video, which so far has proved very reliable - this is explained later in the tutorial.
NOTE: If you made the previous video player that used SWF instead of FLV files, you will notice that we are using a lot of different methods. Most significant is that with FLV we cannot gotoAndPlay specific frames as we can with SWF files. Instead we use the seek method, and it is the NetStream object called "video_ns" that we are instructing to seek, not the video instance on the stage.
Forward-wind
This is much more straightforward. As before, create a button in the Library that looks like a forward-wind icon. Drag an instance of the button onto the stage and give it the instance name of "fw_btn". Then add the following code to the first key frame with the rest:
_root.fw_btn.onRelease = function () {
playpos = video_ns.time;
video_ns.seek(playpos+10);
}
This isn't nearly as complex. When the forward-wind button is released the code sets the value of a variable playpos to the current time position of the movie using video_ns.time. It then simply uses the seek method to tell the NetStream object to jump forward 10 seconds from the current time position in the FLV.
Play and Pause Button
Now we get more complex. For my player I opted to have the Play and Pause buttons be the same button, but have the icon on the button change depending on whether the movie is playing or not. If the movie is playing, the pause icon is visible, telling the user they can click to pause. If the movie is paused, the play icon is visible, telling the user they can click to play.
To accomplish this the play/pause button is not a button at all - it is a movie clip. The movie clip has two frames, one frame with the play icon, the other with the pause icon. The frames are then given labels - "pauseon" and "pauseoff". This allows us to dynamically change which frame is currently visible, and therefore the appearance of the play/pause button. Create a movie clip that does all that, then drag an instance of it to the stage and give it the instance name of "pause_mc". Then add the following code to the first key frame in the root timeline with the rest:
video_ns.onStatus = function() {
if (video_ns.time >= duration-1){
playstatus = 2;
_root.pause_mc.gotoAndStop("pauseon");
}
else
{
playstatus = 1;
_root.pause_mc.gotoAndStop("pauseoff");
}
}
The code above uses a change in the NetStream status to trigger a check. The code checks whether the current position within the FLV file is greater than or equal to 1 second from the end of the file. If so it sets the value of the playstatus variable to "2" (we use this later), and tells the play/pause button to move to the frame labelled "pauseon", so the button shows the pause icon, telling the user they can click to pause.
If the current position within the FLV file shows there is more than 1 second of the movie left to play, then the code sets the value of the playstatus variable to "1", and tells the play/pause button to show the frame labelled "pauseoff", so the button shows the play icon, telling the user they can click to play.
the above code just sets the playstatus variable, and changes the visual appearance of the play/pause button. Now we need to enter the code that actually controls the playing and the pausing. Add the following code to the first key frame in the root timeline with the rest:
_root.pause_mc.onRelease = function () {
if (playstatus == 1)
{
video_ns.pause();
_root.pause_mc.gotoAndStop("pauseoff");
}
else if (playstatus == 2)
{
video_ns.play(currentvid);
}
}
This is where lots of the variables we have been setting earlier, with no visible purpose, suddenly become useful. The code above runs whenever the play/pause button is released.
First it checks the value of the playstatus variable. If the value of playstatus is "1" (which means the FLV file has more than 1 second left to play - see above), then it tells the NetStream object called "video_ns" to pause, and tells the play/pause button to show the frame labelled "pauseoff", so the button shows the play icon, telling the user they can click to play again.
If the value of playstatus is "2" (which means the FLV file is in its last second of playback - see above), then it tells the NetStream object called "video_ns" to play the FLV file again, and uses thevalue of the currentvid variable, which was set when the user click the button to select which video they wanted to see, to tell it which FLV file that was. This currentvid reminder is needed because we are playing FLV files and so must use NetStream and not loadmovie as we would if we were playing SWF files. With loadmovie the SWF file remains loaded into memory and so the program does not need reminding which movie to play because it still has it, with NetStream the file is streamed from its location and not kept in memory - this is why the currentvid variable was needed, to remind the program which FLV to play, without the user having to select it again using one of the video selector buttons we created right at the beginning. This is all about making it work more smoothly for the user - trying to make it work how they expect, rather than expecting them to learn the quirks of how your's works.
Progress Bar
No video player is complete without a progress bar telling the user how quickly the video is progressing, where they are in the video timewise, and how long is left.
To create the progress bar graphics, draw a rectangle on the stage to represent the video progress bar. Make sure the rectangle has a fill and a stroke. Then select the filled area only, press F8 and convert it into a movieclip called progbar. Make sure you set the registration point of the symbol to be top left. Then select the stroke that outlined the rectangle, again press F8 and convert it into a movieclip called progbarframe. Again make sure you set the registration point of the symbol to be top left. Give each an instance names "progbar_mc" and
"progbarframe_mc".
Add the following code to the first key frame in the root timeline with the rest:
onEnterFrame = function() {
comppc = video_ns.time / duration;
_root.progbar_mc._width = _root.progbarframe_mc._width*comppc;
}
The above code sets a variable called comppc with a value that comes out of dividing the current position of the FLV movie in seconds with the duration of the movie in seconds. This gives comppc a a value between 0 and 1. A value of 0.5 would mean the movie was half way through. We then multiply the maximum width of the progress bar (based on the width of the progbarframe_mc) by the value of comppc to set the current width of the progress bar. By using onEnterFrame the progress bar updates several times per second as the movie plays, thus giving an accurate graphical representation of how far the movie has to go.
Progress Bar Jumper
Now we want to make it so the user can click anywhere on the progress bar and jump to that part of the movie. Add the following code to the first key frame in the root timeline with the rest:
_root.progbarframe_MC.onRelease = function() {
barleft = _root.progbarframe_MC._x;
jumppos = (_xmouse-barleft)/_root.progbarframe_MC._width;
if (playstatus == 1)
{
video_ns.seek(Math.round(jumppos*duration));
}
else if (playstatus == 2)
{
video_ns.play(currentvid);
video_ns.seek(Math.round(jumppos*duration));
}
}
The above code is probably the most complex part of the whole program. Funny how the luxuries, the "optional extras", that provide the least functionality are often the most complicated parts of the program.
First we define a variable for the left side of theprogress bar called barleft. This gives us a zero point against which to measure the location of the user's click on the progress bar. Then we define a variable that represents the users click on the progress bar called jumppos.
The value of jumppos is defined by getting the X coordinate of the mouse when the bar is clicked and then subtracting from that the value of barleft (the X coordinate of the the start of the bar). This tells us how far along the bar the user clicked. This number is then divided by the total width of the bar to give a number that represents how far along the bar the user clicked as a value between 0 and 1. A result of 0.5 would mean the user clicked in the middle of the bar.
We then tell the NetStream object to seek to the point in the movie corresponding to where the user clicked on the bar. This is calculated by multiplying the value of jumppos (where on the bar the user clicked) by the value of the duration of the FLV file in seconds. However, I have also used Math.round to convert the result into an integer (by rounding up or down to the nearest whole number). This just helps keep things tidy and means the FLV will jump to a whole second, rather than a fraction of a second which may not exist.
If the value of playstatus is "1" then we just attempt to seek straight to the relevant point in the FLV file. However if the playstatus is "2" this means there is only 1 second or less of the movie to go, so to make sure it works and we get no glitches, we tell the NetStream object to play the currentvid from the beginning and then seek to the relevant point in the FLV file. We have to do this because, as mentioned before, with NetStream the video is not stored in memory, and so if there is less than 1 second left in the video, the streaming might be over before Flash has a chance to seek to another part of the movie. By telling the video to start again using the currentvid variable to remind it which video, and then seek to the relevant point, we can get a smoother operation.
Converting Video to FLV Format
Of course, for this player to be any use, you need to be able to convert your video to FLV format.
One programme that has worked for me without trouble is Free Video to Flash Converter.
It is completely freeware and can convert video into SWF or FLV. You can even export video with its own player interface - and, while this defeats the object for my use of it, since I wanted a custom interface of my own design, some people may find this feature helpful.
The program is pretty self explanatory, all you need to do is remember to export the movie as a FLV and save it with the name you programmed into your player and in the same directory as the player.
The End
And there we have it. Export your player as a SWF into the same directory as the FLV files you linked to and it should just work. Any problems, leave a comment and I will try to help.
Playing Sound with your Computer Keyboard - Flash
He had already produced a prototype that worked by clicking each drum with the mouse, but was not happy with the inability to play the drums properly on it. To play drums you need to be able to switch instrument quickly and at times strike two instruments at the same time. You can't do this with a single mouse and clicking on each drum. It's like playing the drums with one stick.
He had the idea of allowing the user to play the drums using the keys on their computer keyboard, but was unsure how to proceed. Unable to leave teacher mode with a challenge like this I put together the following code.
Stage 1
Create a new AS2 Flash file and insert the following code into the first keyframe:
//This attaches the sound for drum 1, make sure you did the linkage thing in the library
var sound1:Sound = new Sound();
sound1.attachSound("drum_1");
//This attaches the sound for drum 2, make sure you did the linkage thing in the library
var sound2:Sound = new Sound();
sound2.attachSound("drum_2");
//This code listens out for the user to press a key, then, depending on which key is pressed will trigger one of the sounds attached above.
var myDrumKeyListener:Object = new Object();
myDrumKeyListener.onKeyDown = function () {
if (Key.getCode()==65) {
sound1.start();
} else if (Key.getCode()==66) {
sound2.start();
}
}
Key.addListener(myDrumKeyListener);
Stage 2
(Key.getCode()==
and then there is a number, this number is the keycode for the key that plays the sound. You can find a list of keycodes online here:
http://livedocs.adobe.com/flash/mx2004/main_7_2/wwhelp/wwhimpl/common/html/wwhelp.htm?context=Flash_MX_2004&file=00001113.html
Stage 3
Now you need to add the actual sound files. Do this by importing the sounds into the Library. Then right click the first sound and choose "Linkage" from the menu. Select the "Export for Actionscript" and "Export in First Frame" options. Then make sure you give the sound an identifier. This is the name by which the sound will be referenced in the actionscript above. I called the sound for the first drum "drum_1". Then in the actionscript it is referenced as follows:
var sound1:Sound = new Sound();
sound1.attachSound("drum_1");
If you put a different name as the identifier, make sure you also change it in the actionscript.
Once that's all done you can press "OK". Then just repeat Stage 3 for each sound in the library.
And that is about it.
The challenge for my ex-student then, is to modify the code to include more drums and have them respond to an appropriate range of keys on the keyboard.
Have jolly fun.
Demo SWF
Saturday, 26 July 2008
Uke Tuner - Flash Based Ukulele Tuning Application
Now that I teach interactive media, rather than practice commercially for a living, I sometimes get fidgety, wanting to do more of my own but never having the time.
Finally the holiday's arrived and I was able to get inspired, on account of my wife buying a Ukulele. She was using an online tuning system, but it wasn't as helpful as it could have been. The problem with the online tuning system, was that it only gave audio samples of a Ukulele string being plucked. However it is much easier to tune an instrument to a continuous tone. In Uke Tuner I gave the option, plucked note, or continuous tone, so the user can choose their preferred method. Then of course I went overboard on graphics and interactivity - just for the fun of it.
You can download Uke Tuner 0.92 (Beta) here free >
For the more technically minded, graphics were produced in Fireworks then exported as PNG 32 to preserve alpha channels or SWF, for use in Flash. Audio was recorded from a Yamaha PSR-240 keyboard via a line-in cable from the keyboard's headphone socket. Sound was recorded and processed with Audacity then exported as WAV 32-bit for use in Flash. Interactivity was produced in Flash, with ActionScript 2. Flash Audio settings were set to export sound at 22Khz stereo and 128kbps. Playback speed is 30 fps to make it animate more smoothly. The application was compiled with MDM Flash Studio because it has a faster projector engine than the Flash Standalone Player, extends the ActionScript classes available in Flash with some additional functionality, and allows the creator to tweak the display options (such as turning off the blue bar at the top).
Sunday, 20 July 2008
Accessibility and Colour Blindness
While it certainly doesn't make life easier for an Art & Design & Interactive Media student it doesn't make it impossible to work in the design industry either. I did know of a former product designer, who was colour blind, who had a successful career in industry and in teaching.
Even so, as a teacher, it is helpful to have some understanding of colour blindness so I know what to expect, and can help the student develop strategies to cope with areas of difficulty.
One resource I found recently is a website called Vischeck.
Vischeck provides colour blindness simulation tools, including an image previewer, a website previewer and a Photoshop filter. The site also gives information about a Daltonization algorithm for correcting images for colour blind people. All fascinating stuff.
I downloaded the Photoshop filter and installed it for Photoshop and Fireworks. It works fine in both.
I wondered how the normal visible spectrum would look to a colour blind person, and so I used the Photoshop filter to adjust a bog standard colour wheel. The results were truly astonishing:
I just cannot imagine a world so radically different to the one I see now.
Now I know why my student picked a muted grey/green instead of a vibrant green to represent grass in a client visual. To them they looked the same.
This insight into how colour blind people actually see the world is probably the most valuable outcome of this find. Meanwhile the Photoshop filter will allow me to demonstrate it to other people, and to gauge usability of my own designs.
Monday, 17 March 2008
Creative Reading
Saturday, 8 March 2008
Parallax Mapping
Parallax mapping finally begins to overcome the problem with all the other mappings (texture, bump and normal), which is that they all look painted on and flat when viewed up close, especially at an angle.
That is because they are in effect painted on. Parallax mapping works by actually displacing the coordinates of the texture, so that bumps actually obscure dents as you move round in 3D space. Hoorah.
Comparison of mapping methods (Brown University, Rhode Island) click to enlarge.
Friday, 7 March 2008
Normal Mapping
Why do I care? Basically as an interactive media blokey, I am interested in this latest method of adding detail and realism to games.
To begin with 3D games were made using very low res meshes and texture mapping. Bump mapping adds more realism by adding a little height and depth to a surface texture on the polygons - this is done using a grayscale image to represent the height of the bumps, (the lighter the pixel the higher the altitude etc.) but it still looks like blocks with textures. To remove the blockiness of the models you would expect to have to increase the number of polygons they are made up of. This is no good for games where the computer has to render 30+ fps on the fly. This is where normal maps help.
To really grasp this you need to know what a normal is >.
Normal mapping works on a similar principle to bump mapping in that it is essentially a graphic wrapped round a mesh, but it goes much further. Normal maps use an RGB image which instead of containing just height data in each pixel contains the X Y Z 3D orientation of the normal.
These then render much more realistically almost as though they were meshes themselves and have the added bonus of rendering faster. This allows PC's and games consoles to increase the apparent level of detail in the models without increasing the polygon count.
Saturday, 16 February 2008
Flash Projects - #2 - Converting Video to SWF
The reason for this, as I mentioned at the introduction of the last tutorial, was because I wanted to have a video player that worked with the features of Flash MX 2004 standard (which lacks the additional video capability of MX 2004 Professional).
One of the limitations with the standard version of Flash was that it could only encode video to be embedded in the timeline; this would then be exported in SWF format (not FLV).
Note: Freeware applications for converting video to FLV however have become more commonplace, so I have already begun work on a player that uses the netconnect and netstream capabilities of Flash to play FLV videos instead. Look out for this tutorial in a few weeks. Meanwhile...
So how do you encode video to SWF?
You can use Flash to encode video to SWF or some available freeware.
The Flash method
If you have Flash you can do it very easily by choosing File > Import > Import Video.
Flash MX 2004 standard will only encode video to be emdedded into the timeline, Professional and later versions give more options - make sure you select the option that embeds video into the timeline.
Work your way through the wizard and when the video has encoded, make sure the document size (and the video) are the right size for your player (see previous tutorial).
Then export the movie as a SWF and save it with the name you programmed into your player and in the same directory as the player.
All done. However I tend to find that Flash takes an excessively long time over encoding video, and sometimes prefer to use a freeware programe that seems a bit quicker.
The freeware method
One programme that has worked for me without trouble is Free Video to Flash Converter.
It is completely freeware and can convert video into SWF or FLV. You can even export video with its own player interface - and, while this defeats the object for my use of it, since I wanted a custom interface of my own design, some people may find this feature helpful.
The program is pretty self explanatory, all you need to do is remember to export the movie as a SWF and save it with the name you programmed into your player and in the same directory as the player.
And thats it. Again any problems just leave a comment and I will try to help.
Friday, 15 February 2008
Flash Projects - #1 - Movie Player
I first figured this out because I wanted to have a video player but was running Flash MX 2004 standard and so lacked the Video features of Professional.
Download Files
Click here to download source code and files for this tutorial >
Introduction
This tutorial teaches you to build a video player interface only that loads and plays external video files when requested by the user. This means the finished SWF is very small and downloads quickly.
The player includes the following features:
- Playback window
- Play
- Stop
- Fwd
- Rwd
- Clickable progress bar
Note: While for users of Pro flash versions much of this may seem irrelevant because of the pre-compiled video players and skins available. However this project will show you how you can build a completely cutomised interface, allowing your flash projects to be totally original. It also works with external linear SWF animations that don't contain interactivity. You will also begin to understand how you can control playback with actionscript instead of relying entirely on components.
Here goes
First we need to create all the movieclips and buttons we need. Begin by creating the following buttons as symbols in the library:
- Play
- Stop
- Pause
- Fwd
- Rwd
You can either draw them on the stage and then convert them to symbols by selecting one and pressing F8, or you can create a new symbol directly in the Library.
Drag instances of each of them from the library onto the stage (unless they are already there) and name each instance as follows:
- play_btn
- stop_btn
- pause_btn
- rw_btn
- fw_btn
Then draw a rectangle on the stage to represent the video progress bar. Make sure the rectangle has a fill and a stroke. Then select the filled area only, press F8 and convert it into a movieclip called progbar. Make sure you set the registration point of the symbol to be top left. Then select the stroke that outlined the rectangle, again press F8 and convert it into a movieclip called progbarframe. Again make sure you set the registration point of the symbol to be top left.
Give each an instance name on the stage as follows:
- progbar_mc
- progbarframe_mc
Now draw another rectangle on the stage where you want the video clip to appear, and at the size you want it to appear. At this point it is a good idea to know what size of video you are dealing with. I tend to work with relatively small sizes like 320 x 240 for web video, but it is entirely up to you. Select the rectangle and convert it into a movieclip called vidspot. Make sure you set the registration point of the symbol to be top left.
Give it an instance name on the stage of:
- vidspot_mc
Finally you need to create some movieclips that will act as buttons that allow the user to select which video they want to watch. Add these to the stage and give them instance names as follows:
- vid1_mc
- vid2_mc
- etc...
Now we are ready to start coding. The great thing about this player is that all the Actionscript resides in the first keyframe of the movie, so there is no hunting around trying to remember where you put it all. So, create a new layer in the timeline, give the layer the name actions.
Click on the first frame on that layer (make sure it is a keyframe) and open the Actions panel. It is in this panel that all the following Actionscript needs to be entered:
User Media Select Buttons
These are the buttons that allow the user to select which video they want to watch. The way this script works is by replacing the movieclip you named as vidspot_mc with an external SWF that contains the video.
The script is as follows:
_root.vid1_mc.onRelease = function () {
_root.vidspot_mc.loadMovie("videofilename.swf","GET");
}
Type this into the Actions panel for each video you created a button for. Change the vid1_mc and the videofilename.swf to match the instance name and video file name as needed. This script assumes that the external video files are in the same directory as the movie player SWF will be when it is finally exported and uploaded to the web.
Play Button
This script is very simple, it tells whatever SWF is occupying the spot originally taken by vidspot_mc to play.
_root.play_btn.onRelease = function () {
_root.vidspot_mc.play();
}
Stop Button
This script is slightly more complex, in order to make Stop different to Pause, I decided that Stop should also automatically rewind. This script tells whatever SWF is occupying the spot originally taken by vidspot_mc to go back to the first frame and stop.
_root.stop_btn.onRelease = function () {
_root.vidspot_mc.gotoAndStop(1);
}
Pause Button
This script is very simple, it tells whatever SWF is occupying the spot originally taken by vidspot_mc to just stop where it is.
_root.pause_btn.onRelease = function () {
_root.vidspot_mc.stop();
}
This effectively pauses the movie since the play head simply stops in it's tracks. If the user presses the Play button it will simply carry on where it left off.
Rewind Button
This script is considerably more complex, this is because we don't want to rewind to a point before the movie actually starts. The "if else" in the script simply checks that we are currently more frames into the movie, than we plan to jump back. If so, we jump that number of frames back. If not we simply go to the start of the movie.
_root.rw_btn.onRelease = function () {
if (_root.vidspot_mc._currentframe > 240){
_root.vidspot_mc.gotoAndPlay(_root.vidspot_mc._currentframe-240);
} else {
_root.vidspot_mc.gotoAndPlay(1);
}
}
In this case the number 240 represents the number of frames we want to jump back each time the rewind button is released. At 24 frames per second this equates to jumping backward 10 seconds each time the button is clicked. Adjust this figure according to your needs.
Forward-wind Button
As with the rewind button, we don't want tojump BEYOND the end of the movie. This "if else" simply checks that there are still more frames remaining in the movie, than we plan to jump forward. If so, we jump that number of frames. If not we simply go to the end of the movie. Unlike rewind, where the start of the video is easily known (it being frame 1), in this case we need to know how many frames the movie has so we know the number of the last frame. The script does this by finding the _totalframes property of the video file (see line 2 below).
_root.fw_btn.onRelease = function () {
tframe = _root.vidspot_mc._totalframes;
if (_root.vidspot_mc._currentframe <>240) {
_root.vidspot_mc.gotoAndPlay(_root.vidspot_mc._currentframe+240);
} else {
_root.vidspot_mc.gotoAndStop(tframe);
}
}
In this case the number 240 represents the number of frames we want to jump ahead each time the forward wind button is released. At 24 frames per second this equates to jumping forward 10 seconds each time the button is clicked. Adjust this figure according to your needs.
Player Progress Bar
This script controls the bar that shows the viewer how far the movie has played. It is a beautiful simple script. We divide the number of the currentframe of the playing movie by the total number of frames in the movie to give us a number between 0 and 1. A result of 0.5 would mean the movie was half way through. We then multiply the maximum width of the progress bar (based on the width of the progbarframe_mc) by this number to set the current width of the progress bar. By using onEnterFrame the progress bar updates several times per second as the movie plays, thus giving an accurate graphical representation of how far the movie has to go.
onEnterFrame = function() {
comppc = _root.vidspot_mc._currentframe / _root.vidspot_mc._totalframes;
_root.progbar_mc._width = _root.progbarframe_mc._width*comppc;
}
Progress Bar Jumper
This feature did not exist in the original program I wrote, but I decided that it would not be complete unless the user could click anywhere on the progbarframe_mc and jump straight to that part of the movie. As you can see it is slightly more complex.
First we define a variable for the left side of theprogress bar. This gives us a zero point against which to measure the location of the user's click on the progress bar. Then we define a variable that represents the users click on the progress bar as a number between 0 and 1. A result of 0.5 would mean the user clicked in the middle of the bar.
Then we tell the current movie being played to jump to a particular frame number. This is calculated by multiplying the total number of frames by the number based on where the user clicked on the bar. However, I have also used Math.round to convert the result into an integer (by rounding up or down to the nearest whole number). This is vital as frame numbers are whole numbers - e.g. there is no such thing as frame 22.5 - and with Flash if the frame does not exist it simply does nothing - so Math.round gives us a whole existing frame number for us to gotoAndPlay.
_root.progbarframe_mc.onRelease = function() {
barleft = _root.progbarframe_mc._x;
jumppos = (_xmouse-barleft)/_root.progbarframe_mc._width;
_root.vidspot_mc.gotoAndPlay(Math.round(jumppos*_root.vidspot_mc._totalframes));
}
And there we have it. Export your player as a SWF into the same directory as the video files you linked to and it should just work. Any problems, leave a comment and I will try to help.
Lookout for my next post where I explain how to convert video files into SWF for use with this player.
Version 2 of the player (currently working on so watch this space) uses external FLV files rather than SWF so much more up to date.