Are morning commuters using iPhones to listen to NPR?

npr graphAlthough your car has a fully-capable AM radio, and you’re an NPR listener, do you find yourself jacking your iPhone into your car stereo and listening to NPR through its app instead? New data released from NPR seems to indicate that’s what a lot of people are opting to do.

According to its data, NPR has noticed a rather significant spike in its iPhone app usage during typical morning commuter time. What makes that data so interesting — at least to NPR — is that, presumably, these people are in their cars. They’re with radios capable of receiving AM FM signals and, therefore, NPR’s programming over the airwaves. So why use the app?

I say the data isn’t so cut and dry. The sample they are seeing is only 8,000 people, which really isn’t all that many when you consider there are many more people listening to NPR on a daily basis, overall. There’s also this thing called telecommuting, so I wouldn’t assume all of these people are in radio-equipped automobiles. There are also thousands of people who walk to work everyday and thousands more who simply don’t work at all.

If you’re using the NPR app and have access to an AM FM radio, why are you using the app instead of the radio? Let us know in the comments.

[via MacDailyNews]

TUAWAre morning commuters using iPhones to listen to NPR? originally appeared on The Unofficial Apple Weblog (TUAW) on Fri, 20 Aug 2010 08:00:00 EST. Please see our terms for use of feeds.

Read | Permalink | Email this | Comments

TUAW’s Daily App: Monster Dash

Halfbrick Studios really made a splash with their iPhone debut, Fruit Ninja, and now they’ve followed it up with a little game called Monster Dash. It’s a running game in the vein of Canabalt, but rather than dodging skyscraper jumps and bombs, you’re fighting through pixelated monsters while sprinting along. The main addition to the game is a “shoot” button, so in addition to jumping obstacles and gaps as they come up, you can mow down enemies with various weapons, such as the (default) flameburster, uzis, and even a machine gun jetpack (that comes in handy when jumping).

It’s a lot of fun (as you’d probably expect if you’ve played either Canabalt or Fruit Ninja), and the game comes with Halfbrick’s requisite polish, including excellent lush graphics and full OpenFeint compatibility. If there’s a downside, it’s too bad that Halfbrick decided to just stick with the usual arcade formula. It’d be cool if they tried for something a little less shallow and a little more engrossing. This is just a bunch of levels and a chance to rush for the high score; nothing else carries over from one game to the next.

That’s just nitpicking, though. Halfbrick has done another great job on this one and pushed the newborn genre forward with their own twist. It’s well worth the 99 cents. And if you do buy it, try tapping on the title screen monsters just for fun.

TUAWTUAW’s Daily App: Monster Dash originally appeared on The Unofficial Apple Weblog (TUAW) on Fri, 20 Aug 2010 08:30:00 EST. Please see our terms for use of feeds.

Read | Permalink | Email this | Comments

The iPhone 4 comes to Portugal at a ‘louco’ price

The good news: Portugal is getting the iPhone 4 next week. On August 27, mobile provider Optimus will start selling the iPhone 4 (here’s a Google-translated link for the Portuguese-impaired). The bad news: the price is going up by 70 euros, meaning Portuguese customers will pay more for the iPhone 4 than just about anybody else.

I thought we had it bad in New Zealand, where we pay NZ$1299 (about US$918) for an unsubsidized 32 GB iPhone 4. But at 769.90 euros, a 32 GB iPhone 4 costs nearly NZ$100 (US$71) more in Portugal than in New Zealand, where mobile handset prices are usually among the highest in the world. The 16 GB iPhone 4, at 679.90 euros, is an even worse deal: over NZ$130 more (US$92) than the New Zealand price.

I’ve never been thrilled with handset prices in New Zealand, but we are kind of in the middle of nowhere, so it’s almost excusable. It makes much less sense for the Portuguese to have to pay such a high premium for the iPhone 4. Optimus hasn’t offered any reasons for raising the price by 70 euros, and I have to wonder how happy Apple is with the decision — rumor has it that Vodafone’s bungled launch of the iPhone 4 was precipitated by pricing disputes between the two companies, so it’ll be interesting to see if something similar plays out in Portugal.

TUAWThe iPhone 4 comes to Portugal at a ‘louco’ price originally appeared on The Unofficial Apple Weblog (TUAW) on Fri, 20 Aug 2010 02:00:00 EST. Please see our terms for use of feeds.

Read | Permalink | Email this | Comments

SwirlyMessage: Send and Receive SMS/MMS From iPad 3G

SwirlyMessage let you send and receive SMM/MMS from iPad 3G. SwirlyMessage for iPad is developed by the dev behind SwirlyMMS for iPhone.
SwirlyMessage

SwirlyMessage Description

“Send and receive real SMSes and MMSes with your iPad 3G.

To be able to use SwirlyMessage you need an iPad with a built in 3G modem. You also have to make sure that your carrier data plan allows for sending SMS and/or MMS. If you are unsure about this please contact your carrier.”

You iPad 3G MUST be jailbroken. You can jailbreak iPad using the guide linked below:

You can purchase and download SwirlyMessage from Cydia for $12.

SwirlyMessageSwirlyMessageSwirlyMessage

SwirlyMessageSwirlyMessage

You can follow us on Twitter, Join us at Facebook, and also Subscribed to RSS Feed to receive latest updates.

Also checkout:

Digg
Twitter
StumbleUpon
Facebook
Reddit
del.icio.us

Facebook 3.2.1 for iPhone, iPod Touch and iPad Hits the AppStore

Facebook 3.2.1 for iPhone, iPad and iPod Touch is now available in app Store. Facebook pushed the 3.2.1 update soon after the Facebook 3.2 to fix a few bugs. Facebook 3.2.1 features after the jump…


facebook 3.2.1

New in Facebook 3.2.1

  • Bug fixes

New in Facebook 3.2

  • Places. Use Places to see where your friends are and share where you are.
  • You can set the privacy of individual status updates.
  • See all recipients of inbox messages.
  • (iOS 4) Upload photos and videos in the background.

Bug fixes:

  • Fixed a delay when commenting on a post or posting a status update.
  • Fixed some Notes display bugs.
  • Fixed some reliability bugs in News Feed.

You can download Facebook 3.2.1 for iPhone, iPod Touch and iPad from the AppStore for Free! [iTunes Link]

facebook 3.2.1

You can follow us on Twitter, Join us at Facebook, and also Subscribed to RSS Feed to receive latest updates.

Digg
Twitter
StumbleUpon
Facebook
Reddit
del.icio.us

TinyUmbrella 4.02.04: Save SHSH blobs for iOS 4.0.2 and iPad iOS 3.2.2

Notcom, the dev behind TinyUmbrella has released an updated TinyUmbrella 4.02.04 for Windows, Mac OSX, and Linux. TinyUmbrella 4.02.04 supports iOS 4.0.2 and iPad 3.2.2 iOS. TinyUmbrella 4.02.04 download links after the jump…

tinyumbrella
TinyUmbrella let you save SHSH blobs (necessary for restoring older firmware) for iPhone, iPad and iPod Touch. More details on TinyUmbrella can be found here.

Download TinyUmbrella 4.02.04

You can download TinyUmbrella 4.02.04 from the link below:

Download TinyUmbrella

How to Save SHSH blobs

A detailed guide on how to save SHSH blobs for iPhone, iPad and iPod Touch is linked below:

Save SHSH blobs for iOS 4.0.2 and iPad iOS 3.2.2

NOTE: for iOS 4.0.2 and iOS 3.2.2 use advanced options to save SHSH blobs.

Also checkout:

You can follow us on Twitter, Join us at Facebook, and also Subscribed to RSS Feed to receive latest updates.

Digg
Twitter
StumbleUpon
Facebook
Reddit
del.icio.us

157 App Stats For You

There’s a wealth of datapoints out there on the growth of apps, and it can be overwhelming. So Mobile Entertainment has tried to help. They have compiled a presentation with 157 different stats, taking in app stores, consumer usage, analyst predictions, and app success stories. The presentation, which is free to view, embed and download, is below.

The last few slides gets pretty intereresting as they give real numbers of some of the top performing apps.

Blazing Fast iOS Math Library

If you’re app makes extensive use of trigonometry (and if you’re working on game development then you probably are) then you probably make extensive use of the built in math functions.

According to Apple  apps that make extensive use of floating point numbers should not make use of the thumb compiling option which reduces code size.

Dave Dribin has created a math library exclusively making use of integers, and based on the speed of the sine function vs. the standard libary sin and sinf functions it looks like Dave’s trigint library is at least 4x faster.

You can find the library and more info here:
Trigint: An Integer-Based Trigonmetry Library

Thanks for reading, please share this using the buttons below!

[via: Under The Bridge]

©2010 iPhone iOS 4 iTV iPad SDK Development Tutorials, Programming Tips, News. All Rights Reserved.

.

Share and Enjoy:

RSS
Twitter
Facebook
DZone
HackerNews
del.icio.us
FriendFeed

157 App Stats For You

There’s a wealth of datapoints out there on the growth of apps, and it can be overwhelming. So Mobile Entertainment has tried to help. They have compiled a presentation with 157 different stats, taking in app stores, consumer usage, analyst predictions, and app success stories. The presentation, which is free to view, embed and download, is below.

The last few slides gets pretty intereresting as they give real numbers of some of the top performing apps.

Photoshopstar.com needs your input

My name is Luis and i am the new owner of Photoshopstar.com.

Site was bought last month and was transferred to my servers after purchase.

I am already working on Photoshopstar.com fixing small bugs, removing unnecessary code and preparing site for changes.

I have many plans to Photoshopstar.com including fixing older tutorials and update several of them to CS5. I will post on site which tutorials were updated from time to time.

As part of this effort, i would like to hear your thoughts on the site, and what you would like to see in the future.

Feel free to post your ideas and comments on this post to help me create a better Photoshopstar.com to all readers.

Create a Modern Style Icon with a Professional Finish – Vector Premium Tutorial


We have another great Vector Premium tutorial available exclusively for Premium members today. If you want to learn how how to create a professional level Hard Drive icon with shading and lighting the techniques, then we have an awesome tutorial for you.

Continue reading “Create a Modern Style Icon with a Professional Finish – Vector Premium Tutorial”

Quick Tip: How to Change Guitar Strings

When you break a guitar string or haven’t changed your strings since you bought your guitar two years ago, the process of putting on some new ones can be a scary thought if you’ve never done it before. While you could take your guitar to a local music store to have them do it for you, it can often be a few days before you get your guitar back and it will surely add some extra expense in the process.

In this quick tip I’ll show you how you can change the strings on a standard electric guitar and give you some handy pointers along the way.

You’ll need new strings, wire cutters and a tuner.

</p


Create a Realistic Picture Frame With Photoshop – Psd Premium Tutorial


Today, we have another Psd Premium tutorial exclusively available to Premium members. If you want to take your design skills to the next level, then we have an awesome tutorial for you. Learn more after the jump!


This Premium Tutorial is Filled with Creative Tips

Today, we will demonstrate how to create a realistic picture frame with the help of Vanishing Point and layer masks.


Professional and Detailed Instructions Inside

Premium members can Log in and Download! Otherwise, Join Now! Below are some sample images from this tutorial.


Psd Premium Membership

As you know, we run a premium membership system here that costs $9 a month (or $22 for 3 months!) which gives members access to the Source files for tutorials as well as periodic extra tutorials, like this one! You’ll also get access to Net Premium and Vector Premium, too. If you’re a Premium member, you can log in and download the tutorial. If you’re not a member, you can of course join today!

MovieClip Reconstruction with the SharedObject Class

During this tutorial, we will learn how to implement the SharedObject class. We’ll store all the essential data of a MovieClip locally, then reload it next time the application is opened!

We found this awesome author thanks to FlashGameLicense.com, the place to buy and sell Flash games.

Thanks to manicho for the hard disk icon.


Final Result Preview

Let’s take a look at the final result we will be working towards:

Doodle an image in the box with your mouse, and hit the Save button. Refresh this page in your browser, and click Load. You’ll see your doodle reappear, having been loaded from your hard drive; the background animation will even be on the same frame as it was before!


Step 1: Setting Up Our Document Class

Let’s begin by creating a new .fla. Save it and open up the properties panel in Flash. I am using Flash CS5, but this tutorial should work with every Flash CS version. In the properties panel, push the Edit button and make sure that your settings are identical to the image below:


Step 2: Document Class Setup

Now that we’ve setup our .fla, let’s begin our Document Class. To begin, open up your favorite ActionScript code editor and save an .as file called “Main.as” in the same directory as your .fla. Next go into the “Publish” panel of Flash. Set the “Class” textfield to “Main”. Now open Main.as and copy and paste the following code to create our Main document class.

package {

	import flash.display.Bitmap;
	import flash.display.BitmapData;
	import flash.display.Graphics;
	import flash.display.Shape;
	import flash.display.Sprite;
	import fl.controls.ComboBox
	import flash.events.Event;
	import flash.events.MouseEvent;
	import flash.geom.Matrix;
	import flash.geom.Rectangle;
	import flash.net.SharedObject;

	public class Main extends Sprite {

		public function Main():void  {

		}

	}

}

Step 3: Our Main Object

Now we are going to create our main MovieClip. It will contain 3 frames. Each one with a colored shape. Draw a red rectangle, turn it into a MovieClip with F8 and set the name of the MovieClip to “myObject”. Make sure that the registration point is the top left corner. Then create two new empty frames inside the MovieClip. Fill one up with a green triangle and the other with a blue circle.

The final result should look a bit like this:


Step 4: Using a ComboBox

Now we are going to use a ComboBox, which is basically a Drop-down list. Make sure that the instance of myObject on the stage is also labeled myObject. Then open: Window > Components and drag the “ComboBox” item onto the library. If you aren’t using the Flash IDE, you need to Right Click > Export to SWC the ComboBox in the library.

Now we can create the “myComboBox” variable, placed above the constructor function.

private var myComboBox:ComboBox = new ComboBox()

Next add the following code to your Main() constructor:

//Stops the myObject MovieClip on the first frame
myObject.gotoAndStop(1)

//Adds the following Objects to the ComboBox
and gives them each unique labels
myComboBox.addItem({label:"Rectangle"})
myComboBox.addItem({label:"Circle"})
myComboBox.addItem({label:"Triangle"})
//Adds the ComboBox
addChild(myComboBox)
//Moves it to the correct coordinates
myComboBox.move(280,150)

Here is a snapshot of what your application should look like when run:


Step 5: Changing myObject Frames

We want our MovieClip to change frames when we select a different item!

Let’s begin by adding an EventListener to our constructor – the Event.CHANGE event listener – which checks to see when the selected object in the ComboBox changes. This is exactly when the user chooses a new ComboBox item.

myComboBox.addEventListener(Event.CHANGE,changeObjectFrame)

Next we shall create the changeObjectFrame() function. This function checks to see what the current label on the ComboBox is, which is the name of the object the user has selected. It will then go to the correct frame of myObject to display the selected object type.

private function changeObjectFrame(e:Event):void
{
	//myComboBox.selectedLabel is the name of
	the current object selected that we defined
	earlier...

	if (myComboBox.selectedLabel == "Rectangle") {
		myObject.gotoAndStop(1)
	}
	if (myComboBox.selectedLabel == "Triangle") {
		myObject.gotoAndStop(2)
	}
	if (myComboBox.selectedLabel == "Circle") {
		myObject.gotoAndStop(3)
	}
}

You can now go ahead and compile the application. You should be able to switch to a different object by selecting it from the drop-down menu.


Step 6: Adding Animation

Next, let’s add some animation to our program. Go into the myObject MovieClip on the first frame. Select all of the red rectangle and push F8 to turn it into a MovieClip. Make sure that the registration point is at the top left corner. Do this with every shape inside the myObject MovieClip

Next we will have to give each MovieClip an animation. Go into the rectangle shape MovieClip and Right Click > Create Shape Tween on the red shape filling.

Then select the 60th frame of the MovieClip on the timeline and push F6 to create a new keyframe. Do this with the 30th frame as well. Now you can just go to the 30th frame and change the color of the shape fill. I have chosen to change the color to a golden orange. Now if you play the animation, the color should change from Red > Orange > Red.

Go ahead and do this for each shape in the myObject MovieClip. Now you can go ahead and compile the application; each selected shape will change colors.

The current application should act like this:


Step 7: Doodle Canvas

Now, let’s allow the user to draw a little custom doodle on the MovieClip. This is similar to my last tutorial in which we allowed the user to draw a custom design on the player. However, we will take it one step further in this tutorial by allowing the user to SAVE his message. But let’s save that for later!

Let’s get started by setting up an instance of the Shape class. Add this code above your constructor:

private var myCanvas:Shape = new Shape()

Next we are going to add the myCanvas variable to the stage… Add this code to the bottom of our constructor.

addChild(myCanvas))

Step 8: Doodles

We’ll do this very quickly. If you want more explanation on how to use the Shape class for drawing, please check my other tutorial.

Start by creating a mouseIsDown variable…

//Checks to see if the mouse is down
private var mouseIsDown:Boolean = false

Now go ahead and add the following event listeners:

stage.addEventListener(MouseEvent.MOUSE_MOVE, drawDoodle)
stage.addEventListener(MouseEvent.MOUSE_DOWN, mouseDown)
stage.addEventListener(MouseEvent.MOUSE_UP, mouseUp)

And here are the 3 functions which are attached to the EventListeners:

private function mouseUp(e:MouseEvent):void
{
	mouseIsDown = false
}

private function mouseDown(e:MouseEvent):void
{
	mouseIsDown = true

	//Moves mouse pointer to mouse
	myCanvas.graphics.moveTo(myCanvas.mouseX, myCanvas.mouseY);
}

private function drawDoodle(e:MouseEvent):void
{
	//If the mouse is clicked
	if (mouseIsDown) {
		//Makes drawing settings right
		myCanvas.graphics.lineStyle(5, 0, 1)
		//Draws the doodle line
		myCanvas.graphics.lineTo(myCanvas.mouseX, myCanvas.mouseY);  

	}
}

Now you can test out the program and it should be drawing fine. However, we still haven’t limited the drawing space of our canvas, so drawings outside of the myObject boundaries still show. In the next step, we will solve all of this!


Step 9: Masking

In my previous tutorial, the process of masking was very easy because each masked object remained the same throughout all of the application. This time, we need to have a mask that adjusts to each MovieClip.

Let’s go ahead and Right Click > Copy our myObject on the stage. Now we need to Right Click > Paste in Place the object so it is exactly where our myObject was. Now change the instance name to “myObjectAsMask.” Switch to the Main Class and add the following lines to the constructor:

//This should all be self-explanatory!
myCanvas.mask = myObjectAsMask
myObjectAsMask.gotoAndStop(1)

So far, the mask should only work for the first object. We need to adjust the changeObjectFrame function to change our mask to meet the new shape of myObject. Add the highlighted code to the changeObjectFrame function:

private function changeObjectFrame(e:Event):void
{
	if (myComboBox.selectedLabel == "Rectangle") {
		myObject.gotoAndStop(1)
	}
	if (myComboBox.selectedLabel == "Triangle") {
		myObject.gotoAndStop(2)
	}
	if (myComboBox.selectedLabel == "Circle") {
		myObject.gotoAndStop(3)
	}

	//Clears doodle
	myCanvas.graphics.clear()
	//Syncs myObject and myObjectAsMask frames
	myObjectAsMask.gotoAndStop(myObject.currentFrame)
}

Step 10: The Save Button

Next up: we’ll add a save button to our application. Later on this will save all our myObject’s data into a SharedObject. Create a new Button and design it however you want. I have included my own button but showing you how to draw one is not important.

Drag an instance of the button onto the stage and give it the instance name of “saveStuff”. Then add the following event listener to the constructor:

saveStuff.addEventListener(MouseEvent.CLICK, saveObjectData)

Next, add this empty function that we will use to add our code that saves the object.

private function saveObjectData(e:MouseEvent):void
{

}

Step 11: Creating and Accessing a New SharedObject

To start using the SharedObject class, we will need to create a new instance of the SharedObject class. If you haven’t ever used the SharedObject class before, then this would be a good time to check out this tutorial on Working with SharedObjects to get a basic idea of how they work. Use this code to create a SharedObject:

private var mySaveData:SharedObject = SharedObject.getLocal("saveData")

Go inside the saveObjectData function and add the following code to begin our save operation:

// Creates a new array inside the program
var myDataArrayInProgram:Array = new Array()

// Adds some random data to our Array
myDataArrayInProgram.push("WhateverDataYouWant")

// Creates a variable inside the SharedObject
// and sets it's value to the value of our local
// array
mySaveData.data.myDataArray = myDataArrayInProgram

// "Flushes" the data away to be saved in the
// computer (although the name suggests otherwise,
// this actually stores the data!)
mySaveData.flush()

If you want to check to see if this code is effective, just add this snippet of code to the bottom of your function:

trace(mySaveData.data.myDataArray)

Step 12: Saving our Main MovieClip Data

So far, all is good. We’ve managed to create a SharedObject and have successfully stored a few bytes of data in it. The next step is to start preparing our program for reconstructing our MovieClip. In this step, we will add all of the necessary data to our SharedObject for our application to reconstruct the MovieClip from scratch.

To do this, we will need to push all of our data into the myDataArrayInProgram Array so it will be attached to our SharedObject. I’ve modified the saveObjectData function to do all of this. You can view it below:

private function saveObjectData(e:MouseEvent):void
{
	var myDataArrayInProgram:Array = new Array()

	//Adds the object's X location
	myDataArrayInProgram.push(myObject.x)

	//Adds the object's Y location
	myDataArrayInProgram.push(myObject.y)

	//Adds the object's currentFrame
	//(The current object chosen)
	myDataArrayInProgram.push(myObject.currentFrame)

	//Adds the current frame of the
	//current object's animation
	myDataArrayInProgram.push(myObject.getChildAt(0).currentFrame)

	mySaveData.data.myDataArray = myDataArrayInProgram
	mySaveData.flush()
	trace(mySaveData.data.myDataArray)
}

IMPORTANT: getChildAt() accesses the children of the object based on their index. When there is only one object in a MovieClip, you can be sure that getChildAt(0) will get you to it!

MORE IMPORTANTLY: Don’t worry if you get the following error:

1119: Access of possibly undefined property currentFrame through a reference with static type flash.display:DisplayObject.

If so, you probably have Strict Mode enabled in your flash settings. The problem is that getChildAt() returns a DisplayObject, and to flash, that could be a Bitmap, Sprite, MovieClip, etc. The issue with DisplayObject.currentFrame is that only the MovieClip Class has the currentFrame property, because no other class has any animation.

To solve this, go to: File > Publish Settings > Actionscript Settings and uncheck “Errors: Strict Mode”

Editor: Alternatively, you could cast the object returned by getChildAt() as a MovieClip, like so:

myDataArrayInProgram.push((myObject.getChildAt(0) as MovieClip).currentFrame)

This tells Flash, “treat this object as a MovieClip“.


Step 13: Creating a Load Button

We aren’t at the stage yet where we can use our save data, but it is still good to create the UI option to load the SharedObject ahead of time. Just like the save button, you can design this button to be however you want; I’m not going to walk you through drawing it.

Create a new button and drag an instance onto the stage. Then set the instance name to “loadStuff”.

And now just add the following Event Listener:

loadStuff.addEventListener(MouseEvent.CLICK, loadObjectData)

And create the loadObjectData function like so:

private function loadObjectData(e:MouseEvent):void
{

}

Step 14: Clear Everything Button

Now let’s add a new button to our UI. This button will delete everything in our SharedObject and also wipe out the current doodle on myCanvas.

Just like the other buttons, I will choose my own graphic; you can choose your own or use mine.

This time you can set the instance name of the button to “clearStuff”.

Now add this Event Listener:

clearStuff.addEventListener(MouseEvent.CLICK, clearObjectData)

And create the clearObjectData function like so:

private function clearObjectData(e:MouseEvent):void
{
	//Clear SharedObject
	mySaveData.clear()
	//Clears myCanvas graphics
	myCanvas.graphics.clear()
}

Step 15: BitmapData Snapshots

Now you are beginning to ask: “Why can’t I save the user’s doodle like any other property?” Unfortunately, Flash doesn’t allow you to directly save MovieClips, Bitmaps, or even Shapes inside of a SharedObject, but you can do this by saving the pixel by pixel value OF the image.

You must be asking: “But the doodle isn’t a bitmap, it’s a user drawn vector image contained in shape?!” That’s right, but we can convert it to Bitmap based data by taking a snapshot of it with the BitmapData class!

Go ahead and create the following variable above the constructor of our Main application:

private var bitmapDataSnapshot:BitmapData

This variable will be the “camera” that takes a snapshot of the doodle.

Now add the following highlighted lines to the saveObjectData function in the location shown below:

private function saveObjectData(e:MouseEvent):void
{
	var myDataArrayInProgram:Array = new Array()
	myDataArrayInProgram.push(myObject.x)
	myDataArrayInProgram.push(myObject.currentFrame)
	myDataArrayInProgram.push(myObject.getChildAt(0).currentFrame)

	//Creates a new instance of the BitmapData class,
	//makes it the size of the stage, enables transparency,
	//and sets the fill to a transparent white
	bitmapDataSnapshot = new BitmapData(640, 480,true,0)

	//Tells the camera to take a snapshot
	//of myCanvas, skips the next 3 parameters,
	//and tells the snapshot area to only include
	//the stuff covered by the myObject MovieClip
	bitmapDataSnapshot.draw(myCanvas, null, null, null, new Rectangle(250, 30, 150, 100))

	mySaveData.data.myDataArray = myDataArrayInProgram
	mySaveData.flush()
	trace(mySaveData.data.myDataArray)
}

Step 16: Saving BitmapData in a SharedObject

Let’s wrap up the saving process of our program. Now that we have created a BitmapData instance with all of our myCanvas data, we need to store it inside a ByteArray to be sent into our SharedObject. To do this, we can use a very handy function inside of the BitmapData Class. It’s name is getPixels().

getPixels() returns a ByteArray of all of the pixel data of a BitmapData. Unlike the BitmapData Class, ByteArrays can be stored inside SharedObjects so they are the right tool for saving our Doodle.

All you need to do is add this line of code in your saveObjectData function right after you finish doing your BitmapData work:

//Pushes the value of the returned
//ByteArray of the getPixels() function
//into myDataArrayInProgram

//getPixels() requires a Rectangle that
//shows what part of the object's  pixels
//we actually want!

//NOTE: The current rectangle is only
//an approximation of where the doodle
//should show!
mySaveData.data.myDataArray.push(bitmapDataSnapshot.getPixels(new Rectangle(250, 30, 150, 100)))

On to the last step. Once the data is saved, we need to have the user refresh the page, to prove that their doodle has been saved to their hard drive, and not just stored in temporary memory. Draw a black box around the stage and add some text to it that asks the player to refresh. Then select the whole object and push F8. Make sure to check the “Export For Actionscript” box and set the “Class” to “refreshScreen”. You can now delete the object on the stage…

Below is the refreshScreen that I have drawn:

Now add this code to the bottom of your saveObjectData function:

addChild(new refreshScreen())

Your finished saveObjectData function should look like this:

private function saveObjectData(e:MouseEvent):void
{
	var myDataArrayInProgram:Array = new Array()
	myDataArrayInProgram.push(myObject.x)
	myDataArrayInProgram.push(myObject.currentFrame)
	myDataArrayInProgram.push(myObject.getChildAt(0).currentFrame)
	bitmapDataSnapshot = new BitmapData(640, 480,true,0)
	bitmapDataSnapshot.draw(myCanvas, null, null, null, new Rectangle(250, 30, 150, 100))
	myDataArrayInProgram.push(bitmapDataSnapshot.getPixels(new Rectangle(250, 30, 150, 100)))

	mySaveData.data.myDataArray = myDataArrayInProgram
	mySaveData.flush()
	trace(mySaveData.data.myDataArray)

	addChild(new refreshScreen())
}

Step 17: Reconstructing Our Doodle

It’s time to reconstruct our entire Doodle from the ByteArray that we saved earlier!

You must be thinking: “What the heck do I do with a ByteArray, its just a bunch of garbled mumbo-jumbo!” And you are right, it is! Thankfully, Adobe has also given us a great function called setPixels() which you gives the same Rectangle and ByteArray, to recreate the same BitmapData you had!

Before we reconstruct our entire MovieClip, we should go ahead and run a test to see if we can reconstruct the BitmapData itself. Modify your loadObjectData function so it looks like this:

private function loadObjectData(e:MouseEvent):void
{
	//Creates a BitmapData and makes
	//it the size of the stage, and
	//applys all of the old settings
	var loadBitmapData:BitmapData = new BitmapData(640, 480, true, 1)

	//Sets the pixels of loadBitmap
	//using our old rectangle, and
	//by accessing our SaveData ByteArray
	//(4th item in myDataArray (myDataArray[3]))
	loadBitmapData.setPixels(new Rectangle(250, 30, 150, 100), mySaveData.data.myDataArray[3])

	//Creates a new Bitmap and tells it to
	//load its image from loadBitmapData
	var display:Bitmap = new Bitmap(loadBitmapData)

	//Moves the object mask
	//playhead to the right frame
	myObjectAsMask.gotoAndStop(mySaveData.data.myDataArray[2])

	//Masks the image with the mask
	display.mask = myObjectAsMask

	//Adds the Bitmap to the stage
	addChild(display)

}

Step 18: Fully Reconstructing myObject

Now it’s time to put this all together! First, right-click on myObject (in library) > Properties. Now check the “Export For Actionscript” box and set the “Class” to “myObjectType”. Compare your properties to the ones in the image:

If it’s all the same, then we are ready to go! Add this above our constructor:

private var myNewObject:myObjectType;

And add all of this to the top of loadObjectData().

//Creates a new instance of myObjectType (myObject)
myNewObject = new myObjectType()

//Sets the X to the old position
myNewObject.x = mySaveData.data.myDataArray[0]
//Sets the Y to the old postion
myNewObject.y = mySaveData.data.myDataArray[1]
//Selects the old object
myNewObject.gotoAndStop(mySaveData.data.myDataArray[2])
//Moves the playhead to the right animation frame
myNewObject.getChildAt(0).gotoAndStop(mySaveData.data.myDataArray[3])
//Adds the object to the stage
addChild(myNewObject)

//Removes comboBox event listener
myComboBox.removeEventListener(Event.CHANGE, changeObjectFrame)

//Removes the "doStuff" event listeners for buttons
saveStuff.removeEventListener(MouseEvent.CLICK, saveObjectData)
loadStuff.removeEventListener(MouseEvent.CLICK, loadObjectData)
clearStuff.removeEventListener(MouseEvent.CLICK,clearObjectData)

//Removes drawing event listeners
stage.removeEventListener(MouseEvent.MOUSE_MOVE, drawDoodle)
stage.removeEventListener(MouseEvent.MOUSE_DOWN, mouseDown)
stage.removeEventListener(MouseEvent.MOUSE_UP, mouseUp)

//Removes unneeded UI
removeChild(myObject)
removeChild(saveStuff)
removeChild(loadStuff)
removeChild(clearStuff)
removeChild(myComboBox)
removeChild(myCanvas)

Test the app out, it should work perfectly.

Congratulations! You’ve officially reconstructed a MovieClip using the SharedObject class!


Step 19: Adding a Play Animation Button

If the application above works, it should present a paused image of where you saved myObject. To get the animation to play again, let’s create a “Play” button. Here is the one that I’ve chosen:

Drag it just underneath myObject on the stage and set its instance name to “playAnimation”.

Now add this to the bottom of our constructor:

//Hides button
playAnimation.visible = false

//Adds buttons Event Listener
playAnimation.addEventListener(MouseEvent.CLICK, playObjectAnimation)

Then put this at the bottom of loadObjectData().

//Shows button
playAnimation.visible = true

Lastly, add this function to your program:

private function playObjectAnimation(e:MouseEvent):void {
	myNewObject.play()
}

Step 20: Final Source

Here is our Final Application Source Code. If there is any difference between your code and this, go back and see where you took a different path.

package {

	import flash.display.Bitmap;
	import flash.display.BitmapData;
	import flash.display.Graphics;
	import flash.display.Shape;
	import flash.display.Sprite;
	import fl.controls.ComboBox
	import flash.events.Event;
	import flash.events.MouseEvent;
	import flash.geom.Matrix;
	import flash.geom.Rectangle;
	import flash.net.SharedObject;

	public class Main extends Sprite {

		private var myComboBox:ComboBox = new ComboBox()
		private var myCanvas:Shape = new Shape()
		private var mouseIsDown:Boolean = false
		private var mySaveData:SharedObject = SharedObject.getLocal("saveData")
		private var bitmapDataSnapshot:BitmapData
		private var myNewObject:myObjectType 

		public function Main():void  {
			myObject.gotoAndStop(1)

			myComboBox.addItem( { label:"Rectangle" } )
			myComboBox.addItem({label:"Triangle"})
			myComboBox.addItem({label:"Circle"})
			addChild(myComboBox)
			myComboBox.move(280, 150)

			myComboBox.addEventListener(Event.CHANGE, changeObjectFrame)

			addChild(myCanvas)

			stage.addEventListener(MouseEvent.MOUSE_MOVE, drawDoodle)
			stage.addEventListener(MouseEvent.MOUSE_DOWN, mouseDown)
			stage.addEventListener(MouseEvent.MOUSE_UP, mouseUp)

			myCanvas.mask = myObjectAsMask
			myObjectAsMask.gotoAndStop(1)

			saveStuff.addEventListener(MouseEvent.CLICK, saveObjectData)
			loadStuff.addEventListener(MouseEvent.CLICK, loadObjectData)
			clearStuff.addEventListener(MouseEvent.CLICK, clearObjectData)

			playAnimation.visible = false
			playAnimation.addEventListener(MouseEvent.CLICK, playObjectAnimation)
		}

		private function clearObjectData(e:MouseEvent):void
		{
			mySaveData.clear()
			myCanvas.graphics.clear()
		}

		private function loadObjectData(e:MouseEvent):void
		{
			myNewObject = new myObjectType()
			myNewObject.x = mySaveData.data.myDataArray[0]
			myNewObject.y = mySaveData.data.myDataArray[1]
			myNewObject.gotoAndStop(mySaveData.data.myDataArray[2])
			myNewObject.getChildAt(0).gotoAndStop(mySaveData.data.myDataArray[3])
			addChild(myNewObject)

			myComboBox.removeEventListener(Event.CHANGE, changeObjectFrame)

			saveStuff.removeEventListener(MouseEvent.CLICK, saveObjectData)
			loadStuff.removeEventListener(MouseEvent.CLICK, loadObjectData)
			clearStuff.removeEventListener(MouseEvent.CLICK,clearObjectData)

			stage.removeEventListener(MouseEvent.MOUSE_MOVE, drawDoodle)
			stage.removeEventListener(MouseEvent.MOUSE_DOWN, mouseDown)
			stage.removeEventListener(MouseEvent.MOUSE_UP, mouseUp)

			removeChild(myObject)
			removeChild(saveStuff)
			removeChild(loadStuff)
			removeChild(clearStuff)
			removeChild(myComboBox)
			removeChild(myCanvas)

			var loadBitmapData:BitmapData = new BitmapData(640, 480, true, 1)
			loadBitmapData.setPixels(new Rectangle(250, 30, 150, 100), mySaveData.data.myDataArray[4])
			var display:Bitmap = new Bitmap(loadBitmapData)
			myObjectAsMask.gotoAndStop(mySaveData.data.myDataArray[2])
			display.mask = myObjectAsMask
			addChild(display)

			playAnimation.visible = true

		}

		private function playObjectAnimation(e:MouseEvent):void
		{
			myNewObject.getChildAt(0).play()
			playAnimation.visible = false
		}

		private function saveObjectData(e:MouseEvent):void
		{
			var myDataArrayInProgram:Array = new Array()
			myDataArrayInProgram.push(myObject.x)
			myDataArrayInProgram.push(myObject.y)
			myDataArrayInProgram.push(myObject.currentFrame)
			myDataArrayInProgram.push(myObject.getChildAt(0).currentFrame)
			bitmapDataSnapshot = new BitmapData(640, 480,true,0)
			bitmapDataSnapshot.draw(myCanvas, null, null, null, new Rectangle(250, 30, 150, 100))
			myDataArrayInProgram.push(bitmapDataSnapshot.getPixels(new Rectangle(250, 30, 150, 100)))

			mySaveData.data.myDataArray = myDataArrayInProgram
			mySaveData.flush()
			trace(mySaveData.data.myDataArray)
		}

		private function mouseUp(e:MouseEvent):void
		{
			mouseIsDown = false
		}

		private function mouseDown(e:MouseEvent):void
		{
			mouseIsDown = true
			myCanvas.graphics.moveTo(myCanvas.mouseX, myCanvas.mouseY);
		}

		private function drawDoodle(e:MouseEvent):void
		{
			if (mouseIsDown) {
				myCanvas.graphics.lineStyle(5, 0, 1)
				myCanvas.graphics.lineTo(myCanvas.mouseX, myCanvas.mouseY);  

			}
		}

		private function changeObjectFrame(e:Event):void
		{
			if (myComboBox.selectedLabel == "Rectangle") {
				myObject.gotoAndStop(1)
			}
			if (myComboBox.selectedLabel == "Triangle") {
				myObject.gotoAndStop(2)
			}
			if (myComboBox.selectedLabel == "Circle") {
				myObject.gotoAndStop(3)
			}

			myCanvas.graphics.clear()
			myObjectAsMask.gotoAndStop(myObject.currentFrame)
		}

	}

}

Conclusion

As you can see, with a little bit of tweaking, it is absolutely possible to save all MovieClip data into SharedObjects for loading later on. This means that if you are writing a game, you can easily create save states instead of having small checkpoints…

Good luck on using this method of saving data on your games and applications, to help make your programs better than ever!

Thanks for reading!