Essential Guide To Flash Games Chapter 13 Part 1. Modified BasicScreen and new ImageButton class
The Essential Guide To Flash Games only contains 12 chapters, so what is chapter 13? Chapter 13 and beyond will be additions to the book and efg framework that build on what has been created so far. When adding or changing classes in the original efg framework we need to be extra careful that all existing games will still compile. For this reason we will not make wholesale changes to existing classes, but we will add functionality where we can. In some cases we can add this functionality to existing classes through new methods by adding new constructor parameters with default values. In other cases we need to build new classes or extend existing ones.
If you have taken a look at the book and have visited this site for any length of time you will notice that some of the book chapters were greatly expanded versions of tutorials that we had presented as blog entries. Everything was re-written to work with the efg framework and re-coded to fit within some basic common coding standards. We have decided that we will continue to support the book in a similar manner. With chapter 13 and beyond you will be getting a preview of what could possibly be included in the second edition of the book (also in an expanded form). By utilizing the framework and expanding on the existing code-base we are also demonstrating how creating a re-usable, expandable framework can aid the developer in simplifying future development efforts through shared code libraries, re-use and iteration. Plus it’s fun and I get to channel all of my tutorials and dev into an area that will be useful now and in the future.
You will benefit most from this information if you have some familiarity with the book or the efg framework. The entire framework and set of game examples is a free download on the book site. It will make much more sense if you have the book in some form as a reference though.
Chapter 13: Part 1
Modified BasicScreen and the new ImageButton Classes
The plan all along has been for us to keep updating the Essential Guide To Flash Games book with more game and more chapters. Now that the book has been out for a couple months we are going to begin that process by updating the efg framework a bit. The BasicScreen class as presented in the book is a little limited in functionality (on purpose). The point was to build a foundation that readers could add to and extend as needed. It turns out that Steve and I needed to do just that when we sent a couple of the book games (Blaster Mines and Tunnel Panic) virally to promote the book release. We found that we needed to add two basic functions to the class to make it more useful:
1. The ability to add an image to a screen
2. The ability to use images in place of the the text in the SimpleBlitButton class.
The new ImageButton class
We will begin by taking a look a the first new class, ImageButton. Rather than extend the SimpleBlitButton class we found it much more straight-forward to create a similar class with slightly different functionality. This class i adds the ability for the an image to be used for the “off” and “over” states of the button.. In fact, this class is designed to also be expanded with other button states of needed.
Here is the full text of this class. It should be saved in the com/efg/framework package with the name ImageButton.as.
This class only contains the physical look of the button states and provides a mechanism function for changing the state based on a constant. It does not actually contain the listening functions to respond to events. The container class (BasicScreen) will be used for this as it is with the SimpleBlitButton class.
This class extends the Sprite class and contains a single Bitmap object (buttonBitmap). The bitmapData attribute of buttonBitmap will be swapped based on the state of the button. This class was designed to function very similar to the BasicBlitButton class in the original framework.
Note: the “_” character in the code is used to designate line continuation. If you are going to cut and paste the code, search for these lines and re-attach them in you IDE. They are necessary to ensure that the page layout of the site is not affected by the length of the code lines.
package com.efg.framework { import flash.display.Bitmap; import flash.display.BitmapData; import flash.display.Sprite; import flash.geom.Point; /** * ... * @author Jeff Fulton */ public class ImageButton extends Sprite{ public static const OFF:int = 1; public static const OVER:int = 2; public var buttonBitmap:Bitmap; public var offBitmapData:BitmapData; public var overBitmapData:BitmapData; public function ImageButton(off:BitmapData, over:BitmapData, location:Point) { offBitmapData = off; overBitmapData = over; buttonBitmap = new Bitmap(offBitmapData); addChild(buttonBitmap); x = location.x; y = location.y; this.buttonMode = true; this.useHandCursor = true; } public function changeButton(typeval:int):void { if (typeval == OFF) { buttonBitmap.bitmapData = offBitmapData; }else { buttonBitmap.bitmapData = overBitmapData; } } } } |
ImageButton Constants
The constants designate the two simple states of the button: OFF or OVER. These will be controlled by the container class (BasicScreen) and passed into the changeButton() function as needed.
The constructor
The constructor accepts in the two BitmapData objects representing the look for the OFF and OVER states for the button. It also accepts in a Point class instance used to position the button inside it’s container object (the BasicScreen class in this example).
The changeButton() function
This function is the public interface used to change the button state. It is a simple if/else statement now, but can be expanded to add further states if needed. It accepts an integer typeval. This integer must be one of the defined state constants. The bitmapData attribute of the buttonBitmap will be swapped based on the typeval passed in.
The modified BasicScreen class
The original BasicScreen class in the efg framework remains essentially intact, but we are going to add in functionality to add a background image and use an instance of the ImageButton class in place of the SimpleBlitButton if desired.
We we be adding a new function called addImage() that will allow the developer to add a single image to the BasicScreen instance. We thought about allowing the developer to add “N” number of images, but this would necessitate creating our own interface for managing the layering (or display list) inside the BasicScreen. We might add that functionality in the future, but for now a single image can be added to a BasicScreen instance. We will also create a new function called createImageButton() that will allow the current single button on the BasicScreen to be an ImageButton instance instead of the BasicBlitButton. There is a lot more we can do with this class such as allow the creation of multiple buttons, adding swfs as well as multiple images, etc. For now we will be adding this simple functionality and tackle the more advanced additions in a later addition to the framework.
package com.efg.framework { // Import necessary classes from the flash library import flash.display.Bitmap; import flash.display.BitmapData; import flash.display.Sprite; import flash.events.Event; import flash.geom.Point; import flash.text.TextField; import flash.text.TextFormat; import flash.events.Event; import flash.events.MouseEvent; import flash.text.TextFormatAlign; /** * ... * @author Jeff Fulton */ public class BasicScreen extends Sprite { public var displayText:TextField = new TextField(); public var backgroundBitmapData:BitmapData; public var backgroundBitmap:Bitmap; public var okButton:SimpleBlitButton; public var imageButton:ImageButton; public var imageBitmapData:BitmapData; public var imageBitmap:Bitmap; public var useImageButton:Boolean = false; //ID is passed into the constructor. When the OK button is clicked, //a custom event sends this id back to Main private var id:int; //Constructor accepts our two passed in vars and then calls init public function BasicScreen(id:int,width:Number, height:Number, _ isTransparent:Boolean, color:uint) { this.id = id; backgroundBitmapData = new BitmapData(width, height, isTransparent, color); backgroundBitmap = new Bitmap(backgroundBitmapData); addChild(backgroundBitmap); } public function addImage(bitmapData:BitmapData):void { imageBitmapData = bitmapData; imageBitmap = new Bitmap(imageBitmapData); addChild(imageBitmap); } public function createDisplayText(text:String, width:Number, _ location:Point, textFormat:TextFormat):void { displayText.antiAliasType = flash.text.AntiAliasType.ADVANCED; displayText.y = location.y; displayText.x = location.x; displayText.width = width; displayText.defaultTextFormat=textFormat; displayText.text = text; addChild(displayText); } public function createOkButton(text:String,location:Point, width:Number, _ height:Number, textFormat:TextFormat, offColor:uint=0x000000, _ overColor:uint=0xff0000, positionOffset:Number=0):void { useImageButton = false; okButton = new SimpleBlitButton(location.x, location.y, width, height, _ text, 0xffffff, 0xff0000, textFormat, positionOffset); addChild(okButton); okButton.addEventListener(MouseEvent.MOUSE_OVER, okButtonOverListener, false, 0, true); okButton.addEventListener(MouseEvent.MOUSE_OUT, okButtonOffListener, false, 0, true); okButton.addEventListener(MouseEvent.CLICK, okButtonClickListener, false, 0, true); } public function createImageButton(imageOff:BitmapData, imageOver:BitmapData, _ location:Point):void { useImageButton = true; imageButton = new ImageButton(imageOff, imageOver, location); imageButton.addEventListener(MouseEvent.MOUSE_OVER, okButtonOverListener, false, 0, true); imageButton.addEventListener(MouseEvent.MOUSE_OUT, okButtonOffListener, false, 0, true); imageButton.addEventListener(MouseEvent.CLICK, okButtonClickListener, false, 0, true); addChild(imageButton); } public function setDisplayText(text:String):void { displayText.text = text; } //Listener functions //okButtonClicked fires off a custom event and sends the "id" to the listener. private function okButtonClickListener(e:MouseEvent):void { dispatchEvent(new CustomEventButtonId(CustomEventButtonId.BUTTON_ID,id)); } private function okButtonOverListener(e:MouseEvent):void { if (useImageButton) { imageButton.changeButton(ImageButton.OVER); }else{ okButton.changeBackGroundColor(SimpleBlitButton.OVER); } } private function okButtonOffListener(e:MouseEvent):void { if (useImageButton) { imageButton.changeButton(ImageButton.OFF); }else{ okButton.changeBackGroundColor(SimpleBlitButton.OFF); } } } } |
The addImage() function
The addImage() function takes a BitmapData instance as it only parameter and sets the public imageBitmap variable’s bitmapData attribute to reference it. We made this a public attribute so we would not need to code an interface for all of the transformations such as scale, alpha, etc that the developer might want to apply to the image. The external calling class can control this imageBitmap directly. This also applies to positioning the image. We will see an example shortly on how to do this.
The createImageButton() function
This function takes in the same parameters as the ImageButton class: A BitmapData instance for the “OFF” state, a BitmapData instance for the “OVER” state, and a point instance for the location of the button. In turn, this function creates an instance of ImageButton called imageButton and also sets the internal class variable useImageButton to true. This allows the code to switch between using the SimpleBlitButton and the ImageButton as the click through “ok” button. If we were adding this to the framework’s Main.as class we would use that button click to move to the next state in the game loop state machine. For part 1 we simply demonstrate how to use these two classes together without utilizing the entire framework. In part two we will start to utilize the GameFrameWork.as base class and integrate in these new classes.
Creating the BasicScreenDemo.as
Using the the new ImageButton and expanded BasicScreen class we are going to create a simple example called BasicScreenDemo.as. I have done my demo in FlashDevelop and will embed the images needed at compile time. If you are using the Flash IDE you should import the images into the library using the same class names that I use in my embed. I have provided code that will allow you to use images from the library. You will need to comment out the embed statements and the change the variable instantiation for the BitmapData instances to the “//Flash IDE ” lines. If you are using Flash CS4 or CS5 you can embed your assets as long as you set the location of the FlexSDK. In CS5 you will automatically be prompted to do this when you try to compile the first time.
Note: The zip file download contains code, project files, assets, and the .fla file (in CS4 format) to support both versions
Creating the project
1. Inside the /source/projects folder you will want to create a new folder called “ch13_classupdates”.
2. Inside this folder you will want to create a folder called “flashIDE” or “flexSDK” depending on the development environment of your choice.
3. If you are using Flash Develop, Create a Flash Develop project (AS3 Project) inside the flexSDK folder with a class path of com.efg.demos.classupdates. This will create a src/com/efg/demos/classupdates folder. You will also want to create a folder called “assets” in this folder: src/com/efg/demos/classupdates/assets.
4. If you are using the FlashIDE you will want to create the com/efg/demos/classupdates folder inside the source/projects/ch13_classupdates/flashIDE folder. You will also want to Create the BasicScreenDemo.fla in this folder: source/projects/ch13_classupdates/flashIDE/BasicScreenDemo.as
5. Set the dimensions to 400×400 with a frame rate of 30.
6. Add the classes folder that contains the com/efg/framework package to your class path.
Creating the BasicScreenDemo.as class
The BasicScreenDemo.as file will be the “always compile” or “document class” (depending on your IDE of choice).
package com.efg.demos.classupdates { import flash.display.Bitmap; import flash.display.BitmapData; import flash.display.Sprite; import flash.events.Event; import com.efg.framework.BasicScreen; import flash.geom.Point; /** * ... * @author Jeff Fulton */ public class BasicScreenDemo extends Sprite { [Embed(source = 'assets/asciirooidstitle.jpg')] public static const TitleJpg:Class; [Embed(source = 'assets/playbutton_off.jpg')] public static const PlayButtonOffJpg:Class; [Embed(source = 'assets/playbutton_on.jpg')] public static const PlayButtonOnJpg:Class; private var titleScreen:BasicScreen; //FlexSDK private var titleBitmap:Bitmap = new TitleJpg(); // end Flex SDK //Flash IDE //private var titleBitmapData:BitmapData = new TitleJpg(0,0); //end flash IDE public function BasicScreenDemo():void { if (stage) init(); else addEventListener(Event.ADDED_TO_STAGE, init); } private function init(e:Event = null):void { removeEventListener(Event.ADDED_TO_STAGE, init); // entry point titleScreen = new BasicScreen(1, 400, 400, false, 0x000000); //Flex SDK titleScreen.addImage(titleBitmap.bitmapData); //end Flex SDK //Flash IDE //titleScreen.addImage(titleBitmapData); //end Flash IDE titleScreen.imageBitmap.x = 50; titleScreen.useImageButton = true; //Flex SDK titleScreen.createImageButton(new PlayButtonOffJpg().bitmapData, new PlayButtonOnJpg().bitmapData, _ new Point(150, 300)); //end Flex SDK //Flash IDE //titleScreen.createImageButton(new PlayButtonOffJpg(0,0), new PlayButtonOnJpg(0,0), _ new Point(150, 300)); //end Flash IDE addChild(titleScreen); } } } |
This demonstration class simply creates an instance of the BasicScreen class (titleScreen) and then adds an instance of the TitleJpg embedded/imported class to the BasicScreen with the addImage() function call. To add the ImageButton we call the createImageButton() function passing in the PlayButtonOffJpg class, the PlayButtonOnJpg, and a Point instance to place the ImageButton on the TitleScreen.
Here are the assets that we use in this demo:
asciirooidstitle.jpg
playbutton_on.jpg
playbutton_off.jpg
Below is the working swf example:
http://images/blog/chapter13/BasicScreenDemo.swf
By moving the mouse pointer over and off the “Play” Button the state will change.
Download the .zip file with all code, assets, and project files.