ActionScript 3.0 Game Programming University


Gary Rosenzweig 800 East 96th Street Indianapolis, Indiana 46240 USA ActionScript 3.0 Game Programming University Copyright © 2008 by Que Publishing All rights reserved. No part of this book shall be reproduced, stored in a retrieval system, or transmitted by any means, electronic, mechanical, photocopying, recording, or other- wise, without written permission from the publisher. No patent liability is assumed with respect to the use of the information contained herein. Although every precaution has been taken in the preparation of this book, the publisher and author assume no responsibility for errors or omis- sions. Nor is any liability assumed for damages resulting from the use of the information contained herein. ISBN-13: 978-0-7897-3702-1 ISBN-10: 0-7897-3702-7 Library of Congress Cataloging-in-Publication Data: Rosenzweig, Gary. ActionScript 3.0 game programming university / Gary Rosenzweig. p. cm. ISBN 0-7897-3702-7 1. Computer games—Programming. 2. Computer animation. 3. ActionScript (Computer program language) I. Title. QA76.76.C672R73 2007 794.8'1526—dc22 2007028659 Printed in the United States of America First Printing: August 2007 Trademarks All terms mentioned in this book that are known to be trademarks or service marks have been appropriately capitalized. Que Publishing cannot attest to the accuracy of this information. Use of a term in this book should not be regarded as affecting the validity of any trademark or service mark. Warning and Disclaimer Every effort has been made to make this book as complete and as accurate as possible, but no warranty or fitness is implied. The information provided is on an “as is” basis. The author and the publisher shall have neither liability nor responsibility to any person or entity with respect to any loss or damages arising from the information contained in this book or from the use of programs accompanying it. Bulk Sales Que Publishing offers excellent discounts on this book when ordered in quantity for bulk pur- chases or special sales. For more information, please contact U.S. Corporate and Government Sales 1-800-382-3419 corpsales@pearsontechgroup.com For sales outside of the U.S., please contact International Sales international@pearsoned.com Associate Publisher Greg Wiegand Acquisitions Editor Laura Norman Development Editor Laura Norman Managing Editor Gina Kanouse Project Editor Anne Goebel Copy Editor Keith Cline Senior Indexer Cheryl Lenser Proofreader Heather Waye Arle Technical Editor Cheryl Brumbaugh-Duncan Publishing Coordinator Cindy Teeters Book Designer Anne Jones Senior Compositor Gloria Schurick Graphics William Follett Eve Park Contents at a Glance Introduction 1. Using Flash and ActionScript 3.0 2. ActionScript Game Elements 3. Basic Game Framework: A Matching Game 4. Brain Games: Memory and Deduction 5. Game Animation: Shooting and Bouncing Games 6. Picture Puzzles: Sliding and Jigsaw 7. Direction and Movement: Space Rocks 8. Casual Games: Match Three 9. Word Games: Hangman and Word Search 10. Questions and Answers: Trivia and Quiz Games 11. Action Games: Platform Games 12. Game Worlds: Driving and Exploration Game Index Contents Introduction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .1 Flash and Game Development . . . . . . . . . . . . . . . . . . . . . . . . . . . . .2 Who Is This Book For? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .3 What Do You Need To Use This Book? . . . . . . . . . . . . . . . . . . . . . .3 Prerequisite Knowledge . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .3 Software Applications . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .4 Source Files . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .4 Using the Example Games in Your Projects . . . . . . . . . . . . . . . . . . . .4 What You’ll Find in This Book . . . . . . . . . . . . . . . . . . . . . . . . . . . . .5 The FlashGameU.com Website . . . . . . . . . . . . . . . . . . . . . . . . . . . . .5 1. Using Flash and ActionScript 3.0 . . . . . . . . . . . . . . . . . . . .7 What Is ActionScript 3.0? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .8 Creating a Simple ActionScript Program . . . . . . . . . . . . . . . . . . . . . .9 A Simple Use of trace . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .9 Creating Screen Output . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .12 Our First ActionScript 3.0 Class . . . . . . . . . . . . . . . . . . . . . . . . .13 Working with Flash CS3 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .15 Display Objects and Display Lists . . . . . . . . . . . . . . . . . . . . . . . .16 The Stage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .16 The Library . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .17 The Timeline . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .18 Writing and Editing ActionScript . . . . . . . . . . . . . . . . . . . . . . . . . . .19 ActionScript Game Programming Strategies . . . . . . . . . . . . . . . . . .22 Single Class Method . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .22 Smallest Step Approach . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .22 Good Programming Practices . . . . . . . . . . . . . . . . . . . . . . . . . . .23 Basic ActionScript Concepts . . . . . . . . . . . . . . . . . . . . . . . . . . . . .26 Creating and Using Variables . . . . . . . . . . . . . . . . . . . . . . . . . . .26 Condition Statements . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .27 Loops . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .28 Functions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .29 Testing and Debugging . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .29 Types of Bugs . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .29 Methods of Testing . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .30 Using the Debugger . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .31 Publishing Your Game . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .33 Formats . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .33 Flash . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .34 HTML . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .35 ActionScript Game Programming Checklist . . . . . . . . . . . . . . . . . . .36 Publishing and Document Settings . . . . . . . . . . . . . . . . . . . . . . .36 Class, Function, and Variable Names . . . . . . . . . . . . . . . . . . . . .37 Runtime Issues . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .38 Testing Issues . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .39 2. ActionScript Game Elements . . . . . . . . . . . . . . . . . . . . . . .41 Creating Visual Objects . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .42 Using Movie Clips . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .42 Making Buttons . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .44 Drawing Shapes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .47 Drawing Text . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .49 Creating Linked Text . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .51 Creating Sprite Groups . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .53 Setting Sprite Depth . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .55 Accepting Player Input . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .55 Mouse Input . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .55 Keyboard Input . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .56 Text Input . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .58 Creating Animation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .59 Sprite Movement . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .59 Using Timers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .61 Time-Based Animation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .62 Physics-Based Animation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .63 Programming User Interaction . . . . . . . . . . . . . . . . . . . . . . . . . . . .65 Moving Sprites . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .65 Dragging Sprites . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .67 Collision Detection . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .68 Accessing External Data . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .69 External Variables . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .69 Loading Data . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .71 Saving Local Data . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .71 Miscellaneous Game Elements . . . . . . . . . . . . . . . . . . . . . . . . . . . .72 Custom Cursors . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .72 Playing Sounds . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .74 Loading Screen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .75 Random Numbers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .76 Contents v ActionScript 3.0 Game Programming Universityvi Shuffling an Array . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .77 Displaying a Clock . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .78 System Data . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .79 Game Theft and Security . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .80 3. Basic Game Framework: A Matching Game . . . . . . . . . . . .83 Placing Interactive Elements . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .84 Methods for Creating Game Pieces . . . . . . . . . . . . . . . . . . . . . . .85 Setting Up the Flash Movie . . . . . . . . . . . . . . . . . . . . . . . . . . . .86 Creating the Basic ActionScript Class . . . . . . . . . . . . . . . . . . . . .87 Using Constants for Better Coding . . . . . . . . . . . . . . . . . . . . . . .90 Shuffling and Assigning Cards . . . . . . . . . . . . . . . . . . . . . . . . . .92 Game Play . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .95 Adding Keyboard Listeners . . . . . . . . . . . . . . . . . . . . . . . . . . . .95 Setting Up Game Logic . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .96 Checking for Game Over . . . . . . . . . . . . . . . . . . . . . . . . . . . . .100 Encapsulating the Game . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .102 Creating the Game Movie Clip . . . . . . . . . . . . . . . . . . . . . . . . .103 Adding an Introduction Screen . . . . . . . . . . . . . . . . . . . . . . . . .104 Adding a Play Again Button . . . . . . . . . . . . . . . . . . . . . . . . . . .105 Adding Scoring and a Clock . . . . . . . . . . . . . . . . . . . . . . . . . . . . .106 Adding Scoring . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .106 Adding a Clock . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .109 Displaying Time . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .110 Displaying Score and Time after the Game Is Over . . . . . . . . . .112 Adding Game Effects . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .113 Animated Card Flips . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .113 Limited Card-Viewing Time . . . . . . . . . . . . . . . . . . . . . . . . . . .116 Sound Effects . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .117 Modifying the Game . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .119 4. Brain Games: Memory and Deduction . . . . . . . . . . . . . . .121 Arrays and Data Objects . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .122 Arrays . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .122 Data Objects . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .124 Arrays of Data Objects . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .125 Memory Game . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .125 Preparing the Movie . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .126 Programming Strategy . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .127 Class Definition . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .128 Setting the Text, Lights, and Sounds . . . . . . . . . . . . . . . . . . . . .130 Playing the Sequence . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .133 Contents vii Switching Lights On and Off . . . . . . . . . . . . . . . . . . . . . . . . . .134 Accepting and Checking Player Input . . . . . . . . . . . . . . . . . . . .135 Modifying the Game . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .137 Deduction Game . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .138 Setting Up the Movie . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .139 Defining the Class . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .141 Starting a New Game . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .143 Checking Player Guesses . . . . . . . . . . . . . . . . . . . . . . . . . . . . .145 Evaluating Player Moves . . . . . . . . . . . . . . . . . . . . . . . . . . . . .146 Ending the Game . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .149 Clearing Game Elements . . . . . . . . . . . . . . . . . . . . . . . . . . . . .151 Modifying the Game . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .152 5. Game Animation: Shooting and Bouncing Games . . . . . . .155 Game Animation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .156 Time-Based Animation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .156 Coding Time-Based Animation . . . . . . . . . . . . . . . . . . . . . . . . .158 Air Raid . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .161 Movie Setup and Approach . . . . . . . . . . . . . . . . . . . . . . . . . . .162 Flying Airplanes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .162 Moving Gun . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .166 Skyward Bullets . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .169 The Game Class . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .171 Modifying the Game . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .178 Paddle Ball . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .179 Setting Up the Movie . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .179 Class Definition . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .181 Starting the Game . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .183 Starting a New Ball . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .185 Game Animation and Collision Detection . . . . . . . . . . . . . . . . .186 Game Over . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .192 Modifying the Game . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .193 6. Picture Puzzles: Sliding and Jigsaw . . . . . . . . . . . . . . . . .195 Manipulating Bitmap Images . . . . . . . . . . . . . . . . . . . . . . . . . . . .196 Loading a Bitmap . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .196 Breaking a Bitmap into Pieces . . . . . . . . . . . . . . . . . . . . . . . . .198 Sliding Puzzle Game . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .200 Setting Up the Movie . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .201 Setting Up the Class . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .201 Loading the Image . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .204 Cutting the Bitmap into Pieces . . . . . . . . . . . . . . . . . . . . . . . . .204 Shuffling the Pieces . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .206 Reacting to Player Clicks . . . . . . . . . . . . . . . . . . . . . . . . . . . . .209 Animating the Slide . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .211 Game Over and Cleanup . . . . . . . . . . . . . . . . . . . . . . . . . . . . .213 Modifying the Game . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .213 Jigsaw Puzzle Game . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .214 Setting Up the Class . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .214 Loading and Cutting the Image . . . . . . . . . . . . . . . . . . . . . . . .216 Dragging Puzzle Pieces . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .219 Game Over . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .224 Modifying the Game . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .225 7. Direction and Movement: Space Rocks . . . . . . . . . . . . . .227 Using Math to Rotate and Move Objects . . . . . . . . . . . . . . . . . . . .228 The Sin and Cos Functions . . . . . . . . . . . . . . . . . . . . . . . . . . .228 Using Cos and Sin to Drive a Car . . . . . . . . . . . . . . . . . . . . . . .230 Calculating an Angle from a Location . . . . . . . . . . . . . . . . . . . .233 Air Raid II . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .236 Altering the Gun . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .237 Changing the Bullets . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .239 Changes to AirRaid2.as . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .241 Space Rocks . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .242 Game Elements and Design . . . . . . . . . . . . . . . . . . . . . . . . . . .242 Setting Up the Graphics . . . . . . . . . . . . . . . . . . . . . . . . . . . . .244 Setting Up the Class . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .246 Starting the Game . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .248 Score and Status Display Objects . . . . . . . . . . . . . . . . . . . . . . .249 Ship Movement and Player Input . . . . . . . . . . . . . . . . . . . . . . .252 Shields Up! . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .256 Rocks . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .257 Missiles . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .261 Game Control . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .262 Modifying the Game . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .265 8. Casual Games: Match Three . . . . . . . . . . . . . . . . . . . . . .267 Reusable Class: Point Bursts . . . . . . . . . . . . . . . . . . . . . . . . . . . . .268 Developing the Point Burst Class . . . . . . . . . . . . . . . . . . . . . . .269 Using Point Bursts in a Movie . . . . . . . . . . . . . . . . . . . . . . . . .273 Match Three . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .276 Playing Match Three . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .276 Game Functionality Overview . . . . . . . . . . . . . . . . . . . . . . . . . .277 The Movie and MatchThree Class . . . . . . . . . . . . . . . . . . . . . . .278 ActionScript 3.0 Game Programming Universityviii Setting Up the Grid . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .279 Player Interaction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .282 Animating Piece Movement . . . . . . . . . . . . . . . . . . . . . . . . . . .285 Finding Matches . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .287 Finding Possible Moves . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .292 Score Keeping and Game Over . . . . . . . . . . . . . . . . . . . . . . . .295 Modifying the Game . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .296 9. Word Games: Hangman and Word Search . . . . . . . . . . . .297 Strings and Text Fields . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .298 ActionScript 3.0 String Handling . . . . . . . . . . . . . . . . . . . . . . .298 Applying Text Formatting to Text Fields . . . . . . . . . . . . . . . . . .303 Hangman . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .309 Setting Up the Hangman . . . . . . . . . . . . . . . . . . . . . . . . . . . . .309 The Hangman Class . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .310 Word Search . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .313 Development Strategy . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .313 Defining the Class . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .315 Creating the Word Search Grid . . . . . . . . . . . . . . . . . . . . . . . .316 User Interaction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .320 Dealing with Found Words . . . . . . . . . . . . . . . . . . . . . . . . . . . .323 Modifying the Game . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .326 10. Questions and Answers: Trivia and Quiz Games . . . . . . . .327 Storing and Retrieving Game Data . . . . . . . . . . . . . . . . . . . . . . . .328 Understanding XML Data . . . . . . . . . . . . . . . . . . . . . . . . . . . .328 Importing External XML Files . . . . . . . . . . . . . . . . . . . . . . . . . .330 Trapping Load Errors . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .332 Trivia Quiz . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .332 Designing a Simple Quiz Game . . . . . . . . . . . . . . . . . . . . . . . .333 Setting Up the Movie . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .333 Setting Up the Class . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .334 Loading the Quiz Data . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .337 Message Text and Game Button . . . . . . . . . . . . . . . . . . . . . . . .337 Moving the Game Forward . . . . . . . . . . . . . . . . . . . . . . . . . . .339 Displaying the Questions and Answers . . . . . . . . . . . . . . . . . . .340 Judging the Answers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .342 Ending the Game . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .343 Deluxe Trivia Quiz . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .344 Adding a Time Limit . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .344 Adding Hints . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .347 Adding a Factoid . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .349 Contents ix Adding Complex Scoring . . . . . . . . . . . . . . . . . . . . . . . . . . . . .350 Randomizing the Questions . . . . . . . . . . . . . . . . . . . . . . . . . . .352 Picture Quiz . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .353 Better Answer Arrangement . . . . . . . . . . . . . . . . . . . . . . . . . . .353 Recognizing Two Types of Answers . . . . . . . . . . . . . . . . . . . . .355 Creating Loader Objects . . . . . . . . . . . . . . . . . . . . . . . . . . . . .355 Determining the Right Answer . . . . . . . . . . . . . . . . . . . . . . . . .356 Expanding the Click Area . . . . . . . . . . . . . . . . . . . . . . . . . . . .357 Images for Questions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .358 Modifying the Game . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .359 11. Action Games: Platform Games . . . . . . . . . . . . . . . . . . . .361 Designing the Game . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .362 Level Design . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .362 Designing the Class . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .368 Planning Which Functions Are Needed . . . . . . . . . . . . . . . . . . .369 Building the Class . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .370 Class Definition . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .370 Starting the Game and Level . . . . . . . . . . . . . . . . . . . . . . . . . .372 Keyboard Input . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .376 The Main Game Loop . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .377 Character Movement . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .378 Scrolling the Game Level . . . . . . . . . . . . . . . . . . . . . . . . . . . . .384 Checking for Collisions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .385 Enemy and Player Death . . . . . . . . . . . . . . . . . . . . . . . . . . . . .385 Collecting Points and Objects . . . . . . . . . . . . . . . . . . . . . . . . . .387 Showing Player Status . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .389 Ending the Levels and the Game . . . . . . . . . . . . . . . . . . . . . . .389 The Game Dialog Box . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .390 Modifying the Game . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .391 12. Game Worlds: Driving and Exploration Game . . . . . . . . . .393 Creating a Top-Down Driving Game . . . . . . . . . . . . . . . . . . . . . . .394 Creating a Top-Down World . . . . . . . . . . . . . . . . . . . . . . . . . .394 Game Design . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .397 The Class Definition . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .400 The Constructor Function . . . . . . . . . . . . . . . . . . . . . . . . . . . .402 Finding the Blocks . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .404 Placing the Trash . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .404 Keyboard Input . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .406 The Game Loop . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .407 Moving the Car . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .408 ActionScript 3.0 Game Programming Universityx Checking for Trash and Trashcan Collisions . . . . . . . . . . . . . . .411 The Clock . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .413 The Score Indicators . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .413 Game End . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .414 Modifying the Game . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .415 Building a Flash Racing Game . . . . . . . . . . . . . . . . . . . . . . . . . . .415 Racing Game Elements . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .415 Making the Track . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .416 Sound Effects . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .418 Constants and Variables . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .418 Starting the Game . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .419 The Main Game Loop . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .420 Car Movement . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .422 Checking Progress . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .424 The Countdown and the Clock . . . . . . . . . . . . . . . . . . . . . . . . .425 Game Over . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .427 Modifying the Game . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .427 Index . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .429 Contents xi About the Author As a youngster, Gary Rosenzweig was allowed to play video games whenever he wanted, as long as his homework was done first. His parents got him an Atari 2600 and an assortment of games. He loved to play Adventure, Asteroids, Pitfall, Raiders of the Lost Ark, and even that dreadful E.T. game. At age 13, in 1983, his grandmother gave him a new TRS-80 Model III. The first thing he did with it was learn to program. And then, make games. He made some text adventure games, and then some RPG games, and then some arcade games. He was allowed to stay up all night making games, as long as his homework was done first. In high school, Gary got to play with the Apple II computers pretty much whenever he wanted, as long as his schoolwork was done first. He made space shuttle simulators and spreadsheet programs. And some games. Gary went on to study computer science in college at Drexel University. There he was told that with his degree, he could go on to be a programmer at any high-tech firm making business applications. But he wanted to make games, even if it was on the side, after he got his work done first. After a side trip to get a Master’s degree in journalism and mass communication from the University of North Carolina in Chapel Hill, Gary ended up getting a job where he could make games for kids using Macromedia Director. Then, they invented the Internet. It was soon followed by Shockwave, a way to play Director content in web pages. Gary started making his own games for his own web- site in the evening, after his work was done first. In 1996, Gary started his own company, CleverMedia, to produce games for the Web. He was soon creating both Shockwave and Flash games with some of the most creative people he ever met. CleverMedia and its sites grew over the years to become the single largest collection of web-based games by a single company. Gary has created more than 300 games in the past 12 years, most of which can be found at CleverMedia’s main game site, www.GameScene.com. Gary also likes to share what he knows. His sites http://FlashGameU.com, www.Director-Online.com, and www.DeveloperDispatch.com contain information for other developers. He has also written many books, including Macromedia Flash MX ActionScript for Fun & Games, Special Edition Using Director MX, and Advanced Lingo for Games. Gary wrote this book mostly on evenings and weekends, after his other work was done first. Gary lives in Denver, Colorado, with his wife, Debby, and daughter, Luna. Debby and Gary also own The Attic Bookstore, an unusual used bookstore in Englewood, Colorado. Luna is only 5 years old, but is already playing games on her Macintosh com- puter, after her homework is done first, of course. ActionScript 3.0 Game Programming Universityxii Dedication A person should aspire to do three things with his career and life: do something he loves, do it better than anyone else, and make the world a better place. It is hard to find examples of someone who has accomplished all three. Steve Irwin was one such indi- vidual. He was an inspiration to me. Acknowledgments Thanks to everyone at CleverMedia: David Feldman, William Follett, Kevin Frutiger, Layle McFatridge, Eve Park, and Jay Shaffer. And to John Nyquist for his help with this book. Thanks to the good people at Adobe and the Flash development team. ActionScript 3.0 rocks. Thanks to my family: Debby Rosenzweig, Luna Rosenzweig, Jacqueline Rosenzweig, Jerry Rosenzweig, Larry Rosenzweig, Tara Rosenzweig, Rebecca Jacob, Barbara Shifrin, Richard Shifrin, Phyllis Shifrin, Barbara Shifrin, Tage Thomsen, Anne Thomsen, Andrea Thomsen, and Sami Balestri. Thanks also to everyone at Que and Pearson Education for their hard work on this book. Acknowledgments xiii We Want to Hear from You! As the reader of this book, you are our most important critic and commentator. We value your opinion and want to know what we’re doing right, what we could do better, what areas you’d like to see us publish in, and any other words of wisdom you’re willing to pass our way. As an associate publisher for Que Publishing, I welcome your comments. You can email or write me directly to let me know what you did or didn’t like about this book—as well as what we can do to make our books better. Please note that I cannot help you with technical problems related to the topic of this book. We do have a User Services group, however, where I will forward specific technical questions related to the book. When you write, please be sure to include this book’s title and author as well as your name, email address, and phone number. I will carefully review your comments and share them with the author and editors who worked on the book. Email: feedback@quepublishing.com Mail: Greg Wiegand Associate Publisher Que Publishing 800 East 96th Street Indianapolis, IN 46240 USA Reader Services Visit our website and register this book at www.quepublishing.com/register for conve- nient access to any updates, downloads, or errata that might be available for this book. ActionScript 3.0 Game Programming Universityxiv Introduction ■ Flash and Game Development ■ Who Is This Book For? ■ What Do You Need To Use This Book? ■ Using the Example Games in Your Projects ■ What You’ll Find in This Book ■ The FlashGameU.com Website This is a great time to be a Flash game developer. Right now, there is no better develop- ment tool for small and medium-size games. Flash CS3 Professional (a.k.a. Flash 9) is fast, powerful, and easy to develop with. The key to this is ActionScript 3.0, the great new programming language inside this latest version of Flash. ActionScript 1.0 and 2.0 were often frustrating for game developers. They weren’t fast enough to get key tasks done, and odd bugs and unexpected behavior often slowed down production. ActionScript 3.0 is a very different animal. You’ll find yourself developing quickly and effortlessly. Things just work, and work well. And the speed of ActionScript 3.0 will make your game design ideas work just as you imagined them. Let this book become your guide to Flash game development. I hope you enjoy learning from this book as much as I enjoyed writing it. Flash and Game Development In October 1995, I was excited about my future as a game developer. Macromedia had just released Shockwave, and I saw it as a way to develop games that I could distribute myself, over the Web. Only twice since then have I seen something that has made me just as excited about game development as the original Shockwave. The next time was with the release of Shockwave 3D. And the third time was with the release of ActionScript 3.0. Flash games have been around for a while, but always as a the younger brother to Shockwave games. Shockwave was faster, more powerful, and eventually in 3D. With ActionScript 3.0, however, Flash becomes equally as powerful as Shockwave. In some ways, it is more so. For instance, the Flash 9 player is already on 80 percent of the web-browsing computers out there. By the time you get this book, most Flash 8 players would have been upgraded to Flash 9, and we’ll be close to 100 percent. Knowing that Flash 9 is almost as ubiquitous as the Web browser itself empowers us as Flash game developers. Flash 9 even plays on Linux machines. Older versions of Flash play on Web television boxes, game consoles such as the Wii, and even portable devices such as smartphones and the PlayStation Portable. In time, we’ll have the Flash 9 player and ActionScript 3.0 on these kinds of devices, too. You can develop both standalone and web-based versions of your games with Flash. Third-party software enables you to extend your standalone games to make them robust applications. Flash with ActionScript 3.0 is a great, practical way to make small and medium-size games. Introduction2 Who Is This Book For? This book is for anyone using Flash to develop games. However, different types of devel- opers will use this book in different ways. Someone fairly new to both Flash and programming will be able to use this book as a next step after learning basic programming skills. A motivated fast learner might also be able to use this book to learn ActionScript 3.0 from scratch. If you have previous experience programming with ActionScript 1.0 or 2.0, you can use this book to get up to speed on ActionScript 3.0. However, you should try to forget most of what you know about previous versions of ActionScript. Seriously, ActionScript 3.0 is very different from previous versions. In fact, I consider it a whole new programming language. Many Flash users already know the basics of animation and programming but want to move on to developing games. This is the core audience for the book. If you are not a programmer at all, but a designer, illustrator, or animator, you can use the examples in this book as a framework for your own games. In other words, you can just swap out the graphics from the source file examples. Likewise, if you already are an expert ActionScript 3.0 programmer, this book can pro- vide a library of code for you to draw on to make your games. No need to start from scratch. What Do You Need To Use This Book? Most readers will need some previous experience with Flash and programming to get the most from this book. You also need the right tools. Prerequisite Knowledge Readers should be familiar with the Flash CS3 environment. If you are new to Flash, run through the Flash User Guide that comes with Flash CS3. From inside Flash, choose Help, Flash Help or press F1. You might also want to consider a beginner’s book or online tutorial. This book is not geared toward first-time programmers, unless you are just looking to use the examples by substituting your own graphics. Therefore, you should have some programming experience: ActionScript 1.0, 2.0 or 3.0, JavaScript, Java, Lingo, Perl, PHP, C++, or just about any structured programming language. ActionScript 3.0 is not hard to understand if you are at least somewhat familiar with loops, conditions, and functions. Chapter 1, “Using Flash and ActionScript 3.0,” in fact, sums up the basic ActionScript 3.0 syntax. What Do You Need To Use This Book? 3 If you are a programmer, but have never used Flash before, read the parts of the Flash User Guide that pertain to the Flash interface and basic drawing and animation tech- niques. Software Applications You’ll need, of course, Flash CS3 Professional or newer. Flash 8 Studio, the previous version of Flash, does not use ActionScript 3.0 and cannot be used with this book. Flash CS3 is virtually identical on Mac and Windows. The screenshots in this book were taken with the Mac version of Flash, but they should match the Windows version very closely. Future versions of Flash will most likely continue to use ActionScript 3.0 as the core programming language. Some of the menu choices and keyboard shortcuts might change, but you should still be able to use this book. You might want to consider setting your Publish settings for the Flash 9 player and ActionScript 3.0 to ensure maximum compatibility. Source Files You also need the source files for this book. See the end of the Introduction for informa- tion about how to obtain them. Using the Example Games in Your Projects This book includes 16 complete games, including some gems such as match three, a side-scrolling platform game, and word search. The question I often get is this: “Can I use these games in my project?” The answer is this: Yes, as long as you modify the games to make them your own, such as changing the artwork, game play, or other content. Posting the games as-is to your Web site is not acceptable. Also, posting the source code or code listings from this book is unacceptable. When you use these games in your projects, don’t try to pass them off as completely your own work. To do so would be unprofessional. Please credit the book with a link to http://flashgameu.com. However, if you are only using a small portion of the code, or using a game as a basic framework for something very different, no attribution is needed. Basically, just use common sense and courtesy. Thanks. Introduction4 What You’ll Find in This Book Chapter 1, “Using Flash and ActionScript 3.0,” introduces ActionScript 3.0 and some basic concepts such as game programming strategies and a checklist to help you develop games in Flash CS3. Chapter 2, “ActionScript Game Elements,” presents a series of short code snippets and functions, such as creating text fields, drawing shapes, and playing sounds. This is a use- ful and practical library of code that we’ll be using throughout the book (and you’ll be using in your own projects). Chapters 3 through 12 each contain one or more complete games. The text of the chapter walks you through the game code, enabling you to build it yourself if you want. Or, you could use the source file and walk through the code. Chapter 3, “Basic Game Framework: A Matching Game,” is a little different from the rest of the book. Instead of examining game code for a finished game, it builds a game in ten steps, producing a different Flash movie and source code file with each step. It is a great way to learn how to build Flash games. Most of the rest of the chapters introduce a special topic before starting a new game. For instance, Chapter 4 starts with an “Arrays and Data Objects” section. But, the content of this book doesn’t stop with the pages in your hands. There is more to be found online. The FlashGameU.com Website The FlashGameU.com is the companion website to this book. Go there to find the source files, updates, new content, a Flash game development forum, and my blog and podcast on Flash game development. The source files for this book are organized by chapter, and then further divided into archives for each game. There is a link to download the files at the main page of FlashGameU.com. At FlashGameU.com, you’ll also find a blog in which I post new content and try to answer reader questions. If you’ve got a question about something in this book, or about Flash game development in general, you can ask it in the forum or ask me directly through the blog. Hope to see you there! The FlashGameU.com Website 5 This page intentionally left blank 1 Using Flash and ActionScript 3.0 ■ What Is ActionScript 3.0? ■ Creating a Simple ActionScript Program ■ Working with Flash CS3 ■ Writing and Editing ActionScript ■ ActionScript Game Programming Strategies ■ Basic ActionScript Concepts ■ Testing and Debugging ■ Publishing Your Game ■ ActionScript Game Programming Checklist ActionScript is a great programming language for making games. It is easy to learn, fast to develop with, and very powerful. We’ll start by looking at ActionScript 3.0 and the Flash CS3 Professional authoring environment. Then, we’ll build some very simple programs to get familiar with this new version of ActionScript. What Is ActionScript 3.0? ActionScript 3.0 was introduced in 2006 with the release of Flex 2. Flex enables devel- opers to build applications that require the Flash Player, just like Flash does. However, Flash offers a more visual interface for developing applications, one better suited for game development. ActionScript was introduced in 1996 with the release of Flash 4. It wasn’t called ActionScript yet, and you couldn’t even type your code. Instead, you chose statements from a series of drop-down menus. Flash 5 in 2000 improved on that greatly with the formal introduction of ActionScript 1.0. This scripting language contained all the bells and whistles of other web-based development languages, such as Macromedia Director’s Lingo, and Sun’s Java. But, it came up severely short in speed and power. Flash MX 2004, also known as Flash 7, brought us ActionScript 2.0, a much more powerful version of the language that made it easier to create object-oriented programs. It was much closer to ECMA Script, a standard for programming languages developed by the European Computer Manufacturers Association. JavaScript, the programming language used in browsers, is also based on ECMA Script. NOTE The Flash 9 Player has two separate code interpreters built in to it. The first is for older content and will interpret ActionScript 1.0/2.0 code. The second is a faster code interpreter that works with ActionScript 3.0. You get the best performance out of your games if you stick to only using ActionScript 3.0 code. ActionScript 3.0 is the culmination of years of development. As each version of Flash came out, developers pushed it to the limit. The next version took into account what developers were using Flash for, and what the weaknesses of the current version of ActionScript were. Now we have an excellent development environment for 2D game development. You’ll find that one of its main strengths is being able to get games up and running with only a small amount of code. Chapter 1: Using Flash and ActionScript 3.08 NOTE Flash CS3 Professional is actually Flash 9. Adobe has simply bundled together versions of various pieces of software—such as Flash, PhotoShop, Illustrator, and Dreamweaver—into their “CS3” package. The technical version number of Flash in CS3 is Flash 9. It is correct to refer to it as either Flash 9 or Flash CS3. The playback engine, which is also used by Flex, is only referred to as the Flash 9 Player. Creating a Simple ActionScript Program SOURCE FILES http://flashgameu.com A3GPU01_HelloWorld.zip When introducing a new programming language, it is tradition to start off with Hello World programs. The idea is to simply write a program that does nothing other than display the words Hello World on the screen. NOTE The Hello World program dates back to 1974 when it was included in an internal tuto- rial document at Bell Labs. It was the first program that I learned when I was sat in front of a PDP-11 terminal in school in the late 70s. Just about every beginning pro- gramming book has a Hello World example at the beginning. A Simple Use of trace We can create a limited version of Hello World by using the trace function in a script in the main timeline. All that trace does is output some text into Flash’s Output panel. To create a new Flash movie, choose File, New from the menu. You’ll be presented with the New Document window seen in Figure 1.1. Creating a Simple ActionScript Program 9 Figure 1.1 Choose Flash File (ActionScript 3.0) to create a new Flash movie. After clicking the OK button, you’ll get a new Flash movie named Untitled-1. It will appear as a Flash document window, as shown in Figure 1.2. Chapter 1: Using Flash and ActionScript 3.010 Figure 1.2 The Flash docu- ment window includes a timeline and a stage work area. The top part of the document window includes a timeline, with frames starting with 1 and extending to the right—a little more than 65 frames can be seen in Figure 1.2, although this will depend on the window size. The number of frames can extend as far as an animator needs, but as game programmers, we’ll usually only need a few frames to build our games. The timeline can have one or more layers in it. By default, there is one layer, named Layer 1 in the window. In Layer 1, you will see a single keyframe, represented by a box with a hollow dot in it under the frame number 1. NOTE Keyframe is an animation term. If we were learning to animate with Flash, instead of learning to program, we would be using keyframes all the time. Basically, a keyframe is a point in the timeline where the positions of one or more of the animated elements are specifically set. Between keyframes, the elements would change position. For instance, if there were a keyframe on frame 1 where an element is on the left side of the screen, and a keyframe on frame 9 where the same element is on the right side of the screen, in between these keyframes, on frame 5, the element would appear in the middle of the screen. We won’t be using keyframes for animating, but instead we’ll be using them to place elements on the screen in different modes: such as “intro”, “play”, and “gameover”. You can place a script in any keyframe in any layer of the timeline. To do this, select the keyframe, choose the Window menu, and then select Actions. This brings up the Actions panel. You can see the result in Figure 1.3. It might look dif- ferent to you because it can be customized in a number of ways, including having a full set of ActionScript commands and functions in a menu on the left side. Creating a Simple ActionScript Program 11 Figure 1.3 The Actions panel can also be accessed by the key- board shortcut Alt+F9 (Windows) or Option+F9 (Mac). The Actions panel is basically just a text-entry window. However, it can do much more for you, such as help you format your code. We won’t be using the Actions panel much for the purposes of this book because most of our code will be in external classes. To create this simple Hello World program, enter the following text into the Actions panel: trace(“Hello World”); That’s it. You’ve created your first ActionScript 3.0 program. To test it, choose Control, Test Movie, or use the shortcut +Return on Mac, Ctrl+Enter on Windows. If you didn’t build the movie yourself, you can open HelloWorld1.fla and use this file to test. Now, look for the Output panel. It will appear, even if you had that panel closed. But, it tends to be a small panel, so it could easily appear in a corner of your screen without you noticing. Figure 1.4 shows what it should look like. Figure 1.4 The Output panel shows the results of the trace function call. Although this Hello World program technically does output “Hello World,” it will only do so while you are testing the movie in Flash 9. If you were to embed this movie in a browser, it would show nothing on the screen. We’ll need to do a bit more work to create a real Hello World program. Creating Screen Output To have the words Hello World display on the screen, we need more than one line of code. In fact, we need three. The first line will create a new text area to be displayed on the screen, called a text field. This is a container to hold text. The second line will place the words Hello World into that text field. Then, the third line will add that text field to the stage. The stage is the display area of a Flash movie. You can arrange elements on the stage while authoring a movie. During playback, the stage is the area the user sees. In ActionScript 3.0, creating objects like a text field doesn’t add them to the stage. You need to do that yourself. This will come in useful later when you want to group objects together, and not have everything placed directly on the stage. NOTE Any visual element in ActionScript 3.0 is called a display object. It could be a text field, a graphic element, a button, or even a user interface component (such as a pop- up menu). Display objects can also be collections of other display objects. For instance, a display object can hold all the pieces in a chess game, and the chess board is another display object underneath it. The stage itself is a display object, actually a display object known as a movie clip. Here are the three lines of code for our new Hello World program. These would simply replace the one line of code in frame 1 of the timeline from the preceding example: var myText:TextField = new TextField(); myText.text = “Hello World”; addChild(myText); The code creates a variable named myText of the type TextField. It then sets the text property of this text field to “Hello World” before adding it as a child of the stage dis- play object. NOTE The var keyword before the first use of the myText variable tells the compiler that we’ll be creating a variable named myText. Then, the colon and the type, TextField, tell the compiler what type of value this variable will hold (in this case, a reference to a text field). Chapter 1: Using Flash and ActionScript 3.012 The reason the text appears at the upper left and in that particular font is that we have not set any other properties of the text field. After we learn a little more, we can set the text location, size, and font. Our First ActionScript 3.0 Class We won’t be using scripts in the timeline unless we have something that specifically needs to be done on a certain frame in the timeline. For the most part, our code will exist in external ActionScript class files. So, let’s rebuild the Hello World program as an external class. NOTE A class is another way of referring to a Flash object, like a graphic element or the movie itself. We also often refer to a class as the code portion of an object. So you’ll have a movie, and the movie’s class. This would define what data is associated with the movie, and what functions it can perform. To make an external ActionScript file, choose File, New, and select ActionScript File. This opens up a new ActionScript document window that occupies the same space as the Flash movie document window. Instead of a timeline and a stage work area, how- ever, we just have a large text editing area, as shown in Figure 1.6. Creating a Simple ActionScript Program 13 Figure 1.5 The screen shows a tiny “Hello World” at the upper left. The result of this program would be a very tiny “Hello World” in the default serif font at the very upper-left corner of the screen. Choose Control, Test Movie to see it for your- self. The source file is HelloWorld2.fla. Figure 1.5 shows this little text field that we have created. As you can see in Figure 1.6, this program is much longer than the three-line Hello World program we built earlier. Let’s take a look at what each part of the code does. A class file starts off by declaring that it is a package containing a class. Then, it must define what parts of ActionScript are needed in the program. In this case, we need to display objects on the stage, and we need to create a text field. This will require the use of the flash.display classes and the flash.text classes: package { import flash.display.*; import flash.text.*; NOTE You’ll pretty quickly come to know what library classes you need to import at the start of your programs. These are two out of only a handful that we use throughout this entire book. For more unusual ActionScript functions, you can always look in the Flash 9 Help entry for that function to see which class library to import. The next line of code is the class definition. In this case, it needs to be a public class, which means that it can be accessed by the main movie. The name of the class will be HelloWorld3, which must match the name of the file, which is HelloWorld3.as. This class extends MovieClip, which means that it will work with a movie clip (in this case, the stage itself): public class HelloWorld3 extends MovieClip { Chapter 1: Using Flash and ActionScript 3.014 Figure 1.6 The ActionScript document contains a very simple Hello World program. The class contains a single function. The name of this function is HelloWorld3, which exactly matches the name of the class. When a function is named the same as the class name, it will be executed immediately as soon as the class is initialized. This is called the constructor function. In this case, the class is attached to the movie, so this function will run as soon as the movie is initialized. Inside the function are the same three lines of code we used in the previous example: public function HelloWorld3() { var myText:TextField = new TextField(); myText.text = “Hello World!”; addChild(myText); } } } To get this code working in a movie, you need to create a fresh new movie. The exam- ple is called HelloWorld3.fla. This movie doesn’t need to have anything in the time- line at all, but it must be assigned a document class. This indicates which ActionScript file will control the movie. To set a document class, open the Properties panel by choosing Window, Properties, Properties. You’ll see the panel shown in Figure 1.7. Then, enter the class name HelloWorld3 into the document class field. Working with Flash CS3 15 Figure 1.7 The document class for this movie is set to HelloWorld3. Now the movie knows that it must load and use the HelloWorld3.as file. When you test the movie, it will compile the AS class file into the movie. Running the movie will initialize the class, which will run the HelloWorld3 function and display the “Hello World” text. Working with Flash CS3 Although most of our work will be in ActionScript, we need to know some terms, and some basics about working with the Flash CS3 timeline, stage, and library. NOTE If you are new to Flash, check out “Using Flash” in the Help documentation. This sec- tion gives you a detailed explanation of the stage, timeline, library, and other Flash workspace elements and tells you how to handle the Flash interface. Display Objects and Display Lists We’ve already discussed display objects. They are essentially any graphic element. The most versatile of all display objects is the movie clip, which is a full graphic element that includes any number of other display objects, plus a timeline for animation. A simpler version of the movie clip is a sprite. A sprite is essentially a movie clip with only one frame. When we create display objects from scratch in ActionScript, we’ll usu- ally be making sprites. They are naturally more efficient than movie clips because they don’t have the overhead of multiple frames of animation. Other display objects include things such as text fields, bitmaps, and video. Some display objects, movie clips, and sprites can have other display objects in them. For instance, you can have a sprite that contains several other sprites, as well as some text fields and bitmaps. Nesting display objects provides you a way to organize your graphic elements. For instance, you could create a single game sprite to hold all the game elements you create with ActionScript. Then, you could have a background sprite inside of it that contains several background sprite elements. A game pieces sprite could sit on top of that and contain moveable game pieces. Because movie clips and sprites can contain multiple objects, they will each maintain a list of these items to determine the order in which they are displayed. This is called a display list. We can modify this display list to place objects in front of or in back of other objects. NOTE The idea of a display list is new to ActionScript 3.0. If you are used to the ActionScript 2.0 method of levels and depths, forget about that and embrace the simpler display list method. With display lists, nothing is at a set level. Instead, the farthest display object is simply first in the list, and the closest is last in the list. You can still move objects around in the list, and the chances of errors or unwanted side effects are greatly reduced. We can also move display objects from one parent display object to another. This isn’t making a copy of the object, but is actually removing it and adding it again. This makes display objects incredibly versatile and easy to work with. The Stage The stage is the main graphics work area in Flash. It is a representation of the screen that will be seen by users when they are playing the game. Figure 1.8 shows the document window with the stage taking up a majority of the space. It also shows the timeline at the top. Chapter 1: Using Flash and ActionScript 3.016 Many of our games will have a completely blank stage and empty timeline. All the graphic elements will be created by the ActionScript code. However, many games will have graphic elements already sitting on the stage. This is particularly important when a nonprogrammer graphic designer is involved in making a game. He or she might want to lay out interface elements and adjust them during devel- opment. It is simply not practical to have those elements created by ActionScript in cases like this. During development, the stage can be used as a place to create quick graphic elements. For instance, you can draw using the drawing tools on the stage, select the shape, and then press F8 to create a quick movie clip in the library. The Library The Flash library contains any media that you need in your game and will be bundled into the final SWF file. You can also import other media elements into your movie, as you’ll see when we import external bitmap images in Chapter 6, “Picture Puzzles: Sliding and Jigsaw.” Figure 1.9 shows the Library panel. It is usually narrower, but I’ve expanded it to show the Linkage column. Working with Flash CS3 17 Figure 1.8 The document win- dow includes both the stage and the timeline. In Figure 1.9, most of the items in the library are movie clips. The first item is a button, and several that are in the Sounds folder are sounds. Some of the movie clips have an export name in the Linkage column. These are items that can be pulled from the library by our ActionScript code at runtime. The Timeline A Flash movie is broken up into frames. The timeline at the top of the window allows you to choose the frame that is displayed in the stage work area at the bottom of the window. Because we are not producing animations, but game applications, we’ll be using the frames to differentiate between different game screens. Figure 1.10 shows a timeline. Only three frames are in use. They are all keyframes. The first is for a game introduction screen and contains some instructions. The second is the frame where the game is played. The third is a “Game Over” message and a “Play Again” button. Chapter 1: Using Flash and ActionScript 3.018 Figure 1.9 The Library panel shows all the media objects enclosed in the current movie. Figure 1.10 The timeline has been expanded slightly using the pull-down menu at the right, so the frames are a little larger. Each keyframe has a label, although you cannot see it in the timeline. You can see a lit- tle flag in the top layer of each frame, which signifies that there is a label there. To see and set the frame labels, you need to select the frame, and then check the Properties panel. It will contain a Frame field. In this case, it has been set to “start”, and you can edit it if you need (see Figure 1.11). Writing and Editing ActionScript 19 Figure 1.11 The Properties panel allows you to set or change the frame label. If you look back at Figure 1.10, you can see that there are four layers. The first layer, Label, contains three keyframes. The way you create frames and keyframes is to use F5 to add a frame to a layer, and then F7 to add a keyframe among those frames. The second layer, named “Score,” contains only two keyframes, frame 1 and 2. So, frame 3 is just an extension of frame 2. This means the score elements present during game play on frame 2 is still present on frame 3. The timeline, stage, and library will be your primary visual tools for developing your games. Writing and Editing ActionScript Although it is usually necessary to work in the Flash document somewhat to create a game, we’ll be spending most of our time in the ActionScript document window. We already saw this window in Figure 1.6, but Figure 1.12 shows it differently. On the left is a hierarchical menu of ActionScript 3.0 syntax. Figure 1.12 The ActionScript document window features several useful tools at the top. At the very top of the window, you’ll see two tabs. That is because two documents are open: HelloWorld3.fla and HelloWorld3.as. This allows you to work on the Flash movie and the ActionScript document at the same time. You can switch between them by clicking the tabs. You can also have other ActionScript files open, which proves handy if you are working with multiple ActionScript classes at the same time. Notice in Figure 1.12 that the lines of code are indented. The proper way to do this is by using the Tab key. When you press Return or Enter at the end of a line of code, the cursor automatically appears indented to the proper level at the next line. If you want to remove a Tab stop to pull a line closer to the left, just press Delete or Shift+Tab. NOTE You can also select a section of code and press Tab to move it all over to the right by one Tab stop. You can Shift+Tab to move a whole section to the left, too. The script window tools at the top perform various functions that every ActionScript programmer should know how to use. Here is a list (as shown in the window, from left to right): ● Add a New Item to the Script. This is a massive drop-down menu that gives you access to every ActionScript command. There is so much that it is difficult to use for standard commands, but can be useful to find more obscure ones. ● Find. Use this to open the Find and Replace dialog box. You can also use +F (Mac) or Ctrl+F (Windows). ● Check Syntax. This is a handy way to have the Flash compiler do a precheck on the syntax of your script. You can see the results in the Output panel. ● Auto Format. This takes your entire script and reformats it with consistent tab- bing, spacing, and brackets. If you decide to use this, be sure to visit the Preferences for Auto Format to make some decisions about what this button should and should not do. ● Show Code Hint. This is probably the most useful of all the buttons. When you start typing a function, such as gotoAndStop(, you will get a code hint that instantly appears letting you know what parameters the function accepts. However, if you want to edit the function call later, you can position the cursor inside the function parameters and then use this button to bring back the hints. ● Debug Options. This drop-down menu allows you to set and remove break- points. We discuss debugging later in this chapter in the “Testing and Debugging” section. Chapter 1: Using Flash and ActionScript 3.020 ● Collapse Between Braces. If you click this button, the current section of code, between curly braces, collapses to a single line. The code is still there, but hid- den. You can click on the triangle (Mac) or plus sign (Windows) to the left side of the window, or the Expand All button to expand it. Figure 1.13 shows what it looks like when some code has been collapsed. Writing and Editing ActionScript 21 Figure 1.13 A block of code has been collapsed. This is handy when you have a huge script and want to hide sections of code you are not working on. ● Collapse Selection. This collapses the code currently selected. ● Expand All. This will revert all collapsed sections to their normal status. ● Apply Block Comment. Select some code and press this button to turn the selection into a comment by adding /* before and */ after. See the section “ActionScript Game Programming Strategies” for more about commenting your code. ● Apply Line Comment. The current line will be turned into a comment. If multi- ple lines are selected, all the lines will be turned into comments by adding // in front of each line. ● Remove Comment. Turns selected comments back into code. This is handy when you want to temporarily remove code from you program. You can com- ment those lines of code so that they don’t compile, and then remove the com- ment marks to bring the code back. ● Show/Hide Toolbox. This button toggles the list of ActionScript at the left side of the window. At the right of the buttons is a drop-down menu labeled Target. This button enables you to select a Flash movie document that will compile and run when you select Control, Test Movie. This makes it possible to make a change to your code and test the movie without having to switch back to the document window first. Usually, the Flash movie document last viewed is shown here. But, you can select a document if multiple ones are open. Another important feature of the ActionScript document window is the numbers to the left. Each line has its own number. When you get compiler errors when trying to publish your movie, they will refer to the line number so that you can track down the problem. ActionScript Game Programming Strategies ActionScript 3.0 is very versatile. You can follow any number of programming styles and still create games that work well. However, some programmers prefer certain styles over others. I have chosen a method for this book that allows us to focus on the core game code, perhaps sacrificing some advanced organization. Single Class Method The third Hello World program earlier in this chapter is simply one class file linked to a Flash movie of the same name. This simple approach is fast and easy. NOTE An alternative is to use different class files for different game objects and processes. This can make it difficult to keep track of what code is where in small games. For instance, if a ball collides with a paddle in a game, is the collision detection in the ball object’s class or the paddle object’s class? You are certainly welcome to break the code up into multiple classes if you are familiar with that type of organization from your experience with other programming languages. With one class file, all our class properties can be clearly defined as variables at the top of the class. The document class controls the main timeline, meaning that we can call public func- tions in the class from buttons placed on the stage by designers. We can also easily con- trol the main timeline, jumping to different frames. Smallest Step Approach This next piece of information might be the most important in the book. It is simply this: If you can’t figure out how to program something, break it into smaller steps until you can. Chapter 1: Using Flash and ActionScript 3.022 Beginner programmers, and some experienced programmers who simply forget this rule, often get stuck while writing code. They think: “I don’t know how to make the program do a certain task.” However, this is simply a case of the task actually being several tasks, not just one. For example, a programmer might want to make a spaceship rotate around when the player presses the arrow keys. The programmer gets frustrated because he or she is not sure how to accomplish this task. The key is to break up the task of “rotating a spaceship”: Check to see whether the left arrow is pressed. Subtract from the rotation property of the ship sprite. Check to see whether the right arrow is pressed. Add to the rotation property of the ship sprite. The task of rotating a spaceship is actually four smaller tasks combined into one. Sometimes beginning programmers make the same mistake in a bigger way. They assume they cannot create an entire game, because it seems to complex. But, if you break the game into smaller and smaller tasks (and take each one step at a time), you can create any game. A simple whack-a-mole game might require fewer than a hundred tasks, whereas a complex platform game may require several hundred. But each task, if broken into its simplest steps, is just as easy to build. Good Programming Practices While learning to use ActionScript 3.0 to make games, it is also a good idea to keep some general good programming practices in mind. These aren’t so much rules, as guidelines. Even I break them here in there in the very pages of this book. But, there is no doubt that you would be a better programmer if you learn about these practices. Use Comments Well Comment your code with meaningful but simple comments. What seems like extra work now will have you thanking yourself months from now when you need to go back and modify your code. If you are working with other programmers, or think there is even a remote chance that someone else will have to modify your code at some point in the future, this guideline should become a rule. There are generally two types of comments: line comments and block comments. A line comment is simply a short phrase at the end of a line, or sometimes a single line comment just before the line of code. A block comment is a larger comment, usually one sentence or more, before a function or a section of code: ActionScript Game Programming Strategies 23 someActionScriptCode(); // this is a line comment // this is a line comment someActionScriptCode(); /* This is a block comment. Block comments can be much longer. And contain a description of what is to come. */ It is equally as important to make your comments meaningful and brief. Don’t simply restate what the code already says, like this: // loop 10 times for (var i:int=0;i<10;i++) { Also, don’t use a paragraph of text when a few words will do. A long and wordy com- ment can be just as useless as no comment at all. Don’t overdo it. Use Descriptive Variable and Function Names Don’t be afraid to use long and descriptive names for variables and functions. If you do, the code will become partially self-explanatory. Here is an example: public function putStuff() { for(var i:int=0;i<10;i++) { var a:Thing = new Thing(); a.x = i*10; a.y = 300; addChild(a); } } What does that code do? It looks like it places copies of a movie clip on the screen. But what movie clip, for what purpose? How about this: public function placeEnemyCharacters() { for(var enemyNum:int=0; enemyNum<10; enemyNum++) { var enemy:EnemyCharacter = new EnemyCharacter(); enemy.x = enemyNum*10; enemy.y = 300; addChild(enemy); } } Returning to this code months later will be much easier. Chapter 1: Using Flash and ActionScript 3.024 NOTE One common exception to this is the use of i as the incremental variable used with for loops. In the preceding example, I would have left the i and not changed it to enemyNum. Either way is fine, but it has become pretty standard for programmers to use i in for loops. In fact, nested for loops usually go on to use j and k in the inner loops, too. Turn Repetitive or Similar Code into Functions If you need to use the same line of code more than one time in a program, consider turning it into a function of its own and call that function instead. For instance, there might be several places in your game where you want to update the score. If the score is displayed in a text field named scoreDisplay, you do it like this: scoreDisplay.text = “Score: “+playerScore; But instead of including this same line of code in five places, you should put a function call in the five places instead: showScore(); Then, the function can look like this: public function showScore() { scoreDisplay.text = “Score: “+playerScore; } With this code only in one place, it is trivial to change the display word Score to Points. You don’t need to search and replace throughout your code, because it is only in one spot. You can do the same even if the code isn’t identical. For instance, suppose you have a loop where you place 10 copies of movie clip A on the left side of the stage, and another loop where you place 10 copies of movie clip B on the right side of the stage. You could create a function that takes the movie clip reference and the horizontal posi- tion for placement, and will place the movie clips. Then, you can call it twice, once for movie clip A and once for movie clip B. Test Your Code in Small Pieces As you write your code, test it in as small pieces as possible. This way, you catch errors as you write your code. For instance, if you want to make a loop that places ten circles on the screen at random locations with random colors, you want to first create the ten circles at random loca- tions. Test it, and get that portion working just like you want. Then, add the random color functionality. This basically is an extension of the “smallest step approach.” Break your programming tasks into small steps. Create the code for each step. Then, test each step. ActionScript Game Programming Strategies 25 Basic ActionScript Concepts Let’s take a look at the most basic programming syntax in ActionScript 3.0. If you are new to ActionScript, but have been using another programming language, this will be a quick way to see how ActionScript works. In case you have used ActionScript or ActionScript 2.0 before, I point out some places where ActionScript 3.0 differs. Creating and Using Variables Storing values in ActionScript 3.0 can be done with a simple assignment statement. However, you need to declare a variable the first time you use it. You can do this by placing var before the first use of the variable: var myValue = 3; Alternatively, you could declare the variable first and use it later: var myValue; NOTE In ActionScript 2.0, the var statement is not required. In ActionScript 3.0, it is. When you create a variable in this way, it is a very versatile Object type. This means it can hold any type of variable value: A number, a string such as “Hello”, or something more complex like an array or movie clip reference. However, if you declare a variable to be of a specific type, you can only use the variable to store values of that same type: var myValue:int = 7; An int variable type can be any integer, positive or negative. A uint variable is only for positive integers. If you want to use fractional values, also known as floating-point num- bers, you must use the Number type: var myValue:Number = 7.8; There are also String and Boolean types. Strings hold text, and Boolean values must be either true or false. These are the basic primitive types. However, you can also have arrays, movie clip and sprite references, and new types that match the code classes you create. Chapter 1: Using Flash and ActionScript 3.026 NOTE There is a definite efficiency advantage to using narrowly defined variables. For instance, int values can be accessed many times faster than Number values. This can help you speed up critical game processes if you stick to as basic of a type as possible for all variables. Operations on numeric variables are like almost any other programming language. Addition, subtraction, multiplication, and division are performed with the +, -, *, and / operators: var myNumber:Number = 7.8+2; var myOtherNumber:int = 5-6; var myOtherNumber:Number = myNumber*3; var myNextNumber:Number = myNumber/myOtherNumber; You can also use special operators to simplify operations. For instance, the ++ operator will increment a variable by one. The -- operator decreases it by one: myNumber++; You can use +=, -=, *=, and /= to perform an operation on the original variable. For instance, this will add seven to the variable: myNumber += 7; You can also use parenthesis to set the order of operations: var myNumber:Number = (3+7)*2; Strings can also be manipulated with the + operator and the += operator: var myString:String = “Hello”; var myOtherString = myString+”World”; myString += “World”; When we use variables in classes, they become properties of that class. In that case, we must define them further as either private or public. The difference is that private variables cannot be accessed by code outside of the class. For most purposes, this is what you want as the class functions should be the only things that can alter the class variable values. Condition Statements The if statement in ActionScript is the same as it is in many programming languages: if (myValue == 1) { doSomething(); } The == comparison checks for general equality. You can also use >, <, >=, and <= for greater than, less than, greater than or equal to and less than or equal to, respectively. Basic ActionScript Concepts 27 You can add else and else if to extend the if structure: if (myValue == 1) { doSomething(); } else if (myValue == 2) { doSomethingElse(); } else { doNothing(); } You can also have more complex conditions with && and ||. These represent the and and or comparison operators. NOTE Before ActionScript 3.0, you could use the keywords and and or as alternatives to && and ||. These are no longer accepted. if ((myValue == 1) && (myString == “This”)) { doSomething(); } Loops Looping is done with the for statement or the while statement. The for statement has three parts: the initial statement, a condition, and a change statement. For instance, the following code sets the variable i to zero, loops as long as it is less than ten, and increases the value of i each time through the loop: for(var i:int=0;i<10;i++) { doSomething(); } You can use the break command to exit a loop at any time. The continue command skips the rest of the lines of code in the loop and begins the next iteration through the loop. A while loop is basically a loop that continues forever as long as an initial condition is met: var i:int = 0; while (i < 10) { i++; } A variation of the while loop is the do loop. It is essentially the same, except the condi- tional statement is after the loop, ensuring that it executes at least once: Chapter 1: Using Flash and ActionScript 3.028 var i:int = 0; do { i++; } while (i <10); Functions To create functions in ActionScript 3.0, you just need to declare the function, what parameters it takes, and what it returns. Then define the function with the code inside it. If the function is in a class, you need to also define whether it is a public or private function. A private function cannot be accessed outside of the class. With our single- class game development method, we’ll be using mostly private classes. NOTE You might find that functions are sometimes referred to as methods. In the documen- tation, the term method is used frequently, but the keyword function is used to define it, as you will see below. So, I prefer to use the term function. Here is a simple function from inside a class. If this function were in the main timeline, rather than in a class, we would leave the private keyword off: private function myFunction(myNumber:Number, myString:String): Boolean { if (myNumber == 7) return true; if (myString.length < 3) return true; return false; } All this example function does is to return true if either the number is seven, or the string is less than three. It is just a simple example to show the syntax behind creating a function. Testing and Debugging No one, not even the most experienced programmer, writes perfect code. So, we must write code, test, and debug. Types of Bugs There are three reasons to debug your code. The first is that you get an error message when it compiles or runs. In this case, you must figure out the problem and correct it. Usually, you can see the problem immediately. For example, a misspelled variable name. Testing and Debugging 29 The second reason is that the program does not work as expected. Perhaps a character is supposed to move, but doesn’t. Or, user input is not accepted. Or, maybe the bullets the hero fires at the enemy pass right through them. This type of bug needs to be hunted down, and it can sometimes take a while. NOTE By far the most common type of question I get from other programmers is that they have some code that doesn’t work as expected. Can I tell them what is wrong with it? Yes, but the answer is right there in front of them; they just need to use their debug- ging skills to find it. And, as the creator of the code, they are usually in a much better position to do that. A third reason to debug your code is to improve it. You can track down inefficiencies and problems that cause slowdowns. Sometimes this is just as critical as a bug, because a slow game might be unplayable. Methods of Testing You can track down issues with your code in several ways. The simplest is to just walk through the code in your head. For instance, walk though the following code, line by line, and do the calculations like you were the computer: var myNumber:int = 7; myNumber += 3; myNumber *= 2; myNumber++; You don’t need to run the code to tell that the value of myNumber is now 21. For situations where the code is too long, or the calculations are too difficult, a simple trace command sends information to the Output panel for you to examine: var myNumber:int = 7; myNumber += 3; myNumber *= 2; myNumber++; trace(“myNumber = “, myNumber); NOTE Before Flash CS3, the trace command would only accept a single string and send it to the Output panel. Now it can accept any data type, as well as multiple items separated by commas. This makes it much more useful as a debugging tool. Chapter 1: Using Flash and ActionScript 3.030 I use trace statements often while developing. For instance, if the player makes a bunch of choices at the start of the game, I’ll send the results of those choices to the Output panel with trace. That way, while I’m testing, I have a reminder of what options I chose before playing the game in case something unexpected happens. Using the Debugger With Flash CS3, you can use a runtime debugger to check your code while your movie is running. If you have used the ActionScript 2.0 debugger, keep in mind that the ActionScript 3.0 debugger is a whole new animal. Setting a Breakpoint The simplest way to debug a program is to set a break point. You can do this by select- ing a line of your code and choosing Debug, Toggle Breakpoint from the menu. You can also press +B (Mac) or Ctrl+B (Windows) to set or remove a breakpoint. Figure 1.14 shows the DebugExample.as code, with a breakpoint set. You can see it as a dot on the left side of the window before the eighth line. The program simple cre- ates 10 text fields with the numbers 0 through 9 in them, and places them vertically down the left side of the screen. Testing and Debugging 31 Figure 1.14 The cursor was placed in line 8, and then Debug, Toggle Breakpoint was chosen to set a breakpoint there. After a breakpoint is set, you can use Debug, Debug Movie rather than Control, Test Movie to test the movie. When the program hits the line with the breakpoint, it will pause and display a variety of information to you in various debug windows. With the breakpoint set at line 8, and if you use Debug, Debug Movie, a whole set of debugging panels show up, in addition to the running Flash movie. You can see them all in Figure 1.15. Stepping Through the Code There are five buttons at the top of your Debug Console panel at the upper left. The first is a Continue button, which will continue the movie from the point at which it is stopped. The second is an X. This will end the debugging session and continue the movie from this point on without debugging. The other three involve stepping through the code. The first will execute the current line and move on to the next. If the current line of code calls another function, it will run that function. On the other hand, the next button, Step In, steps the program into a new func- tion if one exists on the same line. Using this button again and again will mean you visit every individual line of the program, instead of skipping over function calls. The last button will step out of the current function. So, use this button to finish the current function and go to the next line of the function you just left. Figure 1.16 shows the debug panels after you step into the showNumber function and then move down a few lines. You can see that the Variables panel shows the value of i. You can also expand the myText variable to see all the properties of the text field. At the upper left, you can see where you are in the program. You are currently in the showNumber function, which was called from the constructor function for the class. This comes in handy when you have a function that could be called form multiple places. Knowing how to use the debugger to fix bugs and unexpected behavior is just as impor- tant as knowing how to write the code in the first place. As you work on the games in this book and try to modify them to fit your needs, also work on learning how to debug. Chapter 1: Using Flash and ActionScript 3.032 Figure 1.15 The debug panels show you various information about the state of your program. Publishing Your Game After you have completed a game and tested it to your satisfaction, it is time to publish it. Flash games are usually published to the Web by embedding them in HTML pages. Flash CS3 makes this relatively easy, but there are some options you should understand before publishing. You can access the Publish Settings dialog by choosing File, Publish Settings. There are typically three sections in the Publish Settings dialog: Formats, Flash, and HTML. Formats The Formats settings, shown in Figure 1.17, allow you to select which files to export. The image formats are mostly for substitutions when the user doesn’t have the Flash player installed. And, the QuickTime export is for placing a Flash 5-era Flash movie inside a QuickTime file. None of these apply to us as ActionScript 3.0 game developers. The two Projector options can be used to make stand-alone versions of our games. These represent a whole different way to export your finished movies. Publishing Your Game 33 Figure 1.16 The debug panels show the progress of the program as you step through it. If you have a custom web page template that you already use on your site, the HTML option might not be necessary. In that case, you don’t want a default page to embed your game into. However, you might want to export it anyway and then take the body code from this sample page to use in the proper space on your own page. Flash The Flash settings are the most critical to exporting a complex Flash movie like our games. You’ll want to set it to export Flash Player 9 files, with ActionScript version set to ActionScript 3.0 (see Figure 1.18). You’ll also want to set the Protect from Import option. This will make it harder for someone to download your movie and modify it for his own use. NOTE Unfortunately, there is no surefire way to protect your Flash movie after it has been put on the Web. There are decompiler programs out there that will take a compressed and protected SWF file and convert it to a usable FLA movie. Using Protect from Import and Compress Movie will make this more difficult, but it is always a danger. The rest of the Flash settings concern compression and security settings. You can check the Flash documentation for detailed descriptions of each. Chapter 1: Using Flash and ActionScript 3.034 Figure 1.17 Only Flash and HTML formats are selected for export. HTML The HTML settings are only important if you want to use the HTML page created by Publishing on your site. But, it is at least a good idea to see how Adobe thinks you should publish your Flash movies. Figure 1.19 shows these options. Publishing Your Game 35 Figure 1.18 These are a good set of settings for general Flash game use. Figure 1.19 The HTML settings let you choose an HTML template to export with the Flash movie. The default setting of Flash Only uses JavaScript to embed the movie. It relies on the file AC_RunActiveContent.js, which is produced when publishing, too. The main HTML page then loads the JavaScript in this file, which then places the Flash movie in a
tag inside the web page. NOTE Why go to all the trouble of using JavaScript when you can just use a simple / tag, like you might have done in years past? Because of a patent dispute, Microsoft had to change the way media is embedded into pages in Internet Explorer. Any media embedded directly into a page now requires a click to activate it in Internet Explorer 7 and some versions of Internet Explorer 6. However, this JavaScript method avoids that extra click. One popular option is to have the Flash movie scale to fill the entire browser window. This can be done by simply changing the Dimensions setting to Percent and the Width and Height to 100. Now the movie will scale as large as it can, while still fitting in the window and maintaining its proportions. Changing the Scale to Exact Fit will allow it to lose its proportions and scale vertically to fit the window height and horizontally to fit the window width. Because all the vector graphics in Flash scale nicely, and your code will work fine at any scale, it is sometimes a good idea to allow the player to adjust the size of the game by simply changing the size of their browser window. This way, people with small monitors and large monitors can play the games as they like. Another option is the Quality setting. At the default High setting, the Flash player ren- ders the image at high resolution to get the best anti-aliasing effects at the edges of vec- tor shapes. Changing it to Medium lessens the resolution of anti-aliasing, but increases the performance of the movie. Using Auto High means that it will try to use the High setting, but drop down to Medium if playback is too slow. Using Low quality will remove all anti-aliasing, but offers the highest playback speed. ActionScript Game Programming Checklist When you are building a Flash game, there are a lot of factors to consider. Sometime it is easy to forget a key element which leads to the game not working correctly. To help you avoid some simple problems, here is a handy checklist that you can refer to. Publishing and Document Settings It is easy to forget that there are critical settings in the Publish Settings dialog and the movie’s Properties panel. Chapter 1: Using Flash and ActionScript 3.036 Is the Document Class Set Correctly? Figure 1.7 showed how to set the document class using the movie’s document panel. Forgetting to set this means that the movie will run and simply ignore the class that you created. Publish Settings Set Correctly? Make sure you set the Publish Settings so that the Flash movie is compiled for Flash 9 and ActionScript 3.0. It is doubtful that your movie will even compile if these are not set correctly, but it might be possible. Check Security Settings In the Publish Settings, in the Flash section, there is a Local Playback Security setting. It can be set to either Access Local Files Only or to Access Network Files Only. To make sure Flash movies are secure, you have to choose one or the other. This can be a problem if you have local files you need to access, and this is set to Access Network Files Only. If you are using external files at all, and things are not working as expected when you upload to a server, make this the first place you check. Class, Function, and Variable Names Even if you try to follow the good programming practices noted earlier in this chapter, you can still make some simple mistakes that could be hard to track down. Remember Case Sensitivity When you name a variable or function, case matters. So, myVariable and myvariable are completely different. Likewise, a class named myClass will run the function myClass when it initializes. If you have named it myclass by accident, however, it will not be called. Differences in variable names will usually be caught by the compiler because a mis- spelled variable name would not have been initialized. But, it is possible to forget that you have declared a variable and declare it again, with different capitalization. This is just something to be on the watch for. Are Movie Clip Class Files Present? If a movie clip is given Linkage properties to be used by ActionScript, it can use either the default dynamic class, or you can create a class for it. For instance, you can make an EnemyCharacter movie clip and then have an EnemyCharacter.as class file that is tied to it. However, it is easy to forget this class or misname it. For instance, an Enemycharacter.as file will simply be ignored, and not attached to the EnemyCharacter movie clip. ActionScript Game Programming Checklist 37 Do Classes Extend the Correct Type? You can start off a movie’s class with a definition like this: public class myClass extends Sprite { However, by extending a Sprite rather than a MovieClip, you are assuming that the movie only has one frame. Any code that refers to other frames won’t work as expected. Is the Constructor Function Set to the Right Name? If you have a class named myClass, the constructor function should be named exactly myClass; otherwise, it will not run when the class is initialized. Alternatively, if you don’t want it to run right away, name it something like startMyClass and call it after the frame starts. Runtime Issues There are also problems that don’t cause compiler errors, and don’t appear to be prob- lems at all at first. Then, they can show up later in development and be very frustrating to track down. Are You Setting Properties before the Object Is Ready? This one drives me crazy. Basically, what happens is that you jump to a new frame in the movie or a movie clip, and then try to set or access a property of an object there. However, the frame and its objects haven’t been initialized yet, so the property doesn’t exist. TooEarlyExample.fla and TooEarlyExample.as illustrate this. The class jumps the main timeline to frame 2, where two text fields await. It immediately tries to set the text of the first field, but that just calls a runtime error message. The second field is set when the movie is done initializing and runs the script in that frame. That script in turn calls a function in the class. This function sets the text of the second field without a problem. Are You Disposing of Objects? Although this might not cause much of a problem, it is a good practice to remember to dispose of all the objects you’ve created after you are done using them. For instance, if you have the player shoot bullets around the screen, they might be able to hold down a key and shoot thousands in a minute. When they leave the visible area of the screen, you don’t want these to hang around in memory and get tracked. To completely remove an object, you just need to get rid of all references to it in your variables and arrays, and use removeChild to take it out of its display list. Chapter 1: Using Flash and ActionScript 3.038 Are All Variables Well Typed? Another factor that might not cause immediate problems, but might still be a long-term issue, is variable typing. Don’t use the Number type when int or even uint will do. The later are much faster and take up less memory. If you have thousands of numbers stored in arrays, you might see some slowdown by using Number when int would do. Worse than this example is using untyped variables, which are Objects. They can store numbers and integers, but have far more overhead. Also, look out for creating MovieClips that can be single-framed Sprites. Testing Issues These items relate to things that can happen during testing or things that should be part of your testing approach. Do You Need to Disable Keyboard Shortcuts? If you are using keyboard input while testing your movies, you might find that some keys don’t respond. This is because the test environment has some keyboard shortcuts that are taking these key presses. To turn the keyboard shortcuts off in the testing environment, and allow your movie to act like it would when on the Web, choose Control, Disable Keyboard Shortcuts. Have You Tested at Other Frame Rates? If you are using time-based animation, it shouldn’t matter what frame rate you are set to, 1 or 60; the animation should move along at the same speed. However, it is worth testing at a low frame rate, say 6 or 12, to see what users on slow machines might see. We’ll use time-based animation throughout this book. Also, it is worth testing at slow and high frame rates to see whether there isn’t some system that is still using time-based animation or responses. Have You Tested from a Server? A similar problem rears its head when you assume that objects are all present at the start of a movie. The truth is that Flash movies stream, which means they begin playing before all the media has been loaded. When you are testing a movie locally, however, all the media is instantly there. Then, when you upload and test on a server, some of it might be missing for the first few sec- onds or even minutes. ActionScript Game Programming Checklist 39 NOTE When you test a movie, you can restart the test by selecting View, Simulate Download. Also, look at View, Download Settings to set a desired simulated download rate, like 56K. Then, the movie will restart with the objects streamed in at the desired rate. But, I’d also test with a live server to be sure. The solution to any problem that might arise is to have a loading screen that does noth- ing but wait for all media to be streamed. We’ll look at an example of a loading screen in Chapter 2, “ActionScript Game Elements.” This checklist should make it easier for you to avoid common problems and devote more time to creating games, and less time to tracking down bugs. Now that we have the basics of ActionScript 3.0 covered, the next chapter looks at some short examples of building blocks that you can use to make games. Chapter 1: Using Flash and ActionScript 3.040 2 ActionScript Game Elements ■ Creating Visual Objects ■ Accepting Player Input ■ Creating Animation ■ Programming User Interaction ■ Accessing External Data ■ Miscellaneous Game Elements Before we build complete games, we’ll start with some smaller pieces. The short pro- grams in this chapter give us a look at some basic ActionScript 3.0 concepts and also provide us with some building blocks to use later, and in your own games. SOURCE FILES http://flashgameu.com A3GPU02_GameElements.zip Creating Visual Objects Our first few elements involve the creation and manipulation of objects on the screen. We’ll pull some movie clips from the library, turn movie clips into buttons, draw some shapes and text, and then learn to group items together in sprites. Using Movie Clips When you’ve got a movie clip in the library and want to bring it into your game, there are two ways to do it. The first way is to drag and drop the movie clip onto the stage and give it an instance name in the Property Inspector. Figure 2.1 shows a movie clip moved from the library to the stage, and then named myClipInstance in the Property Inspector. Chapter 2: ActionScript Game Elements42 Figure 2.1 The movie clip object is named Mascot in the library, but the instance of the movie clip on the stage is named myClipInstance. Then, you can manipulate the properties of the movie clip by referring to it by name, like this: myClipInstance.x = 300; myClipInstance.y = 200; The second way to bring a movie clip into your game uses purely ActionScript code. But first, you must set the movie clip to be accessible by setting its Linkage properties. Select the symbol in the library and use the Library panel’s drop-down menu to select Linkage. Turn on Export for ActionScript and set the class name. You’ll get a dialog box that looks like the one shown in Figure 2.2. Creating Visual Objects 43 Figure 2.2 The Linkage Properties dialog is set to allow the Mascot movie clip to be used by ActionScript. NOTE I usually set the class name the same as the movie clip name. It makes it easier to remember. Now we can create new copies of the movie clip using only ActionScript. The way this is done is to create a variable to hold the instance of the object, and then use addChild to put it in a display list: var myMovieClip:Mascot = new Mascot(); addChild(myMovieClip); Because we haven’t set any other properties of the movie clip, it will appear at location 0,0 on the stage. We can set its location using the x and y properties of the instance. We can also set its angle of rotation using the rotation property. The value is in degrees: var myMovieClip:Mascot = new Mascot(); myMovieClip.x = 275; myMovieClip.y = 150; myMovieClip.rotation = 10; addChild(myMovieClip); Although this looks like a lot of work for only one movie clip, ActionScript makes it easy to add multiple copies of a movie clip. The following code will create 10 copies of the Mascot, with horizontal locations changing from left to right by 50 pixels. It will also set the scale of the movie clips to 50 percent: for(var i=0;i<10;i++) { var mascot:Mascot = new Mascot(); mascot.x = 50*i+50; mascot.y = 300; mascot.scaleX = .5; mascot.scaleY = .5; addChild(mascot); } You can see the result of both pieces of code in Figure 2.3. The first Mascot is at the top, at location 275,100. The other Mascots are spread out from 50 to 500 at vertical location 300, and scaled 50 percent. Chapter 2: ActionScript Game Elements44 Figure 2.3 Eleven mascots are created and placed by ActionScript code. You can find this example in the movie UsingMovieClips.fla. The code is in frame 1. Making Buttons You can also create buttons using only ActionScript. They can be made from either movie clips or button symbols stored in the library. To make a movie clip into a clickable button, you only need to assign it a listener. This will allow the movie clip to accept events, in this case a mouse click event: The following code places a new movie clip at 100,150: var myMovieClip:Mascot = new Mascot(); myMovieClip.x = 100; myMovieClip.y = 150; addChild(myMovieClip); To assign a listener, you use the addEventListener function. Include the type of event the listener should respond to. These are constant values that vary depending on the type of object and event. In this case, MouseEvent.CLICK will respond to a mouse click. Then, also include a reference to the function that you will create to handle the event (in this case, clickMascot): myMovieClip.addEventListener(MouseEvent.CLICK, clickMascot); The clickMascot function just sends a message to the Output window. Of course, in an application or game, it would do something more productive: function clickMascot(event:MouseEvent) { trace(“You clicked the mascot!”); } One more thing you might want to do to make the movie clip more button-like is to set the buttonMode property of the movie clip instance to true. This will make the cursor switch to a finger cursor when the user rolls over it: myMovieClip.buttonMode = true; Of course, you can also create instances of button symbols using ActionScript. We do this in the same way as we did with movie clips. In this case, the symbol is linked as the class LibraryButton: var myButton:LibraryButton = new LibraryButton(); myButton.x = 450; myButton.y = 100; addChild(myButton); The main difference between movie clips and button symbols is that the buttons have four specialized frames in their timeline. Figure 2.4 shows the timeline of our LibraryButton symbol. Creating Visual Objects 45 Figure 2.4 The timeline for a button contains four frames repre- senting the three button states and a hit area. The first frame represents the appearance of the button when the cursor is not over it. The second frame is what the button looks like when the cursor is hovering over it. The third frame is what the button looks like when the user has pressed down on the button, but has not yet released the mouse button. The last frame is the clickable area of the button. It is not visible at any time. NOTE The last frame can have a larger image than the rest to allow the user to click on or near the button. Or, if the visible frames of the button have gaps in them, such as they are just letters, or are an odd shape, the last frame can present a more standard circu- lar or rectangular shape to represent the click area. You can also create invisible but- tons by placing nothing on any of the frames except the last one. Figure 2.5 shows the three button states and the hit area for a movie clip. This is just one example. Your button can show over and down states in any number of ways. Chapter 2: ActionScript Game Elements46 Figure 2.5 The four frames that make up a button symbol. You can add a listener to the button in exactly the same way as you can with the movie clip: myButton.addEventListener(MouseEvent.CLICK, clickLibraryButton); function clickLibraryButton(event:MouseEvent) { trace(“You clicked the Library button!”); } The third option for creating a button is to use the SimpleButton type to create a button from scratch. Well, not exactly from scratch. You need to have a movie clip for each of the four frames of the button: Up, Over, Down, and Hit. So, in fact, you need four library elements, instead of just one. To make this type of button, you use the SimpleButton constructor. Each of the four parameters for SimpleButton must be a movie clip instance. In this case, we will use four movie clips: ButtonUp, ButtonOver, ButtonDown, and ButtonHit: var mySimpleButton:SimpleButton = new SimpleButton(new ButtonUp(), new ButtonOver(), new ButtonDown(), new ButtonHit()); mySimpleButton.x = 450; mySimpleButton.y = 250; addChild(mySimpleButton); NOTE You could also use the same movie clip for more than one of the four parameters in SimpleButton. For instance, you could reuse the button up state movie clip for the but- ton hit movie clip. In fact, you could use the same movie clip for all four. This would make a less interesting button, but one that required fewer movie clips in the library. Once again, you can add a listener to the button you created with the addEventListener command: mySimpleButton.addEventListener(MouseEvent.CLICK, clickSimpleButton); function clickSimpleButton(event:MouseEvent) { trace(“You clicked the simple button!”); } The movie MakingButtons.fla includes the code for all three of these buttons and will send a different message to the Output panel when each one is pressed. Drawing Shapes Not all the elements on the screen need to come from the library. You can use ActionScript 3.0 to draw with lines and basic shapes. Every display object has a graphics layer. You can access it with the graphics property. This includes the stage itself, which you can access directly when writing code in the main timeline. To draw a simple line, all you need to do is first set the line style, move to the starting point for the line, and then draw to an end point: this.graphics.lineStyle(2,0x000000); this.graphics.moveTo(100,200); this.graphics.lineTo(150,250); This sets the line style to 2 pixels thick and the color black. Then, a line is drawn from 100,200 to 150,250. NOTE Using the this keyword isn’t necessary. But, when you want the line to be drawn in a specific movie clip instance, you need to specify it by name. For instance: myMovieClipInstance.graphics.lineTo(150,250); So, we’ll include the this here to remind us of that, and make the code more reusable in your projects. Creating Visual Objects 47 You can also create a curved line with curveTo. We’ll have to specify both an end point and an anchor point. This gets rather tricky if you are not familiar with how Bezier curves are created. I had to guess a few times to figure out that this is what I wanted: this.graphics.curveTo(200,300,250,250); And then, we’ll complete the line sequence with another straight line: this.graphics.lineTo(300,200); Now we have the line shown in Figure 2.6, which shows a straight line, then a curve, and then back up to a straight line. Chapter 2: ActionScript Game Elements48 Figure 2.6 A line, curve, and a line make up this drawing. You can also draw shapes. The simplest is a rectangle. The drawRect function takes a position for the upper-left corner, and then a width and a height: this.graphics.drawRect(50,50,300,250); You can also draw a rectangle with rounded edges. The extra two parameters are the width and height of the curved corners: this.graphics.drawRoundRect(40,40,320,270,25,25); A circle and an ellipse are also possible. The drawCircle takes a center point and a radius as the parameters: this.graphics.drawCircle(150,100,20); However, the drawEllipse function takes the same upper left and size parameters as drawRect: this.graphics.drawEllipse(180,150,40,70); You can also create filled shapes by starting with a beginFill function and the color of the fill: this.graphics.beginFill(0x333333); this.graphics.drawCircle(250,100,20); To stop using a fill, you issue an endFill command. Figure 2.7 shows the results of all of the drawing we have done. Creating Visual Objects 49 Figure 2.7 Two lines, a curve, a circle, ellipse, filled circle, rectan- gle, and rounded rectangle. Most of these drawing functions have more parameters. For instance, lineStyle can also take an alpha parameter to draw a semitransparent line. Check the documentation for each of these functions if you want to know more. The preceding examples can be found in DrawingShapes.fla. Drawing Text The Hello World examples in Chapter 1, “Using Flash and ActionScript 3.0,” showed how you could create TextField objects to put text on the screen. The process involves creating a new TextField object, setting its text property, and then using addChild to add it to the stage: var myText:TextField = new TextField(); myText.text = “Check it out!”; addChild(myText); You can also set the location of the field with the x and y properties: myText.x = 50; myText.y = 50; Likewise, you can set the width and height of the field: myText.width = 200; myText.height = 30; It can be difficult to see the boundaries of a text field. A width of 200 might seem like enough to hold the current text, but will it hold different text if you change it? A quick way to see the actual size of a text field is to set the border property to true while you are testing: myText.border = true; Figure 2.8 shows the text field with the border turned on so that you can see its size. Chapter 2: ActionScript Game Elements50 Figure 2.8 A text field at 50,50 with a width of 200 and a height of 30. Another property we should almost always address is selectable. In most cases, you won’t want this turned on, although it is the default. Leaving this property on means that the player’s cursor will turn to a text editing cursor when he hovers over the text giving him the ability to select it: myText.selectable = false; What you most likely want to do when creating text is explicitly set the font, size, and style of the text. We can’t do this directly. Instead, we need to create a TextFormat object. Then, we can set its font, size and bold properties: var myFormat:TextFormat = new TextFormat(); myFormat.font = “Arial”; myFormat.size = 24; myFormat.bold = true; NOTE You can also create a TextFormat object with just one line of code. For instance, the previous example could be done with this: var myFormat:TextFormat = new TextFormat(“Arial”, 24, 0x000000, true); The TextFormat constructor function accepts up to 13 parameters, but null can be used to skip any of them. Consult the documentation for a complete list. Now that we have a TextFormat object, there are two ways to use it. The first is to use setTextFormat on a TextField. This changes the text to use the current style. However, you’d need to apply it each time you change the text property of the field. A better way is to use defaultTextStyle. You do this before you set the text property. The next text will take on the style properties described in the TextFormat. In fact, every time you set the text of that TextField, you’ll be using the same style. This is what we want most of the time in game development use of text fields: myText.defaultTextFormat = myFormat; Figure 2.9 shows the field with the format set. Creating Visual Objects 51 Figure 2.9 The text format has been set to 24-point Arial and bold. You will want to check out many other properties of TextFormat in the documentation if you plan on stretching its abilities. You can also choose to use StyleSheet objects and HTML marked-up text set through the htmlText property of a TextField. The function- ality with style sheets is very deep, so check the documentation if you want to investi- gate further. Creating Linked Text What do you get when you cross a text field and a button? A hypertext link, of course. You can easily make these in ActionScript 3.0, too. The easiest way to create linked text in a TextField is by using the htmlText property of the field and passing in HTML code rather than the plain text used by the text property: var myWebLink:TextField = new TextField(); myWebLink.htmlText = “Visit FlashGameU.com!”; addChild(myWebLink); This works just like it would in a web page, except there is no default style change for the link. It appears in the same color and style as the rest of the text. But, when the user clicks the link, it will navigate away from the current page in the user’s web browser to the page specified in the link. NOTE If the Flash movie is running as a stand-alone Flash projector, clicking this link would launch the user’s browser and take the user to the web page specified. You can also specify the TARGET parameter of the A tag, if you are familiar with it in your HTML work. You can use _top, for instance, to specify the entire page, as opposed to the frame, or _blank to open up a blank window in the browser. If you would like the text to appear blue and underlined, as it might on a web page, you can set a quick style sheet up and set the styleSheet property before setting the htmlText: var myStyleSheet:StyleSheet = new StyleSheet(); myStyleSheet.setStyle(“A”,{textDecoration: “underline”, color: “#0000FF”}); var myWebLink:TextField = new TextField(); myWebLink.styleSheet = myStyleSheet; myWebLink.htmlText = “Visit FlashGameU.com!”; addChild(myWebLink); Figure 2.10 shows the text using both the textFormat property set to Arial, 24, bold, and the styleSheet set to turn the links blue and underlined. Chapter 2: ActionScript Game Elements52 Figure 2.10 Both defaultTextFormat and styleSheet have been used to format the text and the link. But, you don’t need to have your links go to web pages. You can use them just like but- tons, assigning listeners to the text fields that react to them. To do this, you just need to use event: in the HREF tag of the link. Then, supply some text for your listener function to receive: myLink.htmlText = “Click here”; The listener will get the “testing” text as a string in the text property of the event that is returned: addEventListener(TextEvent.LINK, textLinkClick); function textLinkClick(event:TextEvent) { trace(event.text); } So, you could set several links in a TextField and then sort out which link has been clicked using the text property of the event parameter. Then, you could basically use text links just like you use buttons. You can also style the text with defaultTextFormat and styleSheet just like the web link. The file CreatingLinkedText.fla includes examples of both types of links using the same format and style. Creating Sprite Groups Now that we know how to create a variety of screen elements, we can look a little deeper into how display objects and display lists work. We can create Sprite display objects that have no purpose other than to hold other display objects. The following code will create a new Sprite and draw a 200x200 rectangle in it. The rectangle will have a 2-pixel black border and a light gray fill: var sprite1:Sprite = new Sprite(); sprite1.graphics.lineStyle(2,0x000000); sprite1.graphics.beginFill(0xCCCCCC); sprite1.graphics.drawRect(0,0,200,200); addChild(sprite1); We can then position the Sprite, including the shape we drew inside it, to 50,50 on the stage: sprite1.x = 50; sprite1.y = 50; Now we’ll create a second Sprite, just like the first, but position it at 300,100: var sprite2:Sprite = new Sprite(); sprite2.graphics.lineStyle(2,0x000000); sprite2.graphics.beginFill(0xCCCCCC); sprite2.graphics.drawRect(0,0,200,200); sprite2.x = 300; sprite2.y = 50; addChild(sprite2); Now let’s create a third Sprite, this time containing a circle. Instead of using addChild to place it on the stage, however, we’ll place it inside sprite1. We’ll also give it a darker fill: Creating Visual Objects 53 var sprite3:Sprite = new Sprite(); sprite3.graphics.lineStyle(2,0x000000); sprite3.graphics.beginFill(0x333333); sprite3.graphics.drawCircle(0,0,25); sprite3.x = 100; sprite3.y = 100; sprite1.addChild(sprite3); Figure 2.11 shows what the three sprites look like on the screen. Notice that even though we set the x and y properties of the circle to 100,100, it does not appear at 100,100 relative to the stage, but rather it is at 100,100 inside of sprite1. Chapter 2: ActionScript Game Elements54 Figure 2.11 The circle sprite is inside the left rec- tangle’s sprite. The movie now has sprite1 and sprite2 as children of the stage. Then, sprite3 is a child of sprite1. If we make sprite3 a child of sprite2 instead, it will jump to the center of sprite2 because the 100,100 position of sprite3 is now relative to its new parent. The movie CreatingSpriteGroups.fla makes it easier to visualize this by placing a lis- tener on both sprite1 and sprite2. When you click either of them, sprite3 is set to its child. So, you can make sprite3 jump back and forth between parents: sprite1.addEventListener(MouseEvent.CLICK, clickSprite); sprite2.addEventListener(MouseEvent.CLICK, clickSprite); function clickSprite(event:MouseEvent) { event.currentTarget.addChild(sprite3); } NOTE This is also a good example of how one button listener can be used for multiple buttons. The actual object clicked is passed into the listener function via currentTarget. In this case, we can just use that value for addChild. However, you can also compare it to a list of possible objects clicked and execute code based on which object was pressed. In game development, we’ll be creating Sprite groups all the time to hold different types of game elements. If we are using Sprites simply for layering, we’ll keep them all at 0,0, and then we can move elements from Sprite to Sprite without changing their relative screen position. Setting Sprite Depth Worth mentioning at this point is the setChildIndex command. This allows you to move display objects up and down in the display list. In other words, you can put one Sprite on top of the other. Think of the display list as an array, starting with item 0. If you have created three Sprites, they are at positions 0, 1, and 2. Position 2 is the top Sprite and is drawn on top of the others. If you ever want to move a Sprite to the bottom, under all other Sprites, just use the following: setChildIndex(myMovieClip,0); This puts the myMovieClip display object at position 0, and then all the rest move up to fill in the gap it left behind. Setting a Sprite to be higher than all others is a little trickier. You need to set the index to the last item in the display list. So, if there are three items (0, 1, and 2), you need to set it to 2. This can be done with the numChildren property: setChildIndex(myMovieClip,numChildren-1); You need to use the -1 because if there are three children (0, 1, and 2), numChildren returns 3. However, we need to use 2 in setChildIndex. Using 3 will give us an error. The example movie SettingSpriteDepth.fla puts three Sprites on the screen, each overlapping the other. Then, you can click any one to set it to the top position. Accepting Player Input The following sections deal with getting input from the player. This always comes from the keyboard or the mouse because these are the only standard input devices on mod- ern computers. Mouse Input We already know quite well how to turn a Sprite into a button and have it react to mouse clicks. But, the mouse is good for more than just clicking. You can also get the cursor’s location at any time, and Sprites can detect whether the cursor is over them. You can access the cursor’s current stage location at any time with the mouseX and mouseY properties. The following code takes the current location of the cursor and places it in a text field every frame: Accepting Player Input 55 addEventListener(Event.ENTER_FRAME, showMouseLoc); function showMouseLoc(event:Event) { mouseLocText.text = “X=”+mouseX+” Y=”+mouseY; } You can detect when the cursor moves over a Sprite in a similar manner to how you can detect a mouse click. Instead of a click, we are looking for a rollover event. We can add a listener for it to the Sprite: mySprite.addEventListener(MouseEvent.ROLL_OVER, rolloverSprite); function rolloverSprite(event:MouseEvent) { mySprite.alpha = 1; } In this function, we set the alpha property of the Sprite to 1, which is 100 percent opaque. Then, when the cursor leaves the Sprite, we’ll set it to 50 percent: mySprite.addEventListener(MouseEvent.ROLL_OUT, rolloutSprite); function rolloutSprite(event:MouseEvent) { mySprite.alpha = .5; } In the movie MouseInput.fla, the Sprite starts off at 50 percent transparency, and only changes to 100 percent when the cursor is over the Sprite. Figure 2.12 shows both the text field read-out of the cursor location, and this Sprite. Chapter 2: ActionScript Game Elements56 Figure 2.12 The cursor is over the sprite, so it turns opaque. Keyboard Input Detecting keyboard input relies on the two keyboard events: KEY_UP and KEY_DOWN. When the user presses down on a key, the KEY_DOWN message is sent. If you set a listener to lis- ten for it, you’ll be able to do something with it. However, the addEventListener function must reference the stage object. This is because key presses don’t have an obvious target like mouse clicks do. So, there must be an object that has keyboard focus when a movie starts. The stage is that object: stage.addEventListener(KeyboardEvent.KEY_DOWN, keyDownFunction); When a function gets the call from this listener, it will be able to access many properties of the event parameter. One such parameter is charCode, which returns the character number of the key pressed. In the following example, the charCode is converted to a character, and then is displayed in the text field keyboardText: function keyDownFunction(event:KeyboardEvent) { keyboardText.text = “Key Pressed: “+String.fromCharCode(event.charCode); } NOTE Remember to choose Control, Disable Keyboard Shortcuts from the menu while test- ing. Otherwise, your key presses might not get through to the stage at all. The event properties also include keyCode, which is like charCode, but is not affected by the Shift key. For instance, with the Shift key pressed, the A key will give us a charCode of 65 for a capital A. But, with the Shift key released, it gives us a charCode of 97, rep- resenting a lowercase A. The keyCode returns 65 regardless. Other properties of the event include ctrlKey, shiftKey, and altKey, representing whether those modified keys are depressed. In games, we often don’t care about the initial key press, but about whether the player continues to hold down a key. For instance, in a driving game, we want to know whether the player has the accelerator pedal pressed down, represented by the up arrow. To recognize when a key is being held down, the strategy is to look for both KEY_DOWN and KEY_UP. When we detect that a key is pressed down, we set a Boolean variable to true. Then, when the same key is lifted up, we set it to false. To determine whether the key is pressed at any given time, all we need to do is check the Boolean variable. Here is some code that checks the spacebar in the same way. The first function checks to see when the spacebar is pressed, and sets the variable spacePressed to true: stage.addEventListener(KeyboardEvent.KEY_DOWN, keyDownFunction); function keyDownFunction(event:KeyboardEvent) { if (event.charCode == 32) { spacebarPressed = true; } } Accepting Player Input 57 This next function captures a key being lifted up. If this is the spacebar, keyPressed is set to false: stage.addEventListener(KeyboardEvent.KEY_UP, keyUpFunction); function keyUpFunction(event:KeyboardEvent) { if (event.charCode == 32) { spacebarPressed = false; } } Using this method, we can keep track of critical game keys, like the spacebar and the four arrow keys. The example movie KeyboardInput.fla keeps track of the spacebar in this way and also displays a message when the spacebar’s state changes. Text Input Another type of TextField object is an input field. The difference between either a sta- tic or dynamic text field and the input field is that the user can select and type into the input field. To create a TextField that is an input field, just set its type property: var myInput:TextField = new TextField(); myInput.type = TextFieldType.INPUT; addChild(myInput); This creates a hard-to-find and poorly shaped input field at the upper-left corner of the screen. We can do a lot to improve it by setting its properties and using a TextFormat object. The following code sets the format to 12-point Arial, positions the field to 10,10 with a height of 18 and a width of 200. It also turns on the border as you would expect with an input field in a typical piece of software: var inputFormat:TextFormat = new TextFormat(); inputFormat.font = “Arial”; inputFormat.size = 12; var myInput:TextField = new TextField(); myInput.type = TextFieldType.INPUT; myInput.defaultTextFormat = inputFormat; myInput.x = 10; myInput.y = 10; myInput.height = 18; myInput.width = 200; myInput.border = true; addChild(myInput); stage.focus = myInput; The last line of code places the text entry cursor into the field. Chapter 2: ActionScript Game Elements58 A typical TextField is set to be a single line of text. You can change this behavior using the multiline property. For most text input, however, we’ll want only a single line. This means that Return/Enter keys will not be recognized, because a second line of text can’t be created. However, we can capture this key and use it to signal the end of input. To capture the Return key, we place a listener on the key up event. Then, the respond- ing function will check to see whether the key pressed was code number 13, the Return key: myInput.addEventListener(KeyboardEvent.KEY_UP, checkForReturn); function checkForReturn(event:KeyboardEvent) { if (event.charCode == 13) { acceptInput(); } } The acceptInput function takes the text from the input field and stores it in theInputText. Then it sends it to the Output window. It also removes the text field: function acceptInput() { var theInputText:String = myInput.text; trace(theInputText); removeChild(myInput); } NOTE While testing this movie, I found that the test environment sometimes intercepted the Return key, even if I had the Disable Keyboard Shortcuts menu option turned on. Clicking in the window and trying again produced the desired result. This shouldn’t happen when the movie is deployed on the Web. The sample movie TextInput.fla contains the preceding code in action. Creating Animation Next, let’s take a look at some ActionScript that enables us to move Sprites around the screen. And, let’s look at methods for making this movement mimic the real world. Sprite Movement Changing the position of a Sprite or movie clip is as easy as setting its x or y position. To animate one, therefore, we just need to change it at a constant rate. Using the ENTER_FRAME event, we can easily program this kind of constant change. For instance, here is a short program that makes a copy of a movie clip in the library, and then moves it one pixel to the right every frame: Creating Animation 59 var hero:Hero = new Hero(); hero.x = 50; hero.y = 100; addChild(hero); addEventListener(Event.ENTER_FRAME, animateHero); function animateHero(event:Event) { hero.x++; } The hero character now slides across the stage, one pixel at a time. Instead of moving one pixel at a time, you could move, say, ten at a time with += 10 rather than ++. Another way to speed up the hero is to simply increase the frame rate. Instead of the default 12fps (frames per second), you can increase it to, say, 60fps. You do this in the Properties Inspector at the upper-right corner, if the stage is selected, not another movie clip. Figure 2.13 shows the Property Inspector with the Frame rate set to 12fps. Chapter 2: ActionScript Game Elements60 Figure 2.13 The Property Inspector enables you to change the frame rate of the movie. NOTE Just because you choose to have a frame rate of 60fps, doesn’t mean the movie runs at 60fps. It just tries. If there is a lot going on in the movie, and the user’s machine is slow, it will fall short of 60fps. We’ll be looking at time-based animation soon, which will offer a better alternative to frame-based animation. Instead of just having the hero slide across the screen, we can make him walk. We need the help of an animation artist, however. He or she will need to create several frames of a walk cycle and place them in sequential frames of the Hero movie clip. Figure 2.14 shows such a walk cycle. Figure 2.14 A simple looping walk cycle in seven frames. Now we just have to rewrite the animateHero function so that the character moves from frame 2 to frame 8 of the movie clip, which represent the seven frames of animation. Frame 1 is reserved as the “stand” position. We’ll also be told by the artist that the character should move about 7 pixels per frame horizontally to match the walking animation. The resulting code will check the currentFrame property of the movie clip, and if it is on frame 8, it will send the movie clip back to frame 2. Otherwise, it will just go to the very next frame: function animateHero(event:Event) { hero.x += 7; if (hero.currentFrame == 8) { hero.gotoAndStop(2); } else { hero.gotoAndStop(hero.currentFrame+1); } } Try the example movie SpriteMovement.fla to see this code in action. Try different movie frame rates to see him move faster or slower. Using Timers Think of Timers like little message clocks. You create one and start it, and then it ticks away and sends messages at a set interval. For instance, you could create a Timer to call a specific function every second. The way you set up a Timer is to create a new Timer object. You need to pass to it the number of milliseconds between events. You can also pass a second parameter for the number of events to generate before stopping, although we won’t use that here. The following code creates a new Timer that triggers an event every 1,000 milliseconds (every 1 second). It calls the function timerFunction for each of these events: var myTimer:Timer = new Timer(1000); myTimer.addEventListener(TimerEvent.TIMER, timerFunction); To test the Timer, we just have it draw a small circle with every event. The event para- meter sent into the function includes a target property that refers to the Timer. You can use this to get at the currentCount property, which is the number of times the Timer has been triggered. We’ll use this to offset each circle so that it draws a line of circles, from left to right: function timerFunction(event:TimerEvent) { this.graphics.beginFill(0x000000); this.graphics.drawCircle(event.target.currentCount*10,100,4); } Creating Animation 61 Just creating the Timer and attaching a listener to it is not enough. You also have to tell the Timer to begin. You can do that with the start() command: myTimer.start(); The movie UsingTimers.fla demonstrates the preceding code. You can also use a Timer to accomplish the same tasks as we did in the previous section with the enterFrame events. Here is a Timer that will call the same animateHero function to move the character across the screen with a walk cycle. It replaces the addEventListener call: var heroTimer:Timer = new Timer(80); heroTimer.addEventListener(TimerEvent.TIMER, animateHero); heroTimer.start(); You can see this code in action in UsingTimers2.fla. When you run it, the character walks at a similar pace to 12fps. But, you can set the movie’s frame rate to 12, 6, or 60 and the walk will move at the same rate. NOTE Try setting the frame rate to 1fps. With the Timer moving the character every 80 mil- liseconds, it will move the character quite a bit between screen updates. This shows, at least, that Timers can be used to provide consistent movement despite a slower machine, so long as the calculations being performed with each Timer event are not overtaxing the processor. Time-Based Animation Real time-based animation means animation steps based on how much time has passed, not on arbitrary time intervals. A time-based animation step would first calculate the time since the last step. Then, it would move the objects according to this time difference. For instance, if the first time interval is .1 seconds, and the second time interval is .2 seconds, objects will move twice as far after the second time interval to remain consistent. So, the first thing that must be done is a variable should be created that holds the time of the last step. We’ll start it by placing the current time, taken from the getTimer() sys- tem function. This returns the time since the Flash player started, in milliseconds: var lastTime:int = getTimer(); Then, we’ll create an event listener tied to the ENTER FRAME event. It calls animateBall: addEventListener(Event.ENTER_FRAME, animateBall); The animateBall function calculates the time difference, and then sets the lastTime variable to get ready for the next step. It then sets the x location of a movie clip Chapter 2: ActionScript Game Elements62 instance ball. It adds the timeDiff multiplied by .1. So, the movie clip will move 100 pixels every 1000 milliseconds: function animateBall(event:Event) { var timeDiff:int = getTimer()-lastTime; lastTime += timeDiff; ball.x += timeDiff*.1; } The movie TimeBasedAnimation.fla uses this code to move a ball across the screen. Try it first at 12fps. Then try it at 60fps. Notice how the ball gets to the other side of the screen at the same time, but it looks a lot better at 60fps. Physics-Based Animation With ActionScript animation, you can do more than make an object move along a pre- determined path. You can also give it physical properties and have it move like an object in the real world. Physics-based animation can be either frame based or time based. We’ll build on the time-based animation example, but using velocity and gravity to dictate where the object should move. NOTE Gravity is a constant acceleration toward the ground (in this case, the bottom of the screen). In the real world, gravity is 9.8 meters/second or 32 feet/second. In the Flash Player world, everything is measured in pixels per millisecond, which can be scaled to match the real world in any way you want. For instance, if 1 pixel is 1 meter, .0098 is .0098 meters/millisecond, or 9.8 meters/second. However, you could just as easily used .001 or 7 or any number, as long as it “looks” right in your game. We’re not building scientific simulations here, just games. We’ll set the gravity to .0098 and define a starting velocity for the moving element. Velocity is simply the speed and direction of a moving object. With dx and dy represent- ing the change in the horizontal and change in the vertical position, together they rep- resent velocity: // set gravity amount var gravity:Number = .00098; var b:Number = .05; // set starting velcity var dx:Number = .2; var dy:Number = -.8; So, the object, in this case a ball, should move .2 pixels horizontally every millisecond, and –.8 pixels vertically every millisecond. Which means it is being thrown up and somewhat to the right. Creating Animation 63 To control the animation, we’ll create an ENTER FRAME listener and initialize the lastTime variable: // mark start time and add listener var lastTime:int = getTimer(); addEventListener(Event.ENTER_FRAME, animateBall); The animateBall function starts by calculating the amount of time passed since the last animation step: // step animation function animateBall(event:Event) { // get time difference var timeDiff:int = getTimer()-lastTime; lastTime += timeDiff; The dy variable is the vertical speed, and it should change depending on the pull of gravity, metered by the time difference: // adjust vertical speed for gravity dy += gravity*timeDiff; The ball moves according to the two variables: dx and dy. In both cases, the timeDiff is used to determine how much: // move ball ball.x += timeDiff*dx; ball.y += timeDiff*dy; } When you run the movie PhysicsBasedAnimation.fla, you get results that look like the ones shown in Figure 2.15. Chapter 2: ActionScript Game Elements64 Figure 2.15 This time-lapse screen shot shows the positions of the ball at 12fps. Programming User Interaction Beyond the basic user input and sprite movement, we’ve got the combination of both— when user interaction affects the elements on the screen. The following programs are small examples of user interaction with sprites. Moving Sprites Sprites on the screen are typically moved with either the mouse or the keyboard. For the keyboard, the arrow keys are typically used to control the sprite. Earlier in this chapter, you saw how to determine whether the spacebar was pressed. We can use the same basic idea here to determine whether the arrow keys are pressed. although the arrow keys have no visible character representation, they can be repre- sented by the key codes 37, 38, 39, and 40. Figure 2.16 shows the four arrow keys and their key codes. Programming User Interaction 65 Figure 2.16 The four arrow keys can be referenced by these four key codes. We start by creating four Boolean variables to hold the state of the four arrow keys: // initialize arrow variables var leftArrow:Boolean = false; var rightArrow:Boolean = false; var upArrow:Boolean = false; var downArrow:Boolean = false; We need both KEY DOWN and KEY UP listeners, as well as an ENTER FRAME listener to deal with moving the sprite as often as the screen updates: // set event listeners stage.addEventListener(KeyboardEvent.KEY_DOWN, keyPressedDown); stage.addEventListener(KeyboardEvent.KEY_UP, keyPressedUp); stage.addEventListener(Event.ENTER_FRAME, moveMascot); When the user presses an arrow key down, we’ll set its Boolean variable to true: // set arrow variables to true function keyPressedDown(event:KeyboardEvent) { if (event.keyCode == 37) { leftArrow = true; } else if (event.keyCode == 39) { rightArrow = true; } else if (event.keyCode == 38) { upArrow = true; } else if (event.keyCode == 40) { downArrow = true; } } Likewise, when the user releases the arrow keys, we’ll set the Boolean variable to false: // set arrow variables to false function keyPressedUp(event:KeyboardEvent) { if (event.keyCode == 37) { leftArrow = false; } else if (event.keyCode == 39) { rightArrow = false; } else if (event.keyCode == 38) { upArrow = false; } else if (event.keyCode == 40) { downArrow = false; } } Now we can use these Booleans to move the mascot movie clip by a set amount in the proper directions. We’ll store the movement amount in speed, instead of repeating it four times in the code: // move every frame function moveMascot(event:Event) { var speed:Number = 5; if (leftArrow) { mascot.x -= speed; } if (rightArrow) { mascot.x += speed; } if (upArrow) { mascot.y -= speed; } if (downArrow) { mascot.y += speed; } } The movie MovingSprites.fla shows this code in action. Notice that because we are testing each arrow key Boolean separately, you can do combinations. For instance, you Chapter 2: ActionScript Game Elements66 can press the right and down arrows, and the mascot will move down and to the right at the same time. Hold both the left and right arrows and the mascot won’t move at all (because they cancel each other out). Dragging Sprites Another way to move a Sprite around the stage is to let the user click and drag it. Instead of looking at the keyboard, we’ll be looking at the mouse here. When the user clicks the sprite, we’ll start the drag. When the user releases the mouse button, we’ll stop the drag. However, we can’t rely on the cursor being over the sprite when the user releases the button. So, we’ll look for the MOUSE_DOWN event on the mascot sprite, but the MOUSE_UP event on the stage. The stage will get a MOUSE_UP event regardless of whether the cur- sor is over the sprite: // set listeners mascot.addEventListener(MouseEvent.MOUSE_DOWN, startMascotDrag); stage.addEventListener(MouseEvent.MOUSE_UP, stopMascotDrag); mascot.addEventListener(Event.ENTER_FRAME, dragMascot); Another factor is the cursor offset. We want to allow the user to drag the sprite from any point on the sprite. So, if the player clicks at the bottom-right corner of the sprite, the cursor and the bottom-right corner will continue to stay in the same position relative to each other as the user drags. To do this, we’ll figure out the offset between the 0,0 location of the sprite and the location of the mouse click and store it in clickOffset. We’ll also use this variable to determine whether a drag is happening at the moment. If it is, clickOffset will be set to a Point object. If not, it should be null: // offset between sprite location and click var clickOffset:Point = null; When the user clicks the sprite, the click offset is taken from the localX and localY properties of the click event: // user clicked function startMascotDrag(event:MouseEvent) { clickOffset = new Point(event.localX, event.localY); } When the user releases the cursor, the clickOffset is set back to null: // user released function stopMascotDrag(event:MouseEvent) { clickOffset = null; } Programming User Interaction 67 Then, every frame, if the clickOffset is not null, we’ll set the position of the mascot to the current cursor location, minus the offset: // run every frame function dragMascot(event:Event) { if (clickOffset != null) { // must be dragging mascot.x = mouseX - clickOffset.x; mascot.y = mouseY - clickOffset.y; } } Check out DraggingSprites.fla to see this code at work. Try dragging the mascot from different points to see how the clickOffset handles it. Collision Detection After you have objects moving around the screen in game, it is very common to test them for collisions against each other. ActionScript 3.0 contains two native collision-detection functions. The hitTestPoint function tests a point location to see whether it is inside a display object. The hitTestObject function tests two display objects against each other to see whether they overlap. To examine these two functions, let’s create a simple example that examines the cursor location and the location of a moving sprite every frame: addEventListener(Event.ENTER_FRAME, checkCollision); The checkCollision function starts by using hitTestPoint looking at the cursor location to see whether it hits the crescent movie clip on the stage. The first two parameters of the hitTestPoint function are the x and y location of the point. The third location is the type of boundary to use. The default value of false, which means only the bound- ing rectangle of the display object should be taken into account. Unless the sprite is somewhat box shaped, this isn’t good enough for most game use. Instead, by setting the third parameter to true, hitTestPoint will use the actual shape of the display object to determine collision. We’ll put different text into a message text field, depending on the results of hitTestPoint: function checkCollision(event:Event) { // check the cursor location against the crescent if (crescent.hitTestPoint(mouseX, mouseY, true)) { messageText1.text = “hitTestPoint: YES”; } else { messageText1.text = “hitTestPoint: NO”; } Chapter 2: ActionScript Game Elements68 The hitTestObject function doesn’t have a shape option. It only compares the two bounding boxes of two sprites. But, it can still be useful in some cases. The following part of the code makes a star movie clip follow the cursor, and puts a different message in another text field depending on whether their bounding boxes intersect: // move star with mouse star.x = mouseX; star.y = mouseY; // test star versus crescent if (star.hitTestObject(crescent)) { messageText2.text = “hitTestObject: YES”; } else { messageText2.text = “hitTestObject: NO”; } } The example movie CollisionDetection.fla showcases this example. Figure 2.17 shows the cursor is inside the bounding box of the crescent; because we’re testing hitTestPoint with the shape flag set to true, however, it won’t register a collision unless the cursor actually over the crescent. The star and the crescent, meanwhile, are colliding as their bounding boxes intersect. Accessing External Data 69 Figure 2.17 The cursor location and the star are being tested for collision with the crescent. Accessing External Data Sometimes it is necessary to access information outside the game. You can load exter- nal game parameters from the web page or text fields. You can also save and load infor- mation locally. External Variables Suppose you have a game that could vary according to some options, such as a jigsaw puzzle game that could use different pictures, or an arcade game that could run at differ- ent speeds. You can feed variable values into the Flash movie through the HTML page it is sitting on. There are a few different ways to do this; but if you are using the default HTML tem- plate from the publish settings, you can pass in parameter values via the flashvars property of the AC_FL_RunContent function. NOTE The Flash movie is embedded into the web page via the OBJECT and EMBED tags for ActiveX (Internet Explorer) and Plug-In (Firefox) architectures. However, the OBJECT and EMBED tags are in turn written out by a bit of JavaScript provided by Adobe that comes in the AC_RunActiveContent.js file. Depending on your Publish Settings, you will get a copy of this file every time you Publish. Here is a shortened version of the call to AC_FL_RunContent that you would find in the HTML file that publishing from Flash CS3 would export. It includes a flashvars para- meter that I have added: The flashvars format is property name = value pairs, separated by the & symbol between them. So in this case, the property puzzleFile is set to myfilename.jpg, and the property difficultyLevel is set to 7. When the Flash movie starts, it can get these values using the LoaderInfo object. The following line retrieves all the parameters and places them in an object: var paramObj:Object = LoaderInfo(this.root.loaderInfo).parameters; To access an individual value, you just use ActionScript code like this: var diffLevel:String = paramObj[“difficultyLevel”]; You could pass in any number of game constants, such as image names, starting levels, speeds, positions, and so on. A hangman game could be set up with a different word or phrase. A world-exploring game could be given a different start location. When running the movie ExternalVariables.fla, keep in mind that the right way to do it is to load the ExternalVariables.html page in your browser. This has the flashvars parameter all set. If you try to test in Flash, or try to create a new HTML page, those parameters will be missing. Chapter 2: ActionScript Game Elements70 Loading Data Loading data from an external text file is relatively easy. If it is an XML-formatted file, it is ideal. For instance, suppose you want to load a trivia question from a file. The XML data could look like this: This is a test Correct answer Incorrect answer To load the data, you use two objects: a URLRequest and a URLLoader. Then, you listen for the loading to be complete, and call a function of your own: var xmlURL:URLRequest = new URLRequest(“LoadingData.xml”); var xmlLoader:URLLoader = new URLLoader(xmlURL); xmlLoader.addEventListener(Event.COMPLETE, xmlLoaded); The xmlLoaded, in this case, is just some trace statements to show the data was coming in: function xmlLoaded(event:Event) { var dataXML = XML(event.target.data); trace(dataXML.question.text); trace(dataXML.question.answers.answer[0]); trace(dataXML.question.answers.answer[0].@type); } You can see how easy it is to get the XML data from the file. With the XML object being dataXML, you can retrieve the question text with dataXML.question.text and the first answer with dataXML.question.answers[0]. You can get an attribute, like the type of answer by using @type. The LoadingData.fla example reads its data from the LoadingData.xml file. Try chang- ing and adding to the data in the XML file. Then, try playing with the trace statements to access different parts of the data. Saving Local Data A common need in game development is to store bits of local data. For instance, you could store the player’s previous score. Or, you could store some game options. Accessing External Data 71 To store a piece of data on the user’s machine, we’ll use a local SharedObject. Accessing a SharedObject is the same act as creating one. Just asking whether it exists will create it. To do this, just assign a variable to the SharedObject of a certain name, with the getLocal function: var myLocalData:SharedObject = SharedObject.getLocal(“mygamedata”); The myLocalData object is able to take any number of properties of any type: numbers, strings, arrays, other objects, and so on. If you had stored same data in a property of the shared object named gameinfo you could access it with: myLocalData.data.gameinfo: trace(“Found Data: “+myLocalData.data.gameinfo); So, set this gameinfo property. Just set it as you would a regular variable: myLocalData.data.gameinfo = “Store this.”; Try running the test movie SavingLocalData.fla. It uses the trace function to output the myLocalData.data.gameinfo property. Because that isn’t set to anything, you’ll get undefined as the result. But then, it sets the value. So, the second time you run the test, you get “Store this.” Miscellaneous Game Elements Here are some simple scripts that perform a variety of tasks. Most of these can be added to any game movie, if needed. Custom Cursors Suppose you want to replace the standard mouse cursor with something that fits the style of your game. Or, perhaps you want a larger cursor for a child’s game, or a spe- cial cross-hair cursor for a shooting game. Although you can’t change the computer’s cursor, you can make it disappear, at least visually. Then, you can replace it with a sprite that matches the cursor location and floats above everything else. To make the cursor invisible, use the Mouse.hide() command: Mouse.hide(); Then, to have a sprite act as the cursor, place it in a layer above all the other screen elements. Figure 2.18 shows the timeline with three layers. The cursor is the only ele- ment on the second layer, and all other elements are below it in the third layer. Chapter 2: ActionScript Game Elements72 NOTE If you are creating objects with ActionScript, you have to work to keep the cursor above all else. Using the setChildIndex command will allow you to place the cursor at the top after you have created your game objects. To make a sprite follow the cursor, we need an ENTER FRAME listener: addEventListener(Event.ENTER_FRAME, moveCursor); Then, the moveCursor command will simply have the arrow object, which is the stage instance name of the cursor in this case, follow the mouse location: function moveCursor(event:Event) { arrow.x = mouseX; arrow.y = mouseY; } You also need to set the mouseEnabled property of the sprite to false. Otherwise, the hid- den cursor is always over the cursor sprite, and never over sprites under it, like a button: arrow.mouseEnabled = false; Without this line of code, you can move the mouse over a button, and the button will not show its rollover state or accept mouse clicks properly. But, this makes the custom cursor invisible to mouse events. Figure 2.19 shows the custom cursor moving over a simple button. Miscellaneous Game Elements 73 Figure 2.18 The cursor must remain on top of all other screen elements. Figure 2.19 The simple button shows its rollover state, even though the arrow sprite is technically the first sprite under the mouse location. The example movie CustomCursor.fla has a simple button placed on the stage so that you can test the custom cursor rolling over a simple button. Playing Sounds There are two main ways to play sounds in ActionScript 3.0: as internal library sounds or as external files. Probably the best method for most game sound effects is to embed the sounds in the game movie’s library. You can do this by importing the sound using the File, Import, Import to Library menu command. Then, after the sound is in the library, select it and look at its Sound Properties dialog. You can see an example of this dialog in Figure 2.20. Chapter 2: ActionScript Game Elements74 Figure 2.20 The Sound Properties dialog lets you set the class identifier for a sound so that you can use it in ActionScript. To use a sound in ActionScript, you need to set the linkage of the sound to Export for ActionScript, and then the class to a name you will use in your code. In this case, we’ll use the name Sound1. Then, to play the sound, you just need two lines of code: var sound1:Sound1 = new Sound1(); var channel:SoundChannel = sound1.play(); Or, if you want to be more concise, you could do it in one line: var channel:SoundChannel = (new Sound1()).play(); Playing an external file is a little more difficult. First, you need to load the sound into an object. This code loads the sound file PlayingSounds.mp3 into the object sound2: var sound2:Sound = new Sound(); var req:URLRequest = new URLRequest(“PlayingSounds.mp3”); sound2.load(req); Then, to play the sound, you just need the play command: sound2.play(); The example movie PlayingSounds.fla has two buttons: one that plays a library sound, and one that plays an external sound. The external sound is loaded as soon as the movie begins, so it is ready to be played at any time. NOTE It is possible, with longer external sounds, that the sound wouldn’t have completed loading before it is needed. You can detect this by using the isBuffering property of the sound object. You can also use the bytesLoaded and bytesTotal properties for more advanced tracking. However, even if the sound is not quite finished loading, it will start to play as soon as it is loaded. So, for short sounds, it is probably not necessary to worry about it. Loading Screen Flash is built for streaming content. This means that the movie will start when only the bare minimum content has been loaded, such as the elements used on the first frame. This is great for animation. You can have a 1,000-frame hand-crafted animation that will start playing immediately and continue to load elements needed for future frames as the user watches the early frames. But for games, we rarely want to do this. Game elements are used by our ActionScript code almost immediately. If we are missing one of these elements because it hasn’t been loaded yet, the game could fail to play properly. So, most games use a loading screen that forces the movie to wait until everything is downloaded. It also keeps the player informed of the status of the download. A simple way to do this is place a stop on the first frame of the movie so that the movie won’t play until you tell it to: stop(); Then, set an ENTER FRAME listener to call a loadProgress function every frame: addEventListener(Event.ENTER_FRAME, loadProgress); Miscellaneous Game Elements 75 This function gets the status of the movie using this.root.loaderInfo. It has properties bytesLoaded and bytesTotal. We’ll take these and also convert them to kilobytes by dividing by 1,024: function loadProgress(event:Event) { // get bytes loaded and bytes total var movieBytesLoaded:int = this.root.loaderInfo.bytesLoaded; var movieBytesTotal:int = this.root.loaderInfo.bytesTotal; // convert to KiloBytes var movieKLoaded:int = movieBytesLoaded/1024; var movieKTotal:int = movieBytesTotal/1024; To show the player the loading progress, we just put some text into a text field that is already on frame 1 of the movie. It will display text like “Loading: 5K/32K”: // show progress progressText.text = “Loading: “+movieKLoaded+”K/”+movieKTotal+”K”; When the movieBytesLoaded equals the movieBytesTotal, we’ll remove the event lis- tener, and push the movie forward to frame 2. If this is the beginning of an animated sequence, you can use gotoAndPlay instead: // move on if done if (movieBytesLoaded >= movieBytesTotal) { removeEventListener(Event.ENTER_FRAME, loadProgress); gotoAndStop(2); } } The example movie LoadingScreen.fla contains this code in the first frame. It also has a 33K image on the second frame. To test the code, first test the movie normally using Control, Test Movie. Then, in the testing environment, choose View, Download Settings, 56K. Then choose View, Simulate Download. This will simulate loading at 4.7K/sec, and allow you to see the loading screen in action. Random Numbers Random numbers are used in almost any game. They allow for infinite variation and help you keep your code simple. Creating random numbers in ActionScript 3.0 is done with the Math.random function. This returns a value between 0.0 and 1.0, not including 1.0 itself. Chapter 2: ActionScript Game Elements76 NOTE The number returned is generated by a complex algorithm in the Flash Player. It seems to be completely random; but because it is an algorithm, it isn’t technically completely random. However, for our purposes as game developers, we don’t need to worry about it and can consider the numbers returned completely random. So, this code will get a number from 0.0 to 1.0, not including 1.0: var random1:Number = Math.random(); We’ll usually want to define a more specific range for the random number. For instance, you might want a random number between 0 and 10. We define these ranges by simply multiplying the result of Math.random by the range: var random2:Number = Math.random()*10; If you want an integer value, rather than a floating-point number, you could use Math.floor to round the values down. This will give you a random number from 0 to 9: var random3:Number = Math.floor(Math.random()*10); If you want to define a range that doesn’t start at 0, you just need to add to the result. This will give you a result from 1 to 10: var random4:Number = Math.floor(Math.random()*10)+1; The movie RandomNumbers.fla shows these lines of code, with output to the Output panel. Shuffling an Array One of the most common uses of random numbers in games is to set up the game pieces at the start of a game. Typically, this involves a shuffle of playing elements, such as cards, tiles, or playing pieces. For instance, say you have 52 playing pieces that you want to shuffle into a random order, like a dealer would shuffle cards before dealing a hand of poker or blackjack. The way this is done is to first create the array of playing pieces as a simple ordered array. The following code does this with the numbers 0 through 51: // create ordered array var startDeck:Array = new Array(); for(var cardNum:int=0;cardNum<52;cardNum++) { startDeck.push(cardNum); } trace(“Unshuffled:”,startDeck); Miscellaneous Game Elements 77 The result to the Output window will look like this: Unshuffled: 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,3 2,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51 To randomize the array, we choose a random position in the array and take the number from that position and place it in a new array. Then, we delete the number from the old array. We’ll keep doing this until the old array is empty: // shuffle into new array var shuffledDeck:Array = new Array(); while (startDeck.length > 0) { var r:int = Math.floor(Math.random()*startDeck.length); shuffledDeck.push(startDeck[r]); startDeck.splice(r,1); } trace(“Shuffled:”, shuffledDeck); The result will look something like this. Of course, it will be different each time you run the program: Shuffled: 3,42,40,16,41,44,30,27,33,11,50,0,21,23,49,29,20,28,22,32,39,25,17,19,8,7,10,37,2,12,31 ,5,46,26,48,45,43,9,4,38,15,36,51,24,14,18,35,1,6,34,13,47 The example movie ShufflingAnArray.fla demonstrates this procedure. Displaying a Clock Keeping track of time can be done with the getTimer() function. This tells you the number of milliseconds that have elapsed since the Flash player started. A typical internal game clock notes the start of game play by placing the getTimer() value at that moment in a variable. For instance, the game might start 7.8 seconds after the Flash Player starts, perhaps delayed that long while the user finds and clicks the “Start Game” button. So, the value 7800 will be stored in startTime. Then, to get the time at any point, it is just a matter of subtracting startTime from the current time. However, the player isn’t interested in raw milliseconds. The player wants to see some- thing like “1:34” for 1 minute and 34 seconds. Converting milliseconds to a time format is just a matter of dividing by 1,000 to get the number of seconds, and then by 60 to get the number of minutes. Here is an example of a program that places a text field on the screen, captures the time at the start, and then displays the clock every frame. It converts the time to sec- onds and minutes, padding a zero on to the number of seconds if it is less than ten: Chapter 2: ActionScript Game Elements78 var timeDisplay:TextField = new TextField(); addChild(timeDisplay); var startTime:int = getTimer(); addEventListener(Event.ENTER_FRAME, showClock); function showClock(event:Event) { // milliseconds passed var timePassed:int = getTimer()-startTime; // compute minutes and seconds var seconds:int = Math.floor(timePassed/1000); var minutes:int = Math.floor(seconds/60); seconds -= minutes*60; // convert to clock string var timeString:String = minutes+”:”+String(seconds+100).substr(1,2); // show in text field timeDisplay.text = timeString; } Let’s take a closer look at the string conversion. The number of minutes is taken straight from the minutes variable. Then, the colon is appended after it. The number of seconds is handled differently: 100 is added to it, so 7 seconds becomes 107 seconds; 52 seconds becomes 152 seconds; and so on. Then, it is converted to a string with the String constructor. Then, the substring starting at character 1 and with a length of 2 is taken. Because we start counting characters at 0, this means the 07 or the 52 is taken, never the 1 at the start of 107 or 152. The result is strings like 1:07 or 23:52. You can check the example movie DisplayingAClock.fla to see this code in action. System Data It is often necessary to know information about what type of computer your game is being played on. This might affect how you want your game to handle certain situations and levels of detail. For instance, you can get the stage width and height using the stage.stageWidth and stage.stageHeight properties. These values will even change in real time if the movie is set to scale to fit the browser. So, if your movie is built to be 640 pixels wide, but you detect that it is playing at 800 pixels wide, you can choose to show more detail so that the player can see greater detail. Or, you can choose to show fewer frames of animation, because a larger scale means more rendering power is needed. Miscellaneous Game Elements 79 You can also use the Capabilities object to get various pieces of information about the computer. Here is a handy list of the ones that will most affect us as game developers: ● Capabilities.playerType. This returns External if you are testing the movie, StandAlone if it is running as a Flash Projector, PlugIn if it is running in a browser like FireFox or Safari, or ActiveX if it is running in Internet Explorer. So, you could put some cheats into your code that only work if the playerType is External that allow you to test your game, but will not affect the web-based version. ● Capabilities.language. This returns the two-letter code, such as en for English, if the computer is set to use this as the primary language. ● Capabilities.os. Returns the operating system type and version, such as Mac OS 10.4.9. ● Capabilities.screenResolutionX, Capabilities.screenResolutionY. The display resolution, such as 1280 and 1024. ● Capabilities.version. The Flash Player version, such as MAC 9,0,45,0. You can extract the operating system or player version from this. There are many more Capabilities properties you can grab. Check the Flash CS3 doc- umentation. Also see SystemData.fla for a movie that grabs most of the data above and displays it live in a text field. Game Theft and Security Game theft on the Internet is a big problem. Most games are not protected in any way, and it is easy for someone to grab the SWF file and upload it to a website, claiming your work as their own. There are many ways to prevent this. The simplest is to have your game check to make sure it is running from your server. This can be done with the this.root.loaderInfo.url property. It returns the full path of the SWF file, starting with http:// if the file is on the Web. You can then check it against your domain. For instance, to make sure that flashgameu.com appears in the path, you could do this: if (this.root.loaderInfo.url.indexOf(“flashgameu.com”) != -1) { info.text = “Is playing at flashgameu.com”; } else { info.text = “Is NOT playing at flashgameu.com”; } Instead of simply setting a text field, you could stop the game from playing, or send the player to your site with navigateToURL. Chapter 2: ActionScript Game Elements80 After you have secured your game at your site, the next step is to secure it so that someone can’t use an EMBED tag with an absolute URL to your SWF file. With this method, they are embedding your game from your server into their web page on their server. There is no easy way to stop this. However, if you discover it happening, you can always move your SWF file. In fact, you can even replace your SWF file with one that does nothing but redirect the player using navigateToURL. NOTE Some web servers can prevent remote linking. This is mostly used to prevent people from embedding images from your server into their pages. In many cases, it also works with SWF files. You should check with your ISP about this functionality. A more advanced method to prevent embedded linking is relatively complex. Basically, it involves passing in a secret value to the Flash movie by two alternate routes: as a flashvars parameter, and as a bit of text or XML data using URLLoader. If the two secret values don’t match, the Flash movie must be stolen. The idea is to change the value passed in by both methods on a regular basis. So, if someone steals your SWF movie but does not take your HTML code to embed the Flash movie into the page, your movie won’t get the flashvars version of the secret value, and so won’t work for that person. Even if they steal your HTML code, they will have only the current version of the flashvars secret value. For the time being, it will match the URLLoader secret value. After you update the secret value in both places, the old flashvars secret value on the thief’s page will cease to match the new URLLoader value on your server. Of course, it is still possible for someone to steal your SWF game, open it with a SWF Decompiler program, and remove your security. So, there is no 100 percent solution. However, most thieves will look for games that are easy to steal. Don’t make yours one of them. Now that you’ve learned some more ActionScript 3.0 programming techniques through these small code building blocks, it is time to move on and make our first game. Miscellaneous Game Elements 81 This page intentionally left blank 3 Basic Game Framework: A Matching Game ■ Placing Interactive Elements ■ Game Play ■ Encapsulating the Game ■ Adding Scoring and a Clock ■ Adding Game Effects ■ Modifying the Game Chapter 3: Basic Game Framework: A Matching Game84 SOURCE FILES http://flashgameu.com A3GPU03_MatchingGame.zip To build our first game, I’ve chosen one of the most popular games you will find on the Web and in interactive and educational software: a matching game. Matching games are simple memory games played in the physical world using a simple deck of cards with pictures on them. The idea is to place pairs of cards face down in a random arrangement. Then, try to find matches by turning over two cards at a time. When the two cards match, they are removed. If they don’t match, they are turned face down again. A good player is one who remembers what cards he or she sees when a match is not made, and can determine where pairs are located after several failed tries. NOTE Sometimes educational matching games for children don’t have exact matches in a pair of cards. For instance, one card can have a picture of a cat on it, whereas the other card has the word cat. Or, one card can have the number 7, whereas another has 3+4. Computer versions of matching games have advantages over physical versions: You don’t need to collect, shuffle, and place the cards to start each game. The computer does that for you. It is also easier and less expensive for the game developer to create different pictures for the cards with virtual cards rather than physical ones. To create a matching game, we first work on placing the cards on the screen. To do this, we need to shuffle the deck to place the cards in a random order each time the game is played. Then, we take the player’s input and use that to reveal the pictures on a pair of cards. Then, we compare the cards and remove them if they match. We also need to turn cards back to their face-down positions when a match is not found. And then we need to check to see when all the pairs have been found so that the game can end. Placing Interactive Elements Creating a matching game first requires that you create a set of cards. Because the cards need to be in pairs, we need to figure out how many cards will be displayed on the screen, and make half that many pictures. For instance, if we want to show 36 cards in the game, there will be 18 pictures, each appearing on 2 cards. Methods for Creating Game Pieces There are two schools of thought when it comes to making game pieces, like the cards in the matching game. Multiple-Symbol Method The first method is to create each card as its own movie clip. So, in this case, there will be 18 symbols. Each symbol represents a card. One problem with this method is that you will likely be duplicating graphics inside of each symbol. For instance, each card would have the same border and background. So, you would have 18 copies of the border and background. Of course, you can get around this by creating a background symbol that is then used in each of the 18 card symbols. NOTE Using multiple symbols, one for each card, can prove useful if you are picking cards from a large group—like if you need 18 cards from a pool of 100. Or, it could be use- ful if the cards are being imported into the movie from external media files, like a bunch of JPG images. But the multiple-symbol method still has problems when it comes to making changes. For instance, suppose you want to resize the pictures slightly. You’d need to do that 18 times for 18 different symbols. Also, if you are a programmer teaming up with an artist, it is inconvenient to have the artist update 18 or more symbols. If the artist is a contractor, it could run up the budget as well. Single-Symbol Method The second method for working with a set of playing pieces, such as cards, is a single- symbol method. You would have one symbol, a movie clip, with multiple frames. Each frame contains the graphics for a different card. Shared graphics, such as a border or background, can be on a layer in the movie clip that stretches across all the frames. NOTE Even the single-symbol method can use many symbols. For instance, if your playing pieces are deck of poker cards, you may place the four suits (spades, hearts, diamonds, and clubs) in symbols and use them in your main deck symbol on the cards. That way, if you want to change how the hearts look across your whole deck, you can do this by just changing the heart symbol. Placing Interactive Elements 85 This method has major advantages when it comes to updates and changes to the play- ing pieces. You can quickly and easily move between and edit all the frames in the movie clip. You can also easily grab an updated movie clip from an artist with whom you are working. Setting Up the Flash Movie Using the single-symbol method, we need to have at least one movie clip in the library. This movie clip will contain all the cards, and even a frame that represents the back of the card that we must show when the card is face down. Create a new movie that contains a single movie clip called Cards. To create a new movie in Flash CS3, choose File, New, and then you will be presented with a list of file types. You must choose Flash File (ActionScript 3.0) to create a movie file that will work with the ActionScript 3.0 class file we are about to create. Put at least 19 frames in that movie clip, representing the card back and 18 card fronts with different pictures on them. You can open the MatchingGame1.fla file for this exercise if you don’t have your own symbol file to use. Chapter 3: Basic Game Framework: A Matching Game86 Figure 3.1 The Card movie clip is a symbol with 37 frames. Each frame represents a differ- ent card. Figure 3.1 shows a timeline for the Card movie clip we will be using in this game. The first frame is “back” of the card. It is what the player will see when the card is supposed to be face down. Then, each of the other frames shows a different picture for the front of a card. After we have a symbol in the library, we need to set it up so that we can use it with our ActionScript code. To do this, we need to set its properties by selecting it in the library and bringing up the Symbol Properties dialog box (see Figure 3.2). Set the symbol name to Card and its type to Movie Clip. For ActionScript to be able to work with the Cards movie clip, it needs to be assigned a class. By checking the Export for ActionScript box, we automatically get the class name Card assigned to the symbol. This will be fine for our needs here. There is nothing else needed in the Flash movie at all. The main timeline is completely empty. The library has only one movie clip in it, the Cards movie clip. All that we need now is some ActionScript. Creating the Basic ActionScript Class To create an ActionScript class file, choose File, New, and then select ActionScript File from the list of file types; by doing so you create an untitled ActionScript document that you can type into. We start off an ActionScript 3.0 file by defining it as a package. This is done in the first line, as you can see in the following code sample: package { import flash.display.*; Right after the package declaration, we need to tell the Flash playback engine what classes we need to accomplish our tasks. In this case, we go ahead and tell it we’ll be needing access to the entire flash.display class and all its immediate subclasses. This will give us the ability to create and manipulate movie clips like the cards. Placing Interactive Elements 87 Figure 3.2 The Symbol Properties dialog box shows the properties for the symbol Card. The class declaration is next. The name of the class must match the name of the file exactly. In this case, we call it MatchingGame1. We also need to define what this class will affect. In this case, it will affect the main Flash movie, which is a movie clip: public class MatchingGame1 extends MovieClip { Next is the declaration of any variables that will be used throughout the class. However, our first task of creating the 36 cards on the screen is so simple that we don’t need to use any variables. At least not yet. Therefore, we can move right on to the initialization function, also called the construc- tor function. This function runs as soon as the class is created when the movie is played. It must have exactly the same name as the class and the ActionScript file: public function MatchingGame1():void { This function does not need to return any value, so we can put :void after it to tell Flash that nothing will ever be returned from this function. We can also leave the :void off, and it will be assumed by the Flash compiler. Inside the constructor function we can perform the task of creating the 36 cards on the screen. We’ll make it a grid of 6 cards across by 6 cards down. To do this, we use two nested for loops. The first moves the variable x from 0 to 5. The x will represent the column in our 6x6 grid. Then, the second loop will move y from 0 to 5, which will represent the row: for(var x:uint=0;x<6;x++) { for(var y:uint=0;y<6;y++) { Each of these two variables is declared as a uint, an unsigned integer, right inside the for statement. Each will start with the value 0, and then continue while the value is less than 6. And, they will increase by one each time through the loop. NOTE There are three types of numbers: uint, int, and Number. The uint type is for whole numbers 0 or higher. The int type is for whole numbers that can be positive or nega- tive. The Number type can be positive or negative numbers, whole or floating point, such as 3.5 or –173.98. In for loops, we usually use either uint or int types because we only move in whole steps. So, this is basically a quick way to loop and get the chance to create 36 different Card movie clips. Creating the movie clips is just a matter of using new, plus addChild. We also want to make sure that as each new movie clip is created it is stopped on its first frame and is positioned on the screen correctly: Chapter 3: Basic Game Framework: A Matching Game88 var thisCard:Card = new Card(); thisCard.stop(); thisCard.x = x*52+120; thisCard.y = y*52+45; addChild(thisCard); } } } } } NOTE Adding a symbol in ActionScript 3.0 takes only two commands: new, which allows you to create a new instance of the symbol; and addChild, which adds the instance to the display list for the stage. In between these two commands, you want to do things such as set the x and y position of the new symbol. The positioning is based on the width and height of the cards we created. In the exam- ple movie MatchingGame1.fla, the cards are 50 by 50 with 2 pixels in between. So, by multiplying the x and y values by 52, we space the cards with a little extra space between each one. We also add 120 horizontally and 45 vertically, which happens to place the card about in the center of a 550x400 standard Flash movie. Before we can test this code, we need to link the Flash movie to the ActionScript file. The ActionScript file should be saved as MatchingGame1.as, and located in the same directory as the MatchingGame1.fla movie. Placing Interactive Elements 89 Figure 3.3 You need to set the Document class of a Flash movie to the name of the AS file that contains your main script. However, that is not all you need to do to link the two. You also need to set the Flash movie’s Document class property in the Property Inspector. Just select the Properties tab of the Property Inspector while the Flash movie MatchingGame1.fla is the current document. Figure 3.3 shows the Property Inspector, and you can see the Document class field at the bottom right. NOTE You can test a movie when either the Flash movie itself is the current document or an ActionScript file is the current document. When an ActionScript file is the current doc- ument, look in the upper-right part of the document window for a Target indicator. This tells you what Flash movie will be compiled and run when you test. If the wrong file is shown as the Target, you can use the drop-down menu to change it. Figure 3.4 shows the screen after we have tested the movie. The easiest way to test is to go to the menu and choose Control, Test Movie. Chapter 3: Basic Game Framework: A Matching Game90 Figure 3.4 The screen shows 36 cards, spaced and in the center of the stage. Using Constants for Better Coding Before we go any further with developing this game, let’s look at how we can make what we have better. We’ll copy the existing movie to MatchingGame2.fla and the code to MatchingGame2.as. Remember to change the document class of MatchingGame2.fla to MatchingGame2 and the class declaration and constructor function to MatchingGame2. Suppose you don’t want a 6x6 grid of cards. Maybe you want a simpler 4x4 grid. Or even a rectangular 6x5 grid. To do that, you just need to find the for loops in the previ- ous code and change the loops so that they loop with different amounts. A better way to do it is to remove the specific numbers from the code all together. Instead, have them at the top of your code, and clearly labeled, so that you can easily find and change them later on. NOTE Putting specific numbers in your code, such as the 6s for the row and column lengths, is called hard coding. It is considered to be a bad practice for programmers because it makes it harder to adjust your program later, and especially hard for others to inherit your code and find out where they can adjust it. We’ve got several other hard-coded values in our programs. Let’s make a list. Horizontal Rows = 6 Vertical Rows = 6 Horizontal Spacing = 52 Vertical Spacing = 52 Horizontal Screen Offset = 120 Vertical Screen Offset = 45 Instead of placing these values in the code, let’s put them in some constant variables up in our class, to make them easy to find and modify: public class MatchingGame2 extends MovieClip { // game constants private static const boardWidth:uint = 6; private static const boardHeight:uint = 6; private static const cardHorizontalSpacing:Number = 52; private static const cardVerticalSpacing:Number = 52; private static const boardOffsetX:Number = 120; private static const boardOffsetY:Number = 45; NOTE Notice that I chose private static const when defining each constant. The private means that these variables can only be accessed inside this class. The static means that they will have the same values in all instances of the class. And, the const means that the values can never change. If you were to use public var instead, it would give you the opposite declaration: can be accessed outside of the class, and will hold differ- ent values for each instance. Because this is the one and only instance of the class, and there are no outside scripts, it really makes no difference, except for neatness. Now that we have constants, we can replace the code in the constructor function to use them rather than the hard-coded numbers: public function MatchingGame2():void { for(var x:uint=0;x 5) { // first half of flip this.scaleX = .2*(flipStep-6); } else { // second half of flip this.scaleX = .2*(5-flipStep); } // when it is the middle of the flip, go to new frame if (flipStep == 5) { gotoAndStop(flipToFrame); } // at the end of the flip, stop the animation if (flipStep == 0) { this.removeEventListener(Event.ENTER_FRAME, flip); Chapter 3: Basic Game Framework: A Matching Game114 } } } } So, the flipStep variable starts at 10 when the startFlip function is called. It then is reduced by one each frame thereafter. NOTE The scaleX property shrinks or expands the width of a movie clip. A value of 1.0 is the default. A value of 2.0 stretches it to twice its width, and a value of .5 makes it half its width. If flipStep is between 6 and 10, the scaleX property of the card is set to .2*(flipStep-6), which would be .8, .6, .4, .2, and 0. So, it gets thinner with each step. Then, when flipStep is between 5 and 0, the new formula of .2*(5-flipStep) is used. So, it would be 0, .2, .4, .6, .8, and then 1.0; and so, it returns to normal size. At the fifth step, the card jumps to the new frame. It appears to shrink, goes to noth- ing, jumps to the new frame, and then grows again. To accomplish this effect, I had to make one change to how the graphics on the Card movie clip were arranged. In all previous versions of the game, the cards had their upper-left corner at the center of the movie clip. For the change to scaleX to make it appear that the card was flipping around its center, however, I had to center the card graphics on each frame over the center of the movie clip. Compare the Card movie clips in MachingGame9.fla and MatchingGame10.fla to see the difference. See Figure 3.16 to see how this looks when editing the movie clips. Adding Game Effects 115 Figure 3.16 The left side shows the registration point of the movie clip at the upper left, as it is in the first nine example movies of this chap- ter. The right side shows the movie clip centered as it is for the final example. At the last step, the event listener is removed completely. The great thing about this class is that it works just as well when the card is being turned back face down, going to frame 1. Look at MatchingGameObject10.as and see where all the gotoAndStop calls have been replaced with startFlip. By doing this, we are not only creating a flip animation, but we are also giving the Card class more control over itself. Ideally, you might want to give cards complete control over themselves by having the Card10.as class more func- tions, such as those that set the location of the cards at the start of the game. Limited Card-Viewing Time Another nice touch to this game is to automatically turn over pairs of mismatched cards after the player has had enough time to look at them. For instance, the player chooses two cards. They don’t match, so they remain face up for the player to inspect. After two seconds, however, the cards turn over, even if the player hasn’t begun to select another pair. To accomplish this, we’ll use a Timer. A Timer will make adding this feature relatively easy. To start, we’ll need to import the Timer class into our main class: import flash.utils.Timer; Next, we create a timer variable at the start of the class: private var flipBackTimer:Timer; Later on in the clickCard function, we add some code right after the player has chosen the second card, not made a match, and his or her score has been decreased. This Timer code will set up the new timer, which will simply call a function when two sec- onds have gone by: flipBackTimer = new Timer(2000,1); flipBackTimer.addEventListener(TimerEvent.TIMER_COMPLETE,returnCards); flipBackTimer.start(); The TimerEvent.TIMER_COMPLETE event is triggered when a timer is done. Typically, a Timer runs a certain number of times, triggering a TimerEvent.TIMER each time. Then, on the last event, it also triggers the TimerEvent.TIMER_COMPLETE. Because we only want to trigger a single event at some point in the future, we just set the number of Timer events to one, and then look for TimerEvent.TIMER_COMPLETE. When two seconds go by, the returnCards function is called. This is a new function that works just like the later part of the old clickCard function. It flips both the first and sec- ond selections back to the face-down state, and then sets the firstCard and secondCard values to null. It also removed the listener: Chapter 3: Basic Game Framework: A Matching Game116 public function returnCards(event:TimerEvent) { firstCard.startFlip(1); secondCard.startFlip(1); firstCard = null; secondCard = null; flipBackTimer.removeEventListener(TimerEvent.TIMER_COMPLETE,returnCards); } The returnCards function duplicates code that was in clickCard before, so in MatchingGameObject10.as I’ve replaced this duplicate code in clickCard with a simple call to returnCards. This way, we only have one spot in our code that returns a pair of cards to the face-down state. Because returnCards demands a single event parameter, we need to pass that parame- ter into returnCards whether we have something to pass or not. So, the call inside clickCard simply passes a null: returnCards(null); Now if you run the movie and flip two cards, then wait, the cards will flip back on their own. Because we have a removeEventListener command in the returnCards function, the lis- tener is removed even if the returnCards function is triggered by the player turning over another card. Otherwise, the player would turn over a new card, the first two cards would turn back, and then the event would be triggered after two seconds regardless of the fact that the original two cards are already face down. Sound Effects No game is truly complete without sound. ActionScript 3.0 makes adding sound rela- tively easy, although there are quite a few steps involved. The first step is to import your sounds. I’ve created three sounds and want to bring them each into the library: FirstCardSound.aiff MissSound.aiff MatchSound.aiff After we have imported them, they need to have properties changed. Name them all after their filenames, but minus the .aiff. Also, check the Export for ActionScript option and give them the same class name as symbol name. Figure 3.17 shows one of the sound’s Properties dialog box. Adding Game Effects 117 Next, we set up the main game class to play the sounds at the right time. First, we need to import two new classes so that we can use sound: import flash.media.Sound; import flash.media.SoundChannel; Then, we create class variables to hold references to these sounds: var theFirstCardSound:FirstCardSound = new FirstCardSound(); var theMissSound:MissSound = new MissSound(); var theMatchSound:MatchSound = new MatchSound(); I like to pass all sound playback through a single function. Let’s call it playSound and add it to the end of the class: public function playSound(soundObject:Object) { var channel:SoundChannel = soundObject.play(); } Now, when we want a sound to play, we just call playSound with the sound variable we want to use, as follows: playSound(theFirstCardSound); In MatchingGameObject10.as, I’ve added playSound(theFirstCardSound) when the first card is clicked, and when a card is clicked while two mismatched cards are already Chapter 3: Basic Game Framework: A Matching Game118 Figure 3.17 Each sound is a class and can be accessed in ActionScript by its class name. showing. I’ve added playSound(theMissSound) when the second card is turned over and there is no match. I’ve added playSound(theMatchSound) when the second card is turned over and a match is found. This is all that it takes to add sound effects to the game. NOTE You might at this point want to review your publish settings to choose your sound compression settings. Alternatively, you could set the sound compression for each sound individually in its symbol properties. Either way, you probably want to use some- thing pretty low, such as 16Mbps MP3, because these are just simple sound effects. Modifying the Game A few more tiny changes before we are done with the game. First, when we recentered all the cards, it threw off the horizontal and vertical offsets for the card placement. So, that needs to be readjusted: private static const boardOffsetX:Number = 145; private static const boardOffsetY:Number = 70; How did I come up with those numbers? Well, if you really want to know: • The stage is 550 pixels across. There are 6 cards, each spaced 52 pixels apart. That’s 550–6*52 for the total space remaining on the left and the right. Divide by 2 to get the space to the right. However, the cards are centered at 0,0, so I need to subtract half of the width of a card, or 26. So, (550-6*52)/2-26=145; • Same for the vertical offset. (400-6*52)/2-26=70; Another loose end to consider is the cursor. When users go to click a card, they don’t get a special “I can click this” cursor. That is pretty easily changed by just setting the buttonMode property of each card as it is created: c.buttonMode = true; Now we have a finger cursor when the user rolls over the cards. This is already the case for the Play and Play Again buttons because those are Button symbols. One last change I made was to increase the frame rate of the movie from the default 12 frames per second to 60. You can do this by choosing Modify, Document to change the main movie document properties. At 60 frames per second, the flips are much smoother. And with the super-fast ActionScript 3.0 engine, even slow machines can run this game at this high frame rate. Modifying the Game 119 That wraps up the matching game, leaving us with the final version files: MatchingGame10.fla MatchingGameObject10.as Card10.as Chapter 3: Basic Game Framework: A Matching Game120 4 Brain Games: Memory and Deduction ■ Arrays and Data Objects ■ Memory Game ■ Deduction Game In the preceding chapter, we looked at a game that had a single setup of a game board, and you played until you cleared the board. However, many games have more than one setup. These games create a situation for the player to deal with, then the player gets to take action, and then the next situation is set up. You can think of these as turn- based games. In this chapter, we look at two such games: memory and deduction. The first game asks the player to watch and repeat a sequence. Each turn, the sequence gets longer, until the player eventually can’t keep up. The second game asks the player to guess a sequence, taking turns and using feedback to try to do better next turn. The simple setup used in the previous chapter won’t work for these games. We need to use arrays and data objects to store information about the game and use these data objects to determine the outcome of each turn the player makes. Arrays and Data Objects The games we create in this chapter require that we store information about the game and the player’s moves. We use what computer scientists call data structures to do this. Data structures are simply methods for storing groups of information. The simplest data structure is an array. It stores a list of information. ActionScript also has data objects, which store labeled information. In addition, you can nest one inside the other. You can have an array of data objects. Arrays An array is a list of values. For instance, if we want to have a list of characters that a player could choose at the start of a game, we could store that list as such: var characterTypes:Array = new Array(); characterTypes = [“Warrior”, “Rogue”, “Wizard”, “Cleric”]; We could also use the push command to add items to the array. This will produce the same result as the previous code: var characterTypes:Array = new Array(); characterTypes.push(“Warrior”); characterTypes.push(“Rogue”); characterTypes.push(“Wizard”); characterTypes.push(“Cleric”); In these examples, we are making an array of strings. However, arrays can hold any sort of value, such as numbers or even display objects, such as sprites and movie clips. Chapter 4: Brain Games: Memory and Deduction122 Arrays and Data Objects 123 NOTE Not only can arrays store values of any type, but they can mix types. You can have an array like this: [7, “Hello”]. A common use for arrays in games is to store the movie clips and sprites that we create. For instance, in Chapter 3, “Basic Game Framework: A Matching Game,” we created a grid of matching cards. For easy access, we could have stored a reference to each Card in an array. Creating the array might have gone something like this, if we want to create ten cards: var cards:Array = new Array(); for(var i:uint=0;i<10;i++) { var thisCard:Card = new Card(); cards.push(thisCard); } There are many advantages to having your game pieces in an array. For instance, it is easy to loop through them and check each piece for matches or collisions. NOTE You can also nest arrays. So, you can have an array of arrays. This is especially useful for grids of game pieces like in Chapter 3. For instance, a tic-tac-toe board could be represented as [[“X”,”O”,”O”], [“O”,”X”,”O”], [“X”,”O”,”X”]]. You can add new items to arrays, take items out of arrays, sort them, and search through them. Table 4.1 lists some of the most common array functions. Table 4.1 Common Array Functions Function Example Description push myArray.push(“Wizard”) Adds a value to the end of an array pop myArray.pop() Removes the last value of an array and returns it unshift myArray.unshift(“Wizard”) Adds a value to the beginning of an array shift myArray.shift(“Wizard”) Removes the first value in an array and returns it splice myArray.splice(7,2, Removes items from a location in ”Wizard”,”Bard”) the array and inserts new items there indexOf myArray.indexOf(“Rogue”) Returns the location of an item, or –1 if it is not found sort myArray.sort() Sorts an array Arrays are a common and indispensable data structure used in games. In fact, the rest of the data structures in this section use arrays to turn a single data item into a list if data items. Data Objects Arrays are great for storing lists of single values. But what if you want to group some values together? Suppose in an adventure game you want to keep character types, lev- els, and health together in a group. Say, for instance, a character on the screen would be a “Warrior” at level 15 with a health between 0.0 and 1.0. You could use a data object to store these three pieces of information together. NOTE In other programming languages, data objects are the equivalent to associative arrays. Like data objects, associative arrays are a list of items that include a label (a key) and a value. In fact, you can use regular arrays in ActionScript this way, but they aren’t as versatile as data objects. To create a data object, you can define it as a type Object. Then, you can add proper- ties to it with dot syntax. var theCharacter:Object = new Object(); theCharacter.charType = “Warrior”; theCharacter.charLevel = 15; theCharacter.charHealth = 0.8; You could also create this variable the following way: var theCharacter:Object = {charType: “Warrior”, charLevel: 15, charHealth: 0.8}; Objects are dynamic, meaning that you can add new properties to them whenever you want, and also these properties can be of any variable type. You don’t need to declare variables inside an Object; you just need to assign a value to them as in the preceding example. NOTE Data objects in ActionScript are really not any different from normal objects. In fact, you can even assign a function to a data object. For instance, if you have an object with the properties firstname and lastname, you could create a function fullname() that would return firstname+” “+lastname. Data objects and arrays work very well together. For instance, you could create an array of characters like the one above. Chapter 4: Brain Games: Memory and Deduction124 Arrays of Data Objects We’ll be using arrays of data objects to keep track of game elements in almost every game from now on. This will allow us to store the sprites or movie clips themselves, as well as data about them. For instance, a data object could look like this: var thisCard:Object = new Object(); thisCard.cardobject = new Card(); thisCard.cardface = 7; thisCard.cardrow = 4; thisCard.cardcolumn = 2; Now, imagine a whole array of these objects. In the matching game in Chapter 3, we could have put all the cards in objects like this. Or, imagine a whole set of items on the screen, like in an arcade game. An array of objects would store information about each item, such as speed, behavior, location, and so on. NOTE There is another type of object, called a Dictionary. Dictionaries can be used just like Objects, except you can use any value as a key, such as sprites, movie clips, other objects, and just about anything. Data structures like arrays and data objects are important in all but the simplest games. Now let’s use them in two complete game examples. Memory Game SOURCE FILES http://flashgameu.com A3GPU04_MemoryGame.zip A memory game is another simple game played by adults and children alike. It is a rather new game compared to the matching game, which can be played in the absence of technology. A memory game is where a sequence of images or sounds is presented, and the player tries to repeat the sequence. Usually, the sequence starts with one piece and then adds another with each turn. So, the player first repeats a single item, then two, then three, and so on. For instance: A, then AD, then ADC, then ADCB, then ADCBD, and so on. Eventually, the sequence is long enough that the player makes a mistake and the game is over. Memory Game 125 Chapter 4: Brain Games: Memory and Deduction126 Figure 4.1 The timeline of the Lights movie clip has two frames: off and on. The clip here is shown in Preview mode, which you can access with the pull-down menu on the right side of the timeline. The Lights movie clip itself, as seen in Figure 4.1, has two frames that both contain another movie clip, LightColors. In the first frame of Lights, there is a cover over the LightColors movie clip that dims its color in the Shade layer. It is a black cover set to 75 percent alpha, which means only 25 percent of the color underneath shows through. So, the first frame is a dim color, which represents the off state of the lights. The second frame is missing the dark cover, so it is the on state. NOTE Perhaps the most well-known version of the memory game is the 1978 handheld elec- tronic toy Simon. It was created by Ralph Baer, who is considered to be one of the fathers of computer gaming. He created the original Magnavox Odyssey, the first home gaming console. In 2005, he was awarded the National Medal of Technology his role in creating the video game industry. Preparing the Movie In ActionScript 3.0 style, we’ll create all the game elements in our code. This means starting with a blank main timeline, but not a blank library. The library needs to contain at least the movie clip for the playing pieces, which will be Lights in this case. We’ll have five lights, but all five will be contained in one movie clip. In addition, there needs to two versions of each light: on and off. NOTE There is no right or wrong way to create game pieces like the memory lights. You could have a movie clip for every light, or every light’s state. Or you could have placed all ten variations (five lights times two states) in one ten-frame timeline. Sometimes, it is just a matter of taste. If you are a programmer working with an artist on a game, it might be a matter of accommodating the way the artist wants to create the graphics. The LightColors movie clip contains five frames, each showing a different color. Figure 4.2 shows LightColors. Memory Game 127 Figure 4.2 The timeline of the LightColors movie clip has one color per frame. The LightColors movie clip is named lightColors with a lower case l. So, to change the color of a Light, we just need to use lightColors.gotoAndStop with the frame number. We’ll name the movie MemoryGame.fla and the ActionScript file MemoryGame.as. So, that means the Document Class needs to be set to MemoryGame in the Property Inspector panel like we did with the Matching Game in Chapter 3. Programming Strategy The movie starts with nothing, and then ActionScript creates all the screen elements. Therefore, we need to create the five lights and set each to a color. Then, we need to create two text fields: one to instruct players whether they should be watching the sequence or trying to repeat it, the other letting them know how many lights are in the sequence at the moment. NOTE There are plenty of alternatives to using two text fields to display information to the user. For instance, the number of items in the sequence could appear in a circle or box off to one side. The “Watch and listen” and “Repeat” text could instead be symbols that light up like green and red lights on a traffic light. Using text fields is simply a con- venient way to not worry about these design elements and focus here on the game logic code. The Lights movie clips will be stored in an array. There are five lights, so that means five elements in the array. This array will make it easy for us to refer to the movie clips when we need to turn them on or off. We’ll also store the sequence in an array. The sequence will start as an empty array, and we’ll add one random light to it with each turn. After a sequence is done playing, we’ll duplicate the sequence array. Then, as the player clicks the lights to reproduce the sequence, we’ll remove one element from the front of the array with each click. If this element of the sequence matches the click, the player has chosen correctly. We’ll also use Timer objects in this game. To play the sequence, a timer will call a func- tion each second to light up a light. Then, a second timer will trigger a function to turn the light off after another half a second passes. Class Definition The MemoryGame.as will contain the code for this game. Remember to link it to the MemoryGame.fla by setting the movie’s Document class in the Property Inspector. To start off the code, we’ll declare the package and the class. We need to import a few Flash classes. Along with the flash.display.* class for showing movie clips, we need the flash.events.* class for mouse clicks, the flash.text.* class for displaying text, and the flash.utils.Timer for using timers. The flash.media.Sound and flash.media.SoundChannel are needed to play the sounds that accompany the lights. The flash.net.URLRequest class is needed to load the sounds from external files: package { import flash.display.*; import flash.events.*; import flash.text.*; import flash.utils.Timer; import flash.media.Sound; import flash.media.SoundChannel; import flash.net.URLRequest; Chapter 4: Brain Games: Memory and Deduction128 NOTE So, how did I know the names of the classes to import at the start of the code? Simple: I looked them up in the Flash help pages. For instance, to find out what I needed for a text field, I looked up TextField and the definition told me right there that it needed flash.text.*. Actually, rather than looking for that in the documentation page, I usually skip right to the bottom of the page and look at a code example. The import command is easy to find this way. The class definition includes many variable declarations. The only constant we’ll use is the number of lights in the game (in this case, five): public class MemoryGame extends Sprite { static const numLights:uint = 5; We’ll have three main arrays: one to hold references to the five light movie clips. Then two will hold the sequence of lights. The playOrder array will grow with each turn. The repeatOrder array will hold a duplicate of the playOrder array when the player repeats the sequence. It will shrink as the player clicks lights and comparisons are made with each light in the sequence: private var lights:Array; // list of light objects private var playOrder:Array; // growing sequence private var repeatOrder:Array; We need two text fields, one to hold a message to the player at the top of the screen, and one to hold the current sequence length at the bottom of the screen: // text message private var textMessage:TextField; private var textScore:TextField; We’ll be using two timers in the game. The first will turn on each light in the sequence while it is playing. The second will be used to turn off the lights a half second later: // timers private var lightTimer:Timer; private var offTimer:Timer; Other variables needed include gameMode, which will store either “play” or “replay” depending on whether the player is watching the sequence, or trying to repeat it. The currentSelection variable will hold a reference to the Lights movie clips. The soundList array will hold references to the five sounds that will play with the lights: var gameMode:String; // play or replay var currentSelection:MovieClip = null; var soundList:Array = new Array(); // hold sounds Memory Game 129 Those are all the variables we need to keep track of. We could have also included con- stants for the positioning of the text and lights, but we’ll hard code them in for the pur- poses of learning how the code works. Setting the Text, Lights, and Sounds The MemoryGame constructor function runs as soon as the class is initialized. We’ll use it to set up the game screen and load the sounds. Figure 4.3 shows the screen at the very start of the game. Chapter 4: Brain Games: Memory and Deduction130 Figure 4.3 The Memory Game screen shows two text fields and five lights. Adding the Text Before we set up either text field, we’ll create a temporary TextFormat object and define how we want the text to look. We’ll use this temporary variable when creating both text fields, and then we’ll no longer need it. For that reason, we don’t need to define the textFormat (note the lowercase t) variable in the main class, only in this function: public function MemoryGame() { // text formating var textFormat = new TextFormat(); textFormat.font = “Arial”; textFormat.size = 24; textFormat.align = “center”; The upper text field, to be named textMessage, will hold a message to the players to tell them whether they should be watching and listening to the sequence, or whether they need to be clicking lights to repeat the sequence. We’ll place it near the top of the screen. It will be 550 pixels wide, the complete width of the screen. Because textFormat.align is set to “center”, and the text field is the width of the screen, the text should be centered on the screen. We also need to set the selectable property of the field to false; otherwise, the cursor will change to a text selection cursor when the player moves the mouse over the field. NOTE Forgetting to set the selectable property of a text field to false is a common mis- take. By default, the selectable property is true, which means the cursor turns to an editing cursor when the player mouses over it. They can select text; but more impor- tant, they cannot easily click objects below the text. Finally, we set the defaultTextFormat to our textFormat object to define the font, size and alignment for the field: // create the upper text field textMessage = new TextField(); textMessage.width = 550; textMessage.y = 110; textMessage.selectable = false; textMessage.defaultTextFormat = textFormat; addChild(textMessage); The second text field displays the length of the current sequence so that the player can gauge his or her progress. It will be toward the bottom of the screen: // create the lower text field textScore = new TextField(); textScore.width = 550; textScore.y = 250; textMessage.selectable = false; textScore.defaultTextFormat = textFormat; addChild(textScore); Loading the Sounds Next, we’ll load the sounds. In Chapter 3, we used sounds that were in the movie’s library. ActionScript 3.0 doesn’t make this a very versatile way to use sound because each sound in the library needs to be referenced as its own object. Therefore, using five sounds, “note1” to “note5”, would require five separate objects, and separate lines of code for each. However, ActionScript 3.0 has a much more robust set of commands for playing exter- nal sound files. We’ll use those for this game. To set this up, we’ll load five sound files, “note1.mp3” to “note5.mp3”, into an array of sounds. Memory Game 131 NOTE Flash insists that external sounds be in MP3 format. The great thing about MP3 is that you can really control the size and quality of a file with your audio editing software. So, you can create small, low-quality sounds when it is appropriate to cut down download time, or large, high-quality sounds when it is needed. // load the sounds soundList = new Array(); for(var i:uint=1;i<=5;i++) { var thisSound:Sound = new Sound(); var req:URLRequest = new URLRequest(“note”+i+”.mp3”); thisSound.load(req); soundList.push(thisSound); } NOTE The “note”+i+”.mp3” inside the URLRequest function constructs a string like “note1.mp3”. The + symbol concatenates strings and other items into a longer string. So, the result is the concatenation of “note” plus the value of the variable i, plus “.mp3”. Adding the Light Movie Clips Now that we have text fields and sounds, the last main thing we need to add to the screen is the lights. We’ll create five Light movie clips and space them so that they are centered. For each Light object, we’ll send the interior lightColors movie clip to a dif- ferent frame so that each movie clip has a different color. As well as adding the movie clips to the stage with addChild, we’ll also add them to the lights array for future reference. The addEventListener enables the movie clips to react to mouse clicks by calling the clickLight function. We’ll also set the buttonMode property so that the cursor changes to a finger when the user rolls over the light: // make lights lights = new Array(); for(i=0;i