# AS3: Using a SharedObject for showing/hiding a Tutorial

Basically, I am either having trouble understanding how to use SharedObjects correctly, or I am not properly referencing a variable (from a seperate class from which it is defined) within a SharedObject, and I think the latter is my problem, although I’m not sure.

When my character dies, my game goes to a game over screen, where I create 2 variables within a SharedObject: the bestScore (user’s all-time best score in the game) and then a tutorialBoolean (which will determine if the tutorial shows up or does not in future game play). My bestScore works 100% fine, so I set that up correctly. Now the problem is, in a different class, I want to make an if statement, so that if my tutorialBoolean does not exist or is true, the tutorial runs, and if it is false, the tutorial does not run.

When I try to say

if (sharedObject.data.tutorialBoolean) {runTutorial()}


I get TypeError: Error #1009: Cannot access a property or method of a null object reference. And I am sure that it's having trouble with the sharedObject because I have created a tutorialBoolean without using SharedObjects and it works just fine. So all in all, I just want to be able to make an if statement in separate class than where my sharedObject variable is defined. I will probably have to use

if (sharedObject.data.tutorialBoolean == null)...


or

if (sharedObject.data.tutorialBoolean == "undefined")...


although I'm not really sure which one to use....neither is working at the moment. Shouldn't one of these work no matter what?...I mean if my variable is non existent surely one of these would work...

GameOver Class

package  {

import flash.display.MovieClip;
import flash.display.SimpleButton;
import flash.events.MouseEvent;
import flash.text.TextField;
import flash.ui.Mouse;
import flash.net.SharedObject;

public class GameOver extends MovieClip {

public static var sharedObject:SharedObject;
public var finalScore:TextField;
public var bestScore:TextField;

public function GameOver() {

sharedObject = SharedObject.getLocal( "smgScores" );
sharedObject.data.tutorial1BooleanShared = false;
sharedObject.flush();
}

public function onClickRestart(mouseEvent:MouseEvent):void
{
}

{
}

public function setFinalScore( scoreValue:Number ):void
{
trace(sharedObject.data.bestScore);
try
{
finalScore.text = scoreValue.toString();
if ( sharedObject.data.bestScore == null )
{
sharedObject.data.bestScore = scoreValue;
}
if ( scoreValue > sharedObject.data.bestScore )
{
sharedObject.data.bestScore = scoreValue;
}
bestScore.text = sharedObject.data.bestScore.toString();
sharedObject.flush();
}
catch( sharedObjectError:Error )
{
trace( "Caught this error:", sharedObjectError.name, sharedObjectError.message );
bestScore.text = "change flash storage options";
}
}

}


and in my playScreen class I basically just want to be able to say

if (GameOver.sharedObject.data.tutorial1BooleanShared)
{
runTutorial1();
}


But I get the error as I said above. I'm not sure if it's worth reconstructing my classes a bit and using sharedObjects in different places, or if there is a simple fix. I like the structure I have at the moment, so the latter is preferable. Thanks!

There are several things off with your code:

Don't access the shared object from your GameOver screen, unless you can ensure that the object will be instantiated whenever you run PlayScreen. And most likely, this isn't the case.

A clean solution would be to implement a getter that instantiates the object on demand. Eg.

private static var _sharedObject:SharedObject;
public static function get sharedObject():SharedObject {
if(!_sharedObject){
_sharedObject = SharedObject.getLocal( "smgScores" );
}
return _sharedObject;
}


Then you can do:

GameOver.sharedObject.data.tutorial1BooleanShared = false;
GameOver.sharedObject.flush();


Or in your Play-screen:

if (GameOver.sharedObject.data.tutorial1BooleanShared){
// do something
}


I doubt that the sharedObject getter really belongs to the GameOver class, but that's an architectural decision you have to make. Alternatively, you could simply discard the whole getter/accessing via another class and just do the following in your Play-screen:

var so:SharedObject = SharedObject.getLocal( "smgScores" );
if(so && so.data.tutorial1BooleanShared){
// do something
}


Some general advice when dealing with SharedObjects: Make sure to wrap your calls dealing with the SharedObject in try/catch blocks (especially flush and maybe even getLocal(). Some people disable writing of SharedObjects alltogether (in the flash player preferences) and your application might crash on their system if you don't catch the error.

• Alright awesome! It works! Thanks for the great answer. For some reason I was unable to get the second, more simple looking solution to work, but I didn't try it for very long so maybe I was missing something small. The first solution worked great though and I like it better anyways since it taught me more, cheers =). – John Dodson Aug 15 '13 at 20:22