Tired of those old-fashioned animated Christmas cards with Santa Claus laughing, a sleigh flying in the sky with a bunch of trees and sparkling lights?
This year you have no excuse. I’m going to show you how to build a virtual keyboard that plays Jingle Bells. You’ll even be able to extend the concept and add more songs and notes to the piano.
For this tut I’ll be using a combination of Tweenlite, the Flex SDK, the Flash IDE and Flash Develop.
Step 1: New File
Start Adobe Flash and create an ActionScript 3 Flash file.

Step 2: Properties
Open the properties and set the FPS to 30 and the stage size to 600 x 380px.

Step 3: Layer 1
Rename layer 1 as “background” and create a white rectangle of 580×360. Convert it to a movieclip symbol named “frame_mc” and set its position to x:10 y:10.


Step 4: Drop Shadow
Add a drop shadow filter with the following parameters:

Step 5: Keyboard Layer
Add a new layer called “keyboard”, create a primitive rectangle 60×190 with a 5 pixel corner radius and with no stroke. Make it a movieclip symbol and call it “keybase_mc”.


Step 6: Reflection and Glow Layers
Hit F8 and create a new movieclip called “key_mc”. Create two more layers inside key_mc (besides the one already present with keybase_mc). Name them: “reflection” and “glow”. Copy the frame to the newly created layers.

Step 7: glow_mc
NOTE: I’ve changed the frame_mc colors for a while to allow me to see the modifications on the keys. Select the movieclip in the glow layer, name it “glow_mc”, open the filters and edit them according to the image below:

Step 8: reflection_mc
Select the movieclip in the reflection layer, name it “reflection_mc”, open the filters and edit them to match the image below:

Step 9: base_mc
now select the movieclip in the base layer, name it “base_mc”, open the filters and edit them to match the image below:

Step 10: Key
Copy and paste the key until you end up with 7 instances. Arrange them evenly across the stage.

Step 11: Align
Open the align tool and click the “horizontal spacing” icon.

Step 12: Notes

Create a new layer, call it “notes”. Then write down C D E F G A B on the keys add the text to a new movieclip. Open the movieclip filters and edit them such as the image below:

Step 13: Numbers
Create a new layer, call it “numbers”. Write the numbers from 1 to 7, this will represent the numbers that you will press on your keyboard to make the ecard key highlight.


Step 14: Flex SDK Path
Go to edit > preferences > ActionScript > ActionScript 3.0 settings and locate your Flex SDK path (you will need this to embed files directly through code).


Step 15: Flash Develop
Open Flash Develop (I’m just using this cause I like it so much more than the usual ActionScript editor from the flash IDE when writing packages) and create 2 blank as3 files. Name them “Main.as” and “Background.as”, save them in the same folder as your .fla.


Step 16: Document Class
Inside Flash IDE set Main.as as your Document class.

Step 17: Autoplay Button
Create an autoplay movieClip and name it “autoplay_mc”. This will be an autoplay button.

Step 18: Snowflakes
To create some snow flakes falling create a new movieclip, draw a smalll white circle inside and add a linkage identifier of “SnowFlake”.

Step 19: Main.as
In Flash Develop open Main.as, define your Main class extending a movieclip and create a function called Main.
Start by importing these Classes inside your package:
import flash.display.MovieClip; import flash.events.Event; import flash.events.MouseEvent; import flash.events.TimerEvent; import flash.display.StageScaleMode; import flash.events.KeyboardEvent; import flash.utils.Timer; import com.greensock.TweenLite; import com.greensock.easing.*; import Background; //we will create a background class based on perlin noise and a transform matrix along with a few filled shapes so we can have a nice smooth transition import Snow; //i just grabbed kirupas snow and packaged it -> http://troyworks.com/blog/2008/11/26/flash-kirupa-snow-in-as30/ import flash.media.Sound;
Step 20: Variables
Inside your class define these variables:
//this will be our background private var _background:Background; //this will be our snow storm private var snow:Snow; //->notes //Embeding this way requires FLEX SDK -> alternative method is to add these sounds to your library and add a linkage ID to them. [Embed(source="assets/A.mp3")] private var A:Class; private var a:Sound = new A() as Sound; [Embed(source="assets/B.mp3")] private var B:Class; private var b:Sound = new B() as Sound; [Embed(source="assets/C.mp3")] private var C:Class; private var c:Sound = new C() as Sound; [Embed(source="assets/D.mp3")] private var D:Class; private var d:Sound = new D() as Sound; [Embed(source = "assets/E.mp3")] private var E:Class; private var e:Sound = new E() as Sound; [Embed(source="assets/F.mp3")] private var F:Class; private var f:Sound = new F() as Sound; [Embed(source="assets/G.mp3")] private var G:Class; private var g:Sound = new G() as Sound; //Storing the notes in an array will make it easier to link to the keyboard private var notes:Array = //Note sequence for the music private var noteSequence:Array = [f, f, f, f, f, f, f, a, d, e, f, g, g, g, g, g, e, e, d, b, a, f, d, c] //Current note that is playing private var curnote:Number = 0 //Sequence of delay that the music needs to have between the notes private var noteDelay:Array = [100, 100 , 300, 100, 100 ,300, 100, 100, 100,100,200, 100, 100, 200, 90, 100, 90,100, 100, 120, 120, 120, 120, 300] //Timer to play the music private var tunetimer:Timer = new Timer(noteDelay[0]);
Step 21: Main()
The Main function
//Main function waits for the the maintimeline to be added to stage
public function Main():void{
addEventListener(Event.ADDED_TO_STAGE, addedToStage);
}
Step 22: Initialize
After being added to stage we’ll initialize the background and the virtual keyboard:
//when added to stage we can set a stage scale mode, the background and the start the virtual piano
private function addedToStage(e:Event):void {
stage.scaleMode = StageScaleMode.NO_SCALE;
addBackground();
startMachine();
}
Step 23: Background Effects
Let’s sort out the moving background and the Snow:
//adds the background
private function addBackground():void {
_background = new Background(150,150); //the reason the size is smaller is because it's very CPU intensive
_background.x = 5; //to give a white margin for the frame
_background.y = 5;
_background.width = 570 //scale it up to the size right size
_background.height = 350
frame_mc.addChild(_background); //adds background to the frame
snow = new Snow(570, 350) //creates a snow storm instance
Step 24: Virtual Keyboard
The initialization of the virtual keyboard
private function startMachine(e:MouseEvent = null):void {
//associates the keyboard events
stage.addEventListener(KeyboardEvent.KEY_DOWN, onkeyDown)
stage.addEventListener(KeyboardEvent.KEY_UP, onkeyUp)
//associates an autoplay method to the autoplay button
autoplay_mc.addEventListener(MouseEvent.CLICK, startAutoPlay);
autoplay_mc.buttonMode = true;
//associates the notes to the keys
var i:int = 0
while (i < 7) {
this["key"+i].note = notes[i]
i++
}
//makes the highlight of the keys disappear
lowlightKeys();
}
Step 25: Highlight
We need to create a function to remove the highlight from the keys:
private function lowlightKeys() {
var i:int = 0
while (i < 7) {
TweenLite.to(this["key" + i].glow_mc, 0.5,{alpha:0} );
i++
}
}
Step 26: Key Events
Let's now handle the Key up and Key down events:
private function onkeyDown(e:KeyboardEvent):void {
var i:int=0
switch(e.keyCode) {
case 49: //keycode for 1
i=0
break;
case 50: //keycode for 2
i=1
break;
case 51: //keycode for 3
i=2
break;
case 52: //keycode for 4
i=3
break;
case 53: //keycode for 5
i=4
break;
case 54: //keycode for 6
i=5
break;
case 55: //keycode for 7
i=6
break;
}
notes[i].play();
TweenLite.to(this["key" + i].glow_mc, 0.5,{alpha:1} ); //highlights the key
}
private function onkeyUp(e:KeyboardEvent):void {
var i:int=0
switch(e.keyCode) {
case 49:
i=0
break;
case 50:
i=1
break;
case 51:
i=2
break;
case 52:
i=3
break;
case 53:
i=4
break;
case 54:
i=5
break;
case 55:
i=6
break;
}
TweenLite.to(this["key" + i].glow_mc, 0.5,{alpha:0} ); //lowlights the key
}
Step 27: Autoplay Functions
How to start and stop the autoplay
private function startAutoPlay(e:MouseEvent = null) {
curnote = 0; //everytime i start autoplay i reset the current playing note
tunetimer.delay = noteDelay[curnote] * 3 //this increases the delay set previously
tunetimer.addEventListener(TimerEvent.TIMER, autoPlayTune) //adds a listener to the timer event for everytime the timer is triggered
tunetimer.start() //starts the timer
}
private function stopAutoPlay(e:MouseEvent = null) {
tunetimer.stop() //stops timer
tunetimer.removeEventListener(TimerEvent.TIMER, autoPlayTune) //removes the event
}
Step 28: Update
Updating the virtual keyboard along with the music
private function updateMachine():void {
lowlightKeys(); // resets the keys highlights
var i:int = 0
while (i < 7) {
if (this["key" + i].note == noteSequence[curnote]) {
TweenLite.to(this["key" + i].glow_mc, 0.5,{alpha:1} ); //if current note is the one associeated with the key then highlights it
}
i++
}
curnote++ //goes to next note
if (curnote > noteSequence.length) {
curnote = 0; //resets current note
stopAutoPlay(); //stops autoplay
}
}
Step 29: The Complete Code
Here's the full Main.as code
package{
import flash.display.MovieClip;
import flash.events.Event;
import flash.events.MouseEvent;
import flash.events.TimerEvent;
import flash.display.StageScaleMode;
import flash.events.KeyboardEvent;
import flash.utils.Timer;
import com.greensock.TweenLite;
import com.greensock.easing.*;
import Background;
import Snow
import flash.media.Sound;
public class Main extends MovieClip{
private var _background:Background;
private var snow:Snow;
[Embed(source="assets/A.mp3")]
private var A:Class;
private var a:Sound = new A() as Sound;
[Embed(source="assets/B.mp3")]
private var B:Class;
private var b:Sound = new B() as Sound;
[Embed(source="assets/C.mp3")]
private var C:Class;
private var c:Sound = new C() as Sound;
[Embed(source="assets/D.mp3")]
private var D:Class;
private var d:Sound = new D() as Sound;
[Embed(source = "assets/E.mp3")]
private var E:Class;
private var e:Sound = new E() as Sound;
[Embed(source="assets/F.mp3")]
private var F:Class;
private var f:Sound = new F() as Sound;
[Embed(source="assets/G.mp3")]
private var G:Class;
private var g:Sound = new G() as Sound;
private var notes:Array =
private var noteSequence:Array = [f, f, f,
f, f, f,
f, a, d, e, f,
g, g, g,
g, g, e, e,
d, b, a, f, d, c]
private var curnote:Number = 0
private var noteDelay:Array = [100, 100 , 300,
100, 100 ,300,
100, 100, 100,100,200,
100, 100, 200,
90, 100, 90,100,
100, 120, 120, 120, 120, 300]
private var tunetimer:Timer = new Timer(noteDelay[0]);
public function Main():void{
addEventListener(Event.ADDED_TO_STAGE, addedToStage);
}
private function addedToStage(e:Event):void {
stage.scaleMode = StageScaleMode.NO_SCALE;
addBackground();
startMachine();
}
//adds the background
private function addBackground():void {
_background = new Background(150,150);
_background.x = 5;
_background.y = 5;
_background.width = 570
_background.height = 350
frame_mc.addChild(_background);
snow = new Snow(570, 350);
frame_mc.addChild(snow);
}
private function startMachine(e:MouseEvent = null):void {
stage.addEventListener(KeyboardEvent.KEY_DOWN, onkeyDown)
stage.addEventListener(KeyboardEvent.KEY_UP, onkeyUp)
autoplay_mc.addEventListener(MouseEvent.CLICK, startAutoPlay);
autoplay_mc.buttonMode = true;
var i:int = 0
while (i < 7) {
this["key"+i].note = notes[i]
i++
}
lowlightKeys();
}
private function lowlightKeys() {
var i:int = 0
while (i < 7) {
TweenLite.to(this["key" + i].glow_mc, 0.5,{alpha:0} );
i++
}
}
private function onkeyDown(e:KeyboardEvent):void {
var i:int=0
switch(e.keyCode) {
case 49:
i=0
break;
case 50:
i=1
break;
case 51:
i=2
break;
case 52:
i=3
break;
case 53:
i=4
break;
case 54:
i=5
break;
case 55:
i=6
break;
}
notes[i].play();
TweenLite.to(this["key" + i].glow_mc, 0.5,{alpha:1} );
}
private function onkeyUp(e:KeyboardEvent):void {
var i:int=0
switch(e.keyCode) {
case 49:
i=0
break;
case 50:
i=1
break;
case 51:
i=2
break;
case 52:
i=3
break;
case 53:
i=4
break;
case 54:
i=5
break;
case 55:
i=6
break;
}
TweenLite.to(this["key" + i].glow_mc, 0.5,{alpha:0} );
}
//AUTO PLAY FUNCTIONS
private function startAutoPlay(e:MouseEvent = null) {
curnote = 0;
tunetimer.delay = noteDelay[curnote] * 3
tunetimer.addEventListener(TimerEvent.TIMER, autoPlayTune)
tunetimer.start()
}
private function stopAutoPlay(e:MouseEvent = null) {
tunetimer.stop()
tunetimer.removeEventListener(TimerEvent.TIMER, autoPlayTune)
}
private function autoPlayTune(e:TimerEvent) {
if(curnote<noteSequence.length){
noteSequence[curnote].play(); //plays the note
tunetimer.delay = noteDelay[curnote] * 3
}
updateMachine()
}
private function updateMachine():void {
lowlightKeys();
var i:int = 0
while (i < 7) {
if (this["key" + i].note == noteSequence[curnote]) {
TweenLite.to(this["key" + i].glow_mc, 0.5,{alpha:1} );
}
i++
}
curnote++
if (curnote > noteSequence.length) {
curnote = 0;
stopAutoPlay();
}
}
}
}
Step 30: Background Class
Now on to the background class. We'll begin by importing these classes..
import flash.display.Shape;
import flash.events.Event;
import flash.display.Sprite;
import flash.display.MovieClip;
import flash.display.Bitmap;
import flash.display.BitmapData;
import flash.display.BlendMode;
import flash.geom.ColorTransform;
import flash.geom.Rectangle;
import flash.geom.Point;
import flash.geom.Matrix;
import flash.filters.ColorMatrixFilter;
import flash.display.GradientType;
import flash.display.Graphics;
import flash.display.InterpolationMethod;
import flash.display.SpreadMethod;
Step 31: Variables
..then defining the variables:
//Noise
private var dir:Array
private var point:Point
private var bd:BitmapData;
private var bmp:Bitmap;
private var bdmultiply:BitmapData;
private var bms:Sprite;
private var rect:Rectangle
private var cmf:ColorMatrixFilter;
private var w:Number
private var h:Number
//Linear Gradient Fill
private var gshape:Shape
private var gmetrics:Rectangle
private var gmatrix:Matrix
private var gtype:String
private var gspread:String
private var ginterpolation:String
private var gcolours:Array
private var galphas:Array
private var gratios:Array
//Solid Fill
private var sshape:Shape
Step 32: Initial Function
Here's the initial function:
public function Background($width:Number=100, $height:Number=100)
{
w = $width
h = $height
rect = new Rectangle(0, 0, w, h);
point = new Point(0, 0);
dir = [new Point(1, 262), new Point(400, 262)];
//this one is just to give a solid background to the whole stage
initBackgroundSolid();
//this will control the bightness contrast and saturation of the noise
initColorMatrix();
//there will be two noise backgrounds this will initiate them
initBackgroundNoise();
//a gradient is added so we dont get noisiated.. (get it? too much noise gets you noisiated? haha...hmmm)
initBackgroundGradient();
}
Step 33: initColorMatrix()
This function will control the bightness contrast and saturation of the noise, it's a very powerfull filter.
private function initColorMatrix():void {
cmf = new ColorMatrixFilter([2, 0, 0, 0, -20, //red
0, 2, 0, 0, -20, //green
0, 0, 2, 0, -20, //blue
0, 0, 0, 1, -20 ]); //alpha
}
Step 34: Solid Background Color
This one is just to give a solid background to the whole stage.
private function initBackgroundSolid():void {
sshape = new Shape();
sshape.graphics.beginFill(0x170a02,1)
sshape.graphics.drawRect( 0, 0, w, h );
sshape.graphics.endFill();
addChild(sshape)
}
Step 35: Noises
The noises:
private function initBackgroundNoise():void {
//first noise
bd = new BitmapData(w, h, false, 0 );
bmp = new Bitmap(bd);
bmp.smoothing = true;
addChild(bmp);
//second noise that overlaps the first noise through an overlay blend mode
bdmultiply = new BitmapData(w, h, false, 0 );
bms = new Sprite();
bms.addChild(new Bitmap(bdmultiply))
addChild(bms)
bms.blendMode = "overlay";
//renders the background so that the noise seems to be moving
addEventListener(Event.ENTER_FRAME, renderBG);
}
Step 36: Mask
Here's the gradient mask:
private function initBackgroundGradient() {
//this is a basic gradient box with alpha and rotated 90º so that it starts from top-bottom instead of left-right
gshape = new Shape();
gmetrics = new Rectangle();
gmatrix = new Matrix();
gtype = GradientType.LINEAR;
gspread = SpreadMethod.PAD;
ginterpolation = InterpolationMethod.LINEAR_RGB;
gcolours = [ 0x170a02, 0x170a02 ];
galphas = [ 0, 1 ];
gratios = [ 0, 255 ];
gmatrix.createGradientBox(w, h,(Math.PI/180)*90 );
gshape.graphics.clear();
gshape.graphics.beginGradientFill(gtype, gcolours, galphas, gratios, gmatrix, gspread, ginterpolation );
gshape.graphics.drawRect( 0, 0, w, h );
gshape.graphics.endFill();
addChild(gshape)
}
Step 37: Render
It's render time!
private function renderBG(event:Event):void {
//updates noise direction
dir[0].x-= 1.5
dir[0].y-= 0 //these are here for you to play with
dir[1].x-= 0 //these are here for you to play with
dir[1].y -= 0 //these are here for you to play with
//defines the first background bitmap to have a perlin noise
bd.perlinNoise(w, h, 2, 10, false, true, 7, true, dir);
//coloring time (play with these values)
bd.colorTransform(rect, new ColorTransform(1, 0.7, 0.5));
//aplies the brigthness contrast and saturation modifications made earlier
bd.applyFilter(bd, rect, point, cmf)
//the other perlin noise
bdmultiply.perlinNoise(w, h, 3, 21, false, true, 7, true, dir)
//the other perlin noise collors
bdmultiply.colorTransform(rect, new ColorTransform(1, 0.6, 0.4));
}
Step 38: Complete Background Class
Here's the whole background Class:
package
{
import flash.display.Shape;
import flash.events.Event;
import flash.display.Sprite;
import flash.display.MovieClip;
import flash.display.Bitmap;
import flash.display.BitmapData;
import flash.display.BlendMode;
import flash.geom.ColorTransform;
import flash.geom.Rectangle;
import flash.geom.Point;
import flash.geom.Matrix;
import flash.filters.ColorMatrixFilter;
import flash.display.GradientType;
import flash.display.Graphics;
import flash.display.InterpolationMethod;
import flash.display.SpreadMethod;
public class Background extends MovieClip
{
private var dir:Array
private var point:Point
private var bd:BitmapData;
private var bmp:Bitmap;
private var bdmultiply:BitmapData;
private var bms:Sprite;
private var rect:Rectangle
private var cmf:ColorMatrixFilter;
private var w:Number
private var h:Number
private var gshape:Shape
private var gmetrics:Rectangle
private var gmatrix:Matrix
private var gtype:String
private var gspread:String
private var ginterpolation:String
private var gcolours:Array
private var galphas:Array
private var gratios:Array
private var sshape:Shape
public function Background($width:Number=100, $height:Number=100)
{
w = $width
h = $height
rect = new Rectangle(0, 0, w, h);
point = new Point(0, 0);
dir = [new Point(1, 262), new Point(400, 262)];
initBackgroundSolid();
initColorMatrix();
initBackgroundNoise();
initBackgroundGradient();
}
private function initColorMatrix():void {
cmf = new ColorMatrixFilter([2, 0, 0, 0, -20, //red
0, 2, 0, 0, -20, //green
0, 0, 2, 0, -20, //blue
0, 0, 0, 1, -20 ]); //alpha
}
private function initBackgroundSolid():void {
sshape = new Shape();
sshape.graphics.beginFill(0x170a02,1)
sshape.graphics.drawRect( 0, 0, w, h );
sshape.graphics.endFill();
addChild(sshape)
}
private function initBackgroundNoise():void {
bd = new BitmapData(w, h, false, 0 );
bmp = new Bitmap(bd);
bmp.smoothing = true;
addChild(bmp);
bdmultiply = new BitmapData(w, h, false, 0 );
bms = new Sprite();
bms.addChild(new Bitmap(bdmultiply))
addChild(bms)
bms.blendMode = "overlay";
addEventListener(Event.ENTER_FRAME, renderBG);
}
private function initBackgroundGradient() {
gshape = new Shape();
gmetrics = new Rectangle();
gmatrix = new Matrix();
gtype = GradientType.LINEAR;
gspread = SpreadMethod.PAD;
ginterpolation = InterpolationMethod.LINEAR_RGB;
gcolours = [ 0x170a02, 0x170a02 ];
galphas = [ 0, 1 ];
gratios = [ 0, 255 ];
gmatrix.createGradientBox(w, h,(Math.PI/180)*90 );
gshape.graphics.clear();
gshape.graphics.beginGradientFill(gtype, gcolours, galphas, gratios, gmatrix, gspread, ginterpolation );
gshape.graphics.drawRect( 0, 0, w, h );
gshape.graphics.endFill();
addChild(gshape)
}
private function renderBG(event:Event):void {
dir[0].x-= 1.5
dir[0].y-= 0
dir[1].x-= 0
dir[1].y -= 0
bd.perlinNoise(w, h, 2, 10, false, true, 7, true, dir);
bd.colorTransform(rect, new ColorTransform(1, 0.7, 0.5));
bd.applyFilter(bd, rect, point, cmf)
bdmultiply.perlinNoise(w, h, 3, 21, false, true, 7, true, dir)
bdmultiply.colorTransform(rect, new ColorTransform(1, 0.6, 0.4));
}
}
}
Step 39: Snow
The snow class is not mine, it was written by Troy Gardner, I just adapted it from the timeline to a package this is why I'm not commenting on the code. Create a "Snow.as" and copy this code inside.
package
{
import flash.display.MovieClip;
import flash.events.Event;
import flash.utils.Dictionary;
public class Snow extends MovieClip
{
var snowflakes:Array = new Array();
var snowflakeProps:Dictionary= new Dictionary(true);
var max_snowsize:Number = .04;
// pixels
var snowflakesCnt:Number = 150;
var oheight:Number;
var owidth:Number;
public function Snow($width,$height):void {
owidth = $width;
oheight = $height;
// quantity
for (var i:int=0; i<snowflakesCnt; i++) {
var t:MovieClip = new SnowFlake();//
t.name = "snowflake"+i;
t.alpha = 20+Math.random()*60;
t.x = -(owidth/2)+Math.random()*(1.5*owidth);
t.y = -(oheight/2)+Math.random()*(1.5*oheight);
t.scaleX = t.scaleY=.5+Math.random()*(max_snowsize*10);
var o:Object = new Object();
o.k = 1+Math.random()*2;
o.wind = -1.5+Math.random()*(1.4*3);
snowflakeProps[t] = o;
addChild(t);
snowflakes.push(t);
}
addEventListener(Event.ENTER_FRAME,snowFlakeMover)
}
private function shakeUp():void{
for (var i:int=0; i<snowflakes.length; i++) {
var t:MovieClip = snowflakes[i] as MovieClip;
t.x = -(owidth/2)+Math.random()*(1.5*owidth);
t.y = -(oheight/2)+Math.random()*(1.5*oheight);
}
}
private function snowFlakeMover(evt:Event):void {
var dO:MovieClip;
var o :Object;
if(visible && parent.visible){
for (var i:int = 0; i < snowflakes.length; i++) {
dO = snowflakes[i] as MovieClip;
o = snowflakeProps[dO];
dO.y += o.k;
dO.x += o.wind;
if (dO.y>oheight+10) {
dO.y = -20;
}
if (dO.x>owidth+20) {
dO.x = -(owidth/2)+Math.random()*(1.5*owidth);
dO.y = -20;
} else if (dO.x<-20) {
dO.x= -(owidth/2)+Math.random()*(1.5*owidth);
dO.y = -20;
}
}
}
}
}
}
Conclusion
My music skills aren't the greatest, the music may sound a bit strange. Oh well, with this tutorial you should now be able to create your own songs with more notes and different tones :). I hope you liked this tutorial, you'll find the commented code and both cs4 and cs3 versions up on the zip file. Thanks for reading!

nice tutorial, merry christmas
AMAZING!!
It´s really an amazing tutorial, no words for this, thanks a lot for sharing!!
Great!
Awesome tutorial! cheers
Everything is good except from autoplay “Jingle Bells”. I have a feeling you are not using the right notes in Autoplay… Try:
private var noteSequence: Array = [e, e, e,
e, e, e,
e, g, c, d, e,
f, f, f,
f, f, e, e,
e, d, d, e, d]
Thanks for the great tutorial. Happy holidays!
Ya, he started at F instead of E, so all that followed was wrong. Interesting tune, though.
Yeah my playing is awfull :), hopefully you guys will do a better work at comming up with some interesting songs and better timing. More notes and stuff.
Cheers :)
This really is a beautifully designed little app. Nicely done, needs some tuning, but that’s fine with me.
It would be nice recording the buttons you press, also the time between them, i am following this tutorial inserting this feature on it, but ths buttons i´ve created with class. Thanks for this tutorial, it´s amazing
Awsome, i actually thought of adding that but didn’t want to make this too complex, looking forward to see your final result :), thanks for trying it out.
If you thought it, just do!!
It´s a great tutorial and deserves part 2!
Hey, i´ve made a test with no animation, no design, and the code is very different from your´s, it records the key and time…
Check it: http://cavallari.freehostia.com/testswf/?swf=piano.swf
You click on “record” button (it´s not in butonMode=true), use keys from 1 to 7, and them just click play to hear your song… when you click record button again it will overwrite your last song…
Cool, saving it and sharing it would be cool too.
Hey, If you guys think a complete virtual piano with a recording system that saves your tune would be a fun tutorial just let me know and i’ll ask ActiveTuts.
Yes, PART II !!!
Haha the autoplay is awesomely wrong! In a good way!
yeah it could even fit on warp recordings tbh haha ;)
nice tut though… some useful tricks
That tutorial is awesome. It covers many different techniques.
i advise something like this:
private var noteSequence:Array = [e, e, e,
e, e, e,
e, g, c, d, e,
f, f, f,
f, f, e, e,
e, e, g, g, f, d, c]
and the lenghts:
private var noteDelay:Array = [80, 80 , 200,
100, 80 ,200,
100, 100, 150 ,50, 350,
100, 100, 120,
50, 100, 100,150,
50, 50, 100, 100, 100, 100, 300]
cheers :)
Nice :) I’ll push this over to Adrian at Audiotuts+ – see what he thinks!
I agree with Lextastic!
Sorry guys, why the source, after download, and open in flash cs3 doesn’t work?
The panel compiler errors shows many errors in the doc main.as
Warning: 5004: Can not find file ‘playerglobal.swc’ required for the verification of the type of ActionScript 3.0. Sure that the directory ‘$ (AppConfig) / ActionScript 3.0/Classes’ is listed in the classpath global preferences ActionScript 3.0.
- line 1 error 5000: The class ‘Main’ must be a subclass of ‘flash.display.MovieClip’ because it is connected to a library symbol of that type
- line 16 error 1017: Unable to find the definition of base class MovieClip.
Sorry for my english, but i’m italian and don’t write well english! ^_^
Thanks for help!!!
Ah… merry xmas!
I must say, since i don’t have cs3 i could not test it, i just exported the file to cs3 version unaware that could cause any issues, sorry for that, anyway for the first warning message grant skinner has a couple of solutions.
“make sure that you have the playerglobal.swc in the ActionScript 3.0/Classes/playerglobal.swc of your Flash CS3 install directory.
If it is in there, make sure you didn’t delete the line $(AppConfig)/ActionScript 3.0/Classes from your ActionScript 3.0 publish settings”
After that resolved you may have an error about instanciating on a non-constructor, that’s because i completely forgot that you can’t associate the flex sdk by using the method described in this tutorial.
Since i don’t own a copy of cs3 if anyone knows how to use flex sdk with flash cs3 let me know, otherwise do this:
Instead of:
[Embed(source="assets/A.mp3")]
private var A:Class;
private var a:Sound = new A() as Sound;
do this:
import the A sound to the library using your flash IDE, add a linkage name of A
replace the above code with
private var a:A = new A();
do this for all the sounds
i didn’t test it hopefully it works.
Cheers,
FYI – That works just fine for Flash CS3.
i think u have dont have green sock class because your version not detect this.to can download greeshoke from http://www.greensock.com/tweenlite/
thx……
Just like the tutorial from the book Flash cs4 professional by Robert Reinhardt – Chapter 26, but takes things a bit further :)
nice tuturial.but ı have a problem main. as .. if possible a video
Really very nice tut. but i have some problems
I found a nice tune, but cant explain the rithm(
1,6,2,3,4,5,7 and again and again until you feel the rithm)))
@mermaidiaa and @omar, what kind of problems are you guys experiencing?
SWEET
Hey GREAT!!! tutorial, i would like to know where u got the sounds, i want to create a interactive 3D piano and i need the sounds of the notes
That reminded me a lot of the digital Xmas card I did ages ago (2004/5?) for the agency I was working at the time: Young & Rubicam in Geneva-Switzerland.
The concept is the same as here using the keyboard to play notes but more visual (using everyone in the agency as “singing heads” instead of piano keys), the sound was actually recorded notes of people singing as well as having a few save/play/send options. It ended up going viral by accident leaving the small server down to its knees :) It was all done with Flash MX2004 and PHP. It was really fun to build even if I had no time allocated to it and everyone was quite skeptic about a “digital xmas card” (oh big old agencies…) before the results backfired on them to the point they only did digital cards after that.
http://fcolaco.com/blog/2009/07/29/portfolio-yr-xmas-ecard/
Just take a look and play around :)
great.
thank you.
merry christmas.