500
We've just published our 500th video course! Get it FREE for a limited time.
Advertisement

Create a Flickr-Based Pairs Game With Flash: The Interface

by

We've successfully made the core of our game, but only being able to play one level is kind of boring, so let's now set up our game so we can play multiple levels. Then, we'll vastly improve the game's interface.


Also available in this series:

  1. Create a Flickr-Based Pairs Game With Flash: The Basics
  2. Create a Flickr-Based Pairs Game With Flash: The Interface

Step 1: Setting Up the Game for Multiple Levels

Since we are going to be using multiple levels we need to change our perPage variable. I have changed mine to 300, this will allow us to play up to 30 levels (300/10).

We will need a button to continue to the next level, and since we already made our "GameButton" class we just need to instantiate a new button to be used as our "Next Level" button. Add the following to the bottom of your variable declarations.

Next we need a method to be able to add and remove our button throughout the game, so add the following code below the addSearchPanel() function.

The addNextLevelButton() function takes two parameters; the first, xPos, is the x postition at which we will place the button, and the yPos is the y position.

Next we use the setText() method of our "GAMEBUTTON" class to set the buttons text to "NEXT LEVEL", add it to the stage, and add an EventListener to be called when the user clicks on the button.

The removeNextLevelButton() checks if the button is on the stage and if so removes it by calling removeChild().

Next up we need to code our nextLevel function. Add the following code below the removeNextLevelButton() function above.

Here we remove our "nextLevelButton" and call loadCards() which will load a fresh batch of cards.

Now we need to remove the searchPanel whenever the user does a search. Then after they complete a level we will add the nextLevel button.

The best place to do this is in the doRequest() method. Add the following underneath the line loader.load(request) within the doRequest() method.

Here we check to see if the searchPanel is on the stage. If it is use the method clearText() from our "SearchPanel" class and then remove the searchPanel from the stage with a call to removeChild.

Now we need a way to reset our game assets since we are beginning a new Level. Add the following code below the nextLevel() function.

Here we reset our chosenCards to an empty Vector, reset our numCardsLoaded variable to 0, and reset our xPos and yPos variables so our cards will be laid out properly.

One last Step before we can test our Movie. Inside the checkForMatch() function, where we are checking if cardArray.length==0 remove the trace("GAME OVER!!") and replace it with the code below.

Now we can begin a new level when we have matched all of our cards. Go ahead and test the Movie.

This is all good and well but we could use some feedback of how many cards have loaded. So we will do that next.


Step 2: Designing the ProgressContainer Class

We will be designing a "ProgressContainer" class that will be used to show the progress of getting the photo information and the loading of the photo's themselves.

Go to Insert > New Symbol or just press Ctrl+F8. Give it the name "ProgressContainer", make sure "Export for Actionscript" is checked and that the "Class" is set to "ProgressContainer".


Select the Text Tool and make sure the following properties are set under the "CHARACTER" panel.

  • Size: 17pt
  • Color: #F26AF2

Now drag out a TextField onto the stage and then making sure it is selected set the following properties under the "POSITION AND SIZE" panel.

  • X: 3.00
  • Y 9.00
  • W: 267.00
  • H: 23.00

Give this TextField the instance name "infoText".


Next go to Window > Components or just press CTRL + F7 drag out a ProgressBar component into the MovieClip and give it the instance name "pb".



Making sure the ProgressBar is selected give it the following properties under the "POSITION AND SIZE" panel.

  • X: 3.00
  • Y: 50.00
  • W: 267.00
  • H: 20.00

Select the TextField, then right click and choose "Cut". Next create a new layer on the timeline by clicking on the new timeline icon on the bottom left of the timeline and then right click and choose "Paste In Place" on the new layer.


Next we need to design the little "dots".

Right Click on the timeline at frame 10 and choose "Insert Keyframe", then repeat on frames 20, 30, 40 and 50.


In the "TOOLS" panel change the Rectangle to an Oval, and give it the color "#1D8EE7".

Now drag an oval out into the MovieClip and give it the following properties.

  • W: 10.00
  • H: 10.00

Next right-click the oval and choose "Convert to Symbol" -- make sure the "Name" is set to dot.


Now delete it off the stage.

Now we need to add the dots to our MovieClip; click on frame 10, drag out a dot from the Library, and give it the following properties.

  • X: 50.00
  • Y: 35.00

Next click on frame 20, drag a dot out into the MovieClip, and give it the following properties.

  • X: 100.00
  • Y: 35.00

Click on frame 30, drag a dot out, and give it the following properties.

  • X: 150.00
  • Y: 35.00

Click on frame 40, drag a dot out, and give it the following properties.

  • X: 200.00
  • Y: 35.00

Now with our design finished we can write the class for this "ProgressContainer".

Go to File > New and choose "Actionscript File"


Save this file as "ProgressContainer.as" and then enter the following code.

Here we just set up a few methods for our ProgressContainer. The setText() takes a String as a parameter and sets the TextFields .text property to whatever was passed in. The resetProgressBar() method resets the ProgressBar, the setPbvisible() method makes the ProgressBar visible, the setPbInvisible() method makes the ProgressBar invisible, and finally the setPbProgress() method takes two integers as parameters and uses those to set the progress of the ProgressBar.

This completes our "ProgressContainer" class. Next in this tutorial we will put it to use.


Step 3: Using the ProgressContainer

Now that we have a ProgressBar to track our progress, let's put it to use.

We will need a variable to track how many images have loaded and a variable for our ProgressContainer, and we also need a variable for how many cards we are using per game. Add the following variables to the bottom of your variable declarations.

Next we will need some methods to add and remove our ProgressContainer so add the following below the resetAssets() method.

In the addProgressContainer() function we simply set the .x and .y properties and add it to the stage. In the removeProgressContainer() function we check to see if it is on the stage and if so we remove it from the stage by calling removeChild.

We will show the ProgressContainer when we are contacting the server in the doRequest() method so add the following under the line loader.load(request).

Here we add the ProgressContainer set the text to "Contacting Server" and set the ProgressBar to not be visible. Since we are only contacting the server and not loading anything we don't want the ProgressBar visible.

When we are finished contacting the server and getting the information, we want to set the ProgressBar to be visible and change the text to "Loading Images". Inside the completeHandler() function underneath the line imageURLArray = new Array() enter the following.

Now inside the positionCards() function we will update the progress of loading the images. Add the following to the positionCards() function above the line if(numCardsLoaded == 10).

Here we check if ProgressContainer is not already on the stage. If it is not we add it to the stage, increment the numCardsLoaded variable and use setPbProgress to update the ProgressBar.

Then within the same function after shuffleCards(cardArray); add the following line of code.

Here we simply remove our ProgressContainer from the stage by using removeProgressContainer().

You can test the Movie again and you should have a ProgressBar that shows the progress of the images being loaded.


Step 4: Letting the User Start a New Game

It would be nice to let the user be able to start a New Game with a different Search. That's exactly what we will accomplish in this step.

First off we will need a new Button. So add the following variable to "Main.as".

Next up we need some methods to add and remove our button. Add the following code underneath the removeProgressContainer() function.

Here we pass two int's as parameters to the addNewGameButton() and use them to set the .x and .y position of the button. Next we use setText() to set the text of our button, add it to the stage, and add an EventListener that will be called when the user clicks on the button.

In the removeNewGameButton() function we simply remove the button by calling removeChild.

Next we need to code our newGame function. Add the following code below the removeNewGameButton() method.

Here we call our resetAssets() function remove the NewGame button and remove any cards that are left on the stage.

Now we need to add our new game button at the appropriate times.

In the positionCards(), after the if statement if(numCardsLoaded == 10) add the following code.

Next we need to make sure we remove the NewGame Button when we complete a level. So for now add the following in the checkForMatch() inside the if statement that checks if the cardArray.length==0).

You can now test the Movie and you should be able to start a new Game.


Step 5: Designing the Timer Container

Our game times how long it takes the user to get through a level and show how many levels are available. We will create the TimerContainer in this step.

Go to Insert > New Symbol or press CTRL + F8. Give it the name "TimerContainer", make sure "Export for Actionscript" is checked and that Class is set to "TimerContainer".


Select the Text Tool and make sure the following properties are set under the "CHARACTER" Panel.

  • Size: 17pt
  • Color: #1D8EE7

Make sure that it is set to be "Classic Text" and "Static Text" respectively.


Now drag out a TextField and set the text to "Time Passed" and give it the following properties.

  • X: 0.00
  • Y: 6.00
  • W: 90.00
  • H: 22.85

Drag out another TextField, set the text to "Best Time" and set the following properties.

  • X: 154.00
  • Y: 6.00
  • W: 77.00
  • H: 22.85

Now change the type to "Dynamic Text" and drag out a TextField into the MovieClip. Set the color to #F26AF2, give it the instance name "timePassed_txt" and set the following
properties.

  • X: 94.00
  • Y: 6.00
  • W: 60.00
  • H: 22.85

Make sure the type is still set to "Dynamic Text" and drag out another TextField. Make sure the color is still set to #F26AF2, give it the instance name "bestTime_txt" and set the
following properties.

  • X: 0.00
  • Y: 32.00
  • W: 303.00
  • H: 22.85

Last make sure type is "Dynamic Text" and drag out a TextField. Set the color to #1D8EE7, give it the instance name "levelText", make sure it is set to center alignment, and set the following properties on it.

  • X: 0
  • Y: 32.00
  • W: 302.00
  • H: 23.00

This completes the design of the TimerContainer, in the next Step we will write a class for it.


Step 6: Writing the TimerContainer Class

In this Step we will write a class for our TimerContainer.

Go to File > New and choose "Actionscript File" save this as "TimerContainer.as" then enter the following code.

These three functions all work the same. They take a string as a parameter and set the text on the corresponding TextField.

Next we will put this TimerContainer to use in our Game.


Step 7: Using the TimerContainer in Our Game

To be able to use the TimerContainer we must first create one. Add the following to the bottom of your variable declarations.

The timePassed variable will be used to keep track of how much time has passed in seconds.

Since we are using a Timer we need to import it as well. Enter the following at the bottom of your import statements.

Next we will need some methods to add and remove our TimerContainer. Add the following below the newGame function.

In the addTimerContainer function we set the .x and .y properties of the timerContainer, add it to the Stage, create a new Timer, and add an EventListener to the timer.

In the removeTimerContainer we set the timePassed TextField to an empty String by calling setTimePassedText() and passing in an empty String. Then we remove the EventListener from the Timer, set timePassed equal to 0, and use removeChild() to remove the timerContainer from the Stage.

Next we need to code the update function that we added within the EventListener for the Timer. Add the following code below the removeTimerContainer function.

Here we increment the timePassed variable and determine how many seconds and minutes have passed. The seconds variable takes the remainder of timePassed/60 by using
the modulus operator. The minutes variable takes timePassed/60 and the uses Math.floor to round it down. If you're interested in learning more
about how this works check out my tutorial on creating a custom timer.

Add the following code to the positionCards() function just above the addNewGameButton() function.

Here we are simply adding the timerContainer to the stage and starting the timer.

We will need to remove the timerContainer when we begin a new game so enter the following inside the newGame() function just below the call to removeNewGameButton().

We also need to remove the timerContainer it when we begin a new level so add the following code to the checkForMatch() function just below where you put
the addNextLevel() function.

You can now test the movie and should have a timer that times how long it takes you to get through a level.


Step 8: Calculating the Best Time

Our game tracks the best time as the user progresses through the levels. We will add that functionality in this step.

We first need a variable to keep track of the best time so add the following to the bottom of your variable declarations.

Here we set bestTime to a very high number since it is very unlikely that it would take the player that long to complete a level.

Add the following below the checkForMatch function.

Here we check if timePassed is less than bestTime; if it is we have a new best time so we set bestTime equal to the timePassed, then we use the same method as the update() method to calculate the minutes and seconds the we update the bestTime_txt TextFiels within our TimerContainer.

Add the following to the checkForMatch() method just above where you added removeTimerContainer().

We will need to reset the bestTime when we start a new game so add the following to at the bottom of the newGame() method.

You can now test the movie


Step 9: Keeping Track of the Levels

Our game keeps track of how many levels there are in the game, and how many the user has been through. We will code that functionality in this step.

We need need a variable to keep track of how many levels there are and also the current level so enter the following to the bottom of your variable declarations.

Within the completeHandler() function just above loadCards() add the following.

This takes the length of the imageURLArray and divide it by 10 since we are using 10 images in our game.

Next inside the positionCards function underneath the addNewGameButton() add the following code.

Here we increment the level variable and set the levelText TextField within the TimerContainer to show which level we are on.

When we start a new game we need to reset the numLevels and level variables so add the following to the newGame() function just below the call to
timerContainer.setBestTimeText().

You can now test the movie and see the levels being tracked.


Step 10: Creating the InfoPanel

Our game uses an info panel to show some info if an error occurs in the game, for instance if enough images are not returned for a game, or there is an server error. We will
create this infoPanel in this step.

Go to Insert > New Symbol of just press CTRL+F8. Give it the name "InfoPanel" and make sure "Export for Actionscript" is checked, and that the Class is set to "InfoPanel".


Select the rectangle tool and in the "PROPERTIES" panel give it the following properties.

  • Fill Color: #F26AF2
  • Stroke Color: #1D8EE7
  • RECTANGLE OPTIONS: 9.00 on all sides

Now Drag out a Rectangle onto the stage and double click it to select both the fill and stroke, and the give it the following properties.

  • X: -150.00
  • Y: -100.00
  • W: 300.00
  • H: 200.00

Next select the Text tool and drag out a TextField on top of the rectangle, give it the instance name "infoText" and then give it the following properties.

  • X: -140.00
  • Y: -92
  • W: 283.00
  • H: 184.00
  • Size: 17pt

You can close this MovieClip, next we will make a class for the infoPanel.


Step 11:Coding the InfoPanel Class

Go to File > New and choose "Actionscript File". Then enter the following code.

Here we add one method which sets the text of the infoText Textfield.


Step 12: Checking Whether Enough Images Were Returned

In this Step we will check if enough images were returned for a game.

Enter the following at the bottom of your variable declarations.

We will want to make sure when we run our doRequest() function that the infoPanel is removed from the stage, so enter the following code under the if statement that
checks if the searchPanel is on the stage.

Next we will check that at least 10 images are returned, since our game needs at least 10 images to make a game. Enter the following code within the completeHanlder().

Here we check whether the imageURLArray.length is less than 10 and if it is we set the .x and .y properties of the infoPanel, set its text to an appropriate message and add it to the stage. Next we add the searchPanel so the user can search again and remove the ProgressContainer.

Test the movie and enter some random characters. The infoPanel should show alerting you that not enough images were returned.


Step 13: Getting info for a Single Photo

The flickr API requires that you give the owner of the files attribution within your application. That is what we will accomplish in this step.

The first thing we will need to do is add this information. We will setup another URLRequest for each individual photo that is returned in our completeHandler, then
we will add the information from that single photo to the imageURL Array. Enter the following code within the completeHandler() function.

Here we call the photos.getInfo method of the Flickr API. We pass the photo.id as an argument to the photos.getInfo method, which will
return the information for the particular photo.

Next we set up an URLRequest a Loader add an EventListener and then load the request.

Next up we will code the infoLoaded method we added in the EventListener.


Step 14: Coding the infoLoaded() function

We will need a variable to keep track of how many images have been processed as well as a the number of photos that were returned. Add the following to the bottom of
your variable declarations.

We set imageNum to -1 since we will increment it each time a photo is Loaded

Add the following within the complete handler just above the line numLevels = imageURLArray.length / 10.

Add the following below the completeHandler function.

There are a few changes we will need to make to our other functions, but lets dissect this one first.

We first increment the imageNum variable. Next we set the ProgressBar's progress, set a variable index to 0, setup a URLLoader loader, put the URLLoader data into a String and then use JSON.decode to turn the string into an Object.

We loop through the imageURLArray checking if the imageURLArray's photoid matches the decodedJSON.photo.id, and if they do we set the index variable equal to i then we update the imageURLArray with a username and photoURL key.

Basically this for loop check whether the image in the imageURLArray matches the current image that is being processed in the for loop.

Last we check whether the imageNum variable is equal to the numberPhotosReturned - 1, then we reset the ProgressBar, set its text, and call the loadCards() function.

We are now loading the cards within the infoLoaded() function instead of the completeHandler() function, since we want to get the photos' information before we load the cards.

Remove the else statement within the completeHandler method that has the loadCards() function.

Within the completeHandler() method change the text "Loading Images" to "Getting Photo Information".

We need to reset imageNum to -1 when we restart a new search so inside of the resetAssets method add the following.

You can now test the Movie and see the progress of loading the photo information as well as the cards.


Step 15:Creating the Attribute Cards

First off we need a new Vector to hold our attribute cards. Enter the following at the bottom of your variable declarations.

Next we will need to create these cards. We will do this in the loadCards() method. Below is the loadCards method with the changes highlighted.

We intitiate attributeCards to a new Vector, then we make an attributeCard variable, set its properties and lastly we push it into the attributeCards Vector.


Step 16:Creating the AttributeTextField class

We will create a custom TextField to show our attributions. Go to File > New "Actionscript File" save this file as "AttributeTextField.as", and then enter the following code.

We first import the classes we will be using. Then we declare two varibles css which we will hold a string of css, and textStyleSheet which we will use
to parse the css string.

Next we set some properties on the TextField, code the css string, parse it, and finally set the StyleSheet for this TextField.


Step 17: Showing the Attributions

Now we are ready to show the attribute cards at the end of the levels. We will code a showAttributions() method to accomplish this. But first we need a reference to AttributeTextField.

Enter the following code at the bottom of your variable declarations.

We will also need to import the TextField so enter the following at the bottom of your import statements.

Next enter the following beneath the calculateBestTime() method.

We call our resetAssets() method, calculateBestTime() method, and remove the TimerContainer and NewGameButton by calling the respective methods.

Next we setup some variables to hold the x and y positions of our Cards and Text. We then loop through the attributeCards Vector.

We check whether i%2 is equal to 0 (which means it's an even-numbered card) and if it is, we reset the xPosPics and xPosText to their original values. We then make a tempCard variable which is the current card in the attributeCards Vector, set it's .x and .y positions and add it to the stage with addChild.

Next we create an attributesText variable, and set its .x, .y, and .width properties.

We then create an attText variable using the styles we set in our AttributeTextField class, and use the methods of our Card getUserName and getPhotoURL to assign the proper UserName and URL to the correct Photo within this string.

Next we set the htmlText of our attributesText equal to the attText we just created and we use the .name property to give the attributesText a name so we can reference it later in our code. Finally we add it to the stage.

We add 300 onto the xPosPics and xPosText so our cards(Images) are spaced out correctly. Remember if i%2 is equal to 0 we reset these.

Last we check whether level!=numLevels if it is not equal we add the nextLevelButton otherwise we add the newGameButton.

Within the checkForMatch function where you are checking if(cardArray.length==0) remove everything from within that function and replace it with showAttributions.

We will also need a method to remove the attributionCards so add the following below the showAttributions() method.

We first check whether the nextLevelButton is on the stage, and if so we remove it.

We then loop through the attributeCards Vector, check if they are on the stage and if so we remove them. Next we use getChildByName to make sure that the attributesText fields are not null, and if they are not we remove them.

Within the nextLevel() method add the following.

And within the newGame method also add the following.

Add the following change to the completeHandler() method.

Here we code the ioErrorHandler() method we added in the EventListeners above. Add the following beneath the addListeners() method.

This method gets called whenever there is an IOError with our Loaders. We first remove the progress container. Then we set the infoPanel's .x and .y properties, set its text to an appropriate message and add it to the stage, then we add the searchPanel to the stage so the user can try a new search.

You can now test the movie. Try disconnecting from the internet to make sure this works!


Step 19: Designing the Start Page

In this Step we will design the Start Page of our game.

Go to Insert > New Symbol or just press CTRL +F8. Give it the Name "StartPage".


Go to Insert > New Symbol or just press CTRL+F8. Give it the Name "InstructionsPage".


Select the rectangle tool and give it the following properties

  • Stroke Color: #F26AF2
  • Fill Color: #1D8EE7

Under "FILL AND STROKE" give it a stroke of 3.00, and under "RECTANGLE OPTIONS" set the corner radius to 9.00 on each.


Now drag out a rectangle into the InstructionsPage MovieClip. Double click the rectangle you just dragged out to select both the fill and stroke and give it the following properties.

  • X: -275.00
  • Y: -250.00
  • W: 550.00
  • H: 500.00

Next select the Text Tool and drag out a TextField on top of the rectangle you just drew. Make sure it is set to "Classic Text" and "Static Text" then give it the following properties.

  • X: -235.00
  • Y: -215.00
  • W: 440.00
  • H: 319.65
  • Size: 17pt

Inside this textfield, put some instructions for the game. Below are the instructions I used.

You can now close this MovieClip.

Now go to the library and double click on the "StartPage" to open it for editing.

Inside the library there are some ".pngs" with the names "building.png", "camera2.png", "dog.png", "flower.png", and "waterfall.png". I dragged these out onto the "StartPage" and used the FreeTransform tool to rotate some of them.

Next I put two textfields on the Stage one with the text "PHOTO" and the other with the text "MATCH". I used the following properties for them.

  • Color for "PHOTO": #1D8EE7
  • Color for "MATCH": #F26AF2
  • Size: 40pt

Now go to the library and drag out the "InstructionsPage" and make sure it covers all the images and text. When I dragged mine out it had the following properties.

  • X: 300.00
  • Y: 266.00

Give it the instance name "instructionsPage".

Still withing the "StartPage" MovieClip drag out three "GameButtons" and position them as follows.

  • Button1 X: 55.00
  • Button2 X: 234.00
  • Button3 X: 415.00
  • All Buttons Y: 522.00

Next give the buttons the instance names "startBtn", instructionsBtn", and "aboutBtn" going left to right. You can now close this MovieClip.

In the next Step we will design the "About Game" Page.


Step 20: Designing the AboutGamePage

Select the Rectangle tool; make sure the fill is set to white and there is no stroke.


Drag a Rectangle out on the stage. Making sure this rectangle is selected, give it the following properties.

  • X: 0.00
  • Y: 0.00
  • W: 600.00
  • H: 520.00

Now right-click on this rectangle and choose "Convert To Symbol". Give it the name "AboutGame"

Select the Text Tool and drag out a TextField into this MovieClip. Give it the following properties.

  • Color: #1D8EE7
  • X: 75.00
  • Y: 50.00
  • W: 494.00
  • H: 86.00
  • Size: 17.0 pt

I used this TextField to explain a little about the game. Below is the text I used.

Next I pulled out of the library the images for the startpage, the "building.png", "dog.png", "flower.png" and "waterfall.png". And below are their "X" and "Y" values.

  • Building X: 42.00
  • Dog X: 315.00
  • Flower X: 42.00
  • Waterfall X: 315.00
  • Building Y: 202.00
  • Dog Y: 202.00
  • Flower Y: 373.00
  • WaterFall Y: 373.00

Now you can exit out of this MovieClip. Make sure an instance is on stage and give it the instance name "AboutGamePage", then set the following properties on it.

  • X: 602.00
  • Y: 0.00

We want to make sure this MovieClip is above everything else so make sure it is selected then go to Modify > Arrange > Bring to Front.

In the next Step we will wire up the ActionScript for our StartPage.


Step 21: Adding ActionScript to the StartPage

If it's not already on stage, drag out an instance of the "StartPage" and give it the instance name "startPage".


Inside the setupGameElements() remove the line addSearchPanel() and replace it with the following.

Here we set the text on our buttons and add a few EventListeners to them, we also set the "instructionsPage" initial width, height, and alpha.

Now we need to define handler function for our EventListeners. Enter the following code below the setupGameElements() method.

Here we remove the "startPage" and "aboutGamePage" and add the searchPanel to start the game. Add the followind under the removeStartPage() method you just created.

Here we first make sure that the "aboutGamePage" .x is at 601, so it is sitting just of the right side of the stage. Then we set the "instructionsPage" .alpha to 1, and use TweenLite to animate its .width to 570 and its .height to 500. Add the following code below the showInstructions() method you just created.

Here we simply use TweenLite to animate the "aboutGamePage" .x to 0.

Since we are using TweenLite we need to import it. Add the following at the bottom of your import statements.


Step 22: Finishing the AboutGamePage

We need to give attributions to the owners of the images we used on our start page. We will do just that in this final Step of the tutorial.

Add the following code just below the showAboutGame() method you created in the Step above.

Here we set up four AttributeTextField instances and four Strings to hold the information about the images; we then add them to the "aboutGamePage" and set the .width, .x and .y properties for each of them.


Conclusion

You now have a entertaining photo matching game utilizing the Flickr API. Can you think of some other ways to use the Flickr API for fun and games? Thanks for reading and I hope you have found this tutorial useful.

Advertisement