Introduction
Welcome to another UDK tutorial from Mavrik Games! In this tutorial, I'll show you how to implement a simple menu system (or a "Front End" as it's called in the UDK world) using Flash, ActionScript 3.0, and Scaleform. There are a few tutorials on this subject already out there (Matt Doyle's video series is a really good place to start), but most of them are based on ActionScript 2. I realize that it's just an idiosyncrasy of mine, but I can't stomach writing code in an older version of a language when a newer version is available (especially if I'm already more familiar with the newer version ;)). Also, as great as the Scaleform video series by Matt Doyle is, it focuses on how the front end is implemented for Unreal Tournament and UT type games (UT based Unrealscript classes/first person shooters). That's perfect for some, but I wanted to step back one level and show how to make a front end for games outside of the FPS genre using UDK based classes and not UT. Third of all, I wanted to go into more detail about the code involved and a few tricks I picked up through my experimenting. This tutorial assumes a basic knowledge of Flash Professional and ActionScript, but if you need more information about those topics, there is an excellent (albeit lengthy) set of video tutorials by Doug Winnie on Adobe TV. If you don't have Flash Professional, you can buy a month to month subscription, which is a much cheaper option if you're only going to use it a few times for your indie games. Also be aware that this is a programming tutorial with a substantial amount of Unrealscript, so some coding knowledge is expected.
I've tried to keep my tutorials self-contained, meaning that you could just go through them in any order you wanted without needing to reference any of the others. For this menu system though, one of the screens is a "Load Menu", meaning you will need a system to save and load games. I have written a tutorial that goes over the system I use to do this, so if you have the time, It would be good to go through that tutorial first. I won't go over that save system in this tutorial, so you should download the pieces we need from that system here and drop them into your project after everything's been set up. You can also download all the code and content for this tutorial here.
In this first part of the tutorial, I'm going to go over setting up your environment using the Project Suite Management Utility (PSMU) and Pixel Mine's nFringe plugin for Visual Studio. The PSMU handles most of the basic file structure setup, but in order to get all the Flash files (.fla & .swf), CLIK components, ActionScript, Unrealscript and UDK Editor/Content Browser components to play nicely together, I'll go over how to organize the files and configure Flash to follow the necessary file structure. Finally, I'll go through the process of creating the Menu system in Flash Professional, which will consist of using an asset library file for resource sharing and creating three separate Flash files - one for each "screen" in the menu system.
Setup
To set up the project, I recommend using Pixel Mine’s nFringe plugin for Visual Studio and Mavrik Games' Project Suite Management Utility. If you’re never used those tools before and you don’t want to, you can still follow this tutorial as long as you know how to set up your environment. I’m going to go through this tutorial assuming you’re using them though.
The Project Suite Management Utility takes care of all the required setup by creating a Visual Studio solution for your suite and a Visual Studio project for your game, as well as setting up the configuration files and content directories. If this is the first time you’re running the PSMU, it will ask you to select the root directory of your UDK installation. Once you’ve selected the folder, create a project suite. You can call it whatever you want, but mine is called “Tutorial”. Add a game to the suite (I'm calling it ScaleformMenu) and select it in the list. In the config files section, check the option for "DefaultUI.ini" in addition to the other config files already selected by default. In Part 3: Unrealscript and Kismet, we'll use this config file to save and load some graphics settings data, so it needs to be overridden. Leave the rest of the settings at default and click the execute button.
Project Structure
This menu system is a "multi-page" system, meaning the main menu will have buttons for a load menu and an options menu, and clicking those buttons will take you to those menu pages. There are two ways (that I have found) to do this. We could include each page on different points in the timeline in one Flash file and just use some "gotoAndPlay" calls to navigate back and forth. For any somewhat complicated system though, this can get very messy very fast. What I prefer to do instead is create a separate Flash file for each menu screen and keep everything a little more unitized. That way, things are much cleaner and easier to work with. This does throw up a few hurdles, but I'll show you how to get over them.
Before we get to setting up Flash, I want to go over how I've set up my file structure for my Scaleform projects. This is important because we will be doing some file referencing in our Flash files, so we need our file structure set up correctly. If you're using Mavrik Games' Project Suite Management Utility, it will have already set up a part of this file structure for you. It places folders for each suite in the Development\Flash folder and a folder for each game project within those folders. This is where I like to do the actual Flash development, so I keep my .fla and .as files here. It also creates a folder for each game project in the UDKGame\Flash directory suffixed with GFx. In order for the UDK to import our .swf files, they have to be located in this Flash directory. The package and group names for the imported UDK Flash assets depend on the file structure here. What we want is to create a package called ScaleformMenuGFx, a group called SFMFrontEnd (SFM is the abbreviation I'll use quite a bit for ScaleformMenu), and the actual assets called SF_MainMenu, SF_LoadMenu, and SF_OptionsMenu. I like to prefix my assets with two or three letters that tie them to what kind of asset they are so they're easier to search for, so I use SF for Scaleform. To get that structure, we need to create a folder inside the ScaleformMenuGFx folder called SFMFrontEnd, and we'll place our SF_MainMenu.swf, SF_LoadMenu.swf and SF_OptionsMenu.swf files here once they're compiled.
Because we're going to have separate Flash files for each menu screen, we're going to use a resource library swf to do some resource sharing (which I'll explain in more detail as we go). This is done to avoid duplicating assets, so create another folder called SF_Library in the UDKGame\Flash\ScaleformMenuGFx directory (a sibling to the SFMFrondEnd folder). As mentioned in the Scaleform Quick Start Guide, images used in a .swf file need to be in a sibling folder with the same name as the .swf file, so our "library" swf will be called SF_Library.swf and all the images it uses will go in the SF_Library folder.
Next, head over to the Development\Flash\Tutorial\ScaleformMenu folder. Create a folder called "as", one called "FrontEnd" and one called "Lib". The "as" folder is where we will put our Actrionscript document and object classes for the Flash files we'll be creating. The "FrontEnd" folder is where we will put all of our Flash files for our menu system, and the "Lib" folder is where we'll place the Flash file for our resource library. Inside the "as" folder, create a "frontend" folder and a "lib" folder. These are the separate packages for our code. We'll place all the document classes for each menu screen in the "frontend" folder, and the code for any common components (such as the custom mouse cursor class) in the "lib" folder. We separate these out simply for organizational purposes and ease of reuse, which is a common practice in most programming environments.
Flash Configuration
Now it's time to start configuring Flash Professional. I'll be using Flash CS5.5, but CS5 is quite similar. Open up Flash and create a new Actionscriopt 3.0 project. If you haven't already added the Scaleform extension, follow the Setup Guide on the UDN. Click on the "Properties" tab to view the document properties. Click on the wrench next to the "Size" under the "Properties" dropdown, and change it to whatever resolution you like (I'm using 1280 x 720). Also, change the Frame rate to 30. Click on the "Make Default" button so that each menu screen we make has the same dimensions and frame rate then click the "OK" button. Save this file as SF_MainMenu.fla in the Development\Flash\Tutorial\ScaleformMenu\FrontEnd folder. Next, click on the "Publish Settings" button under the "PUBLISH" dropdown. Uncheck the HTML Wrapper format under the "Other Formats" category on the left - we just want the .swf file. We want the actual swf to end up in the UDKGame\Flash folder where the UDK can find it to import it, so set the output file to "../../../../../UDKGame/Flash/ScaleformMenuGFx/SFMFrontEnd/SF_MainMenu.swf". Notice the relative path name and the "slash(/)" for the path name instead of the windows "backslash(\)". The relative path name is so we don't have to change this every time a new version of the UDK comes out and the "slash(/)" is because Adobe focuses on Macintosh development and (in the input boxes at least) they expect their directory path names to follow the Unix convention. Now click on the wrench next to the "Script" dropdown (which should be set to ActionScript 3.0). This opens up the ActionScript settings specific to this current document. In the "Source Path" tab, change the "." next to the folder in the only entry to "../as/frontend". This is the relative path to the "frontend" package for our ActionScript files. Now enter SF_MainMenu in the input box for the Document class and click on the pencil icon to edit the class.
Click OK until all the dialog windows close and you're back out to the main project workspace. If clicking on the pencil opened a tab for the SF_MainMenu class in the workspace (which it would have unless you have another ActionScript editing IDE such as Flash Builder installed and told Flash to open the file using it instead), go ahead and save it in the Development\Flash\Tutorial\ScaleformMenu\as\frontend folder as SF_MainMenu.as and close it for now.
Now that we have the source path set up for this particular Flash project, we also want to set up some global source paths for all our ActionScript (including the "lib" folder) and the CLIK components. In the menu at the top of Flash, click on Edit->Preferences. In the "Category" box on the left, click on "ActionScript" and then the "ActionScript 3.0 Setting" button near the bottom of the window. In the "Source Path" section, add an entry for our "as" folder and one for the CLIK components, making sure to use relative paths:
Adding CLIK Components to the Components Library
Now we want to add our CLIK components to the component library available to Flash. If you click on the little Components symbol in one of the tool bars (it looks like three toy blocks stacked together) and switch to the "Components" tab in the pop out window, you'll see a list of all the components available. We want to add the CLIK Components to that list. Navigate to the Development\Flash\AS3\CLIK\components folder and copy the CLIK_Components_AS3.fla file to your desktop. Rename this file to just CLIK and open it in Flash. This next part is a little tedious, but thankfully doesn't take too long. In the "Library" tab, expand the folders to reveal each component. Go through each component (only the components, not the Assets), right click on it and choose "Component Definition". In the window that pops up, look for the checkbox for "Display in Components panel" and turn it on.
When you've turned this option on for each component, save and close the CLIK.fla file. Move it into the C:\Program Files\Adobe\Adobe Flash CS5.5\Common\Configuration\Components folder (or C:\Program Files (x86)\Adobe\Adobe Flash CS5.5\Common\Configuration\Components for 64 bit operating systems) and click on the Components symbol again in Flash. In the top right corner of the window that pops out, there's a little dropdown symbol. Click on it and the first option should be "Reload Components". Click this option and a new folder called "CLIK" should show up in the list. If you expand that folder, you'll see all the CLIK components, which you can drag and drop onto the stage.
SF_Library
Now we're going to create our library file. We're going to have three different menu screens in three different files, but we don't want to have to recreate our buttons and background in each file, nor do we want to have to keep copies of any images we use for each file to reference, so we're going to use a library swf to hold all of the common assets for the three menus. It's also a nice way to consolidate our content for our Flash projects so that it only has to be updated in one place. Create a new ActionScript 3.0 file and open up the Publish Settings. Uncheck the HTML Wrapper format and set the output file to "../../../../../UDKGame/Flash/ScaleformMenuGFx/SF_Library.swf" - right alongside our folder with the same name. We won't be doing anything with ActionScript in this file so there's no need to change the source path. Now switch to the "Library" tab and create two new folders: Background and Cursor. For the background, we'll just use the same default background as UDK: UDKGame\Flash\UDKFrontEnd\udk_loading\blood_bg1_png.png, but we need to copy it to our UDKGame\Flash\ScaleformMenuGFx\SF_Library folder. Let's also rename it to something easier: Background.png. Back in Flash, we just need to import it. Click on File->Import->Import to Library and browse to the image we just copied over. Flash will automatically create a symbol for it, but all we need is the image, so you can delete the symbol.
In order for the UDK to be able to import images, we need to set them up correctly in our Flash file to "Export for ActionScript". Right click the Background.png asset in the "Library" tab and select "Properties". In the "Bitmap Properties" window that pops up, the first tab is the "Options tab, and all we need to do here is check the box next to "Allow smoothing" and change the dropdown box option beneath it to "Lossless (PNG/GIF)". You'll notice that the path to the image is absolute, and unfortunately, I haven't been able to figure out any way to change it to be relative. That being the case, any time you upgrade your UDK version and continue to work on these Flash files, you'll have to come into this SF_Library.fla file and change any of the paths for the imported images. Luckily, they'll only be referenced here in the SF_Library file, so it shouldn't mess up your other Flash files.
Now switch over to the "ActionScript" tab and check the "Export for ActionScript" option. Name the class the same as the image name but without the extension - so "Background". Finally, check the "Export for runtime sharing" box and type in "../SF_Library.swf" in the URL input. This is the path that any swfs that import this asset will need to reference in order to find the asset. Since our menu swf files will be one folder deeper than our "SF_Library.swf" file, we have to back up one level with "../". The "Export for runtime sharing" option enables us to "embed" the image into just one .swf file (SF_Library.swf). Any other .fla files that use this image will need to "Import for runtime sharing". The image remains "embedded" in the original .swf file, but at runtime, the other .swf files will look for the image in the SF_Library.swf file. That way, we don't duplicate our images for every single .swf that uses them. This also means that the UDK only needs to import them into the Content Browser once, and any other .swf assets that reference them will know where to find them. When you're done, click the OK button and you'll get a warning about Flash not being able to find a definition for the class in the classpath. That's fine since there isn't one, so just click OK. Now move the Background.png object in the "Library" tab into the Background folder we created earlier.
Go through the same process to import an image for a cursor and set up the image properties the same way as the properties for the Background.png image except for two differences: don't delete the symbol that's automatically created (we'll need it to attach some ActionScript to it) and don't select the option for "Export for runtime sharing". We don't need to export this image for runtime sharing because it will not be placed on the stage in any of our .fla files, nor will we include it in any of their libraries, so it will not need to be "Import[ed] for runtime sharing". Instead, we will be creating the cursor in ActionScript code which will be linked to the auto-generated symbol. The cursor image we'll use for the tutorial is UDKGame\Flash\UDKFrontEnd\udk_manager\cursor_png.png which we'll rename to just Cursor.png in the UDKGame\Flash\ScaleformMenuGFx\SF_Library folder.
When you're finished with the cursor's image's properties, right click on the symbol created for the image and go into its properties. Rename it to "CursorSymbol" and change the "Type" to "Movie Clip". We can't attach ActionScript to a "Graphic" type symbol, and a "Button" doesn't make any sense, so "Movie Clip" it is. Check the box next to "Export for ActionScript" and give it a "Class" name of "lib.MenuCursor" (lib is the package in our "as" folder and "MenuCursor" will be the name of the class). Again, you don't need to export the CursorSymbol for runtime sharing because we'll only be referencing it through code; we won't be including it in any of the other .fla files libraries. When everything is set, click the pencil next to the "Class" name to create the ActionScript class. For now, just save it as is in the Development\Flash\Tutorial\ScaleformMenu\as\lib folder as MenuCursor.as and don't bother changing anything just yet - we'll get to that later.
Now it's time for the button. Click the Components icon and expand the CLIK folder in the Components tab of the window that pops out. Click and drag the "DefaultButton" component into the "Library" tab. This will create a folder called Button as well. Expand the "Button" folder and double click the "DefaultButton" component to edit it. Unlock the textField layer in the timeline and click on the "textField" text on the button. Switch to the properties tab and click the "Embed" button to embed the font you want, selecting the "Basic Latin" character range in the options tab of the window that pops up. Now switch to the ActionScript tab in that window and check the "Export for ActionScript" and "Export for runtime sharing" options. Remember to enter "../SF_Library.swf" as the export URL. Click OK and switch back to the "Library" tab. You can name the "DefaultButton" component and the font whatever you want since we won't be referencing them in ActionScript. Now you can edit the button and the text to look however you want, give it animations, effects etc. For simplicity's sake, I just doubled the size and set the font size to 32 because I thought the button was a little small. Alternatively, you can design the button first and turn it into a "DefaultButton" afterward. Do this by right clicking on the symbol in the library and choosing "Component Definition". Enter "scaleform.clik.controls.Button" in the "Class" field and click OK and the parameters will automatically be added.
So far, we've set up everything in our "Library" tab to export for runtime sharing except for the cursor image and symbol. We're also not going to set up the DefaultButton for runtime sharing because Components cannot be shared at runtime (it throws up errors and won't compile if you try), only assets can. We can, however, use something called "Authortime Sharing" so that all our changes to the button can stay in one place - the SF_Library.fla file. With authortime sharing, any time you want to update the component, you just have to update it in the original file (in our case, the SF_Library.fla) and any fla files that use it can just update the asset by right clicking it in the library tab and selecting "Update". Alternatively, we can have the component automatically update itself by checking the "Update automatically" option in the component's properties in the fla files that use it. As we'll see next, authortime sharing will be set up automatically when we copy the DefaultButton component from the library to the individual menu scenes.
SF_MainMenu
Now that we have everything set up and the SF_Library in place, it's time to start designing the Main Menu. With both SF_Library.fla and SF_MainMenu.fla open, copy the "Background" and "Button" folders from SF_Library.fla's "Library" tab and paste them into the SF_MainMenu.fla's "Library" tab. The properties for each of the assets should get set automatically, but check them just to be sure. For all assets ("Background.png" and "ButtonFont"), instead of the "Export for ActionScript" and "Export for runtime sharing" options, the "Import for runtime sharing" option should be checked and the URL should be "../SF_Library.swf". For the "DefaultButton" component, the "Export for ActionScript" option should still be checked and in the "Authortime Sharing" section at the bottom of the window, the "File" should be "..\Lib\SF_Library.fla" and the "Symbol name" should be "DefaultButton" (unless you changed the symbol name in the SF_Library.fla file). If you'd like, you can check the box for the "Update automatically" option so that you don't have to do a manual update any time you change the button in the SF_Library.fla file.
Now it's time to build the scene, so first, we should set up our layers in the "Timeline". It's a good idea to keep a separate layer for your ActionScript code so that it's all in one place, and I also like to create separate layers for my background and buttons. Name the existing layer "Actions", and create two more layers beneath it - "Buttons" and "Background". Select the "Background" layer and drag the "Background.png" asset from the "Library" tab onto the stage and set the "X" and "Y" coordinates to 0. The image's dimensions should match the stage's (1280 x 720), so it shouldn't need to be scaled at all. Now lock the "Background" layer, switch to the "Buttons" layer and drag four "DefaultButton" components from the "Library" tab to the stage lining them up vertically. Select the top button on the stage and open the "Properties" tab. Give it an instance name of "newGameBtn" then expand the "Component Parameters" dropdown. Enter in "New Game" for the "label" property. This is the text that will appear on the button at runtime. Do the same for the other buttons, using instance names "loadGameBtn", "optionsBtn", and "exitGameBtn" and labels "Load Game", "Options" and "Exit Game" in order from top to bottom.
There are two ways to access and initialize CLIK Widgets from Unrealscript: through a set of accessor functions provided in the GFxMoviePlayer and GFxObject classes or through an event function called "WidgetInitialized" in the GFxMoviePlayer class. We're going to use the "WidgetInitialized" function, so in order to make that work, we have to tell the CLIK components in ActionScript to call this function after they've been set up in ActionScript. Under the "Component Parameters" section for the CLIK components, there's an option called "enableInitCallback", so check that option for every CLIK Widget that we'll need access to in Unrealscript - in this case, each "DefaultButton" component on the stage.
If you'd like, you can make the menu more interesting by adding animations or fades or whatever else you want to do. Seeing as how this isn't a Flash tutorial though, I'm just going to leave it looking like this by adding a call to "stop();" on the first frame of my "Actions" layer. That's it for the Main Menu, now let's set up the Options and Load Game menus.
SF_OptionsMenu
The Options Menu page will be fairly simple - we'll just have a couple of OptionSteppers to change the Resolution and the Anti-Aliasing settings. Create a new ActionScript3.0 document and save it in the Development\Flash\Tutorial\ScaleformMenu\FrontEnd folder as SF_OptionsMenu.fla. Under the "Properties" tab, open up the document's "Publish Settings" and uncheck the "HTML Wrapper" option under the "Other Formats" section. Set the "Output file" to "../../../../../UDKGame/Flash/ScaleformMenuGFx/SFMFrontEnd/SF_OptionsMenu.swf" then click on the wrench next to the "Script" section to set the ActionScript settings. Type in "SF_OptionsMenu" for the "Document class" and click the pencil icon to create the file. Change the first entry in the ActionScript "Source path" tab to "../as/frontend" then click the OK button on both pop up windows. Save the script file that opened when you clicked on the pencil icon as "SF_OptionsMenu.as" in the Development\Flash\Tutorial\ScaleformMenu\as\frontend folder.
Now that the file is all set up, let's start laying out the components. In the "Timeline" tab, create three layers as we did before: "Actions", "Buttons" and "Background". Now in the "Library" tab, copy and paste the "Background" and "Button" folders from the SF_Library.fla file. Drag the "Background.png" image to the stage onto the "Background" layer. Set the "x" and "y" coordinates to "0" so that it covers up the whole stage. Go ahead and lock the "Background" layer and switch to the "Buttons" layer. Drag two "DefaultButton" components onto the stage, one in the lower left and one in the lower right. These will be our "Cancel" and "Save" buttons that will take us back to the Main Menu, canceling or applying the changes we make to the settings. Name the one on the left "cancelBtn" and give it a label of "Cancel". The one on the right should have an instance name of "saveBtn" and a label of "Save".
Now we need a couple of components that I didn't put in the SF_Library.fla file - the "DefaultLabel" and "DefaultOptionStepper" components. Since we're only going to be using these components in the Options Menu, they really don't need to be in the SF_Library.fla file. If you're going to use them elsewhere though, it would be a good idea to include them for Authortime Sharing so that they only need to be maintained in one place. Open up the Components window (remember the icon in the toolbar looks like three little toy blocks) and drag these two components into your library. You can keep them as they are, but again, I edited them a little by increasing their size (just like I did with the "DefaultButton" component). I also moved the arrows for the "DefaultOptionStepper" to the left and right of the text field (purely for my own aesthetic preferences).
Drag two "DefaultLabel" and two "DefaultOptionStepper" components out onto the stage. Arrange them so that the labels are to the left of the option steppers. For the labels, type in "Resolution:" and "Anti-Aliasing:" in the "text" property of their "Component Parameters". The labels don't need instance names since we won't be referring to them in code at all, but we do need to name the option steppers. For the resolution option stepper, give it an instance name of "resolutionStepper", and name the anti-aliasing stepper "aliasingStepper". Also, remember to check the option "enableInitCallback" for each of the "DefaultOptionStepper" and "DefaultButton" components on the stage. We don't need to check this option for the "DefaultLabel" objects because again, we won't be accessing them from our Unrealscript code. Finally, place a call to "stop();" on the first frame of the "Timeline" in the "Actions" layer. That's all we'll do in Flash for this screen; the rest of the magic happens in ActionScript and Unrealscript!
SF_LoadMenu
The Load Menu will consist of three "slots" of saved games that you can choose from and a "Back" button to return to the Main Menu. We've been through this process twice now, so I'll just do a quick run-through. Create a new ActionScript3.0 document, save it in the Development\Flash\Tutorial\ScaleformMenu\FrontEnd folder as SF_LoadMenu.fla and setup the "Publish Settings" the same as the SF_MainMenu.fla and SF_Options.fla (uncheck HTML Wrapper, set the "Ouput file" to "../../../../../UDKGame/Flash/ScaleformMenuGFx/SFMFrontEnd/SF_LoadMenu.swf", set the document class to "SF_LoadMenu", create and save the class file, and change the ActionScript source path to "../as/frontend"). Create the "Actions", "Buttons" and "Background" layers. Copy the "Background" and "Button" folders from the SF_Library.fla "Library" tab and paste them into the SF_LoadMenu.fla "Library" tab. Drag the "Background.png" image to the stage with the "Background" layer selected, line it up, and lock the layer. Drag four "DefaultButton" components onto the stage with the "Buttons" layer selected. Line three of them up vertically in the center of the stage and one of them at the bottom left of the stage. For the three buttons in the center of the stage, uncheck their "enabled" flags in the component properties and type in "Empty" for their labels. We'll enable them through Unrealscript if we find a saved game associated with their slot. Give the one in the bottom left a label of "Back". Set the instance names for the three buttons in the center of the stage to "slotOneBtn", "slotTwoBtn", and "slotThreeBtn" respectively and the one in the bottom left to "backBtn". Check the "enableInitCallback" option for each of the "DefaultButtons" on the stage. Right click frame one of the "Actions" layer and choose "Actions" to open up the ActionScript editor for that frame and type in "stop();" (or add any animations/fades/tweens etc. that you want).
That's it for the Flash/design side of things. From here on out, it's nothing but code and Kismet. In Part 2: ActionScript, I'll go over the ActionScript classes we'll use and talk about how to expand the functionality for the different menu screens and components.