<?xml version='1.0' encoding='UTF-8'?><?xml-stylesheet href="http://www.blogger.com/styles/atom.css" type="text/css"?><feed xmlns='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/' xmlns:georss='http://www.georss.org/georss' xmlns:gd='http://schemas.google.com/g/2005' xmlns:thr='http://purl.org/syndication/thread/1.0'><id>tag:blogger.com,1999:blog-8678980820383323367</id><updated>2011-10-22T06:36:55.482-07:00</updated><title type='text'>Flex game development</title><subtitle type='html'>Create your own games with Adobe Flex and Action Script</subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://grandy-flexdev.blogspot.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8678980820383323367/posts/default?max-results=100'/><link rel='alternate' type='text/html' href='http://grandy-flexdev.blogspot.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><author><name>Grandy</name><uri>http://www.blogger.com/profile/13061370372593845090</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='29' height='32' src='http://4.bp.blogspot.com/_4Xe_fkP2r2A/StiN3kMzX2I/AAAAAAAAAAU/wWM-ILREdfw/S220/MySelf.png'/></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>26</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>100</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-8678980820383323367.post-8883873755184030590</id><published>2010-04-29T10:15:00.000-07:00</published><updated>2010-04-30T12:50:40.519-07:00</updated><title type='text'>Keyboard controls</title><content type='html'>&lt;div style="text-align: justify;"&gt;In &lt;a href="http://grandy-flexdev.blogspot.com/2010/03/pause-continue-and-settings.html"&gt;chapter 24&lt;/a&gt; it was explained how to handle keyboard events. In this chapter, we will add new functionality into existing code, that will allow player to control the snake with cursor keys.&lt;br /&gt;&lt;br /&gt;If you wish to find out the difference between controlling the snake with cursor keys or with the mouse, try the final version of the game, embedded bellow.&lt;br /&gt;&lt;div style="text-align: justify;"&gt;&lt;center&gt;&lt;br /&gt;&lt;table border="1"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td align="center"&gt;&lt;embed align="center" height="480" src="http://bgrandovec.hostzi.com/Files/SnakesAdventure.swf" type="application/x-shockwave-flash" width="480"&gt;&lt;/embed&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/center&gt;&lt;/div&gt;&lt;br /&gt;&lt;b&gt;KeyDown&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;In &lt;a href="http://grandy-flexdev.blogspot.com/2010/03/pause-continue-and-settings.html"&gt;chapter 24&lt;/a&gt; we added &lt;b&gt;keyUp&lt;/b&gt; event handler to application, which called functions &lt;b&gt;KeyUp&lt;/b&gt; (SnakesAdventure.as) and &lt;b&gt;KeyUp_Game&lt;/b&gt; (Game.as), whenever any key on the keyboard was released. In case user pressed Escape key, game paused right after the key was released and program switched to GAME_MENU state. &lt;br /&gt;&lt;br /&gt;When the player intends to change direction of the snakes motion, he would expect that direction will change right after the key was pressed, not released. That's why we have to implement new event handler, that will handle &lt;b&gt;keyDown&lt;/b&gt; events.&lt;br /&gt;&lt;br /&gt;New event handler is defined in file SnakesAdventure.mxml inside mx:Canvas element:&lt;/div&gt;&lt;br /&gt;&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace; font-size: x-small;"&gt;keyDown="KeyDown(event)"&lt;/div&gt;&lt;br /&gt;&lt;div style="text-align: justify;"&gt;Whenever any key on the keyboard is pressed, program calls &lt;b&gt;KeyDown&lt;/b&gt; function, implemented in file SnakesAdventure.as:&lt;/div&gt;&lt;br /&gt;&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace; font-size: x-small;"&gt;private function KeyDown(event:KeyboardEvent):void  &lt;br /&gt;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;switch (state)&lt;br /&gt;&amp;nbsp;&amp;nbsp;{  &lt;br /&gt;&amp;nbsp;&amp;nbsp;case GAME:  &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;KeyDown_Game(event);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;break;&lt;br /&gt;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;}&lt;/div&gt;&lt;br /&gt;&lt;div style="text-align: justify;"&gt;We've used the same approach here, that was used in &lt;b&gt;KeyUp&lt;/b&gt;. Whenever the event occurs, the event handling routine executes the appropriate &lt;b&gt;KeyDown_Game&lt;/b&gt;, if the GAME state is active. &lt;b&gt;KeyDown_Game&lt;/b&gt; function can be found in Game.as:&lt;/div&gt;&lt;br /&gt;&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace; font-size: x-small;"&gt;private function KeyDown_Game(event:KeyboardEvent):void &lt;br /&gt;{   &lt;br /&gt;&amp;nbsp;&amp;nbsp;switch (gameState)&lt;br /&gt;&amp;nbsp;&amp;nbsp;{  &lt;br /&gt;&amp;nbsp;&amp;nbsp;case GAME_PLAYED:&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;var direction:int = snake.getDirection(); &lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;switch (event.keyCode)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;case Keyboard.UP:&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if ((direction == Snake.EAST) || (direction == Snake.WEST))&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;snake.setDirection(Snake.NORTH);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;break;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;case Keyboard.DOWN: &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if ((direction == Snake.EAST) || (direction == Snake.WEST))&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;snake.setDirection(Snake.SOUTH);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;break; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;case Keyboard.LEFT: &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if ((direction == Snake.NORTH) || (direction == Snake.SOUTH))&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;snake.setDirection(Snake.WEST);    &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;break; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;case Keyboard.RIGHT:&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if ((direction == Snake.NORTH) || (direction == Snake.SOUTH))&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;snake.setDirection(Snake.EAST);       &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;break;       &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;} &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;break;&lt;br /&gt;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;}&lt;/div&gt;&lt;br /&gt;&lt;div style="text-align: justify;"&gt;When the player presses any key during the game (while GAME_PLAYED state is active), function &lt;b&gt;KeyDown_Game&lt;/b&gt; checks if it was one of cursor keys. If it was, &lt;b&gt;if&lt;/b&gt; statement verifies if direction of motion can be changed to desired direction. For instance, player cannot change direction from north to south by pressing the down key. Only east and west directions are legal in this case.&lt;br /&gt;&lt;br /&gt;If you download project &lt;a href="http://bgrandovec.hostzi.com/Files/SnakesAdventure.zip"&gt;package&lt;/a&gt; of the final version of the Snake's adventure, and open Game.as file, you will see that final version of &lt;b&gt;KeyDown_Game&lt;/b&gt; function is much more complex. This is because in final version of the game, it can be activated by pressing one of the cursor keys.&lt;br /&gt;&lt;br /&gt;If you implemented the similar keyboard event handler in your own game, you most probably noticed one problem, which are related with this new functionality.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Focus&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;When the game is embedded into web page, game panel does not have focus by default, which means the program will not receive events when key is pressed. Game panel is focused whenever user clicks on game panel with the mouse button. This is one of the reasons that something like "Click here..." is displayed at the beginning of almost any Flash game.&lt;br /&gt;&lt;br /&gt;The following situation is much harder to deal with: game panel lost focus while the game is running and again, program stopped receiving key events. Situations like this happen rarely, but when they are, it can be quite frustrating for the player. One solution for situations like this, is to pause the game, and display the banner that says, for example, "Game paused, click here when you are ready".&lt;br /&gt;&lt;br /&gt;All you have to do, is to define two event handlers in the root element (&lt;b&gt;mx:Application&lt;/b&gt;) of mxml file. This is the example from SnakesAdventure.mxml:&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace; font-size: x-small;"&gt;&amp;lt;mx:Application xmlns:mx="http://www.adobe.com/2006/mxml"&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;name="SnakesAdventure"&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;backgroundColor="#000000"&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;horizontalAlign="center"&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;creationComplete="Init();"&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;enterFrame="UpdateFrame();"    &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;activate="Activated(event);"&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;deactivate="Deactivated(event);"&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;paddingLeft="0"&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;paddingTop="0"&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;paddingBottom="0"&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;paddingRight="0"&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;width="480" height="480"&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;preloader="Classes.PreLoader"&amp;gt;&lt;br /&gt;...&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;div style="text-align: justify;"&gt;Attribute &lt;b&gt;deactivate&lt;/b&gt; creates new event handler, that executes &lt;b&gt;Deactivated&lt;/b&gt; function. &lt;b&gt;deactivate&lt;/b&gt; events occur whenever player clicks outside the game panel, browser is minimized, new window or tab becomes active... Attribute &lt;b&gt;activate&lt;/b&gt; creates event handler, that executes &lt;b&gt;Activated&lt;/b&gt; function. Event is dispatched when application becomes active and has focus. You can find example of both functions in file SnakeAdventures.as.&lt;br /&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8678980820383323367-8883873755184030590?l=grandy-flexdev.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://grandy-flexdev.blogspot.com/feeds/8883873755184030590/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://grandy-flexdev.blogspot.com/2010/04/keyboard-controls.html#comment-form' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8678980820383323367/posts/default/8883873755184030590'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8678980820383323367/posts/default/8883873755184030590'/><link rel='alternate' type='text/html' href='http://grandy-flexdev.blogspot.com/2010/04/keyboard-controls.html' title='Keyboard controls'/><author><name>Grandy</name><uri>http://www.blogger.com/profile/13061370372593845090</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='29' height='32' src='http://4.bp.blogspot.com/_4Xe_fkP2r2A/StiN3kMzX2I/AAAAAAAAAAU/wWM-ILREdfw/S220/MySelf.png'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8678980820383323367.post-5757223196904360448</id><published>2010-04-28T11:01:00.000-07:00</published><updated>2010-04-30T11:39:59.803-07:00</updated><title type='text'>Custom progress bar</title><content type='html'>&lt;div style="text-align: justify;"&gt;Previous 24 chapters teaches you, how to make your own game with Flex. In the following few chapters I will focus mostly on the alternatives, that should considered, before you submit or publish your own product. I call them alternatives, because there are some disadvantages, you should consider, before you implement them. Of course both advantages and disadvantages will be mentioned in the tutorial.&lt;br /&gt;&lt;br /&gt;&lt;div style="text-align: justify;"&gt;&lt;center&gt;&lt;br /&gt;&lt;table border="1"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td align="center"&gt;&lt;embed align="center" height="480" src="http://bgrandovec.hostzi.com/Files/SnakesAdventure.swf" type="application/x-shockwave-flash" width="480"&gt;&lt;/embed&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/center&gt;&lt;/div&gt;&lt;br /&gt;In &lt;a href="http://grandy-flexdev.blogspot.com/2010/01/embedding-into-web-page.html"&gt;chapter 10&lt;/a&gt; it was explained, how to embed SWF file into the HTML web page. Now let's presume you have made a web page where you have publish the demo of your game. Everything works fine, even the progress bar is displayed, while the game is downloading. This is the default progress bar that appears in many Flex applications. Player will most probably see it only the first time he/she enters the web page. The next time, demo will load immediately, because it was stored on the local file system, after it was downloaded for the first time.&lt;br /&gt;&lt;br /&gt;You may be asking, why bother implementing custom progress bar, that will be visible only for few seconds and will not affect the players experience at all. Well, the best answer, I can give you, is: because you can. Snake's Adventure is my third game made with Flex, and I got a little tired of watching the same progress bar, I have also seen in numerous other games and demos. I just had to do something about it.&lt;br /&gt;&lt;br /&gt;I hope that you have noticed, how the new progress bar in game, embedded above, works. If you did not pay attention before, you can reload the page and you will most probably see the progress bar for one or two seconds, because the SWF file is already cached. If you wish to see the slower version (depends on the bandwidth of your internet connection) you can clear the browsers cache or open this page in different browser. You can also visit &lt;a href="http://bgrandovec.hostzi.com/Content/Play_SnakesAdventure.htm"&gt;Snake's Adventure official web page&lt;/a&gt; on my website.&lt;br /&gt;&lt;br /&gt;Anyway, let's focus on implementation of the custom progress bar. Custom progress bar has to be implemented in its own class. Class and all embedded resources, that are required to display the progress bar, are stored at the beginning of SWF file. Until this part of SWF file is downloaded, area taken by embedded file in the web page, remains blank. It is wise to keep the size of embedded resources at minumum (use JPEG format for background image and please, do not try to play mp3 files, while the game is downloading).&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Application preloader attribute&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;Unless it is not defined, that custom progress bar should be displayed during download, default progress bar will be displayed. Inside the main source file (.mxml) we have to define, which class contains the implementation of the custom progress bar. &lt;b&gt;preloader&lt;/b&gt; attribute inside mx:Application element at the top of SnakesAdventure.mxml, defines the class:&lt;/div&gt;&lt;br /&gt;&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace; font-size: x-small;"&gt;preloader="Classes.PreLoader"&lt;/div&gt;&lt;br /&gt;&lt;div style="text-align: justify;"&gt;&lt;b&gt;class PreLoader&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;Implementation of custom progress bar can be found in PreLoader.as file, which is located inside Classes folder. You can view complete file with additional comments, if you download the project &lt;a href="http://bgrandovec.hostzi.com/Files/SnakesAdventure.zip"&gt;package&lt;/a&gt; of the final version of the Snake's adventure. This is the short (but fully functional) version of PreLoader.as:&lt;/div&gt;&lt;br /&gt;&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace; font-size: x-small;"&gt;package Classes &lt;br /&gt;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;import flash.geom.*;&lt;br /&gt;&amp;nbsp;&amp;nbsp;import flash.display.*;&lt;br /&gt;&amp;nbsp;&amp;nbsp;import flash.utils.*;&lt;br /&gt;&amp;nbsp;&amp;nbsp;import flash.events.*;&lt;br /&gt;&amp;nbsp;&amp;nbsp;import flash.net.*;&lt;br /&gt;&amp;nbsp;&amp;nbsp;import mx.preloaders.*; &lt;br /&gt;&amp;nbsp;&amp;nbsp;import mx.events.*;&lt;br /&gt;&amp;nbsp;&amp;nbsp;import mx.controls.*;&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;public class PreLoader extends Sprite implements IPreloaderDisplay&lt;br /&gt;&amp;nbsp;&amp;nbsp;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;protected var _msecMinimumDuration:Number = 1000;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;protected var _IsInitComplete:Boolean = false;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;protected var _timer:Timer;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;protected var _bytesLoaded:uint = 0;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;protected var _bytesExpected:uint = 1;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;protected var _fractionLoaded:Number = 0;&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;public function PreLoader()&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;super();&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;private var screenBuffer:BitmapData = null;&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;virtual protected function draw():void&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{          &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;screenBuffer.copyPixels(titleScreenBitmap,&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;new Rectangle(0, 0, 480, 480),&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;new Point(0,0));  &lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;screenBuffer.copyPixels(progressBitmap,&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;new Rectangle(21, 8, 286 * _fractionLoaded, 36),&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;new Point(96,305));                               &lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;screenBuffer.copyPixels(progressBitmap,&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;new Rectangle(0, 50, 330, 70),&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;new Point(75,290)); &lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;graphics.clear();    &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;graphics.beginBitmapFill(screenBuffer, null, false, false);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;graphics.drawRect(0, 0, 480, 480);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;graphics.endFill();   &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;[Embed(source="../Images/TitleScreen.jpg")] private var titleScreenImg:Class;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;private var titleScreenBitmap:BitmapData = null;     &lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;[Embed(source="../Images/ProgressBar.png")] private var progressBarImg:Class;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;private var progressBitmap:BitmapData = null;  &lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;virtual public function initialize():void&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;screenBuffer = new BitmapData(480, 480, false, 0x00000000);    &lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;titleScreenBitmap = new BitmapData(480,480,true);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;titleScreenBitmap.draw(new titleScreenImg()); &lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;progressBitmap = new BitmapData(330,120,true,0x00000000);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;progressBitmap.draw(new progressBarImg()); &lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;_timer = new Timer(1);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;_timer.addEventListener(TimerEvent.TIMER, timerHandler);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;_timer.start();&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;protected var _preloader:Sprite;&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;virtual public function set preloader(value:Sprite):void&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;_preloader = value;&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;value.addEventListener(ProgressEvent.PROGRESS, progressHandler);    &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;value.addEventListener(Event.COMPLETE, completeHandler);&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;value.addEventListener(FlexEvent.INIT_PROGRESS, initProgressHandler);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;value.addEventListener(FlexEvent.INIT_COMPLETE, initCompleteHandler);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;virtual public function set backgroundAlpha(alpha:Number):void{}&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;virtual public function get backgroundAlpha():Number { return 1; }&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;protected var _backgroundColor:uint = 0xffffffff;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;virtual public function set backgroundColor(color:uint):void { _backgroundColor = color; }&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;virtual public function get backgroundColor():uint { return _backgroundColor; }&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;virtual public function set backgroundImage(image:Object):void {}&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;virtual public function get backgroundImage():Object { return null; }&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;virtual public function set backgroundSize(size:String):void {}&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;virtual public function get backgroundSize():String { return "auto"; }&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;protected var _stageHeight:Number = 480;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;virtual public function set stageHeight(height:Number):void { _stageHeight = height; }&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;virtual public function get stageHeight():Number { return _stageHeight; }&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;protected var _stageWidth:Number = 480;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;virtual public function set stageWidth(width:Number):void { _stageWidth = width; }&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;virtual public function get stageWidth():Number { return _stageWidth; }&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;virtual protected function progressHandler(event:ProgressEvent):void&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;_bytesLoaded = event.bytesLoaded;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;_bytesExpected = event.bytesTotal;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;_fractionLoaded = Number(_bytesLoaded) / Number(_bytesExpected);&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;draw();&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;virtual protected function completeHandler(event:Event):void&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;virtual protected function initProgressHandler(event:Event):void&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;draw();&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;virtual protected function initCompleteHandler(event:Event):void&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;_IsInitComplete = true;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;virtual protected function timerHandler(event:Event):void&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if (_IsInitComplete &amp;amp;&amp;amp; getTimer() &amp;gt; _msecMinimumDuration)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{    &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;_timer.stop();&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;dispatchEvent(new Event(Event.COMPLETE));&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;else&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;draw();&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}  &lt;br /&gt;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;}&lt;/div&gt;&lt;br /&gt;&lt;div style="text-align: justify;"&gt;Even without comments, &lt;b&gt;PreLoader&lt;/b&gt; class contains a lot of code. There are only few parts, that you need to understand, if you wish to create a different version of progress bar. &lt;br /&gt;&lt;br /&gt;&lt;b&gt;Embed&lt;/b&gt; statements take care of compiling all required resources (images) into SWF file.&lt;br /&gt;&lt;br /&gt;Function &lt;b&gt;initialize&lt;/b&gt; is executed right after class and resources are download. This is the perfect place to create screen buffer and all &lt;b&gt;BitmapData&lt;/b&gt; objects with copies of embedded images. At the end, we create a Timer object, that will trigger every millisecond (only in theory, in practice it will trigger approximately every ten milliseconds) and execute &lt;b&gt;timerHandler&lt;/b&gt; function, implemented at the bottom of the class.&lt;br /&gt;&lt;br /&gt;In &lt;b&gt;preloader&lt;/b&gt; function we assigned four event listeners:&lt;br /&gt;- ProgressEvent.PROGRESS will execute &lt;b&gt;progressHandler&lt;/b&gt; function from time to time as the SWF is downloading. Event has two properties &lt;b&gt;bytesLoaded&lt;/b&gt; (size of SWF file, that has already been downloaded) and &lt;b&gt;bytesTotal&lt;/b&gt; (total size of SWF file)&lt;br /&gt;- Event.COMPLETE will execute &lt;b&gt;completeHandler&lt;/b&gt; function, when download is finished&lt;br /&gt;- FlexEvent.INIT_PROGRESS will execute &lt;b&gt;initProgressHandler&lt;/b&gt; function from time to time as the initialization continues&lt;br /&gt;- FlexEvent.INIT_COMPLETE will execute &lt;b&gt;initCompleteHandler&lt;/b&gt; function when initialization is complete.&lt;br /&gt;&lt;br /&gt;Function &lt;b&gt;draw&lt;/b&gt; will be called frequently from &lt;b&gt;progressHandler&lt;/b&gt; and &lt;b&gt;timerHandler&lt;/b&gt; functions. Whenever &lt;b&gt;draw&lt;/b&gt; is called, background image (TitleScreen.jpg) is copied into screen buffer, first. After that, fraction of upper portion of progress bar image (ProgressBar.png) is copied. Lower portion of progress bar image is copied over the progress bar. This is the reason that progress bar is maybe not so obvious as it should be, but you can fix this in your own version.&lt;/div&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://3.bp.blogspot.com/_4Xe_fkP2r2A/S9m3FC6fmVI/AAAAAAAAAEA/yG8RXPmNMVI/s1600/ProgressBar.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://3.bp.blogspot.com/_4Xe_fkP2r2A/S9m3FC6fmVI/AAAAAAAAAEA/yG8RXPmNMVI/s320/ProgressBar.png" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;&lt;div style="text-align: justify;"&gt;Finally, the content of screen buffer is copied into the &lt;b&gt;graphics&lt;/b&gt; object of the container, that takes care of displaying progress bar on the screen.&lt;br /&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8678980820383323367-5757223196904360448?l=grandy-flexdev.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://grandy-flexdev.blogspot.com/feeds/5757223196904360448/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://grandy-flexdev.blogspot.com/2010/04/custom-progress-bar.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8678980820383323367/posts/default/5757223196904360448'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8678980820383323367/posts/default/5757223196904360448'/><link rel='alternate' type='text/html' href='http://grandy-flexdev.blogspot.com/2010/04/custom-progress-bar.html' title='Custom progress bar'/><author><name>Grandy</name><uri>http://www.blogger.com/profile/13061370372593845090</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='29' height='32' src='http://4.bp.blogspot.com/_4Xe_fkP2r2A/StiN3kMzX2I/AAAAAAAAAAU/wWM-ILREdfw/S220/MySelf.png'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://3.bp.blogspot.com/_4Xe_fkP2r2A/S9m3FC6fmVI/AAAAAAAAAEA/yG8RXPmNMVI/s72-c/ProgressBar.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8678980820383323367.post-3326658245316993632</id><published>2010-03-21T08:45:00.001-07:00</published><updated>2010-04-30T11:13:02.835-07:00</updated><title type='text'>Pause, continue and settings</title><content type='html'>&lt;div style="text-align: justify;"&gt;There is not much more to say about Flex game development, at least from the technical point of view. If you followed this tutorial from the beginning, you should have enough knowledge to make a great game. You just need a good idea and will to realize it.&lt;br /&gt;&lt;br /&gt;As far as programming is concerned, Snake's Adventure is almost complete. But overall, it is still far from finished. It requires more content, graphics, sound effects and music. &lt;br /&gt;&lt;br /&gt;There are still few things to do, before this tutorial is complete. At the beginning of this tutorial, we were working on game menu. While we were exploring the basics of graphics and event handling, we implemented &lt;b&gt;new game&lt;/b&gt; option in the game menu, but &lt;b&gt;continue&lt;/b&gt; and &lt;b&gt;settings&lt;/b&gt; options still remain unimplemented.&lt;br /&gt;&lt;br /&gt;&lt;div style="text-align: justify;"&gt;&lt;center&gt;&lt;br /&gt;&lt;table border="1"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td align="center"&gt;&lt;embed align="center" height="480" src="http://bgrandovec.hostzi.com/Files/SnakesAdventure_P24.swf" type="application/x-shockwave-flash" width="480"&gt;&lt;/embed&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/center&gt;&lt;/div&gt;&lt;br /&gt;&lt;b&gt;Pausing the game&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;When the player has to pause the game for a moment, he will most probably press Escape or Space key on the keyboard. Our program is currently able to detect when mouse key is pressed or released. If we wish it would be able to detect key events, we have to implement Keyboard event handler. Piece of cake...&lt;br /&gt;&lt;br /&gt;Open file SnakesAdventure.mxml and add new event handler to mx:Canvas element:&lt;/div&gt;&lt;br /&gt;&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace; font-size: x-small;"&gt;keyUp="KeyUp(event)"&lt;/div&gt;&lt;br /&gt;&lt;div style="text-align: justify;"&gt;Whenever any key on the keyboard is released, program executes &lt;b&gt;KeyUp&lt;/b&gt; function, implemented in file SnakesAdventure.as:&lt;/div&gt;&lt;br /&gt;&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace; font-size: x-small;"&gt;private function KeyUp(event:KeyboardEvent):void  &lt;br /&gt;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;switch (state)&lt;br /&gt;&amp;nbsp;&amp;nbsp;{  &lt;br /&gt;&amp;nbsp;&amp;nbsp;case GAME:  &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;KeyUp_Game(event);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;break;&lt;br /&gt;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;}&lt;/div&gt;&lt;br /&gt;&lt;div style="text-align: justify;"&gt;We've used the same approach here, that was used in all other event handlers. Whenever the event occurs, the event handling routine executes the appropriate function, according to value of &lt;b&gt;state&lt;/b&gt; variable (active state). &lt;b&gt;KeyUp_Game&lt;/b&gt; function belongs at the end of the file Game.as:&lt;/div&gt;&lt;br /&gt;&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace; font-size: x-small;"&gt;private function KeyUp_Game(event:KeyboardEvent):void  &lt;br /&gt;{ &lt;br /&gt;&amp;nbsp;&amp;nbsp;if (event.keyCode == Keyboard.ESCAPE)&lt;br /&gt;&amp;nbsp;&amp;nbsp;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;saveState = gameState;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;ChangeState_Game(GAME_FADE_OUT);    &lt;br /&gt;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;}&lt;/div&gt;&lt;br /&gt;&lt;div style="text-align: justify;"&gt;&lt;b&gt;KeyboardEvent&lt;/b&gt; has many properties, one of them is &lt;b&gt;keyCode&lt;/b&gt; - the index of key that caused the event. For example, ESCAPE key has index 27, SPACE key has index 32... but I prefer using public constants, defined in the &lt;a href="http://livedocs.adobe.com/flex/3/langref/flash/ui/Keyboard.html"&gt;Keyboard class&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;When ESCAPE key is pressed, active game state (&lt;b&gt;gameState&lt;/b&gt;) is stored into &lt;b&gt;saveState&lt;/b&gt; variable and GAME_FADE_OUT state becomes active. Add definition of &lt;b&gt;saveState&lt;/b&gt; variable to other definitions, at the beginning of the file.&lt;/div&gt;&lt;br /&gt;&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace; font-size: x-small;"&gt;private var saveState:int = 0;&lt;/div&gt;&lt;br /&gt;&lt;div style="text-align: justify;"&gt;Value of variable needs to be reseted, whenever the game begins. Add this statement into &lt;b&gt;New_Game&lt;/b&gt; function:&lt;/div&gt;&lt;br /&gt;&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace; font-size: x-small;"&gt;saveState = 0;&lt;/div&gt;&lt;br /&gt;&lt;div style="text-align: justify;"&gt;In the current version, &lt;b&gt;Reset_Game&lt;/b&gt; function is executed, after the game state GAME_FADE_OUT ends. Now, the program needs to distinguish whether the screen faded out because the player made the mistake or because the ESCAPE key was pressed. We can use &lt;b&gt;saveState&lt;/b&gt; variable for this. In the &lt;b&gt;Draw_Game&lt;/b&gt; function, replace the GAME_FADE_OUT case in &lt;b&gt;switch&lt;/b&gt; statement, with this version:&lt;/div&gt;&lt;br /&gt;&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace; font-size: x-small;"&gt;case GAME_FADE_OUT: &lt;br /&gt;&amp;nbsp;&amp;nbsp;Apply_FadeEffect(gameTime); &lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;if (gameTime &amp;gt;= 1)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if (saveState == 0)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Restart_Game();  &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;else&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;state = GAME_MENU;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;ChangeState_GameMenu(TITLE_SHOW);      &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&amp;nbsp;&amp;nbsp;break;&lt;/div&gt;&lt;br /&gt;&lt;div style="text-align: justify;"&gt;If the value of &lt;b&gt;saveState&lt;/b&gt; variable is zero, function &lt;b&gt;Reset_Game&lt;/b&gt; is executed, otherwise active state of the program is changed to GAME_MENU.&lt;br /&gt;&lt;br /&gt;Recompile and run the program and press ESCAPE key, while the game is running. Key should trigger screen fade-out event and after few seconds game menu should become visible. But it doesn't, because the game panel does not have the focus. Adding this statement at the end of &lt;b&gt;UpdateFrame&lt;/b&gt; function in file SnakesAdventure.as, should solve the problem:&lt;/div&gt;&lt;br /&gt;&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace; font-size: x-small;"&gt;gamePanel.setFocus(); &lt;/div&gt;&lt;br /&gt;&lt;div style="text-align: justify;"&gt;&lt;b&gt;Continue the game&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;To be honest, the functionality that we implemented so far, does not pause the game. The player cannot return into the game, because &lt;b&gt;continue&lt;/b&gt; option is disabled. We will make some changes in file GameMenu.as, that will enable &lt;b&gt;continue&lt;/b&gt; option, when value of &lt;b&gt;saveState&lt;/b&gt; variable is set (not zero).&lt;br /&gt;&lt;br /&gt;In &lt;b&gt;Draw_GameMenu&lt;/b&gt; function, change the statement:&lt;/div&gt;&lt;br /&gt;&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace; font-size: x-small;"&gt;if (i == OPTION_CONTINUE)&lt;br /&gt;&amp;nbsp;&amp;nbsp;srcY = 0;&lt;/div&gt;&lt;br /&gt;&lt;div style="text-align: justify;"&gt;to&lt;/div&gt;&lt;br /&gt;&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace; font-size: x-small;"&gt;if ((i == OPTION_CONTINUE) &amp;amp;&amp;amp; (saveState == 0))&lt;br /&gt;&amp;nbsp;&amp;nbsp;srcY = 0;&lt;/div&gt;&lt;br /&gt;&lt;div style="text-align: justify;"&gt;In the &lt;b&gt;switch&lt;/b&gt; statement, replace:&lt;/div&gt;&lt;br /&gt;&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace; font-size: x-small;"&gt;case OPTION_CONTINUE:&lt;br /&gt;&amp;nbsp;&amp;nbsp;srcY = 100;&lt;br /&gt;&amp;nbsp;&amp;nbsp;break;&lt;/div&gt;&lt;br /&gt;&lt;div style="text-align: justify;"&gt;with&lt;/div&gt;&lt;br /&gt;&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace; font-size: x-small;"&gt;case OPTION_CONTINUE:&lt;br /&gt;&amp;nbsp;&amp;nbsp;srcY = saveState != 0 ? 50 : 100;&lt;br /&gt;&amp;nbsp;&amp;nbsp;break;&lt;/div&gt;&lt;br /&gt;&lt;div style="text-align: justify;"&gt;From now on, &lt;b&gt;continue&lt;/b&gt; option will be displayed as enabled, whenever the "paused" mode is active. To activate the option in the "paused" mode, we have to make a change in function &lt;b&gt;MouseDown_GameMenu&lt;/b&gt;. Replace the second &lt;b&gt;if&lt;/b&gt; statement:&lt;/div&gt;&lt;br /&gt;&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace; font-size: x-small;"&gt;if (i != OPTION_CONTINUE)&lt;/div&gt;&lt;br /&gt;&lt;div style="text-align: justify;"&gt;with&lt;/div&gt;&lt;br /&gt;&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace; font-size: x-small;"&gt;if ((i != OPTION_CONTINUE) || (saveState != 0))&lt;/div&gt;&lt;br /&gt;&lt;div style="text-align: justify;"&gt;When the "paused" mode is active, the &lt;b&gt;continue&lt;/b&gt; option looks active and responds to mouse events. We just have to implement the transition from game menu, back into the game.&lt;br /&gt;&lt;br /&gt;Add new case into inner &lt;b&gt;switch&lt;/b&gt; statement in &lt;b&gt;MouseUp_GameMenu&lt;/b&gt; function:&lt;/div&gt;&lt;br /&gt;&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace; font-size: x-small;"&gt;case OPTION_CONTINUE:    &lt;br /&gt;&amp;nbsp;&amp;nbsp;selectedOption = OPTION_CONTINUE;      &lt;br /&gt;&amp;nbsp;&amp;nbsp;ChangeState_GameMenu(GAMEOPTIONS_OUT);      &lt;br /&gt;&amp;nbsp;&amp;nbsp;break;&lt;/div&gt;&lt;br /&gt;&lt;div style="text-align: justify;"&gt;This will activate GAMEOPTIONS_OUT game menu state, after mouse button is released. Eventually, game menu options will disappear and title screen will fade out. At this point we have to reactive GAME program state in &lt;b&gt;Draw_GameMenu&lt;/b&gt; function. Add new case into &lt;b&gt;switch&lt;/b&gt; statement under case TITLE_HIDE block:&lt;/div&gt;&lt;br /&gt;&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace; font-size: x-small;"&gt;case OPTION_CONTINUE:&lt;br /&gt;&amp;nbsp;&amp;nbsp;state = GAME;&lt;br /&gt;&amp;nbsp;&amp;nbsp;ChangeState_Game(GAME_CONTINUE);&lt;br /&gt;&amp;nbsp;&amp;nbsp;break; &lt;/div&gt;&lt;br /&gt;&lt;div style="text-align: justify;"&gt;GAME_CONTINUE game state is new in the project. During this state, game screen will fade in and after one second, game state index, that was previously stored into &lt;b&gt;saveState&lt;/b&gt; variable, will become active again.&lt;br /&gt;&lt;br /&gt;Add the definition of constant GAME_CONTINUE, at the beginning of Game.as file.&lt;/div&gt;&lt;br /&gt;&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace; font-size: x-small;"&gt;private static const GAME_CONTINUE:int       = 8;&lt;/div&gt;&lt;br /&gt;&lt;div style="text-align: justify;"&gt;and new case into &lt;b&gt;switch&lt;/b&gt; statement inside &lt;b&gt;Draw_Game&lt;/b&gt; function:&lt;/div&gt;&lt;br /&gt;&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace; font-size: x-small;"&gt;case GAME_CONTINUE:   &lt;br /&gt;&amp;nbsp;&amp;nbsp;Apply_FadeEffect(1 - gameTime); &lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;if (gameTime &amp;gt;= 1)&lt;br /&gt;&amp;nbsp;&amp;nbsp;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;ChangeState_Game(saveState);       &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;saveState = 0;&lt;br /&gt;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&amp;nbsp;&amp;nbsp;break; &lt;/div&gt;&lt;br /&gt;&lt;div style="text-align: justify;"&gt;&lt;b&gt;Settings&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;This is the last option in the game menu that still remain unimplemented. In this section we will enable the option to display settings menu with sound and music volume control. Menu will also feature option that will close settings menu and reactivate game menu.&lt;br /&gt;&lt;br /&gt;Settings menu functionality will be implemented is implemented in separate file - SettingsMenu.as. This file is part of project &lt;a href="http://bgrandovec.hostzi.com/Files/SnakesAdventure_P24.zip"&gt;package&lt;/a&gt; for this chapter, the content of the file will be explained later. For now, just add new include statement at the beginning of SnakesAdventure.as:&lt;/div&gt;&lt;br /&gt;&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace; font-size: x-small;"&gt;include "SettingsMenu.as";&lt;/div&gt;&lt;br /&gt;&lt;div style="text-align: justify;"&gt;Implementation of settings menu will be similar to implementation of game menu. SETTINGS_MENU constant value will represent 'settings menu' state of the program. Add the definition to definitions of other program state constants:&lt;/div&gt;&lt;br /&gt;&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace; font-size: x-small;"&gt;private static const SETTINGS_MENU:int    = 2;&lt;/div&gt;&lt;br /&gt;&lt;div style="text-align: justify;"&gt;Value two is already used in GAME constant, that is why you have to change its value to 3. Before we focus on the implementaton of settings menu, we have to call appropriate functions in event handling routines, the same way we did for all other states.&lt;br /&gt;&lt;br /&gt;We have to add new cases into &lt;b&gt;switch&lt;/b&gt; statement inside:&lt;br /&gt;- &lt;b&gt;Draw&lt;/b&gt; function:&lt;/div&gt;&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace; font-size: x-small;"&gt;&amp;nbsp;&amp;nbsp;case SETTINGS_MENU:&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Draw_SettingsMenu(ellapsedTime);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;break;  &lt;/div&gt;&lt;br /&gt;&lt;div style="text-align: justify;"&gt;- &lt;b&gt;MouseDown&lt;/b&gt; function:&lt;/div&gt;&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace; font-size: x-small;"&gt;&amp;nbsp;&amp;nbsp;case SETTINGS_MENU:&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;MouseDown_SettingsMenu(event);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;break;  &lt;/div&gt;&lt;br /&gt;&lt;div style="text-align: justify;"&gt;- &lt;b&gt;MouseUp&lt;/b&gt; function:&lt;/div&gt;&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace; font-size: x-small;"&gt;&amp;nbsp;&amp;nbsp;case SETTINGS_MENU:&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;MouseUp_SettingsMenu(event);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;break;  &lt;/div&gt;&lt;br /&gt;&lt;div style="text-align: justify;"&gt;- &lt;b&gt;MouseMoved&lt;/b&gt; function:&lt;/div&gt;&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace; font-size: x-small;"&gt;&amp;nbsp;&amp;nbsp;case SETTINGS_MENU:&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;MouseMoved_SettingsMenu(event);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;break;  &lt;/div&gt;&lt;br /&gt;&lt;div style="text-align: justify;"&gt;All four functions are implemented in SettingsMenu.as. The file contains almost two hundred lines of code, that is not much different from the code in GameMenu file. I will display and explain all the code in this tutorial, I will rather focus on important parts.&lt;br /&gt;&lt;br /&gt;Settings menu contains its own state automaton with three possible sub-states: &lt;br /&gt;- SETTINGSOPTIONS_IN becomes active first and it last only one second. Within this second, all three options move from the left edge of the frame to the centre.&lt;br /&gt;- while SETTINGSOPTIONS_WAIT state is active, player can change the sound and music volume. When 'Return' option is selected, it activates&lt;br /&gt;- SETTINGSOPTIONS_OUT state and all three options move from the centre of the frame to the right edge, until they disappear. At this moment, program activates GAME_MENU state and eventually, game menu options become visible again.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Draw_SettingsOptions&lt;/b&gt; takes care of displaying settings menu options. It is not much different from &lt;b&gt;Draw_GameMenu&lt;/b&gt;, even the same algorithm is used to shift the options to the centre and away from the centre of the frame.&lt;br /&gt;&lt;br /&gt;Image file SettingsOptions.png contains option labels and two volume bars. This image is part of the project &lt;a href="http://bgrandovec.hostzi.com/Files/SnakesAdventure_P24.zip"&gt;package&lt;/a&gt; and has to be embedded into the project, before it can be used (Images.as).&lt;br /&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://1.bp.blogspot.com/_4Xe_fkP2r2A/S6e6C0T8v0I/AAAAAAAAAD4/2_TgXIJ4RI0/s1600-h/SettingsOptions.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://1.bp.blogspot.com/_4Xe_fkP2r2A/S6e6C0T8v0I/AAAAAAAAAD4/2_TgXIJ4RI0/s320/SettingsOptions.png" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;Options and labels inside each option are drawn the same way, that was used to draw game menu options. The only important difference is the code, that displays volume control at the bottom of sound and music volume option. This code can be found at the end of &lt;b&gt;Draw_SettingsOptions&lt;/b&gt; function:&lt;/div&gt;&lt;br /&gt;&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace; font-size: x-small;"&gt;switch (i)&lt;br /&gt;{&lt;br /&gt;case OPTION_SOUNDVOLUME:&lt;br /&gt;&amp;nbsp;&amp;nbsp;screenBuffer.copyPixels(settingsOptionsBitmap,&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;new Rectangle(0, 150, 260, 25),&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;new Point(110 + srcX,277 + i * 70));  &lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;screenBuffer.copyPixels(settingsOptionsBitmap,&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;new Rectangle(24, 183, int(212 * soundVolume), 7),&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;new Point(134 + srcX,285 + i * 70));                               &lt;br /&gt;&amp;nbsp;&amp;nbsp;break;&lt;br /&gt;case OPTION_MUSICVOLUME:&lt;br /&gt;&amp;nbsp;&amp;nbsp;screenBuffer.copyPixels(settingsOptionsBitmap,&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;new Rectangle(0, 150, 260, 25),&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;new Point(110 + srcX,277 + i * 70)); &lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;screenBuffer.copyPixels(settingsOptionsBitmap,&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;new Rectangle(24, 183, int(212 * musicVolume), 7),&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;new Point(134 + srcX,285 + i * 70));                                 &lt;br /&gt;&amp;nbsp;&amp;nbsp;break;&lt;br /&gt;}  &lt;/div&gt;&lt;br /&gt;&lt;div style="text-align: justify;"&gt;The same approach is used to draw both controls, but different variables are used to display the volume bar and they are displayed in different locations, of course. Variable &lt;b&gt;soundVolume&lt;/b&gt; was introduced in &lt;a href="http://grandy-flexdev.blogspot.com/2010/01/playing-sound-effects.html"&gt;chapter 12 - Playing sound effects&lt;/a&gt; and it is declared in file Sounds.as. Variable &lt;b&gt;musicVolume&lt;/b&gt; is the copy of this variable, and it contains the value that will be used to control the volume of music played.&lt;br /&gt;&lt;br /&gt;The complete image, that represents the empty bar, is copied into the screen buffer first. Afterwards, the image of blue bar is copied into the screen buffer. The portion of image, that is used in the process, is calculated from value of &lt;b&gt;soundVolume&lt;/b&gt; or &lt;b&gt;musicVolume&lt;/b&gt; variable. Value of both variables can range from 0.0 to 1.0, value is multiplied by 212 (the length of the bar image) and calculated value defines the width of the source image that is copied into screen buffer.&lt;br /&gt;&lt;br /&gt;Whenever the player clicks inside the sound/music volume control, the bar in the control should change its size and volume of sound or music should change accordingly. &lt;b&gt;MouseDown_SettingsMenu&lt;/b&gt; function takes care of this:&lt;/div&gt;&lt;br /&gt;&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace; font-size: x-small;"&gt;private function MouseDown_SettingsMenu(event:MouseEvent):void  &lt;br /&gt;{ &lt;br /&gt;&amp;nbsp;&amp;nbsp;var mx:int = event.localX;&lt;br /&gt;&amp;nbsp;&amp;nbsp;var my:int = event.localY;&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;if (settingsMenuState == SETTINGSOPTIONS_WAIT)&lt;br /&gt;&amp;nbsp;&amp;nbsp;{ &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if ((mx &amp;gt;= 130) &amp;amp;&amp;amp; (mx &amp;lt;= 341) &amp;amp;&amp;amp; (my &amp;gt;= 283) &amp;amp;&amp;amp; (my &amp;lt;= 293))&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;soundVolume = (mx - 130) / 211;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;StoreData(SOUND_VOLUME);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;PlaySound(OPTIONSELECTED_SOUND);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if ((mx &amp;gt;= 130) &amp;amp;&amp;amp; (mx &amp;lt;= 341) &amp;amp;&amp;amp; (my &amp;gt;= 353) &amp;amp;&amp;amp; (my &amp;lt;= 363))&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;musicVolume = (mx - 130) / 211;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;StoreData(MUSIC_VOLUME);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;PlaySound(OPTIONSELECTED_SOUND);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if ((mx &amp;gt;= 110) &amp;amp;&amp;amp; (mx &amp;lt; 370) &amp;amp;&amp;amp; (my &amp;gt;= 390) &amp;amp;&amp;amp; (my &amp;lt; 440))&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;pressedOption = OPTION_EXIT;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;PlaySound(OPTIONSELECTED_SOUND);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;}  &lt;/div&gt;&lt;br /&gt;&lt;div style="text-align: justify;"&gt;When mouse button is pressed and SETTINGSOPTIONS_WAIT state is active, function performs three checks. First it checks, if mouse cursor is positioned inside sound volume bar. If it is, value of &lt;b&gt;soundVolume&lt;/b&gt; variable is calculated from horizontal position of the left edge of bar, mouse cursor position and bar length. New value of &lt;b&gt;soundVolume&lt;/b&gt; variable is stored into SharedObject, the same way we stored highest score in &lt;a href="http://grandy-flexdev.blogspot.com/2010/03/scoring-points.html"&gt;chapter 21&lt;/a&gt;. Second check takes care of music volume control and works the same way. Finally, the function checks if mouse cursor is inside "Return" option and if it is, option index is stores into &lt;b&gt;pressedOption&lt;/b&gt; variable. Each time user clicks inside one of this areas, sound effect is played.&lt;br /&gt;&lt;br /&gt;Now, that we have settings menu implemented, we just have to activate it, whenever user chooses "Settings" option. In file Game.as add new case into inner &lt;b&gt;switch&lt;/b&gt; statement in &lt;b&gt;MouseUp_GameMenu&lt;/b&gt; function:&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace; font-size: x-small;"&gt;case OPTION_SETTINGS:    &lt;br /&gt;&amp;nbsp;&amp;nbsp;selectedOption = OPTION_SETTINGS;      &lt;br /&gt;&amp;nbsp;&amp;nbsp;ChangeState_GameMenu(GAMEOPTIONS_OUT);      &lt;br /&gt;&amp;nbsp;&amp;nbsp;break;&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;div style="text-align: justify;"&gt;This will activate GAMEOPTIONS_OUT game menu state, after mouse button is released. After one second, game menu options will disappear and at this point, SETTINGS_MENU program state has to be activated in &lt;b&gt;Draw_GameMenu&lt;/b&gt; function. Inside &lt;b&gt;switch&lt;/b&gt; statement, change the &lt;b&gt;if&lt;/b&gt; statement in case of GAMEOPTIONS_OUT:&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace; font-size: x-small;"&gt;if (gameMenuTime &gt;= 1)&lt;br /&gt;&amp;nbsp;&amp;nbsp;if (selectedOption == OPTION_SETTINGS)&lt;br /&gt;&amp;nbsp;&amp;nbsp;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;state = SETTINGS_MENU; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;ChangeState_SettingsMenu(SETTINGSOPTIONS_IN);&lt;br /&gt;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&amp;nbsp;&amp;nbsp;else&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;ChangeState_GameMenu(TITLE_HIDE);&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;div style="text-align: justify;"&gt;Finally, we have to update &lt;b&gt;LoadData&lt;/b&gt; and &lt;b&gt;StoreData&lt;/b&gt; functions in SnakesAdventure.as. &lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace; font-size: x-small;"&gt;private function LoadData():void  &lt;br /&gt;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;var so:SharedObject = SharedObject.getLocal("SnakesAdventure");&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;if (so.size &gt; 0)   &lt;br /&gt;&amp;nbsp;&amp;nbsp;{           &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if (so.data.hiscore != null)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;hiscore = so.data.hiscore;&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if (so.data.soundVolume != null)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;soundVolume = so.data.soundVolume;&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if (so.data.musicVolume != null)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;musicVolume = so.data.musicVolume;      &lt;br /&gt;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;private static const HISCORE:int     = 1;&lt;br /&gt;private static const SOUND_VOLUME:int = 2;&lt;br /&gt;private static const MUSIC_VOLUME:int = 3;&lt;br /&gt;&lt;br /&gt;private function StoreData(what:int):void  &lt;br /&gt;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;var so:SharedObject = SharedObject.getLocal("SnakesAdventure");&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;switch (what)&lt;br /&gt;&amp;nbsp;&amp;nbsp;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;case HISCORE:&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;so.data.hiscore = hiscore; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;break;&lt;br /&gt;&amp;nbsp;&amp;nbsp;case SOUND_VOLUME:&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;so.data.soundVolume = soundVolume; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;break;&lt;br /&gt;&amp;nbsp;&amp;nbsp;case MUSIC_VOLUME:&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;so.data.musicVolume = musicVolume; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;break;&lt;br /&gt;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;so.flush();   &lt;br /&gt;} &lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;div style="text-align: justify;"&gt;From now on, &lt;b&gt;LoadData&lt;/b&gt; function, that is called during initialization phase, will also restore value of sound and music volume from SharedObject. &lt;b&gt;StoreData&lt;/b&gt; function is now capable of storing the value of global variable &lt;b&gt;soundVolume&lt;/b&gt; or &lt;b&gt;musicVolume&lt;/b&gt; into SharedObject. This will happen whenever user changes volume of sound or music in settings menu.&lt;br /&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8678980820383323367-3326658245316993632?l=grandy-flexdev.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://grandy-flexdev.blogspot.com/feeds/3326658245316993632/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://grandy-flexdev.blogspot.com/2010/03/pause-continue-and-settings.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8678980820383323367/posts/default/3326658245316993632'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8678980820383323367/posts/default/3326658245316993632'/><link rel='alternate' type='text/html' href='http://grandy-flexdev.blogspot.com/2010/03/pause-continue-and-settings.html' title='Pause, continue and settings'/><author><name>Grandy</name><uri>http://www.blogger.com/profile/13061370372593845090</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='29' height='32' src='http://4.bp.blogspot.com/_4Xe_fkP2r2A/StiN3kMzX2I/AAAAAAAAAAU/wWM-ILREdfw/S220/MySelf.png'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://1.bp.blogspot.com/_4Xe_fkP2r2A/S6e6C0T8v0I/AAAAAAAAAD4/2_TgXIJ4RI0/s72-c/SettingsOptions.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8678980820383323367.post-6472722233061489878</id><published>2010-03-17T10:33:00.001-07:00</published><updated>2010-03-25T08:44:06.469-07:00</updated><title type='text'>Per-pixel collision</title><content type='html'>&lt;div style="text-align: justify;"&gt;In &lt;a href="http://grandy-flexdev.blogspot.com/2010/03/tiled-background.html"&gt;previous chapter&lt;/a&gt; we implemented tiled background and now the background image does not repeat as much as it did in older versions. But there is still something missing: it is just an image. Nothing happens when snakes runs into the rock and eggs can float over the pit just like it wasn't there.&lt;br /&gt;&lt;br /&gt;We have to implement collision detection again, but none of the methods that we have learned in &lt;a href="http://grandy-flexdev.blogspot.com/2010/02/collision-detection.html"&gt;chapter 19&lt;/a&gt;, will be of much use here. We have to somehow distinguish between the dangerous and non-dangerous parts of each tile, before we can detect collision.&lt;br /&gt;&lt;br /&gt;There are many was to do this. We could write the list of tiles that will trigger the death of the snake, whenever it enters the area, where tile is displayed. This would be quite simple to implement, but not precise enough. If we could provide the same information for small chunks of the tile, let's say 4x4, precision would be very much increased, but the whole process would require to much work. We will use the approach, that is the most precise and does not require to much extra work.&lt;br /&gt;&lt;br /&gt;&lt;div style="text-align: justify;"&gt;&lt;center&gt;&lt;br /&gt;&lt;table border="1"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td align="center"&gt;&lt;embed align="center" height="480" src="http://bgrandovec.hostzi.com/Files/SnakesAdventure_P23.swf" type="application/x-shockwave-flash" width="480"&gt;&lt;/embed&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/center&gt;&lt;/div&gt;&lt;br /&gt;&lt;b&gt;Per-pixel collision&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;To implement per-pixel collision, we first need information, which pixels in the tile set can trigger the collision and which can't. This information will be stored in the copy of the original image, where only pixels that matter, are visible. The rest of the pixels are transparent.&lt;br /&gt;&lt;br /&gt;Bellow is the image that will be used in this chapter, to detect collision. If you download project &lt;a href="http://bgrandovec.hostzi.com/Files/SnakesAdventure_P23.zip"&gt;package&lt;/a&gt; for this chapter, you can find the image inside Images folder, under the name Background.png.&lt;br /&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://1.bp.blogspot.com/_4Xe_fkP2r2A/S6Ee7U18jHI/AAAAAAAAADw/TNb6_gDtS2Q/s1600-h/Background.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="400" src="http://1.bp.blogspot.com/_4Xe_fkP2r2A/S6Ee7U18jHI/AAAAAAAAADw/TNb6_gDtS2Q/s400/Background.png" width="200" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;I am making tiles for the game with image editor, that supports layers (I guess all good image editors supports them). To create such an image, I disable all layers, that don't matter, and remove colour information to decrease the size of the file.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Background.as&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;Image file has to be embedded, before it can be used:&lt;/div&gt;&lt;br /&gt;&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace; font-size: x-small;"&gt;[Embed(source="../Images/Background.png")] private var collisionsImg:Class;   &lt;/div&gt;&lt;br /&gt;&lt;div style="text-align: justify;"&gt;We need additional BitmapData object, where pixels from embedded image will be copied:&lt;/div&gt;&lt;br /&gt;&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace; font-size: x-small;"&gt;private var bitmapCollision:BitmapData = null; &lt;/div&gt;&lt;br /&gt;&lt;div style="text-align: justify;"&gt;Function &lt;b&gt;checkCollision&lt;/b&gt; works similar to &lt;b&gt;draw&lt;/b&gt; function, but instead of copying pixels from Background.jpg into screen buffer, it checks if the pixels on the same location, but from different image - Background.png, are transparent or not.&lt;/div&gt;&lt;br /&gt;&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace; font-size: x-small;"&gt;public function checkCollision(bounds:Rectangle):Boolean&lt;br /&gt;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;if (bitmapCollision == null)&lt;br /&gt;&amp;nbsp;&amp;nbsp;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;bitmapCollision = new BitmapData(300,600,true,0x00000000);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;bitmapCollision.draw(new collisionsImg());&lt;br /&gt;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;for (var y:int = bounds.y; y &amp;gt; bounds.y - bounds.height; y--)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;for (var x:int = bounds.x; x &amp;lt; bounds.x + bounds.width; x++)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;var tileX:int = x / TILE_SIZE;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;var tileY:int = y / TILE_SIZE;&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if ((tileX &amp;lt; 0) || (tileX &amp;gt; 9) || (tileY &amp;lt; 0))&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return true;&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;var cells:Array = rows[tileY % rows.length];&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;var tile:Point = cells[tileX];&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;var pix:uint = bitmapCollision.getPixel32(x % TILE_SIZE + (tile.x - 1) * TILE_DIST, tile.y * TILE_DIST - y % TILE_SIZE);&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if ((pix &amp;gt;&amp;gt; 24 &amp;amp; 0xFF) &amp;gt; 0)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return true;            &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;return false;&lt;br /&gt;}&lt;/div&gt;&lt;br /&gt;&lt;div style="text-align: justify;"&gt;Data from embedded image is copied into BitmapData object, but only the first time the function is called. The code inside &lt;b&gt;for&lt;/b&gt; loops, scans the entire area of the game world, that is specified within &lt;b&gt;bounds&lt;/b&gt; parameter. Area is checked pixel by pixel and within each iteration, game world coordinates are transformed into tile coordinates and vertical and horizontal index of the tile are obtained from &lt;b&gt;rows&lt;/b&gt; Array.&lt;br /&gt;&lt;br /&gt;Function &lt;b&gt;getPixel32&lt;/b&gt; in BitmapData class, returns ARGB colour value of the pixel on specified location. Returned value is &lt;b&gt;uint&lt;/b&gt; (unsigned integer) which is 32-bit numeric value: 8 bits for alpha channel, 8 bits for red, green and blue colour. There are only first 8 bits, that we are interested in. If all those bits equal to zero, pixel is fully transparent and collision is not detected; the search continues. If value is greater than zero, pixel is not transparent, collision is detected and function immediately exits and returns true.&lt;br /&gt;&lt;br /&gt;Now that we have a tool to detect collision, we can use it.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Game.as&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;First, we will update &lt;b&gt;CheckCollision&lt;/b&gt; function. You can append this statement to the end of the function:&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace; font-size: x-small;"&gt;//check snake and the background&lt;br /&gt;if (background.checkCollision(headBounds))&lt;br /&gt;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;snake.kill();&lt;br /&gt;&amp;nbsp;&amp;nbsp;return snake;     &lt;br /&gt;}&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;div style="text-align: justify;"&gt;It cannot be more simple than that: &lt;b&gt;headBounds&lt;/b&gt; object represents the area in the game world, where head of the snake is currently position. This is the area that &lt;b&gt;checkCollision&lt;/b&gt; function in Background class will have to check. When function returns true, the head of the snake is positioned over at least one pixel, that is non-transparent in the copy of background image, that is used for collision detection.&lt;br /&gt;&lt;br /&gt;If you recompile the game and play it, the snake will die whenever it hits the rocks. The problem is, that eggs are sometimes randomly positioned on the rocks and they cannot be eaten by the snake. We have to update &lt;b&gt;CreateRandomEgg&lt;/b&gt; function, to fix this problem.&lt;br /&gt;&lt;br /&gt;Replace the &lt;b&gt;return&lt;/b&gt; statement at the end of the &lt;b&gt;CreateRandomEgg&lt;/b&gt; function, with:&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace; font-size: x-small;"&gt;var newEgg:Egg = new Egg(x,y,initial);&lt;br /&gt;&lt;br /&gt;//check the background&lt;br /&gt;if (background.checkCollision(newEgg.getBounds2(20)))&lt;br /&gt;&amp;nbsp;&amp;nbsp;return CreateRandomEgg(initial); &lt;br /&gt;&lt;br /&gt;return newEgg;&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;div style="text-align: justify;"&gt;The previous version of &lt;b&gt;CreateRandomEgg&lt;/b&gt; function, made new egg on random location in the game world, within the visible area of the player If the egg was positioned to close to the snakes body, function was called again, until correct location was not found.&lt;br /&gt;&lt;br /&gt;The new version works the same, but it also makes sure that new egg is not positioned on the rock, over the pit... In fact it checks the area, that is much bigger than the area, which is returned by &lt;b&gt;getBounds&lt;/b&gt; function from Egg class. New egg is generated at least 25 pixels away from nearest dangerous area. This area is returned by new function in Egg class - &lt;b&gt;getBounds2&lt;/b&gt;. The implementation of this function has to be added to Egg.as file:&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace; font-size: x-small;"&gt;public function getBounds2(margin:int):Rectangle    &lt;br /&gt;{ &lt;br /&gt;&amp;nbsp;&amp;nbsp;return new Rectangle(position.x - 5 - margin, position.y + 9 + margin, 11 + 2 * margin, 16 + 2 * margin);&lt;br /&gt;}&lt;br /&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8678980820383323367-6472722233061489878?l=grandy-flexdev.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://grandy-flexdev.blogspot.com/feeds/6472722233061489878/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://grandy-flexdev.blogspot.com/2010/03/per-pixel-collision.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8678980820383323367/posts/default/6472722233061489878'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8678980820383323367/posts/default/6472722233061489878'/><link rel='alternate' type='text/html' href='http://grandy-flexdev.blogspot.com/2010/03/per-pixel-collision.html' title='Per-pixel collision'/><author><name>Grandy</name><uri>http://www.blogger.com/profile/13061370372593845090</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='29' height='32' src='http://4.bp.blogspot.com/_4Xe_fkP2r2A/StiN3kMzX2I/AAAAAAAAAAU/wWM-ILREdfw/S220/MySelf.png'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://1.bp.blogspot.com/_4Xe_fkP2r2A/S6Ee7U18jHI/AAAAAAAAADw/TNb6_gDtS2Q/s72-c/Background.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8678980820383323367.post-4461496790520841759</id><published>2010-03-13T08:04:00.000-08:00</published><updated>2010-03-25T08:40:32.019-07:00</updated><title type='text'>Tiled background</title><content type='html'>&lt;div style="text-align: justify;"&gt;In &lt;a href="http://grandy-flexdev.blogspot.com/2010/02/background-and-scrolling.html"&gt;chapter 20&lt;/a&gt; we implemented scrolling background, which was big improvement compared to the previous version, which had solid colour background only. Because the grass image is only 640 pixels high, it soon starts to repeat itself and becomes boring. Of course, bigger image with nicer and more diverse graphics would certainly make the game look much better, but at what cost?&lt;br /&gt;&lt;br /&gt;Let's make some calculations. Background scrolls by one pixel per frame, which makes 24 pixels per second or 1440 per minute. Let's say that average time to complete each stage in the game, would be five minutes. In case it is required, that background image does not repeat itself, it must be more than 7200 pixels high. In case JPEG compression is used and quality is not to low, file size of the image would be somewhere between one and two megabytes. For one stage...&lt;br /&gt;&lt;br /&gt;If you are developing a web game and you plan to keep the size of the game as small as possible, you should consider implementing tiled background. &lt;/div&gt;&lt;br /&gt;&lt;div style="text-align: justify;"&gt;&lt;center&gt;&lt;br /&gt;&lt;table border="1"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td align="center"&gt;&lt;embed align="center" height="480" src="http://bgrandovec.hostzi.com/Files/SnakesAdventure_P22.swf" type="application/x-shockwave-flash" width="480"&gt;&lt;/embed&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/center&gt;&lt;/div&gt;&lt;br /&gt;&lt;div style="text-align: justify;"&gt;&lt;b&gt;Tiles&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;Tiles are small images which are used to create large images, maps or terrain. Tiles are not easy to make, creation of tile sets requires skill and lots of hard work. Fortunately, there are lots of free tile sets on the internet, that you can use in your own game.&lt;br /&gt;&lt;br /&gt;There are different ways to create a background, map, terrain... from tiles. Game developers usually use a special editor to create them. Instead of complete bitmap, only location and index (or name) of each tile is stored into file. File size of even big maps is usually measured in kilobytes.&lt;br /&gt;&lt;br /&gt;For this chapter, I made an image that contains 72 tiles. Size of each tile is 48x48 pixels and there are two pixels of empty space between each tiles. There are 12 rows of tiles in the image (600 pixels), each row consist of six tiles (300 pixels). Image Background.jpg can be found inside project &lt;a href="http://bgrandovec.hostzi.com/Files/SnakesAdventure_P22.zip"&gt;package&lt;/a&gt; for this chapter under Images folder.&lt;br /&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://2.bp.blogspot.com/_4Xe_fkP2r2A/S5vNxPaAfZI/AAAAAAAAADo/N_vBkaI87ok/s1600-h/Background.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="400" src="http://2.bp.blogspot.com/_4Xe_fkP2r2A/S5vNxPaAfZI/AAAAAAAAADo/N_vBkaI87ok/s400/Background.jpg" width="200" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;If you already tried to play the game, you most certainly noticed, that now it takes more time before background starts to repeat itself. By using tiles from new Background.jpg, which is a slightly smaller than previous version, background image is now almost three times bigger then before.&lt;br /&gt;&lt;br /&gt;Implementation of tiles did not require many changes in the code. On the other hand, creation of tile set and creation of background map was not an easy task.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Level.xml&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;XML is probably not the best format to the store structure of the background, map or terrain. But XML documents are so well supported in ActionScript, that I just had to use it.&lt;br /&gt;&lt;br /&gt;Bellow is the XML document that can be found inside project &lt;a href="http://bgrandovec.hostzi.com/Files/SnakesAdventure_P22.zip"&gt;package&lt;/a&gt; for this chapter inside Levels folder under the name Level_1.xml.&lt;/div&gt;&lt;br /&gt;&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace; font-size: x-small;"&gt;&amp;lt;level&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;lt;row&amp;gt;05-6,01-2,01-3,01-1,01-2,01-3,01-1,01-2,07-1,07-2&amp;lt;/Row&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;lt;row&amp;gt;02-1,02-2,02-3,02-1,02-2,02-3,02-1,02-2,02-3,08-2&amp;lt;/Row&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;lt;row&amp;gt;03-1,03-2,03-3,03-1,03-2,03-3,03-1,03-2,03-3,09-2&amp;lt;/Row&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;lt;row&amp;gt;10-2,10-2,10-3,01-1,01-2,01-3,01-1,10-1,10-2,10-2&amp;lt;/Row&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;lt;row&amp;gt;11-2,11-2,11-3,02-1,02-2,02-3,02-1,11-1,11-2,11-2&amp;lt;/Row&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;lt;row&amp;gt;11-2,11-2,11-3,03-1,03-2,03-3,03-1,11-1,11-2,11-2&amp;lt;/Row&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;lt;row&amp;gt;12-2,12-2,12-3,01-1,01-2,01-3,01-1,12-1,12-2,12-2&amp;lt;/Row&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;lt;row&amp;gt;02-1,02-2,02-3,02-1,02-2,02-3,02-1,02-2,02-3,02-1&amp;lt;/Row&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;lt;row&amp;gt;04-3,03-2,03-3,03-1,03-2,03-3,03-1,03-2,03-3,03-1&amp;lt;/Row&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;lt;row&amp;gt;04-6,01-2,01-3,01-1,01-2,01-3,01-1,01-2,01-3,04-2&amp;lt;/Row&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;lt;row&amp;gt;06-3,06-4,02-3,02-1,02-2,02-3,02-1,02-2,02-3,05-2&amp;lt;/Row&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;lt;row&amp;gt;07-3,07-4,03-3,03-1,03-2,03-3,03-1,03-2,06-1,06-2&amp;lt;/Row&amp;gt; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;lt;row&amp;gt;05-6,01-2,01-3,01-1,01-2,01-3,01-1,01-2,07-1,07-2&amp;lt;/Row&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;lt;row&amp;gt;02-1,02-2,02-3,02-1,02-2,02-3,02-1,02-2,02-3,03-4&amp;lt;/Row&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;lt;row&amp;gt;04-3,03-2,03-3,03-1,03-2,03-3,03-1,03-2,01-4,06-2&amp;lt;/Row&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;lt;row&amp;gt;05-3,01-2,01-3,01-4,01-5,01-6,01-1,01-2,02-4,02-5&amp;lt;/Row&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;lt;row&amp;gt;08-3,02-2,02-3,03-4,03-5,02-6,02-1,02-2,03-4,03-5&amp;lt;/Row&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;lt;row&amp;gt;09-3,03-2,03-3,04-4,04-5,04-6,03-1,03-2,05-4,07-2&amp;lt;/Row&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;lt;row&amp;gt;04-3,01-2,01-3,05-4,05-5,05-6,01-1,01-2,01-3,04-4&amp;lt;/Row&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;lt;row&amp;gt;05-3,02-2,02-3,02-1,02-2,02-3,02-1,02-2,02-3,05-4&amp;lt;/Row&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;lt;row&amp;gt;03-6,03-2,03-3,03-1,03-2,03-3,03-1,03-2,03-3,03-1&amp;lt;/Row&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;lt;row&amp;gt;04-6,01-2,01-3,01-1,01-2,01-3,01-1,01-2,01-3,04-2&amp;lt;/Row&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;lt;row&amp;gt;06-3,06-4,02-3,02-1,02-2,02-3,02-1,02-2,02-3,05-2&amp;lt;/Row&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;lt;row&amp;gt;07-3,05-6,03-3,03-1,03-2,03-3,03-1,03-2,06-1,06-2&amp;lt;/Row&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;lt;row&amp;gt;05-6,01-2,01-3,01-1,01-2,01-3,01-1,01-2,07-1,07-2&amp;lt;/Row&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;lt;row&amp;gt;02-1,02-2,02-3,02-1,02-2,02-3,02-1,02-2,02-3,03-4&amp;lt;/Row&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;lt;row&amp;gt;04-3,03-2,03-3,03-1,03-2,03-3,03-1,03-2,01-4,06-2&amp;lt;/Row&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;lt;row&amp;gt;05-3,01-2,01-3,01-1,01-2,01-3,01-1,01-2,02-4,02-5&amp;lt;/Row&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;lt;row&amp;gt;08-3,06-6,02-3,02-1,02-2,02-3,02-1,02-2,03-4,03-5&amp;lt;/Row&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;lt;row&amp;gt;09-3,03-2,03-3,03-1,03-2,03-3,03-1,03-2,05-4,07-2&amp;lt;/Row&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;lt;row&amp;gt;04-3,01-2,01-3,01-1,01-2,01-3,01-1,01-2,01-3,04-4&amp;lt;/Row&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;lt;row&amp;gt;05-3,02-2,02-3,02-1,02-2,02-3,02-1,02-2,02-3,05-4&amp;lt;/Row&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;lt;row&amp;gt;03-6,03-2,03-3,03-1,03-2,03-3,03-1,03-2,03-3,03-1&amp;lt;/Row&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;lt;row&amp;gt;04-6,01-2,01-3,01-1,01-2,01-3,01-1,01-2,01-3,04-2&amp;lt;/Row&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;lt;row&amp;gt;06-3,06-4,02-3,02-1,02-2,02-3,02-1,02-2,02-3,05-2&amp;lt;/Row&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;lt;row&amp;gt;07-3,07-4,03-3,03-1,03-2,03-3,03-1,03-2,06-1,06-2&amp;lt;/Row&amp;gt;&lt;br /&gt;&amp;lt;/Level&amp;gt;&lt;/div&gt;&lt;br /&gt;&lt;div style="text-align: justify;"&gt;Inside this document is the structure of the background for stage one. Because all tiles have size 48x48 pixels, there are exactly ten tiles required in one row. Columns are separated with commas, each tile is described with vertical and horizontal index, according to both values we know exactly which tile has to be displayed.&lt;br /&gt;&lt;br /&gt;Elements &lt;b&gt;row&lt;/b&gt; in the document are positioned in the same direction as the tiles will be displayed in the background. Element at the end of the document represents the bottom row, that will be visible at the beginning of the game. Top most &lt;b&gt;row&lt;/b&gt; element represents the row at the top of the background, which will become visible after approximately one minute of play.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;XML object&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;ActionScript 3.0 includes a group of classes for XML which feature powerful and easy-to-use functionality for working with XML data. Before we can use the Level_1.xml document, we have to embed it.&lt;br /&gt;&lt;br /&gt;I put the statement, that embeds the XML document, inside Game.as file, just before the New_Game function.&lt;/div&gt;&lt;br /&gt;&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace; font-size: x-small;"&gt;[Embed(source="Levels\\Level_1.xml", mimeType="application/octet-stream")] private var level_1XML:Class;&lt;/div&gt;&lt;br /&gt;&lt;div style="text-align: justify;"&gt;This is not much different than the statement that takes care of embedding image files, but this time additional parameter &lt;b&gt;mimeType&lt;/b&gt; is required.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Create_Level&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;This is the new function in the Game.as, that will take care of the creation of every stage. It will be called from &lt;b&gt;New_Game&lt;/b&gt; and &lt;b&gt;Restart_Game&lt;/b&gt; functions.&lt;/div&gt;&lt;br /&gt;&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace; font-size: x-small;"&gt;private function Create_Level():void&lt;br /&gt;{ &lt;br /&gt;&amp;nbsp;&amp;nbsp;var xml:XML = null;&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;switch (level)&lt;br /&gt;&amp;nbsp;&amp;nbsp;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;case 1:&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;xml = XML(new level_1XML());   &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;break;&lt;br /&gt;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;scrollPos = 0;&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;background = new Background(xml);  &lt;br /&gt;&amp;nbsp;&amp;nbsp;snake = new Snake(SCREEN_WIDTH / 2,SCREEN_HEIGHT / 3,20);     &lt;br /&gt;&amp;nbsp;&amp;nbsp;egg = CreateRandomEgg(true);&lt;br /&gt;}&lt;/div&gt;&lt;br /&gt;&lt;div style="text-align: justify;"&gt;According to the value of &lt;b&gt;level&lt;/b&gt; variable, new XML object is made from embedded XML documents. Because at the moment, there is only one stage implemented, &lt;b&gt;switch&lt;/b&gt; statement with only one &lt;b&gt;case&lt;/b&gt; looks kind of funny. But I hope it will help you understand how the system works: each stage has its own XML document, that contains all the data required to create a stage. XML documents have to be embedded before they can be used. At the beginning of the stage, XML object is made from XML document and data inside the document is used during initialization phase.&lt;br /&gt;&lt;br /&gt;The code after the &lt;b&gt;switch&lt;/b&gt; statement used to be part of the implementation of &lt;b&gt;New_Game&lt;/b&gt; and &lt;b&gt;Restart_Game&lt;/b&gt; functions. This code was replaced with single statement that calls &lt;b&gt;Create_Level&lt;/b&gt; function. The only difference is the &lt;b&gt;xml&lt;/b&gt; parameter in &lt;b&gt;Background&lt;/b&gt; constructor.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Class Background ver.3&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;Class has been changed completely, again. Constructor will scan the &lt;b&gt;row&lt;/b&gt; elements in XML document and extract the data from the elements value. This data will be used to display visible tiles during the game.&lt;/div&gt;&lt;br /&gt;&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace; font-size: x-small;"&gt;public class Background&lt;br /&gt;{     &lt;br /&gt;&amp;nbsp;&amp;nbsp;private static const SCREEN_WIDTH:int     = 480;&lt;br /&gt;&amp;nbsp;&amp;nbsp;private static const SCREEN_HEIGHT:int    = 480; &lt;br /&gt;&amp;nbsp;&amp;nbsp;private static const TILE_SIZE:int        = 48;  &lt;br /&gt;&amp;nbsp;&amp;nbsp;private static const TILE_DIST:int        = 50;    &lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;[Embed(source="../Images/Background.jpg")] private var backgroundImg:Class;&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;private var bitmap:BitmapData = null;&lt;br /&gt;&amp;nbsp;&amp;nbsp;private var rows:Array = new Array();&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;public function Background(xml:XML) &lt;br /&gt;&amp;nbsp;&amp;nbsp;{      &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;var rowCount:int = 0;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;var rowXML:XML = xml.Row[rowCount];&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;while (rowXML != null)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{    &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;var cellStr:Array = rowXML.text().split(",");   &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;var cells:Array = new Array();&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;for (var i:int = 0; i &amp;lt; cellStr.length; i++)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;var str:Array = cellStr[i].split("-");&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;cells.push(new Point(int(str[1]),int(str[0])));&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;rows.unshift(cells);&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;rowXML = xml.Row[++rowCount];&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;public function draw(screenBuffer:BitmapData,visible:Rectangle):void&lt;br /&gt;&amp;nbsp;&amp;nbsp;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if (bitmap == null)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;bitmap = new BitmapData(300,600,true,0x00000000);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;bitmap.draw(new backgroundImg());&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;var startRow:int = (visible.y - visible.height) / TILE_SIZE;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; var endRow :int = visible.y / TILE_SIZE + 1;&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;for (var i:int = startRow; i &amp;lt;= endRow; i++)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;var cells:Array = rows[i % rows.length];&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if (cells != null)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;for (var j:int = 0; j &amp;lt;= 9; j++)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;var tile:Point = cells[j];&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;screenBuffer.copyPixels(bitmap,&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;new Rectangle((tile.x - 1) * TILE_DIST,(tile.y - 1) * TILE_DIST,TILE_SIZE,TILE_SIZE),&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;new Point(j * TILE_SIZE,visible.y - TILE_SIZE - i * TILE_SIZE));&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;}  &lt;/div&gt;&lt;br /&gt;&lt;div style="text-align: justify;"&gt;At the top of the file there are two new constant definitions: TILE_SIZE holds the value of horizontal and vertical size, TILE_DIST is the value of offset between tiles.&lt;br /&gt;&lt;br /&gt;Data from &lt;b&gt;row&lt;/b&gt; elements in the XML document are stored into &lt;b&gt;rows&lt;/b&gt; Array. As you can see, class constructor now requires XML object. &lt;b&gt;row&lt;/b&gt; elements from XML object are accessed inside the &lt;b&gt;while&lt;/b&gt; loop until the element with &lt;b&gt;rowCount&lt;/b&gt; index exist. Value of each element is split by comma separator, horizontal and vertical index of the tile are stored into Point object. All tiles for one row are stored into Array and inserted into &lt;b&gt;rows&lt;/b&gt; Array.&lt;br /&gt;&lt;br /&gt;At the beginning of &lt;b&gt;draw&lt;/b&gt; function are calculated indexes of first and last visible row. All this rows are visible and tiles in the row have to be drawn. Horizontal and vertical index, that was stored into Point object, is transformed into coordinates of the top-left corner of the tile in the source image and area of 48x48 pixels is copied into screen buffer.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Background creation&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;If you tried to add new or change existing content of Level_1.xml file, you most probably soon found out, that it is not as simple as you thought it would be. Even small changes are sometimes hard to make. You need to know which tiles you wish to change, you have to count the vertical and horizontal indexes of new tiles and enter them on the right place in XML document. Each time you make a change, you have to recompile and restart the game. And finally you have to play the game until the changes become visible. If you make one mistake, you have to repeat the whole process until you are satisfied.&lt;br /&gt;&lt;br /&gt;There is not much you can do to improve the whole process, unless you use an editor. I am sure there are lots of free editors on the internet, if you already found a good one that has all that you need, use it. You will most probably have to make some adjustments in the code, but it will make your life much easier. &lt;br /&gt;&lt;br /&gt;There is one thing we can do to improve the process of background creation. We can implement the special mode that will allow us to preview the stage before the game begins, by using mouse wheel. This mode should be available only during development process.&lt;br /&gt;&lt;br /&gt;First, new event listener is needed for Canvas object. Assign &lt;b&gt;mouseWheel&lt;/b&gt; event listener to mx:Canvas element in SnakesAdventure.mxml file:&lt;/div&gt;&lt;br /&gt;&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace; font-size: x-small;"&gt;mouseWheel="MouseWheelMoved(event)"&lt;/div&gt;&lt;br /&gt;&lt;div style="text-align: justify;"&gt;Whenever mouse cursor is position inside game frame and mouse wheel is moved, &lt;b&gt;MouseWheelMoved&lt;/b&gt; function will be executed. &lt;b&gt;MouseWheelMoved&lt;/b&gt; belongs into SnakesAdventure.as file:&lt;/div&gt;&lt;br /&gt;&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace; font-size: x-small;"&gt;private var prevDate:Date = null; &lt;br /&gt;&lt;br /&gt;private function MouseWheelMoved(event:MouseEvent):void &lt;br /&gt;{ &lt;br /&gt;&amp;nbsp;&amp;nbsp;if (prevDate == null) &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;prevDate = new Date(); &lt;br /&gt;&amp;nbsp;&amp;nbsp;else &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if (new Date().time - prevDate.time &amp;lt; 50)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;else&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;prevDate = new Date();&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;switch (state)&lt;br /&gt;&amp;nbsp;&amp;nbsp;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;case GAME:&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;MouseWheelMoved_Game(event);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;break;&lt;br /&gt;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;event.preventDefault();&lt;br /&gt;} &lt;/div&gt;&lt;br /&gt;&lt;div style="text-align: justify;"&gt;Code at the beginning prevents the function to execute twice for one event. This sometimes happens when SWF file is embedded into HTML page, which is opened with Internet Explorer.&lt;br /&gt;&lt;br /&gt;The rest of the code is quite simple: while GAME state is active, function &lt;b&gt;MouseWheelMoved_Game&lt;/b&gt; is called. This function is implemented in Game.as file: &lt;/div&gt;&lt;br /&gt;&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace; font-size: x-small;"&gt;private function MouseWheelMoved_Game(event:MouseEvent):void  &lt;br /&gt;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;switch (gameState)&lt;br /&gt;&amp;nbsp;&amp;nbsp;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;case GAME_START:  &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if (event.delta &amp;gt; 0)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;scrollPos += 48 * 2;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;else&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;scrollPos -= 48 * 2;&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if (scrollPos &amp;lt; 0)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;scrollPos = 0; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;break;&lt;br /&gt;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;} &lt;/div&gt;&lt;br /&gt;&lt;div style="text-align: justify;"&gt;Mouse wheel event contains property &lt;b&gt;delta&lt;/b&gt;. If its value is positive, mouse wheel was moved forward and value of &lt;b&gt;scrollPos&lt;/b&gt; variable is increased for 96, which is exactly height of two tiles. When mouse wheel is moved backward, value of &lt;b&gt;delta&lt;/b&gt; property is negative and value of &lt;b&gt;scrollPos&lt;/b&gt; variable is decreased for the same amount.&lt;br /&gt;&lt;br /&gt;Value of &lt;b&gt;scrollPos&lt;/b&gt; variable must be reseted before the game begins. Add this statement at the end of ChangeState_Game function:&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace; font-size: x-small;"&gt;if (gameState == GAME_STARTED)&lt;br /&gt;&amp;nbsp;&amp;nbsp;scrollPos = 0;&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;div style="text-align: justify;"&gt;From now on you can preview the stage before you test it. When game is embedded into web page, scrolling will most probably not work, because web browser scrolls the content of the page when mouse wheel is moved. Buy as I said, this mode should be used only during development process and removed in final version of the game.&lt;br /&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8678980820383323367-4461496790520841759?l=grandy-flexdev.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://grandy-flexdev.blogspot.com/feeds/4461496790520841759/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://grandy-flexdev.blogspot.com/2010/03/tiled-background.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8678980820383323367/posts/default/4461496790520841759'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8678980820383323367/posts/default/4461496790520841759'/><link rel='alternate' type='text/html' href='http://grandy-flexdev.blogspot.com/2010/03/tiled-background.html' title='Tiled background'/><author><name>Grandy</name><uri>http://www.blogger.com/profile/13061370372593845090</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='29' height='32' src='http://4.bp.blogspot.com/_4Xe_fkP2r2A/StiN3kMzX2I/AAAAAAAAAAU/wWM-ILREdfw/S220/MySelf.png'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://2.bp.blogspot.com/_4Xe_fkP2r2A/S5vNxPaAfZI/AAAAAAAAADo/N_vBkaI87ok/s72-c/Background.jpg' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8678980820383323367.post-5783393975428560541</id><published>2010-03-05T09:17:00.001-08:00</published><updated>2010-03-25T08:26:32.453-07:00</updated><title type='text'>Scoring points</title><content type='html'>&lt;div style="text-align: justify;"&gt;In this chapter we will add three variables in the game and display their values during the game. If you think this will be a simple task, you will be amazed how much additional work is sometimes required by a simple task.&lt;/div&gt;&lt;br /&gt;&lt;div style="text-align: justify;"&gt;&lt;center&gt;&lt;br /&gt;&lt;table border="1"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td align="center"&gt;&lt;embed align="center" height="480" src="http://bgrandovec.hostzi.com/Files/SnakesAdventure_P21.swf" type="application/x-shockwave-flash" width="480"&gt;&lt;/embed&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/center&gt;&lt;/div&gt;&lt;br /&gt;&lt;div style="text-align: justify;"&gt;&lt;b&gt;score, hiscore, lives&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;Those are the names of new global variables, add their definition at the top of Game.as file:&lt;/div&gt;&lt;br /&gt;&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace; font-size: x-small;"&gt;private var score:int = 0;&lt;br /&gt;private var hiscore:int = 0;&lt;br /&gt;private var lives:int = 3;&lt;/div&gt;&lt;br /&gt;&lt;div style="text-align: justify;"&gt;Value of &lt;b&gt;score&lt;/b&gt; variable will increase each time the snake eats the egg. This value will be assigned to &lt;b&gt;hiscore&lt;/b&gt; variable at the end of the game, but only when value of &lt;b&gt;score&lt;/b&gt; variable is greater than value of &lt;b&gt;hiscore&lt;/b&gt; variable. Initial value of variable &lt;b&gt;lives&lt;/b&gt; represents the number of fatal mistakes that allowed, before the game is over. Each time the snake hits something or the egg hits the bottom edge of the frame, value will be decreased by one. Value of those variables will be displayed during the game on the top of the game frame.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Draw_ScoreLives&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Draw_ScoreLives&lt;/b&gt; function takes care of displaying current score, highest score and number of lives that are still available. We will use the similar approach to display numbers, that we've used in the &lt;a href="http://grandy-flexdev.blogspot.com/2010/02/stage-one.html"&gt;chapter 14&lt;/a&gt; to display the number of current stage at the beginning of each stage. All graphics that is required to display numbers, labels and icons is inside new file ScoreLives.png.&lt;br /&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://2.bp.blogspot.com/_4Xe_fkP2r2A/S5FLEOHCOoI/AAAAAAAAADY/ie2BUdhQhKk/s1600-h/ScoreLives.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://2.bp.blogspot.com/_4Xe_fkP2r2A/S5FLEOHCOoI/AAAAAAAAADY/ie2BUdhQhKk/s320/ScoreLives.png" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;This image is part of the project &lt;a href="http://bgrandovec.hostzi.com/Files/SnakesAdventure_P21.zip"&gt;package&lt;/a&gt; for this chapter, you can find it inside Images folder. Image has to be embedded before it can be used. Add this statement inside Images.as:&lt;br /&gt;&lt;br /&gt;&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace; font-size: x-small;"&gt;[Embed(source="Images/ScoreLives.png")] private var scoreLivesImg:Class;&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;Implementation of Draw_ScoreLives funciton and two definitions, belong to Game.as file:&lt;/div&gt;&lt;br /&gt;&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace; font-size: x-small;"&gt;private var scoreLivesBitmap:BitmapData = null;&lt;br /&gt;private static var scoreDigitPos:Array = new Array(123, 139, 151, 165, 179, 195, 209, 224, 238, 253, 270);&lt;br /&gt;&lt;br /&gt;private function Draw_ScoreLives():void&lt;br /&gt;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;if (scoreLivesBitmap == null)&lt;br /&gt;&amp;nbsp;&amp;nbsp;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;scoreLivesBitmap = new BitmapData(290,30,true,0x00000000);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;scoreLivesBitmap.draw(new scoreLivesImg());&lt;br /&gt;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;//score&lt;br /&gt;&amp;nbsp;&amp;nbsp;screenBuffer.copyPixels(scoreLivesBitmap,&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;new Rectangle(37, 0, 80, 30),&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;new Point(4,0));&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;var scoreStr:String = score.toString();&lt;br /&gt;&amp;nbsp;&amp;nbsp;var xpos:int = 90;&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;for (var i:int = 0; i &amp;lt; 4; i++)&lt;br /&gt;&amp;nbsp;&amp;nbsp;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;var digit:int = 4 - i &amp;gt; scoreStr.length ? 0 : scoreStr.charCodeAt(i - (4 - scoreStr.length)) - 48;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;var digitPos:int = scoreDigitPos[digit];&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;var digitWidth:int = scoreDigitPos[digit + 1] - digitPos;&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;screenBuffer.copyPixels(scoreLivesBitmap,&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;new Rectangle(digitPos, 0, digitWidth, 30),&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;new Point(xpos,0));&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;xpos += 15;&lt;br /&gt;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;//hiscore &lt;br /&gt;&amp;nbsp;&amp;nbsp;screenBuffer.copyPixels(scoreLivesBitmap,&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;new Rectangle(0, 0, 117, 30),&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;new Point(SCREEN_WIDTH - 186,0)); &lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;xpos = SCREEN_WIDTH - 66;&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;var hiscoreStr:String = hiscore.toString();&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;for (var i2:int = 0; i2 &amp;lt;  4; i2++)&lt;br /&gt;&amp;nbsp;&amp;nbsp;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;var digit2:int = 4 - i2 &amp;gt; hiscoreStr.length ? 0 : hiscoreStr.charCodeAt(i2 - (4 - hiscoreStr.length)) - 48;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;var digitPos2:int = scoreDigitPos[digit2];&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;var digitWidth2:int = scoreDigitPos[digit2 + 1] - digitPos2;&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;screenBuffer.copyPixels(scoreLivesBitmap,&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;new Rectangle(digitPos2, 0, digitWidth2, 30),&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;new Point(xpos,0));&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;xpos += 15;&lt;br /&gt;&amp;nbsp;&amp;nbsp;} &lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;//lives&lt;br /&gt;&amp;nbsp;&amp;nbsp;xpos = SCREEN_WIDTH / 2 - 10 - lives * 10; &lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;for (var i3:int = 0; i3 &amp;lt; lives; i3++)&lt;br /&gt;&amp;nbsp;&amp;nbsp;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if (((gameState != GAME_KILLED) &amp;amp;&amp;amp; (gameState != GAME_FAILED)) || (i3 &amp;gt; 0) || (gameTime - int(gameTime) &amp;lt; 0.5))&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;screenBuffer.copyPixels(scoreLivesBitmap,&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;new Rectangle(271, 0, 20, 30),&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;new Point(xpos,0));&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;xpos += 20;&lt;br /&gt;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;} &lt;/div&gt;&lt;br /&gt;&lt;div style="text-align: justify;"&gt;At the top of the section are definitions of two global variables:&lt;br /&gt;- &lt;b&gt;scoreLivesBitmap&lt;/b&gt; is reference to BitmapData object, the copy of the embedded ScoreLives.png image.&lt;br /&gt;- &lt;b&gt;scoreDigitPos&lt;/b&gt; Array contains horizontal position of each digit in the ScoreLives.png image.&lt;br /&gt;&lt;br /&gt;First time the &lt;b&gt;Draw_ScoreLives&lt;/b&gt; function is called, it creates new BitmapData object and copies the content of embedded image into the object. Reference to this object is assigned to &lt;b&gt;scoreLivesBitmap&lt;/b&gt; variable.&lt;br /&gt;&lt;br /&gt;Inside the body of &lt;b&gt;Draw_ScoreLives&lt;/b&gt; function are three comments: score, hiscore and lives. Each comment indicates the beginning of the code that takes care of displaying value of the variable with the same name. "Score section" is displayed on the left side of the frame, "Hi-Score section" is on the right and "Lives section" in the middle.&lt;br /&gt;&lt;br /&gt;The code that draws "Score section" and "Hi-Score section" is very similar. Even the same label from the source image, is used to draw "Score" and "Hi-Score" label in the game. Displayed value consist of four digits, each digit is drawn inside &lt;b&gt;for&lt;/b&gt; loop from left to right. Just before the loop starts, new String object is made from value of the variable. If the String object has less than four digits, zeros are displayed in front of the actual number. Values of &lt;b&gt;digitPos&lt;/b&gt; and &lt;b&gt;digitWidth&lt;/b&gt; are calculated from horizontal position of the digits in the source image, defined in &lt;b&gt;scoreDigitPos&lt;/b&gt; Array. When displaying zero, &lt;b&gt;digitPos&lt;/b&gt; gets the value of first element in the Array and &lt;b&gt;digitWidth&lt;/b&gt; is the difference between position of character one and zero. In the &lt;b&gt;copyPixels&lt;/b&gt; statement, both values are used to define the area (Rectangle) of required digit in the source image.&lt;br /&gt;&lt;br /&gt;Value of &lt;b&gt;lives&lt;/b&gt; variable is displayed with the icons on the top-middle section of the game frame. Each icon is drawn inside the &lt;b&gt;for&lt;/b&gt; loop, the &lt;b&gt;if&lt;/b&gt; condition before &lt;b&gt;copyPixels&lt;/b&gt; statement, makes left icon to blink, when the player makes the mistake.&lt;br /&gt;&lt;br /&gt;Function &lt;b&gt;Draw_ScoreLives&lt;/b&gt; will be called once per frame from &lt;b&gt;Draw_Game&lt;/b&gt; function. Add this statement behind the code that draws background, egg and the snake (before the &lt;b&gt;switch&lt;/b&gt; statement):&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace; font-size: x-small;"&gt;Draw_ScoreLives();  &lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;div style="text-align: justify;"&gt;Now you can compile and play the game. But no matter what you do, number of scored points and icons will not change.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Scoring points, loosing lives...&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;At the beginning of the game, we have to reset values of &lt;b&gt;score&lt;/b&gt; and &lt;b&gt;lives&lt;/b&gt; variable. The New_Game function is perfect place to do that:&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace; font-size: x-small;"&gt;score = 0;&lt;br /&gt;lives = 3;&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;div style="text-align: justify;"&gt;When the snake eats the egg, value of &lt;b&gt;score&lt;/b&gt; variable will be increased by 5. Collision between the snake and the egg is checked in &lt;b&gt;CheckCollision&lt;/b&gt; function. Add the following statement after &lt;b&gt;snake.append();&lt;/b&gt; statement:&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace; font-size: x-small;"&gt;score += 5;&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;div style="text-align: justify;"&gt;You can select a different number, if you like, but big numbers will require more digits to display score/hiscore points.&lt;br /&gt;&lt;br /&gt;When player makes the fatal mistake, value of &lt;b&gt;lives&lt;/b&gt; variable will decrease by one. When it reaches zero, the game is over. Replace the current version of &lt;b&gt;Restart_Game&lt;/b&gt; function with:&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace; font-size: x-small;"&gt;private function Restart_Game():void&lt;br /&gt;{  &lt;br /&gt;&amp;nbsp;&amp;nbsp;lives--;&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;if (lives == 0)&lt;br /&gt;&amp;nbsp;&amp;nbsp;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if (score &gt; hiscore)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;hiscore = score;&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;StoreData(HISCORE);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;state = GAME_MENU;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;ChangeState_GameMenu(TITLE_SHOW);&lt;br /&gt;&amp;nbsp;&amp;nbsp;}  &lt;br /&gt;&amp;nbsp;&amp;nbsp;else&lt;br /&gt;&amp;nbsp;&amp;nbsp;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;scrollPos = 0;&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;snake = new Snake(SCREEN_WIDTH / 2,SCREEN_HEIGHT / 3,20); &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;egg = CreateRandomEgg(true); &lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;ChangeState_Game(GAME_FADE_IN);&lt;br /&gt;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;}&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;div style="text-align: justify;"&gt;&lt;b&gt;Restart_Game&lt;/b&gt; function was implemented in &lt;a href="http://grandy-flexdev.blogspot.com/2010/02/collision-detection.html"&gt;chapter 19&lt;/a&gt;. This function is called few seconds after player made a mistake. Previous version just made a new Snake and Egg objects, reseted &lt;b&gt;scrollPos&lt;/b&gt; variable and restarted the game (state GAME_FADE_IN). New version does all the same, but only if value of &lt;b&gt;lives&lt;/b&gt; variable, which is decreased by one at the start of the function, is more than zero.&lt;br /&gt;&lt;br /&gt;If value is zero, it is game over. First, value of &lt;b&gt;score&lt;/b&gt; variable is compared to value of &lt;b&gt;hiscore&lt;/b&gt; variable. If values of &lt;b&gt;score&lt;/b&gt; variable is greater, the player just broke new record, value of &lt;b&gt;score&lt;/b&gt; variable is assigned to &lt;b&gt;hiscore&lt;/b&gt; variable and &lt;b&gt;StoreData&lt;/b&gt; function is called. This function will be implemented at the end of the chapter. Finally, GAME_MENU state becomes active and eventually, program displays title screen and game menu.&lt;br /&gt;&lt;br /&gt;When the player enters game menu, mouse cursor needs to be replaced. Add new statement at the end of &lt;b&gt;Draw_GameMenu&lt;/b&gt; function in GameMenu.as:&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace; font-size: x-small;"&gt;SetMouseCursor(0,false);&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;div style="text-align: justify;"&gt;&lt;b&gt;Load/StoreData&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;When the player sets the new score, value of &lt;b&gt;hiscore&lt;/b&gt; variable has to be stored permanently, and available the next time, when the player starts the game. Shared Objects are the perfect place to store this kind of data. Data is actually stored on the local computer, within the user's home directory. &lt;br /&gt;&lt;br /&gt;We called &lt;b&gt;StoreData&lt;/b&gt; function from &lt;b&gt;Reset_Game&lt;/b&gt; function, to store the value of &lt;b&gt;hiscore&lt;/b&gt; variable. Add the implementation of this function at the end of file SnakesAdventure.as:&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace; font-size: x-small;"&gt;private static const HISCORE:int     = 1;&lt;br /&gt;&lt;br /&gt;private function StoreData(what:int):void  &lt;br /&gt;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;var so:SharedObject = SharedObject.getLocal("SnakesAdventure");&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;switch (what)&lt;br /&gt;&amp;nbsp;&amp;nbsp;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;case HISCORE:&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;so.data.hiscore = hiscore; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;break;&lt;br /&gt;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;so.flush();   &lt;br /&gt;}&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;div style="text-align: justify;"&gt;In front of &lt;b&gt;StoreData&lt;/b&gt; function is definition of one global constant HISCORE (in the following chapters we will add more of them). This constant can be used in &lt;b&gt;StoreData&lt;/b&gt; function call, as value of &lt;b&gt;what&lt;/b&gt; parameter. If HISCORE constant is used as a parameter value, function knows that value of &lt;b&gt;hiscore&lt;/b&gt; variable needs to be stored.&lt;br /&gt;&lt;br /&gt;Function &lt;b&gt;getLocal&lt;/b&gt; from &lt;b&gt;SharedObject&lt;/b&gt; class, returns the reference to SharedObject named "SnakesAdventure". Value of &lt;b&gt;hiscore&lt;/b&gt; variable is stored into &lt;b&gt;data&lt;/b&gt; collection, under the &lt;b&gt;hiscore&lt;/b&gt; attribute. If the attribute with this name does not exist, it is created; in case it exits, current value is replaced with new one. After all attributes are set, function &lt;b&gt;flush&lt;/b&gt; writes data into file.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;LoadData&lt;/b&gt; function will load the data from "SnakesAdventure" SharedObject and assign values of attributes to variables with the same name.&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace; font-size: x-small;"&gt;private function LoadData():void  &lt;br /&gt;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;var so:SharedObject = SharedObject.getLocal("SnakesAdventure");&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;if (so.size &gt; 0)   &lt;br /&gt;&amp;nbsp;&amp;nbsp;{           &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if (so.data.hiscore != null)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;hiscore = so.data.hiscore;&lt;br /&gt;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;}&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;div style="text-align: justify;"&gt;Function &lt;b&gt;getLocal&lt;/b&gt; always returns the reference to SharedObject object with name "SnakesAdventure". If it does not exist, it creates new - empty one. If attribute &lt;b&gt;size&lt;/b&gt; is equal to zero, there is no data and we can skip the loading procedure. Existence of &lt;b&gt;hiscore&lt;/b&gt; attribute in &lt;b&gt;data&lt;/b&gt; collection has to be checked, before its value can be assigned to &lt;b&gt;hiscore&lt;/b&gt; variable.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Init&lt;/b&gt; function at the beginning of the file SnakesAdventure.as is a good place to call &lt;b&gt;LoadData&lt;/b&gt; function:&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace; font-size: x-small;"&gt;LoadData();&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;div style="text-align: justify;"&gt;In the initialzation phase of the program, &lt;b&gt;LoadData&lt;/b&gt; function is called and value of &lt;b&gt;hiscore&lt;/b&gt; attribute, from the "SnakesAdventure" SharedObject, is assigned to &lt;b&gt;hiscore&lt;/b&gt; variable. If the attribute does not exist, variable &lt;b&gt;hiscore&lt;/b&gt; has default value - 0. When the player breaks new record, value of &lt;b&gt;score&lt;/b&gt; is assigned to &lt;b&gt;hiscore&lt;/b&gt; variable (in &lt;b&gt;Restart_Game&lt;/b&gt; function) and stored into SharedObject. At the end, all data in the SharedObject is written into file.&lt;br /&gt;&lt;br /&gt;Shared objects are application dependant: if you test the game in two different browsers, for example FireFox and Opera, both of them have its own "SnakesAdventure" SharedObject.&lt;br /&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8678980820383323367-5783393975428560541?l=grandy-flexdev.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://grandy-flexdev.blogspot.com/feeds/5783393975428560541/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://grandy-flexdev.blogspot.com/2010/03/scoring-points.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8678980820383323367/posts/default/5783393975428560541'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8678980820383323367/posts/default/5783393975428560541'/><link rel='alternate' type='text/html' href='http://grandy-flexdev.blogspot.com/2010/03/scoring-points.html' title='Scoring points'/><author><name>Grandy</name><uri>http://www.blogger.com/profile/13061370372593845090</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='29' height='32' src='http://4.bp.blogspot.com/_4Xe_fkP2r2A/StiN3kMzX2I/AAAAAAAAAAU/wWM-ILREdfw/S220/MySelf.png'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://2.bp.blogspot.com/_4Xe_fkP2r2A/S5FLEOHCOoI/AAAAAAAAADY/ie2BUdhQhKk/s72-c/ScoreLives.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8678980820383323367.post-4634966565729846845</id><published>2010-02-28T07:06:00.001-08:00</published><updated>2010-03-25T08:20:54.042-07:00</updated><title type='text'>Background and scrolling</title><content type='html'>&lt;div style="text-align: justify;"&gt;In this chapter, we will make three changes in the game: &lt;br /&gt;- single colour in the background will be replaced with an image&lt;br /&gt;- vertical scrolling will be implemented&lt;br /&gt;- instead of predefined positions of the eggs we will use random positions&lt;br /&gt;&lt;br /&gt;Because of the background image, the graphics will look a lot less boring, vertical scrolling will improve the gameplay and random positions will make game less predictable.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Background&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;I made this background image from the grass texture from one of my older games. The image is part of the project &lt;a href="http://bgrandovec.hostzi.com/Files/SnakesAdventure_P20.zip"&gt;package&lt;/a&gt; for this chapter, you can find it inside Images folder under the name Background.jpg.&lt;br /&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://3.bp.blogspot.com/_4Xe_fkP2r2A/S4qWGO5yAUI/AAAAAAAAADQ/qw46fVxgVd0/s1600-h/Background.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://3.bp.blogspot.com/_4Xe_fkP2r2A/S4qWGO5yAUI/AAAAAAAAADQ/qw46fVxgVd0/s320/Background.jpg" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;So far, all images in the project were in &lt;b&gt;PNG&lt;/b&gt; format, because it supports alpha transparency and employs lossless data compression. &lt;b&gt;JPEG&lt;/b&gt; image format was so much more appropriate in this case, that I had to make an exception. File size of the same image in &lt;b&gt;JPEG&lt;/b&gt; format is almost five times (130KB) less than if &lt;b&gt;PNG&lt;/b&gt; format is used (700+KB).&lt;br /&gt;&lt;br /&gt;Again, we will put all the functionality that takes care of embedding, drawing... into it's own class. Create new text file and store it, under the name Background.as, into folder Classes. Copy the following content into file:&lt;/div&gt;&lt;br /&gt;&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace; font-size: x-small;"&gt;package Classes &lt;br /&gt;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;import flash.geom.*; &lt;br /&gt;&amp;nbsp;&amp;nbsp;import flash.display.*; &lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;public class Background&lt;br /&gt;&amp;nbsp;&amp;nbsp;{     &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;private static const SCREEN_WIDTH:int     = 480;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;private static const SCREEN_HEIGHT:int    = 480; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;private static const IMAGE_HEIGHT:int     = 640;    &lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;[Embed(source="../Images/Background.jpg")] private var backgroundImg:Class;&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;private var bitmap:BitmapData = null;&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;public function draw(screenBuffer:BitmapData,visible:Rectangle):void&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if (bitmap == null)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;bitmap = new BitmapData(SCREEN_WIDTH,IMAGE_HEIGHT,true,0x00000000);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;bitmap.draw(new backgroundImg());&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;screenBuffer.copyPixels(bitmap,&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;new Rectangle(0,0,SCREEN_WIDTH,SCREEN_HEIGHT),&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;new Point(0,0));&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&amp;nbsp;&amp;nbsp;} &lt;br /&gt;}&lt;/div&gt;&lt;br /&gt;&lt;div style="text-align: justify;"&gt;Because constants defined in SnakesAdventure.as are out of the scope of this package/class, SCREEN_WIDTH/HEIGHT constants had to be defined here, too. Background image width and game frame width are the same, but image height and game frame height are not. Image height is defined with IMAGE_HEIGHT constant. I made background image that is higher than game frame, to reduce repetition in vertical scrolling. &lt;br /&gt;&lt;br /&gt;This class does not include definition of constructor, default constructor will be used when the class is instantiated. Implementation of &lt;b&gt;draw&lt;/b&gt; function has nothing that we haven't seen before: BitmapData object is made from embedded image (only the first time) and pixels are copied from BitmapData object into screen buffer.&lt;br /&gt;&lt;br /&gt;Now we can use Background class to display background image during the game. All we have to do is to define &lt;b&gt;background&lt;/b&gt; variable, instantiate the Background class and call it's &lt;b&gt;draw&lt;/b&gt; function once per frame. &lt;br /&gt;&lt;br /&gt;Put &lt;b&gt;background&lt;/b&gt; variable definition before definition of &lt;b&gt;snake&lt;/b&gt; variable, at the beginning of Game.as:&lt;/div&gt;&lt;br /&gt;&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace; font-size: x-small;"&gt;private var background:Background = null;&lt;/div&gt;&lt;br /&gt;&lt;div style="text-align: justify;"&gt;Background object has to be made at the beginning of the game. Add this statement inside New_Game function:&lt;/div&gt;&lt;br /&gt;&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace; font-size: x-small;"&gt;background = new Background();&lt;/div&gt;&lt;br /&gt;&lt;div style="text-align: justify;"&gt;Background has to be drawn before the snake and the egg. Previously, background colour was painted with &lt;b&gt;screenBuffer.fillRect...&lt;/b&gt; statement, which can now be replaced with:&lt;/div&gt;&lt;br /&gt;&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace; font-size: x-small;"&gt;background.draw(screenBuffer,new Rectangle(0,SCREEN_HEIGHT,SCREEN_WIDTH,SCREEN_HEIGHT)); &lt;/div&gt;&lt;br /&gt;&lt;div style="text-align: justify;"&gt;&lt;b&gt;Vertical scrolling&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;Because this game is called Snake's adventure, players will most certainly expect more that just a snake chasing the eggs on the static background. With implementation of vertical scrolling we will create the sense that snake is constantly moving in the northern direction. Of course, to create the sense of real adventure, the game needs much more than just vertical scrolling.&lt;br /&gt;&lt;br /&gt;Implementation of vertical scrolling will not require so much work, because we have already done most of the work. If you remember from previous chapters, &lt;b&gt;draw&lt;/b&gt; functions in all classes, already have &lt;b&gt;visible&lt;/b&gt; parameter, which represent the area of the game world that is visible at the moment the function is executing. Snake and Egg classes already take into account the coordinates of visible area, when copying source images into screen buffer (visible.y - position.y). &lt;br /&gt;&lt;br /&gt;Vertical scrolling will be active only while the game is played (GAME_PLAYED state). Once per frame, visible area of the game world will be moved by one pixel in the northern direction.&lt;br /&gt;&lt;br /&gt;OK, let's start with the implementation. First, we need new variable, value of variable will be increased once per frame. Add new variable after definition of &lt;b&gt;level&lt;/b&gt; variable at the top of Game.as:&lt;/div&gt;&lt;br /&gt;&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace; font-size: x-small;"&gt;private var scrollPos:int = 0;&lt;/div&gt;&lt;br /&gt;&lt;div style="text-align: justify;"&gt;Value of variable has to be reset at the beginning of the level. Add this statement into New_Game and Restart_Game functions:&lt;/div&gt;&lt;br /&gt;&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace; font-size: x-small;"&gt;scrollPos = 0;&lt;/div&gt;&lt;br /&gt;&lt;div style="text-align: justify;"&gt;Vertical position of visible area needs to be increased by value of &lt;b&gt;scrollPos&lt;/b&gt; variable. Replace the second parameter in all three &lt;b&gt;draw&lt;/b&gt; statements at the top of Draw_Game function, with:&lt;/div&gt;&lt;br /&gt;&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace; font-size: x-small;"&gt;new Rectangle(0,SCREEN_HEIGHT + scrollPos,SCREEN_WIDTH,SCREEN_HEIGHT)  &lt;/div&gt;&lt;br /&gt;&lt;div style="text-align: justify;"&gt;If you applied the changes correctly, the source code, should look like this:&lt;/div&gt;&lt;br /&gt;&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace; font-size: x-small;"&gt;background.draw(screenBuffer, &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;new Rectangle(0,SCREEN_HEIGHT + scrollPos,SCREEN_WIDTH,SCREEN_HEIGHT));   &lt;br /&gt;&lt;br /&gt;if (egg != null)&lt;br /&gt;&amp;nbsp;&amp;nbsp;egg.draw(screenBuffer, &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;new Rectangle(0,SCREEN_HEIGHT + scrollPos,SCREEN_WIDTH,SCREEN_HEIGHT));  &lt;br /&gt;&lt;br /&gt;if (snake != null)&lt;br /&gt;&amp;nbsp;&amp;nbsp;snake.draw(screenBuffer, &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;new Rectangle(0,SCREEN_HEIGHT + scrollPos,SCREEN_WIDTH,SCREEN_HEIGHT));   &lt;/div&gt;&lt;br /&gt;&lt;div style="text-align: justify;"&gt;Value of &lt;b&gt;scrollPos&lt;/b&gt; variable will be increased inside Draw_Game function only while GAME_PLAYED state is active. Add the following statement inside the &lt;b&gt;switch&lt;/b&gt; statement at the end of &lt;b&gt;case GAME_PLAYED&lt;/b&gt; (before break):&lt;/div&gt;&lt;br /&gt;&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace; font-size: x-small;"&gt;scrollPos++; &lt;/div&gt;&lt;br /&gt;&lt;div style="text-align: justify;"&gt;Although we have not finished the implementation, you can now compile and run the game to see how it works. Background is still static, but the egg is moving in the southern direction, which is OK. And so is the snake, but you can only notice this when it moves in the horizontal direction.&lt;br /&gt;&lt;br /&gt;Now, open Background.as file and replace &lt;b&gt;copyPixels&lt;/b&gt; statement in the &lt;b&gt;draw&lt;/b&gt; function, with the code that supports vertical scrolling:&lt;/div&gt;&lt;br /&gt;&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace; font-size: x-small;"&gt;var start:int = IMAGE_HEIGHT - visible.y % IMAGE_HEIGHT;&lt;br /&gt;var end:int = start + SCREEN_HEIGHT &amp;gt; IMAGE_HEIGHT ? IMAGE_HEIGHT - start : SCREEN_HEIGHT;&lt;br /&gt;&lt;br /&gt;screenBuffer.copyPixels(bitmap,&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;new Rectangle(0,start,SCREEN_WIDTH,end),&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;new Point(0,0));&lt;br /&gt;&lt;br /&gt;if (end &amp;lt; SCREEN_HEIGHT)&lt;br /&gt;&amp;nbsp;&amp;nbsp;screenBuffer.copyPixels(bitmap,&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;new Rectangle(0,0,SCREEN_WIDTH,SCREEN_WIDTH - end),&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;new Point(0,end));&lt;/div&gt;&lt;br /&gt;&lt;div style="text-align: justify;"&gt;This may be a little bit hard to understand, but let me try to explain why we have to copy pixels from source image into screen buffer, in two steps. Background image is by 160 pixels higher that visible area. In some cases source image fits inside the visible area, but in some cases doesn't.&lt;br /&gt;&lt;br /&gt;At the start of the game, Rectangle(0,160,480,480) defines the area of source image that is copied into screen buffer. Vertical position is decreasing by one per frame and after 160 frames, area from the source image, defined by Rectangle(0,0,480,480), is copied. At this moment, background image is visible from top to bottom minus 160 pixels.&lt;br /&gt;&lt;br /&gt;When the next time &lt;b&gt;Background.draw&lt;/b&gt; function is called, background image is copied into screen buffer in two steps. First, the bottom row of source image is copied on the top of screen buffer. The rest of the screen buffer is filled with area from the source image, defined by Rectangle(0,0,480,479). And so on...&lt;br /&gt;&lt;br /&gt;Unfortunately, grass image (Background.jpg) that is used for the background, doesn't help much to understand how this code works. Maybe it would help, if you temporary use a different image for the background. Rename Background.jpg to, let's say, Background2.jpg. Resize one of your photos to 480x640 pixels and add it to project inside Images folder under the name Background.jpg.&lt;br /&gt;&lt;br /&gt;If you compile and run the game, vertical scrolling should work fine, but after few seconds you will notice, that controls and collision detection do not work correctly.&lt;br /&gt;&lt;br /&gt;Let's fix this. Change the statement, that flips screen coordinates to game world coordinates in &lt;b&gt;SetGameCursor&lt;/b&gt; and &lt;b&gt;MouseDown_Game&lt;/b&gt; function, from:&lt;/div&gt;&lt;br /&gt;&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace; font-size: x-small;"&gt;my = SCREEN_HEIGHT - my;&lt;/div&gt;&lt;br /&gt;&lt;div style="text-align: justify;"&gt;to&lt;/div&gt;&lt;br /&gt;&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace; font-size: x-small;"&gt;my = SCREEN_HEIGHT + scrollPos - my;&lt;/div&gt;&lt;br /&gt;&lt;div style="text-align: justify;"&gt;This should fix problems with controls. Code that detects collision between the head of the snake and top and bottom edge of the frame will be fixed the same way. Vertical position of both edges has to be increased by the value of &lt;b&gt;scrollPos &lt;/b&gt; variable. Change the code in &lt;b&gt;CheckCollision&lt;/b&gt; function to:&lt;/div&gt;&lt;br /&gt;&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace; font-size: x-small;"&gt;//check snake and the edge of the screen&lt;br /&gt;if ((headBounds.x &amp;lt;= 0) || &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;(SCREEN_WIDTH - headBounds.x - headBounds.width &amp;lt;= 0) || &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;(headBounds.y - headBounds.height &amp;lt;= scrollPos) ||&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;(SCREEN_HEIGHT + scrollPos - headBounds.y &amp;lt;= 0))&lt;br /&gt;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;snake.kill();&lt;br /&gt;&amp;nbsp;&amp;nbsp;return false;&lt;br /&gt;} &lt;/div&gt;&lt;br /&gt;&lt;div style="text-align: justify;"&gt;Implementation of vertical scrolling is now complete, but one problem still remains: egg positions specified in Egg.position Array became useless. You can take into account the scrolling and adjust vertical positions, but after first iteration, coordinates will still be useless. We have to implement the mechanism, that will set random position of new egg, according to vertical position of visible area.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;CreateRandomEgg&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;CreateRandomEgg is the new function in Game.as file, that creates new egg on random position inside the visible area of game world. Add implementation of the function into Game.as file:&lt;/div&gt;&lt;br /&gt;&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace; font-size: x-small;"&gt;private function CreateRandomEgg(initial:Boolean):Egg&lt;br /&gt;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;var x:int = (int)(Math.random() * (SCREEN_WIDTH - 40)) + 20;&lt;br /&gt;&amp;nbsp;&amp;nbsp;var y:int = initial ? (int)(Math.random() * (SCREEN_HEIGHT / 2)) + SCREEN_HEIGHT / 2 :&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;(int)(Math.random() * (SCREEN_HEIGHT * 2 / 3)) + SCREEN_HEIGHT / 3 + scrollPos; &lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;for (var i:int = 0; i &amp;lt; snake.getLength(); i++)&lt;br /&gt;&amp;nbsp;&amp;nbsp;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;var partPosition:Point = snake.getPartPosition(i);&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if (Point.distance(partPosition, new Point(x,y)) &amp;lt; 30)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return CreateRandomEgg(initial);&lt;br /&gt;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;return new Egg(x,y,initial);&lt;br /&gt;}&lt;/div&gt;&lt;br /&gt;&lt;div style="text-align: justify;"&gt;Function requires &lt;b&gt;initial&lt;/b&gt; parameter that we already used in &lt;b&gt;Egg&lt;/b&gt; class constructor. Variables &lt;b&gt;x&lt;/b&gt; and &lt;b&gt;y&lt;/b&gt; represent horizontal and vertical position of new egg. Both values are random, horizontal position can range from 20 to SCREEN_WIDTH - 20. Offset of 20 pixels ensures, that egg is not positioned to close to the left or right edge of the frame.&lt;br /&gt;&lt;br /&gt;Vertical position of first (initial) egg is randomly selected in the upper section of visible area. Other eggs can be positioned a little be lower on the screen.&lt;br /&gt;&lt;br /&gt;Position of new egg cannot be too close to snake's body. Code inside the &lt;b&gt;for&lt;/b&gt; loop, checks if distance between the egg and each body parts is outside the range of 30 pixels. If all body parts are outside the range, new Egg object is created and returned.&lt;br /&gt;&lt;br /&gt;Implementation of &lt;b&gt;CreateRandomEgg&lt;/b&gt; function calls &lt;b&gt;getPartPosition&lt;/b&gt; function from Snake class that is currently unimplemented. And so is the Egg class constructor that is used her. We will implement both of them later.&lt;br /&gt;&lt;br /&gt;New Egg objects are made inside New_Game, Restart_Game and Draw_Game function. Replace all statements that creates Egg object from:&lt;/div&gt;&lt;br /&gt;&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace; font-size: x-small;"&gt;egg = new Egg(true); &lt;/div&gt;&lt;br /&gt;&lt;div style="text-align: justify;"&gt;with&lt;/div&gt;&lt;br /&gt;&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace; font-size: x-small;"&gt;egg = CreateRandomEgg(true); &lt;/div&gt;&lt;br /&gt;&lt;div style="text-align: justify;"&gt;Just be careful that you don't mix up true and false values. Before you can compile the project, we have to implement &lt;b&gt;getPartPosition&lt;/b&gt; function and change the Egg class constructor.&lt;br /&gt;&lt;br /&gt;Add implementation of &lt;b&gt;getPartPosition&lt;/b&gt; function inside the Snake class (file Snake.as):&lt;/div&gt;&lt;br /&gt;&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace; font-size: x-small;"&gt;public function getPartPosition(part:int):Point&lt;br /&gt;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;return partPosition[part];&lt;br /&gt;} &lt;/div&gt;&lt;br /&gt;&lt;div style="text-align: justify;"&gt;Replace the current version of Egg class (file Egg.as) constructor with:&lt;/div&gt;&lt;br /&gt;&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace; font-size: x-small;"&gt;public function Egg(x:int,y:int,initial:Boolean) &lt;br /&gt;{      &lt;br /&gt;&amp;nbsp;&amp;nbsp;if (initial)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;phase = 10; &lt;br /&gt;&amp;nbsp;&amp;nbsp;else&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;phase = 1;     &lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;position = new Point(x,y);     &lt;br /&gt;}&lt;/div&gt;&lt;br /&gt;&lt;div style="text-align: justify;"&gt;The code is much more simple now, because &lt;b&gt;CreateRandomEgg&lt;/b&gt; function does most of the work. You can also remove definitions of &lt;b&gt;positions&lt;/b&gt; Array and &lt;b&gt;nextPosition&lt;/b&gt; variable, because it won't be needed any more.&lt;br /&gt;&lt;br /&gt;You can compile and run the game now. As you can see, we've made a big progress in this chapter. But there is still one thing missing: the game does not check if the egg hits the lower edge of the game frame. If the egg is not eaten in time, it is game over.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;CheckCollision&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;Improved version of this function now looks like this:&lt;/div&gt;&lt;br /&gt;&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace; font-size: x-small;"&gt;private function CheckCollision():Object&lt;br /&gt;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;var headBounds:Rectangle = snake.getBounds(0);&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;//check egg and the bottom of the screen&lt;br /&gt;&amp;nbsp;&amp;nbsp;var eggBounds:Rectangle = egg.getBounds(); &lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;if (eggBounds.y - eggBounds.height &amp;lt;= scrollPos)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return egg;&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;//check snake and egg&lt;br /&gt;&amp;nbsp;&amp;nbsp;if ((egg != null) &amp;amp;&amp;amp; egg.active())&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if (headBounds.intersects(eggBounds))&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;egg.eat();&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;snake.append();&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;//check snake and the edge of the screen&lt;br /&gt;&amp;nbsp;&amp;nbsp;if ((headBounds.x &amp;lt;= 0) ||&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;(SCREEN_WIDTH - headBounds.x - headBounds.width &amp;lt;= 0) ||&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;(headBounds.y - headBounds.height &amp;lt;= scrollPos) ||&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;(SCREEN_HEIGHT + scrollPos - headBounds.y &amp;lt;= 0))&lt;br /&gt;&amp;nbsp;&amp;nbsp;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;snake.kill();&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return snake;&lt;br /&gt;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;//check snakes body&lt;br /&gt;&amp;nbsp;&amp;nbsp;for (var i:int = 7; i &amp;lt; snake.getLength(); i++)&lt;br /&gt;&amp;nbsp;&amp;nbsp;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;var partBounds:Rectangle = snake.getBounds(i);&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if (headBounds.intersects(partBounds))&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;snake.kill();&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return snake;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;return null;&lt;br /&gt;}&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;div style="text-align: justify;"&gt;New version is not much different from previous version but there are two important differences:&lt;br /&gt;- function first checks if bottom section of egg icon is outside the game frame&lt;br /&gt;- function now returns Object instead of Boolean. If there is no collision, that causes the end of the game, function returns &lt;b&gt;null&lt;/b&gt;. If head of the snake hits the edge of the screen or its own body, function returns &lt;b&gt;snake&lt;/b&gt; object. If egg hits the lower edge of the screen, function returns &lt;b&gt;egg&lt;/b&gt; object.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;CheckCollision&lt;/b&gt; is called from Draw_Game function once per frame. Because new version of this function returns a different type, we have to also modify the code inside the Draw_Game function (inside case GAME_PLAYED):&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace; font-size: x-small;"&gt;var obj:Object = CheckCollision();&lt;br /&gt;&lt;br /&gt;if (obj is Snake)&lt;br /&gt;&amp;nbsp;&amp;nbsp;ChangeState_Game(GAME_KILLED);&lt;br /&gt;&lt;br /&gt;if (obj is Egg)&lt;br /&gt;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;egg.blink();&lt;br /&gt;&amp;nbsp;&amp;nbsp;ChangeState_Game(GAME_FAILED); &lt;br /&gt;}&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;div style="text-align: justify;"&gt;When the Snake object is returned, state GAME_KILLED becomes active and animation of dying snake is displayed. If Egg object is returned, we have to perform different animation. Egg will blink during GAME_FAILED state, which will be active for only few seconds.&lt;br /&gt;&lt;br /&gt;Add the definition of GAME_FAILED constant to other constant at the top of Game.as &lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace; font-size: x-small;"&gt;private static const GAME_FAILED:int         = 6;&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;div style="text-align: justify;"&gt;Currently, the GAME_FADE_OUT constant has value 6, change its value to 7. The following section belongs before &lt;b&gt;case GAME_FADE_OUT&lt;/b&gt; statement inside Draw_Game function:&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace; font-size: x-small;"&gt;case GAME_FAILED:&lt;br /&gt;&amp;nbsp;&amp;nbsp;if (!egg.blink())&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;ChangeState_Game(GAME_FADE_OUT);   &lt;br /&gt;&amp;nbsp;&amp;nbsp;break;&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;div style="text-align: justify;"&gt;While the GAME_FAILED state is active, &lt;b&gt;blink&lt;/b&gt; function of Egg object is called until it returns value false. Function &lt;b&gt;blink&lt;/b&gt; will take care of blinking egg.&lt;br /&gt;&lt;br /&gt;This new animation requires new variable in Egg class (file Egg.as):&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace; font-size: x-small;"&gt;private var blinking:int = 0;&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;div style="text-align: justify;"&gt;This variable will be used as a counter, that will be set only the first time &lt;b&gt;blink&lt;/b&gt; function is called, and decreased by one, during the execution of the function. According to the value of the variable, value of &lt;b&gt;phase&lt;/b&gt; variable is set. Value of &lt;b&gt;phase&lt;/b&gt; variable is used to display the egg icon with different levels of transparency.&lt;br /&gt;&lt;br /&gt;Add the implementation of &lt;b&gt;blink&lt;/b&gt; function inside the Egg class:&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace; font-size: x-small;"&gt;public function blink():Boolean&lt;br /&gt;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;if (blinking == 0)  &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;blinking = 70;&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;blinking--;&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;phase = blinking % 10;&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;if (blinking / 10 % 2 == 1)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;phase = 10 - phase;&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;return (blinking != 0);&lt;br /&gt;}&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;div style="text-align: justify;"&gt;&lt;center&gt;&lt;br /&gt;&lt;table border="1"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td align="center"&gt;&lt;embed align="center" height="480" src="http://bgrandovec.hostzi.com/Files/SnakesAdventure_P20.swf" type="application/x-shockwave-flash" width="480"&gt;&lt;/embed&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/center&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8678980820383323367-4634966565729846845?l=grandy-flexdev.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://grandy-flexdev.blogspot.com/feeds/4634966565729846845/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://grandy-flexdev.blogspot.com/2010/02/background-and-scrolling.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8678980820383323367/posts/default/4634966565729846845'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8678980820383323367/posts/default/4634966565729846845'/><link rel='alternate' type='text/html' href='http://grandy-flexdev.blogspot.com/2010/02/background-and-scrolling.html' title='Background and scrolling'/><author><name>Grandy</name><uri>http://www.blogger.com/profile/13061370372593845090</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='29' height='32' src='http://4.bp.blogspot.com/_4Xe_fkP2r2A/StiN3kMzX2I/AAAAAAAAAAU/wWM-ILREdfw/S220/MySelf.png'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://3.bp.blogspot.com/_4Xe_fkP2r2A/S4qWGO5yAUI/AAAAAAAAADQ/qw46fVxgVd0/s72-c/Background.jpg' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8678980820383323367.post-2968248530928729250</id><published>2010-02-24T06:20:00.001-08:00</published><updated>2010-03-25T08:09:50.955-07:00</updated><title type='text'>Collision detection</title><content type='html'>&lt;div style="text-align: justify;"&gt;This is not the first time that we are implementing collision detection in Snakes Adventure. First time we've made it in the game menu, where collision between mouse cursor and game options is detected on mouse events. In previous chapter we implemented &lt;b&gt;CheckCollision&lt;/b&gt; function, which once per frame, detects collision between the head of the snake and the egg. In this chapter we will improve collision detection between the head of the snake and the egg and add new code that checks if the head collides with the edges of the frame or other body parts.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;getBounds&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;We will implement &lt;b&gt;getBounds&lt;/b&gt; function in both classes: Snake and Egg. Both functions will return position and size of the sensitive area of the object. Position and size will be stored inside Rectangle object.&lt;br /&gt;&lt;br /&gt;Function &lt;b&gt;getBounds&lt;/b&gt; for Egg class (Egg.as) is simple:&lt;/div&gt;&lt;br /&gt;&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace; font-size: x-small;"&gt;public function getBounds():Rectangle    &lt;br /&gt;{ &lt;br /&gt;&amp;nbsp;&amp;nbsp;return new Rectangle(position.x - 5, position.y + 9, 11, 16);&lt;br /&gt;}&lt;/div&gt;&lt;br /&gt;&lt;div style="text-align: justify;"&gt;Function returns the area around the centre of the egg, which is a lot smaller than area, where pixels from the source image are copied to (because most of those pixels are transparent).&lt;br /&gt;&lt;br /&gt;Function &lt;b&gt;getBounds&lt;/b&gt; for Snake class (Snake .as) is far more complex, because it returns the area of one part of the body, not the whole body. Function requires parameter &lt;b&gt;part&lt;/b&gt; - the index of the part.&lt;/div&gt;&lt;br /&gt;&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace; font-size: x-small;"&gt;public function getBounds(part:int):Rectangle&lt;br /&gt;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;var pos:Point = partPosition[part];&lt;br /&gt;&amp;nbsp;&amp;nbsp;var direction:int = partDirection[part];&lt;br /&gt;&amp;nbsp;&amp;nbsp;var phase:int = partPhase[part];&lt;br /&gt;&amp;nbsp;&amp;nbsp;var rectangle:Rectangle = null;&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;if (part == 0) //head&lt;br /&gt;&amp;nbsp;&amp;nbsp;{        &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;phase = partPhase[1];         &lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;switch (direction)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;case NORTH:&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;rectangle = new Rectangle(pos.x - 6 + northHeadOffset[phase],pos.y + 12,13,16);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;break;          &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;case EAST:&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;rectangle = new Rectangle(pos.x - 4,pos.y + 6 - eastHeadOffset[phase],16,13); &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;break;          &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;case SOUTH:         &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;rectangle = new Rectangle(pos.x - 6 + southHeadOffset[phase],pos.y + 4,13,16);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;break;          &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;case WEST:&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;rectangle = new Rectangle(pos.x - 12,pos.y + 6 - westHeadOffset[phase],16,13);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;break;                             &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&amp;nbsp;&amp;nbsp;else&lt;br /&gt;&amp;nbsp;&amp;nbsp;if (part == partPosition.length - 1) //tail       &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;switch (direction)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;case NORTH:         &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;rectangle = new Rectangle(pos.x - 5 + northHeadOffset[phase],pos.y + 3,11,10);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;break;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;case EAST: &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;rectangle = new Rectangle(pos.x - 6,pos.y + 5 - eastHeadOffset[phase],10,11);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;break;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;case SOUTH: &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;rectangle = new Rectangle(pos.x - 5 + southHeadOffset[phase],pos.y + 7,11,10); &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;break;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;case WEST:&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;rectangle = new Rectangle(pos.x - 5,pos.y + 5 - westHeadOffset[phase],10,11);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;break;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}                          &lt;br /&gt;&amp;nbsp;&amp;nbsp;else  //body&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;switch (direction)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;case NORTH:         &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;rectangle = new Rectangle(pos.x - 6 + northHeadOffset[phase],pos.y + 2,12,4);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;break;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;case EAST: &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;rectangle = new Rectangle(pos.x - 2,pos.y + 6 - eastHeadOffset[phase],4,12);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;break;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;case SOUTH: &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;rectangle = new Rectangle(pos.x - 6 + southHeadOffset[phase],pos.y + 2,12,4); &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;break;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;case WEST:&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;rectangle = new Rectangle(pos.x - 2,pos.y + 6 - westHeadOffset[phase],4,12);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;break;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;return rectangle;&lt;br /&gt;}&lt;/div&gt;&lt;br /&gt;&lt;div style="text-align: justify;"&gt;Function returns rectangular area of each body part, position and size are similar to those, used in the &lt;b&gt;draw&lt;/b&gt; function, but area is a lot smaller.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;CheckCollision&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;Current version of collision detection between the head of the snake and the egg work like this: if horizontal or vertical distance between both positions was less than 12 pixels, collision was detected.&lt;br /&gt;&lt;br /&gt;Now that we have both &lt;b&gt;getBounds&lt;/b&gt; functions implemented, we can use them to improve collision detection between the head of the snake and the egg. Replace content of &lt;b&gt;CheckCollision&lt;/b&gt; function in Game.as:&lt;/div&gt;&lt;br /&gt;&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace; font-size: x-small;"&gt;var headBounds:Rectangle = snake.getBounds(0);&lt;br /&gt;&lt;br /&gt;//check egg&lt;br /&gt;if ((egg != null) &amp;amp;&amp;amp; egg.active())&lt;br /&gt;&amp;nbsp;&amp;nbsp;if (headBounds.intersects(egg.getBounds()))&lt;br /&gt;&amp;nbsp;&amp;nbsp;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;egg.eat();&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;snake.append();&lt;br /&gt;&amp;nbsp;&amp;nbsp;}&lt;/div&gt;&lt;br /&gt;&lt;div style="text-align: justify;"&gt;First, area of snakes head is stored into &lt;b&gt;headBounds&lt;/b&gt; Rectangle and if egg is "active", &lt;b&gt;intersects&lt;/b&gt; function checks if there is collision between two Rectangles. The rest of the source code is the same as in previous version.&lt;br /&gt;&lt;br /&gt;Collision detection is more precise now, because snake's head movement and direction are now taken into account. But you will most probably not notice any difference while playing the game. &lt;br /&gt;&lt;br /&gt;In the original game, the snake dies when the head hits the edge of the game area or body part. This is not hard to implement. Add this section at the end of &lt;b&gt;CheckCollision&lt;/b&gt; function:&lt;/div&gt;&lt;br /&gt;&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace; font-size: x-small;"&gt;//check the edge of the screen&lt;br /&gt;if ((headBounds.x &amp;lt;= 0) || (SCREEN_WIDTH - headBounds.x - headBounds.width &amp;lt;= 0) ||&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;(headBounds.y - headBounds.height &amp;lt;= 0) || (SCREEN_HEIGHT - headBounds.y &amp;lt;= 0))&lt;br /&gt;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;snake.kill();&lt;br /&gt;&amp;nbsp;&amp;nbsp;return false;&lt;br /&gt;} &lt;/div&gt;&lt;br /&gt;&lt;div style="text-align: justify;"&gt;Simple, isn't it? The &lt;b&gt;if&lt;/b&gt; statement checks if &lt;b&gt;headBounds&lt;/b&gt; Rectangle is outside left, right, bottom or top edge of the game frame. If it is, snake dies. We are using unimplemented function &lt;b&gt;kill&lt;/b&gt; from Snake class, that will be implemented at the end of the chapter. Statement &lt;b&gt;return false;&lt;/b&gt; is currently illegal, because function declaration says that function doesn't return anything. Replace &lt;b&gt;void&lt;/b&gt; with &lt;b&gt;Boolean&lt;/b&gt; in the function declaration. From now on, we will use return value to indicate if snake died (false) or not (true).&lt;br /&gt;&lt;br /&gt;The following section of code checks if the head of the snake hit the body part. Add it to the end of &lt;b&gt;CheckCollision&lt;/b&gt; function:&lt;/div&gt;&lt;br /&gt;&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace; font-size: x-small;"&gt;//check body&lt;br /&gt;for (var i:int = 7; i &amp;lt; snake.getLength(); i++)&lt;br /&gt;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;var partBounds:Rectangle = snake.getBounds(i);&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;if (headBounds.intersects(partBounds))&lt;br /&gt;&amp;nbsp;&amp;nbsp;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;snake.kill();&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return false;&lt;br /&gt;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;return true;&lt;/div&gt;&lt;br /&gt;&lt;div style="text-align: justify;"&gt;This code checks if rectangular area of body parts intersects with the head. If collision is detected, snake dies, function exits and value false is returned. If there is no collision, function exits and returns true. There is another undefined function from Snake class used here - &lt;b&gt;getLength&lt;/b&gt; function will be implemented at the end of the chapter. &lt;br /&gt;&lt;br /&gt;Great, now the game knows when the player made mistake. There are only few things we have to do, before we are done:&lt;br /&gt;- stop the game&lt;br /&gt;- display animation of dying snake&lt;br /&gt;- perform fade out &lt;br /&gt;- restart the level&lt;br /&gt;&lt;br /&gt;&lt;b&gt;GAME_KILLED/FADE_OUT&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;These two constants define two new game states. During the GAME_KILLED state, animation of dying snake will be displayed. GAME_FADE_OUT state will be active for one second and within this second, fade out effect will be applied. Add both definitions to other constants at the top of Game.as:&lt;/div&gt;&lt;br /&gt;&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace; font-size: x-small;"&gt;private static const GAME_KILLED:int         = 5;&lt;br /&gt;private static const GAME_FADE_OUT:int       = 6;&lt;/div&gt;&lt;br /&gt;&lt;div style="text-align: justify;"&gt;Now we will use the value that is returned by &lt;b&gt;CheckCollision&lt;/b&gt; function. Change the &lt;b&gt;CheckCollision&lt;/b&gt; statement in Draw_Game function (GAME_PLAYED state) to:&lt;/div&gt;&lt;br /&gt;&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace; font-size: x-small;"&gt;if (!CheckCollision())&lt;br /&gt;&amp;nbsp;&amp;nbsp;ChangeState_Game(GAME_KILLED); &lt;/div&gt;&lt;br /&gt;&lt;div style="text-align: justify;"&gt;When the false value is returned (snake died), game state is change to GAME_KILLED. &lt;br /&gt;&lt;br /&gt;Add the source code for both states inside &lt;b&gt;switch&lt;/b&gt; statement in Draw_Game function:&lt;/div&gt;&lt;br /&gt;&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace; font-size: x-small;"&gt;case GAME_KILLED:&lt;br /&gt;&amp;nbsp;&amp;nbsp;if (!snake.kill())&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;ChangeState_Game(GAME_FADE_OUT);   &lt;br /&gt;&amp;nbsp;&amp;nbsp;break;&lt;br /&gt;case GAME_FADE_OUT: &lt;br /&gt;&amp;nbsp;&amp;nbsp;Apply_FadeEffect(gameTime); &lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;if (gameTime &amp;gt;= 1)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Restart_Game();       &lt;br /&gt;&amp;nbsp;&amp;nbsp;break;  &lt;/div&gt;&lt;br /&gt;&lt;div style="text-align: justify;"&gt;While the GAME_KILLED is active &lt;b&gt;kill&lt;/b&gt; function (still unimplemented function that takes care of animation of dying snake) from Snake class is called until it returns value false. At this point GAME_FADE_OUT becomes active, during this state fade out effect is applied for one second and when the screen is completely black, &lt;b&gt;Restart_Game&lt;/b&gt; function is called.&lt;br /&gt;&lt;br /&gt;Before we implement this function, you can make a little change in &lt;b&gt;SetMouseCursor&lt;/b&gt; function. Change the last statement of the function to: &lt;/div&gt;&lt;br /&gt;&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace; font-size: x-small;"&gt;SetMouseCursor(cursorDirection,gameState &amp;gt; GAME_PLAYED);  &lt;/div&gt;&lt;br /&gt;&lt;div style="text-align: justify;"&gt;Now the grey mouse cursor icon will be displayed while GAME_KILLED or GAME_FADE_OUT state is active.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Restart_Game&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;Implementation of this function is very similar to &lt;b&gt;New_Game&lt;/b&gt; function, that is why the code is positioned next to it:&lt;/div&gt;&lt;br /&gt;&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace; font-size: x-small;"&gt;private function Restart_Game():void&lt;br /&gt;{  &lt;br /&gt;&amp;nbsp;&amp;nbsp;snake = new Snake(SCREEN_WIDTH / 2,SCREEN_HEIGHT / 3,20); &lt;br /&gt;&amp;nbsp;&amp;nbsp;egg = new Egg(true); &lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;ChangeState_Game(GAME_FADE_IN);&lt;br /&gt;}&lt;/div&gt;&lt;br /&gt;&lt;div style="text-align: justify;"&gt;New Snake and Egg objects are created the same way as they are in &lt;b&gt;New_Game&lt;/b&gt; function, game state is also set to GAME_FADE_IN. The only difference is that &lt;b&gt;New_Game&lt;/b&gt; function also sets &lt;b&gt;level&lt;/b&gt; variable to 1.&lt;br /&gt;&lt;br /&gt;There is one more thing we have to do, to make sure everything looks the same after restart. We have to reset &lt;b&gt;nextPosition&lt;/b&gt; counter in Egg class, otherwise the initial egg will most probably not be at the same position. Replace Egg constructor in Egg.as file:&lt;/div&gt;&lt;br /&gt;&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace; font-size: x-small;"&gt;public function Egg(initial:Boolean) &lt;br /&gt;{      &lt;br /&gt;&amp;nbsp;&amp;nbsp;if (initial)&lt;br /&gt;&amp;nbsp;&amp;nbsp;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;phase = 10; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;nextPosition = 0;&lt;br /&gt;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&amp;nbsp;&amp;nbsp;else&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;phase = 1;     &lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;position = positions[nextPosition];         &lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;nextPosition++;&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;if (nextPosition == positions.length)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;nextPosition = 0;        &lt;br /&gt;}&lt;/div&gt;&lt;br /&gt;&lt;div style="text-align: justify;"&gt;If value of parameter &lt;b&gt;initial&lt;/b&gt; is true, value of &lt;b&gt;nextPosition&lt;/b&gt; variable is set to 0. The rest of the code is the same as before.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Snake class&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;We have to implement all the functions in Snake class (Snake.as) that we used in &lt;b&gt;CheckCollision&lt;/b&gt; function: &lt;b&gt;getLength&lt;/b&gt; and &lt;b&gt;kill&lt;/b&gt;. Implementation of the first one is simple:&lt;/div&gt;&lt;br /&gt;&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace; font-size: x-small;"&gt;public function getLength():int&lt;br /&gt;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;return partPosition.length;&lt;br /&gt;} &lt;/div&gt;&lt;br /&gt;&lt;div style="text-align: justify;"&gt;Function returns the number of body parts, which is equal to number of objects in each Array from Snake class.&lt;br /&gt;&lt;br /&gt;Before we start implementing the animation of dying snake, I advise you to try the game at the bottom of the page to see how animation snake looks like. In the first phase body parts are slowly transformed into bones. In the second phase bones are transformed into half-transparent bones and in the final phase bones slowly disappear.&lt;br /&gt;&lt;br /&gt;Of course, this animation requires new graphics. I added new images into Snake.png file, that now looks like this:&lt;br /&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://3.bp.blogspot.com/_4Xe_fkP2r2A/S4gEet3eH0I/AAAAAAAAADI/QoOeHoHyKbU/s1600-h/Snake.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://3.bp.blogspot.com/_4Xe_fkP2r2A/S4gEet3eH0I/AAAAAAAAADI/QoOeHoHyKbU/s320/Snake.png" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;If you download project &lt;a href="http://bgrandovec.hostzi.com/Files/SnakesAdventure_P19.zip"&gt;package&lt;/a&gt; for this chapter, you can find this image inside Images folder. Body parts, bones and half-transparent bones are separated by 80 pixels in vertical direction.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Snake.kill&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;The &lt;b&gt;kill&lt;/b&gt; function is called once from &lt;b&gt;CheckCollision&lt;/b&gt; function and once per frame from &lt;b&gt;Draw_Game&lt;/b&gt; while GAME_KILLED state is active. When &lt;b&gt;kill&lt;/b&gt; function returns false, animation of dying snake is complete and game state GAME_FADE_OUT becomes active.&lt;br /&gt;&lt;br /&gt;Before we start implementing &lt;b&gt;kill&lt;/b&gt; function, we will add two variables at the beginning of class:&lt;/div&gt;&lt;br /&gt;&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace; font-size: x-small;"&gt;private var killed:Boolean = false;&lt;/div&gt;&lt;br /&gt;&lt;div style="text-align: justify;"&gt;The first time &lt;b&gt;kill&lt;/b&gt; function will execute, the value of variable will be set to true.&lt;/div&gt;&lt;br /&gt;&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace; font-size: x-small;"&gt;private var deadPart:Array = new Array(); &lt;/div&gt;&lt;br /&gt;&lt;div style="text-align: justify;"&gt;This array will be used for animation, each body part will have its own numeric value inside this array, that will represent the animation phase.&lt;br /&gt;&lt;br /&gt;Add implementation of &lt;b&gt;kill&lt;/b&gt; to Snake class:&lt;/div&gt;&lt;br /&gt;&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace; font-size: x-small;"&gt;public function kill():Boolean&lt;br /&gt;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;if (!killed)&lt;br /&gt;&amp;nbsp;&amp;nbsp;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;killed = true;&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;for (var i:int = 0; i &amp;lt; partPosition.length; i++)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;deadPart.push(0);&lt;br /&gt;&amp;nbsp; }&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;if ((deadPart.indexOf(0) == -1) &amp;amp;&amp;amp;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;(deadPart.indexOf(1) == -1) &amp;amp;&amp;amp;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;(deadPart.indexOf(2) == -1))&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return false;&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;for (var j:int = 0; j &amp;lt;= 2; j++)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if (deadPart.indexOf(j) != -1)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;while (true)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;var index:int = (int)(Math.random() * (deadPart.length - 0.1));&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if (deadPart[index] == j)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;deadPart[index] = deadPart[index] + 1;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return true;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;return true;&lt;br /&gt;}  &lt;/div&gt;&lt;br /&gt;&lt;div style="text-align: justify;"&gt;The first time &lt;b&gt;kill&lt;/b&gt; function is executed, &lt;b&gt;killed&lt;/b&gt; variable is set to true and &lt;b&gt;deadParts&lt;/b&gt; Array gains one numeric object with zero value for each body part.&lt;br /&gt;&lt;br /&gt;"if ((deadPart.indexOf(0) ..." statement checks if there is an object in &lt;b&gt;deadParts&lt;/b&gt; Array with value 0, 1 or 2. Function &lt;b&gt;indexOf&lt;/b&gt; checks if there is an object in the array, that has value equal to value of the parameter, and returns its index. -1 indicates that there is no such object.&lt;br /&gt;&lt;br /&gt;If all objects have value 3, it means that animation is complete and function exits and value false is returned.&lt;br /&gt;&lt;br /&gt;The last section of the code checks if there is an object in &lt;b&gt;deadParts&lt;/b&gt; Array with value 0, 1 or 2. If there is no object with value 0, first phase of animation is complete. If there is object with value 1 in the Array in means that animation is still in the second phase. &lt;br /&gt;&lt;br /&gt;Code inside &lt;b&gt;while&lt;/b&gt; loop randomly selects an object in the array and if this object has desired value (value of &lt;b&gt;j&lt;/b&gt; counter), its value is increased by one. For example, if in the first phase of animation, fifth object in the array is randomly selected, its value is increased from zero to one and player can see the fifth body part transformed into bones.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Snake.draw&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;Animation of dying snake requires a lot of changes in &lt;b&gt;draw&lt;/b&gt; function, unfortunately, source code of this function has become much too long to be displayed on this page. I advise you to download project &lt;a href="http://bgrandovec.hostzi.com/Files/SnakesAdventure_P19.zip"&gt;package&lt;/a&gt; for this chapter and copy the content of &lt;b&gt;draw&lt;/b&gt; function from Snake.as into your own project.&lt;br /&gt;&lt;br /&gt;New Snake.png file requires changes in the creation of BitmapData object constructor, because the height of the source image has increased:&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace; font-size: x-small;"&gt;bitmap = new BitmapData(96,240,true,0x00000000);&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;div style="text-align: justify;"&gt;At the beginning of &lt;b&gt;for&lt;/b&gt; loop that iterates through all body parts, there is new definition of &lt;b&gt;deadPartOffset&lt;/b&gt; variable with value set to 0. When &lt;b&gt;deadPart&lt;/b&gt; array is not empty, game is in the "dying snake animation" mode. If &lt;b&gt;deadPart&lt;/b&gt; object of the part, that function is currently drawing, has value 3, drawing is skipped. Otherwise &lt;b&gt;deadPartOffset&lt;/b&gt; value is calculated from &lt;b&gt;deadPart&lt;/b&gt; object value multiplied by 80, which is the vertical distance between source images for each phase of animation:&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace; font-size: x-small;"&gt;var deadPartOffset:int = 0;&lt;br /&gt;&lt;br /&gt;if (deadPart.length &gt; 0) &lt;br /&gt;&amp;nbsp;&amp;nbsp;if (deadPart[i] == 3)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;continue;&lt;br /&gt;&amp;nbsp;&amp;nbsp;else&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;deadPartOffset = deadPart[i] * 80;&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;div style="text-align: justify;"&gt;Value of &lt;b&gt;deadPartOffset&lt;/b&gt; variable has been used in each &lt;b&gt;copyPixels&lt;/b&gt; statement. Here is one example: &lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace; font-size: x-small;"&gt;screenBuffer.copyPixels(bitmap,&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;new Rectangle(72,51 + deadPartOffset,10,11),&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;new Point(pos.x - 12,visible.y - pos.y - 5)); &lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;div style="text-align: justify;"&gt;&lt;center&gt;&lt;br /&gt;&lt;table border="1"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td align="center"&gt;&lt;embed align="center" height="480" src="http://bgrandovec.hostzi.com/Files/SnakesAdventure_P19.swf" type="application/x-shockwave-flash" width="480"&gt;&lt;/embed&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/center&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8678980820383323367-2968248530928729250?l=grandy-flexdev.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://grandy-flexdev.blogspot.com/feeds/2968248530928729250/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://grandy-flexdev.blogspot.com/2010/02/collision-detection.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8678980820383323367/posts/default/2968248530928729250'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8678980820383323367/posts/default/2968248530928729250'/><link rel='alternate' type='text/html' href='http://grandy-flexdev.blogspot.com/2010/02/collision-detection.html' title='Collision detection'/><author><name>Grandy</name><uri>http://www.blogger.com/profile/13061370372593845090</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='29' height='32' src='http://4.bp.blogspot.com/_4Xe_fkP2r2A/StiN3kMzX2I/AAAAAAAAAAU/wWM-ILREdfw/S220/MySelf.png'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://3.bp.blogspot.com/_4Xe_fkP2r2A/S4gEet3eH0I/AAAAAAAAADI/QoOeHoHyKbU/s72-c/Snake.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8678980820383323367.post-4302655718793238510</id><published>2010-02-18T09:04:00.000-08:00</published><updated>2010-03-25T08:00:09.538-07:00</updated><title type='text'>Eating the eggs</title><content type='html'>&lt;div style="text-align: justify;"&gt;In this chapter, I will not talk about how to cook or fry the egg. Instead I will teach you how to displays the egg on the screen and how to make the game able to recognize when it has been eaten by the snake. &lt;br /&gt;&lt;br /&gt;We will create new class that takes care of creation and presentation of the egg, add new code that checks collision between the egg and the snake and increases the length of the snake, after the egg is eaten. At the end we will make some improvements in the code that controls the movement of the snake.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Egg class&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;Class represents the object in the game that can be eaten by the snake. Implementation of the class takes care of creation, positioning and drawing. We will put complete implementation of the class into one file (Egg.as) and put this file inside Classes folder. Here is the content of the file:&lt;/div&gt;&lt;br /&gt;&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace; font-size: x-small;"&gt;package Classes &lt;br /&gt;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;import flash.geom.*; &lt;br /&gt;&amp;nbsp;&amp;nbsp;import flash.display.*; &lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;public class Egg&lt;br /&gt;&amp;nbsp;&amp;nbsp;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;private var position:Point = null;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;private var eaten:Boolean = false;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;private var phase:int = 0;&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;private static var positions:Array = new Array(new Point(120,430),new Point(300,320),new Point(70,30),new Point(240,280),new Point(400,130),new Point(360,180));  &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;private static var nextPosition:int = 0;&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;public function Egg(initial:Boolean) &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{      &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;position = positions[nextPosition];&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;phase = initial ? 10 : 1;      &lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;nextPosition++;&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if (nextPosition == positions.length)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;nextPosition = 0;        &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;public function getPosition():Point&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return position;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;public function active():Boolean&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return (phase == 10);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}    &lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;public function eat():void&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if (active())    &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;eaten = true;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;public function update():Boolean&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if (eaten)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;phase--;&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if (phase &amp;lt;= 0)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return false;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;else&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;phase++;&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if (phase &amp;gt; 10)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;phase = 10;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return true;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;[Embed(source="../Images/Egg.png")] private var eggImg:Class;&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;private var bitmap:BitmapData = null;&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;public function draw(screenBuffer:BitmapData,visible:Rectangle):void&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if (bitmap == null)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;bitmap = new BitmapData(300,30,true,0x00000000);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;bitmap.draw(new eggImg());&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}    &lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;screenBuffer.copyPixels(bitmap,&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;new Rectangle(300 - phase * 30,0,30,30),&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;new Point(position.x - 15,visible.y - position.y - 15)); &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&amp;nbsp;&amp;nbsp;} &lt;br /&gt;}&lt;/div&gt;&lt;br /&gt;&lt;div style="text-align: justify;"&gt;Implementation of this class is simple compared to the &lt;b&gt;Snake&lt;/b&gt; class, but it still requires some explanation. Class has the following members:&lt;br /&gt;- &lt;b&gt;position&lt;/b&gt;: contains horizontal and vertical position of the egg in the game world&lt;br /&gt;- &lt;b&gt;eaten&lt;/b&gt;: is set to &lt;b&gt;true&lt;/b&gt; when the snake eats the egg&lt;br /&gt;- &lt;b&gt;phase&lt;/b&gt;: is used to display the egg image with different levels of transparency&lt;br /&gt;- &lt;b&gt;positions&lt;/b&gt;: contain six different positions, where eggs are displayed. You can add new positions if you like&lt;br /&gt;- &lt;b&gt;nextPosition&lt;/b&gt;: index of the Point in &lt;b&gt;positions&lt;/b&gt; Array that will be used to set the position of new egg&lt;br /&gt;- &lt;b&gt;constructor&lt;/b&gt; (Egg): parameter &lt;b&gt;initial&lt;/b&gt; must be set to true for the egg that is made at the beginning of the stage. First egg is visible after it has been made (&lt;b&gt;phase&lt;/b&gt; set to 10), other eggs are not (&lt;b&gt;phase&lt;/b&gt; set to 1). Position of the first egg is stored in the first element in &lt;b&gt;positions&lt;/b&gt; Array, position of the second egg is in the second element... when the value of &lt;b&gt;nextPosition&lt;/b&gt; variable reaches the end of the Array, it is set to zero and first element is used again.&lt;br /&gt;- &lt;b&gt;getPosition&lt;/b&gt;: returns position of the egg.&lt;br /&gt;- &lt;b&gt;active&lt;/b&gt;: returns true only when &lt;b&gt;phase&lt;/b&gt; variable has value 10.&lt;br /&gt;- &lt;b&gt;eat&lt;/b&gt;: this function will be called when the snake is inside the range of the egg. Function checks if egg is active and it has not been eaten before and then sets the &lt;b&gt;eaten&lt;/b&gt; to true.&lt;br /&gt;- &lt;b&gt;update&lt;/b&gt;: function will be called once per frame. When the egg is eaten, value of &lt;b&gt;phase&lt;/b&gt; will be decrease by one until it reaches the zero. At this point function returns false, which indicates that egg has been eaten and it has completely disappeared and can be replaced with new one.&lt;br /&gt;- &lt;b&gt;draw&lt;/b&gt;: creates BitmpaData from embedded image if necessary and displays the egg image with required level of transparency. Level of transparency is controlled with &lt;b&gt;phase&lt;/b&gt; variable.&lt;br /&gt;&lt;br /&gt;Egg.png contains egg icons with ten different levels of transparency and can be found inside Images folder in &lt;a href="http://bgrandovec.hostzi.com/Files/SnakesAdventure_P18.zip"&gt;project&lt;/a&gt; package for this chapter.&lt;br /&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://4.bp.blogspot.com/_4Xe_fkP2r2A/S4AImFz9ybI/AAAAAAAAADA/IynzAXcAonA/s1600-h/Egg.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://4.bp.blogspot.com/_4Xe_fkP2r2A/S4AImFz9ybI/AAAAAAAAADA/IynzAXcAonA/s320/Egg.png" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;&lt;b&gt;Game.as&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;Egg class implements all the functionality to display the egg on the screen, we just have to use it. Open Game.as file and add definition of &lt;b&gt;egg&lt;/b&gt; variable right after &lt;b&gt;snake&lt;/b&gt; variable:&lt;/div&gt;&lt;br /&gt;&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace; font-size: x-small;"&gt;private var egg:Egg = null;&lt;/div&gt;&lt;br /&gt;&lt;div style="text-align: justify;"&gt;We only need one variable, because there can be only one egg in the game at the time. First egg object will be made at the beginning of the game (New_Game function), value of &lt;b&gt;initial&lt;/b&gt; parameter is set to true.&lt;/div&gt;&lt;br /&gt;&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace; font-size: x-small;"&gt;egg = new Egg(true); &lt;/div&gt;&lt;br /&gt;&lt;div style="text-align: justify;"&gt;Now we can display the egg by calling &lt;b&gt;draw&lt;/b&gt; function int Draw_Game function. Insert this code before the code that draws the snake:&lt;/div&gt;&lt;br /&gt;&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace; font-size: x-small;"&gt;if (egg != null)&lt;br /&gt;&amp;nbsp;&amp;nbsp;egg.draw(screenBuffer,new Rectangle(0,SCREEN_HEIGHT,SCREEN_WIDTH,SCREEN_HEIGHT));  &lt;/div&gt;&lt;br /&gt;&lt;div style="text-align: justify;"&gt;We have to call &lt;b&gt;update&lt;/b&gt; function once per frame. Draw_Game function is executed once per frame, that's why we will call &lt;b&gt;update&lt;/b&gt; here. We have to call it only when GAME_PLAYED state is active. Replace existing code in Draw_Game function for this state with:&lt;/div&gt;&lt;br /&gt;&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace; font-size: x-small;"&gt;if (egg != null)&lt;br /&gt;&amp;nbsp;&amp;nbsp;if (!egg.update())&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;egg = new Egg(false);&lt;br /&gt;&lt;br /&gt;if (snake != null)&lt;br /&gt;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;snake.move();&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;CheckCollision();&lt;br /&gt;}&lt;/div&gt;&lt;br /&gt;&lt;div style="text-align: justify;"&gt;Function &lt;b&gt;update&lt;/b&gt; returns false when the egg has been eaten and it has completely disappeared. This is good time to create new egg, but this time with &lt;b&gt;initial&lt;/b&gt; parameter set to false.&lt;br /&gt;&lt;br /&gt;Right after &lt;b&gt;snake.move&lt;/b&gt; statement, function &lt;b&gt;CheckCollision&lt;/b&gt; checks if there is collision between the egg and the snake. Implementation of this function is our next task.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;CheckCollision&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;Function CheckCollision checks if there is collision between the egg and the head of the snake. The head is inside the range when horizontal or vertical distance is less or equal 12 pixels. This is not very precise solution but in practice it works OK:&lt;/div&gt;&lt;br /&gt;&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace; font-size: x-small;"&gt;private function CheckCollision():void&lt;br /&gt;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;var snakePosition:Point = snake.getPosition();&lt;br /&gt;&amp;nbsp;&amp;nbsp;var snakeDirection:int = snake.getDirection(); &lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;if ((egg != null) &amp;amp;&amp;amp; egg.active())&lt;br /&gt;&amp;nbsp;&amp;nbsp;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;var distanceToEgg:Point = egg.getPosition().subtract(snakePosition);&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if ((Math.abs(distanceToEgg.x) &amp;lt;= 12) &amp;amp;&amp;amp; (Math.abs(distanceToEgg.y) &amp;lt;= 12))&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;egg.eat();&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;snake.append();&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;} &lt;/div&gt;&lt;br /&gt;&lt;div style="text-align: justify;"&gt;When the snake is close enough to the egg, &lt;b&gt;eat&lt;/b&gt; function is called which sets the &lt;b&gt;eaten&lt;/b&gt; variable to true. Length of the snake is increased within &lt;b&gt;append&lt;/b&gt; function from Snake class.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Snake.append&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;Task of append function is quite simple: it adds new part at the end of the snake body. In fact it copies all three properties (position, direction and phase) of the last part, adjusts the position and phase and pushes new values at the end of Array.&lt;/div&gt;&lt;br /&gt;&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace; font-size: x-small;"&gt;public function append():void&lt;br /&gt;{ &lt;br /&gt;&amp;nbsp;&amp;nbsp;var position:Point = partPosition[partPosition.length - 1];      &lt;br /&gt;&amp;nbsp;&amp;nbsp;var direction:int = partDirection[partPosition.length - 1];&lt;br /&gt;&amp;nbsp;&amp;nbsp; var phase:int = partPhase[partPosition.length - 1];&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;switch (direction)&lt;br /&gt;&amp;nbsp;&amp;nbsp;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;case NORTH:&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;partPosition.push(new Point(position.x,position.y - SPEED));   &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;partPhase.push((phase + 1) % 9);   &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;break;&lt;br /&gt;&amp;nbsp;&amp;nbsp;case EAST:&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;partPosition.push(new Point(position.x - SPEED,position.y));      &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;partPhase.push(((phase - 1) &amp;lt; 0 ? 8 : phase - 1)  % 9);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;break;&lt;br /&gt;&amp;nbsp;&amp;nbsp;case SOUTH:&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;partPosition.push(new Point(position.x,position.y + SPEED));&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;partPhase.push(((phase - 1) &amp;lt; 0 ? 8 : phase - 1)  % 9);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;break;&lt;br /&gt;&amp;nbsp;&amp;nbsp;case WEST:&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;partPosition.push(new Point(position.x + SPEED,position.y));&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;partPhase.push((phase + 1) % 9);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;break;&lt;br /&gt;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;partDirection.push(direction);&lt;br /&gt;}  &lt;/div&gt;&lt;br /&gt;&lt;div style="text-align: justify;"&gt;You can now compile and play the game. When the game begins there is an egg located in upper-left corner. When the snake is close enough, the egg disappears and new one appears in lower right corner. Length of the snake is slightly increased, maybe you will not notice this after first egg, but after eating five or six eggs, snake will become significantly longer.&lt;br /&gt;&lt;br /&gt;I am sure, you had problems controlling the snake. It is not your fault, controls are not very precise and too complicated. We have to fix this.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Phase 4&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;In &lt;a href="http://grandy-flexdev.blogspot.com/2010/02/snake-advanced-version.html"&gt;chapter 16&lt;/a&gt; we implemented advanced version of snake. If you remember, snake can change direction only when &lt;b&gt;phase&lt;/b&gt; value of leading part equals 0. In the worst case scenario, snake moves by 32 pixels (SPEED * 8) before it changes the direction. This is the reason why it is sometimes almost impossible to hit the egg. I made some changes in source code of &lt;b&gt;move&lt;/b&gt; function: now snake can change direction even if &lt;b&gt;phase&lt;/b&gt; value of leading part equals 4.&lt;br /&gt;&lt;br /&gt;New version of &lt;b&gt;move&lt;/b&gt; function can be found in Snake.as file inside &lt;a href="http://bgrandovec.hostzi.com/Files/SnakesAdventure_P18.zip"&gt;project&lt;/a&gt; package for this chapter. If you recompile and try the game again, you will see that snake now changes direction almost immediately after mouse is pressed.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;SetGameCursor/MouseDown_Game&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;At the moment, controlling of the snake requires a lot of mouse movement. We can make things a lot more simple if we change the rules. When snake is moving in vertical direction, we will only check if mouse cursor is on the left or right side at the time of mouse click. When snake is moving in horizontal direction, we will check if mouse is above or below. This makes the code much more simple and controlling much easier.&lt;br /&gt;&lt;br /&gt;New version of SetGameCursor function in Game.as now looks like this:&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace; font-size: x-small;"&gt;private function SetGameCursor():void  &lt;br /&gt;{  &lt;br /&gt;&amp;nbsp;&amp;nbsp;var mx:int = mouseX;&lt;br /&gt;&amp;nbsp;&amp;nbsp;var my:int = mouseY;&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;my = SCREEN_HEIGHT - my;&lt;br /&gt;&amp;nbsp;&amp;nbsp;var position:Point = snake.getPosition();&lt;br /&gt;&amp;nbsp;&amp;nbsp;var direction:int = snake.getDirection(); &lt;br /&gt;&amp;nbsp;&amp;nbsp;var cursorDirection:int = 0;&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;if ((direction == Snake.NORTH) || (direction == Snake.SOUTH))&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if (mx - position.x &gt; 0)  &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;cursorDirection = Snake.EAST;      &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;else&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;cursorDirection = Snake.WEST; &lt;br /&gt;&amp;nbsp;&amp;nbsp;else&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if (my - position.y &gt; 0)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;cursorDirection = Snake.NORTH;      &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;else&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;cursorDirection = Snake.SOUTH; &lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;SetMouseCursor(cursorDirection,false);  &lt;br /&gt;}&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;div style="text-align: justify;"&gt;Source code for GAME_PLAYED state inside MouseDown_Game function:&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace; font-size: x-small;"&gt;case GAME_PLAYED:&lt;br /&gt;&amp;nbsp;&amp;nbsp;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;my = SCREEN_HEIGHT - my;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;var position:Point = snake.getPosition();&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;var direction:int = snake.getDirection(); &lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if ((direction == Snake.NORTH) || (direction == Snake.SOUTH))&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if (mx - position.x &gt; 0)  &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;snake.setDirection(Snake.EAST);      &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;else&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;snake.setDirection(Snake.WEST); &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;else&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if (my - position.y &gt; 0)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;snake.setDirection(Snake.NORTH);      &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;else&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;snake.setDirection(Snake.SOUTH); &lt;br /&gt;}&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;div style="text-align: justify;"&gt;Controlling is now much more comfortable, source code is much shorter and more clear.&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;div style="text-align: justify;"&gt;&lt;center&gt;&lt;br /&gt;&lt;table border="1"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td align="center"&gt;&lt;embed align="center" height="480" src="http://bgrandovec.hostzi.com/Files/SnakesAdventure_P18.swf" type="application/x-shockwave-flash" width="480"&gt;&lt;/embed&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/center&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8678980820383323367-4302655718793238510?l=grandy-flexdev.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://grandy-flexdev.blogspot.com/feeds/4302655718793238510/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://grandy-flexdev.blogspot.com/2010/02/eating-eggs.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8678980820383323367/posts/default/4302655718793238510'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8678980820383323367/posts/default/4302655718793238510'/><link rel='alternate' type='text/html' href='http://grandy-flexdev.blogspot.com/2010/02/eating-eggs.html' title='Eating the eggs'/><author><name>Grandy</name><uri>http://www.blogger.com/profile/13061370372593845090</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='29' height='32' src='http://4.bp.blogspot.com/_4Xe_fkP2r2A/StiN3kMzX2I/AAAAAAAAAAU/wWM-ILREdfw/S220/MySelf.png'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/_4Xe_fkP2r2A/S4AImFz9ybI/AAAAAAAAADA/IynzAXcAonA/s72-c/Egg.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8678980820383323367.post-3485020610523674241</id><published>2010-02-14T07:23:00.000-08:00</published><updated>2010-03-25T07:50:57.484-07:00</updated><title type='text'>Custom mouse cursors</title><content type='html'>&lt;div style="text-align: justify;"&gt;In Flex applications, system arrow cursor is displayed by default. Developers can use other icons defined in MouseCursor class, like hourglass, hand... Icons look fine when user interface is made from Flex UI components, but are a bit to boring for games and usually don't fit with the games graphics at all.&lt;br /&gt;&lt;br /&gt;So far, we didn't pay any attention to mouse cursor, that is why only default arrow icon was displayed in the game. In this chapter we will embed nine new images into the game and use them to display mouse cursor. One image will be used for the mouse cursor in the game menu, the rest will be set according to location of mouse cursor and the snake. New images can be found inside Images folder in &lt;a href="http://bgrandovec.hostzi.com/Files/SnakesAdventure_P17.zip"&gt;project&lt;/a&gt; package for this chapter.&lt;br /&gt;&lt;br /&gt;There are two ways to implement custom mouse cursors in the Flex applications: &lt;br /&gt;- hiding mouse cursor with &lt;b&gt;Mouse.hide()&lt;/b&gt; and drawing new image, part of the image or animation, on the location of mouse cursor &lt;br /&gt;- replacing active mouse cursor with new image by using functions from CursorManager class.&lt;br /&gt;&lt;br /&gt;We will use the second approach to learn how to use CustomManager, although first approach is more flexible. You can see how new mouse cursors look if you start the game bellow. If the snake runs out of the screen, reload the page to restart the game.&lt;br /&gt;&lt;br /&gt;&lt;div style="text-align: justify;"&gt;&lt;center&gt;&lt;br /&gt;&lt;br /&gt;&lt;table border="1"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td align="center"&gt;&lt;embed align="center" height="480" src="http://bgrandovec.hostzi.com/Files/SnakesAdventure_P17.swf" type="application/x-shockwave-flash" width="480"&gt;&lt;/embed&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/center&gt;&lt;/div&gt;&lt;br /&gt;&lt;b&gt;CursorManager&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;Adobe® Flex Language Reference: The CursorManager class controls a prioritized list of cursors, where the cursor with the highest priority is currently visible. If the cursor list contains more than one cursor with the same priority, the Cursor Manager displays the most recently created cursor.&lt;br /&gt;&lt;br /&gt;Before we can use CursorManager, we have to import it. Add new import statement into SnakesAdventure.as:&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace; font-size: x-small;"&gt;import mx.managers.CursorManager;&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;div style="text-align: justify;"&gt;CursorManager class contains fifteen public functions but we will use only two: &lt;b&gt;removeCursor&lt;/b&gt; and &lt;b&gt;setCursor&lt;/b&gt;. We will implement all the functionality that removes active cursor and set new one, in &lt;b&gt;SetMouseCursor&lt;/b&gt; function in file SnakesAdventure.as:&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace; font-size: x-small;"&gt;private var cursorID:Number = 0;&lt;br /&gt;private var mouseCursorDirection:int = -1;&lt;br /&gt;private var mouseCursorDisabled:Boolean = false;&lt;br /&gt;&lt;br /&gt;private function SetMouseCursor(direction:int,disabled:Boolean):void  &lt;br /&gt;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;if ((mouseCursorDirection != direction) || (mouseCursorDisabled != disabled))&lt;br /&gt;&amp;nbsp;&amp;nbsp;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;mouseCursorDirection = direction;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;mouseCursorDisabled = disabled;&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;CursorManager.removeCursor(cursorID);   &lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;switch (direction)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;case 0:&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;cursorID = CursorManager.setCursor(mouseCursorImg);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;break;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;case Snake.NORTH:&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if (disabled)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;cursorID = CursorManager.setCursor(mouseCursorNDImg);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;else&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;cursorID = CursorManager.setCursor(mouseCursorNImg);      &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;break; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;case Snake.EAST:&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if (disabled)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;cursorID = CursorManager.setCursor(mouseCursorEDImg);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;else&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;cursorID = CursorManager.setCursor(mouseCursorEImg);      &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;break; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;case Snake.SOUTH:&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if (disabled)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;cursorID = CursorManager.setCursor(mouseCursorSDImg);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;else&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;cursorID = CursorManager.setCursor(mouseCursorSImg);      &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;break; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;case Snake.WEST:&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if (disabled)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;cursorID = CursorManager.setCursor(mouseCursorWDImg);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;else&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;cursorID = CursorManager.setCursor(mouseCursorWImg);      &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;break;   &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;}&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;div style="text-align: justify;"&gt;&lt;b&gt;SetMouseCursor&lt;/b&gt; function requires two parameters, cursor image is selected according to value of both parameters. Zero value of &lt;b&gt;direction&lt;/b&gt; parameter sets game menu cursor. If value equals NORTH, EAST, SOUTH or WEST constant from Snake class, function picks the image with arrow that points in the same direction. Parameter &lt;b&gt;disabled&lt;/b&gt; controls if grey (true) or coloured (false) version of image is used.&lt;br /&gt;&lt;br /&gt;Two global variables: &lt;b&gt;mouseCursorDirection&lt;/b&gt; and &lt;b&gt;mouseCursorDisabled&lt;/b&gt;, make sure that mouse cursor is not replaced, if values of both parameters define the same mouse cursor that is currently active. Values are stored whenever mouse cursor icon is changed and compared with values of &lt;b&gt;direction&lt;/b&gt;/&lt;b&gt;disabled&lt;/b&gt; the next time function is called. If both pair of values are equal, the whole process is skipped.&lt;br /&gt;&lt;br /&gt;Before we can use &lt;b&gt;SetMouseCursor&lt;/b&gt; function, we have to embed new cursor images into the application. Add this code into Images.as file:&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace; font-size: x-small;"&gt;[Embed(source="Images/MouseCursor.png")]private var mouseCursorImg:Class;&lt;br /&gt;[Embed(source="Images/MouseCursor_N.png")]private var mouseCursorNImg:Class;&lt;br /&gt;[Embed(source="Images/MouseCursor_ND.png")]private var mouseCursorNDImg:Class;&lt;br /&gt;[Embed(source="Images/MouseCursor_E.png")]private var mouseCursorEImg:Class;&lt;br /&gt;[Embed(source="Images/MouseCursor_ED.png")]private var mouseCursorEDImg:Class;&lt;br /&gt;[Embed(source="Images/MouseCursor_S.png")]private var mouseCursorSImg:Class;&lt;br /&gt;[Embed(source="Images/MouseCursor_SD.png")]private var mouseCursorSDImg:Class;&lt;br /&gt;[Embed(source="Images/MouseCursor_W.png")]private var mouseCursorWImg:Class;&lt;br /&gt;[Embed(source="Images/MouseCursor_WD.png")]private var mouseCursorWDImg:Class;&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;div style="text-align: justify;"&gt;We embedded all required images and implemented SetMouseCursor function, now we can use it to get rid of system arrow cursor.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Game menu cursor&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;We can set new mouse cursor at the start of the program. &lt;b&gt;Init&lt;/b&gt; function is called right after Flex finishes its part of program initialization procedure. Let's set the game menu cursor at the beginning of &lt;b&gt;Init&lt;/b&gt; function: &lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace; font-size: x-small;"&gt;SetMouseCursor(0,false);&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;div style="text-align: justify;"&gt;If you compile and run the game at this point, you can see, that new cursor is displayed only when it is positioned inside game frame. Outside the frame cursor icon is set back to default.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Game cursor&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;Cursor in the game is set according to its position and position of the head of the snake. We will implement all functionality inside &lt;b&gt;SetGameCursor&lt;/b&gt; function, this time without any parameters. Function will be used and implemented inside Game.as file. Add call to &lt;b&gt;SetGameCursor&lt;/b&gt; at the end of &lt;b&gt;Draw_Game&lt;/b&gt; function:&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace; font-size: x-small;"&gt;SetGameCursor();  &lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;div style="text-align: justify;"&gt;We will use the same approach here that we did in &lt;b&gt;MouseDown_Game&lt;/b&gt; when mouse button was pressed during the game. Direction, that mouse cursor arrow will point to, is calculated from mouse cursor position and position of the snake. Disabled cursor (geay icon) is set, when snake movement cannot change in that direction. For instance, when snake is moving in the northern direction, north and south direction cannot be set.&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace; font-size: x-small;"&gt;private function SetGameCursor():void  &lt;br /&gt;{  &lt;br /&gt;&amp;nbsp;&amp;nbsp;var mx:int = mouseX;&lt;br /&gt;&amp;nbsp;&amp;nbsp;var my:int = mouseY;&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;my = SCREEN_HEIGHT - my;&lt;br /&gt;&amp;nbsp;&amp;nbsp;var position:Point = snake.getPosition();&lt;br /&gt;&amp;nbsp;&amp;nbsp;var direction:int = snake.getDirection(); &lt;br /&gt;&amp;nbsp;&amp;nbsp;var cursorDirection:int = 0;&lt;br /&gt;&amp;nbsp;&amp;nbsp;var cursorDisabled:Boolean = true;   &lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;if (Math.abs(mx - position.x) &gt; Math.abs(my - position.y))&lt;br /&gt;&amp;nbsp;&amp;nbsp;{ //check east/west&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if (mx - position.x &gt; 0)  &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;cursorDirection = Snake.EAST;      &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;else&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;cursorDirection = Snake.WEST;&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if (Math.abs(mx - position.x) &gt; Snake.SPEED)      &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if ((direction == Snake.NORTH) || (direction == Snake.SOUTH)) &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;cursorDisabled = false;&lt;br /&gt;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&amp;nbsp;&amp;nbsp;else&lt;br /&gt;&amp;nbsp;&amp;nbsp;{ //check south/north&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if (my - position.y &gt; 0)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;cursorDirection = Snake.NORTH;      &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;else&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;cursorDirection = Snake.SOUTH;&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if (Math.abs(my - position.y) &gt; Snake.SPEED)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if ((direction == Snake.EAST) || (direction == Snake.WEST))  &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;cursorDisabled = false;         &lt;br /&gt;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;SetMouseCursor(cursorDirection,cursorDisabled);  &lt;br /&gt;}&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;div style="text-align: justify;"&gt;We cannot obtain position of mouse cursor from MouseEvent object as we did in MouseUp/Down/Moved functions. Current position of mouse cursor is obtained from  &lt;b&gt;mouseX&lt;/b&gt; and &lt;b&gt;mouseY&lt;/b&gt; properties of Application class.&lt;br /&gt;&lt;br /&gt;Value of &lt;b&gt;cursorDirection&lt;/b&gt; variable is set according to difference between mouse cursor position and position of the head of the snake. If difference between &lt;b&gt;y&lt;/b&gt; values is positive and greater that difference between &lt;b&gt;x&lt;/b&gt;, value is set to NORTH. If difference between &lt;b&gt;y&lt;/b&gt; values is negative but absolute value is greater that absolute value of difference between &lt;b&gt;x&lt;/b&gt;, value is set to SOUTH. And so on. Value of &lt;b&gt;cursorDisabled&lt;/b&gt; is set to true by default, and set to false only if direction of snake movement can change to &lt;b&gt;cursorDirection&lt;/b&gt;.&lt;br /&gt;&lt;br /&gt;At the end, &lt;b&gt;SetMouseCursor&lt;/b&gt; function implemented in SnakesAdventure.as, is called. &lt;br /&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8678980820383323367-3485020610523674241?l=grandy-flexdev.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://grandy-flexdev.blogspot.com/feeds/3485020610523674241/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://grandy-flexdev.blogspot.com/2010/02/custom-mouse-cursor.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8678980820383323367/posts/default/3485020610523674241'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8678980820383323367/posts/default/3485020610523674241'/><link rel='alternate' type='text/html' href='http://grandy-flexdev.blogspot.com/2010/02/custom-mouse-cursor.html' title='Custom mouse cursors'/><author><name>Grandy</name><uri>http://www.blogger.com/profile/13061370372593845090</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='29' height='32' src='http://4.bp.blogspot.com/_4Xe_fkP2r2A/StiN3kMzX2I/AAAAAAAAAAU/wWM-ILREdfw/S220/MySelf.png'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8678980820383323367.post-2946043953329790602</id><published>2010-02-09T13:39:00.001-08:00</published><updated>2010-03-24T14:26:42.548-07:00</updated><title type='text'>Snake - advanced version</title><content type='html'>&lt;div style="text-align: justify;"&gt;In the previous chapter we implemented new functionality that displays and controls the movement of the snake. It probably required a lot of your time to understand how things work and maybe some of you were a bit disappointed with the look of the snake. Some people like this old-school look, others will preferer that snake character actually looks like snake.&lt;br /&gt;&lt;br /&gt;It is best that you start the game and see for yourself how will the new version of snake look like, after we finish this chapter. Control snake movement with mouse control: direction of movement is changed when mouse button is pressed, vector between mouse cursor and snake's head defines new direction. If the snake runs out of the screen, just reload the page.&lt;br /&gt;&lt;br /&gt;&lt;div style="text-align: justify;"&gt;&lt;center&gt;&lt;br /&gt;&lt;br /&gt;&lt;table border="1"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td align="center"&gt;&lt;embed align="center" height="480" src="http://bgrandovec.hostzi.com/Files/SnakesAdventure_P16.swf" type="application/x-shockwave-flash" width="480"&gt;&lt;/embed&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/center&gt;&lt;/div&gt;&lt;br /&gt;If you do not like this new look, skip this chapter and rather spent some time to improve the graphics of the snake from the previous chapter. Otherwise, keep reading.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Snakes new groove&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;To implement advanced version of snake, we need new graphics. New version of file Snake.png can be found inside Images folder in &lt;a href="http://bgrandovec.hostzi.com/Files/SnakesAdventure_P16.zip"&gt;project&lt;/a&gt; package for this chapter. As you can see on the (enlarged) image bellow, it now  contains images of different parts of snakes body in all possible directions: horizontal and vertical version of the body, heads and tails for all directions and image that fills the gap between two parts with different directions.&lt;br /&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://1.bp.blogspot.com/_4Xe_fkP2r2A/S3LvWEJ0VZI/AAAAAAAAAC4/aJ5KjCuvTjo/s1600-h/Snake.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="160" src="http://1.bp.blogspot.com/_4Xe_fkP2r2A/S3LvWEJ0VZI/AAAAAAAAAC4/aJ5KjCuvTjo/s200/Snake.png" width="192" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;Implementation of advanced version of the snake will require a lot of changes in the existing source code. Fortunately, most of the changes will be made in the Snake class (Snake.as). In the Game.as we have to only change the value of &lt;b&gt;length&lt;/b&gt; parameter in Snake constructor:&lt;/div&gt;&lt;br /&gt;&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace; font-size: x-small;"&gt;snake = new Snake(SCREEN_WIDTH / 2,SCREEN_HEIGHT / 3,20);  &lt;/div&gt;&lt;br /&gt;&lt;div style="text-align: justify;"&gt;If you slowed down the movement of the snake at the end of previous chapter, by calling &lt;b&gt;move&lt;/b&gt; function once per two frames, it is best that you change the code back to:&lt;/div&gt;&lt;br /&gt;&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace; font-size: x-small;"&gt;if (snake != null)&lt;br /&gt;&amp;nbsp;&amp;nbsp;snake.move();&lt;/div&gt;&lt;br /&gt;&lt;div style="text-align: justify;"&gt;Because the value of SPEED constant has been decreased to four, the &lt;b&gt;move&lt;/b&gt; function changes the position of the snake by four pixels only. Updating the position of the snake once per two frames will really look anoying. Change the SPEED constant in the Snake class to:&lt;/div&gt;&lt;br /&gt;&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace; font-size: x-small;"&gt;public static const SPEED:int       = 4;&lt;/div&gt;&lt;br /&gt;&lt;div style="text-align: justify;"&gt;In the previous version of the snake, position of each part was stored to Point object and all Point objects were kept inside &lt;b&gt;partPosition&lt;/b&gt; Array. For advanced version, we also need to store direction of each part, otherwise we cannot display correct image of tail and image that fills the gap between two parts with different directions. Directions of all parts will be kept inside &lt;b&gt;partDirection&lt;/b&gt; Array.&lt;br /&gt;&lt;br /&gt;There is one more thing we need, to display body parts correctly. I call this data a &lt;b&gt;phase&lt;/b&gt;, value of all is kept inside &lt;b&gt;partPhase&lt;/b&gt; Array. &lt;b&gt;Phase&lt;/b&gt; can have value from 0 to 8, each value is used to display a different part of snake body.&lt;br /&gt;&lt;br /&gt;Change the section at the beginning of Snake class, that defines class members to:&lt;/div&gt;&lt;br /&gt;&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace; font-size: x-small;"&gt;private var direction:int = NORTH;  &lt;br /&gt;private var newDirection:int = NORTH;    &lt;br /&gt;private var partPosition:Array = new Array();&lt;br /&gt;private var partDirection:Array = new Array(); &lt;br /&gt;private var partPhase:Array = new Array(); &lt;/div&gt;&lt;br /&gt;&lt;div style="text-align: justify;"&gt;There is one new member that I haven't mentioned, yet. Variable &lt;b&gt;newDirection&lt;/b&gt; will be used to store the value of new direction in &lt;b&gt;setDirection&lt;/b&gt; function. In previous version, we immediately changed the value of &lt;b&gt;direction&lt;/b&gt; and consequently snake immediately  changed the direction of movement. In the advanced version, we have to wait until the time is right, before we can change the direction. The right time is when &lt;b&gt;phase&lt;/b&gt; value of leading part (head) equals 0.&lt;br /&gt;&lt;br /&gt;Snake class constructor now looks like this: &lt;/div&gt;&lt;br /&gt;&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace; font-size: x-small;"&gt;public function Snake(xPos:int,yPos:int,length:int) &lt;br /&gt;{  &lt;br /&gt;&amp;nbsp;&amp;nbsp;for (var i:int = 0; i &amp;lt; length; i++)&lt;br /&gt;&amp;nbsp;&amp;nbsp;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;partPosition.push(new Point(xPos,yPos - i * SPEED));&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;partDirection.push(direction);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;partPhase.push(i % 9);&lt;br /&gt;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;}&lt;/div&gt;&lt;br /&gt;&lt;div style="text-align: justify;"&gt;Position of all parts is set the same way as in previous version, direction for all parts is set to NORTH, &lt;b&gt;phase&lt;/b&gt; values are set in following order 0, 1, 2, 3, 4, 5, 6, 7, 8, 0, 1, 2, 3...&lt;br /&gt;&lt;br /&gt;Implementation of functions &lt;b&gt;getPosition&lt;/b&gt; and &lt;b&gt;getDirection&lt;/b&gt; has not changed, on the other hand, &lt;b&gt;setPosition&lt;/b&gt; function now stores new direction in &lt;b&gt;newDirection&lt;/b&gt; variable instead directly to &lt;b&gt;direction&lt;/b&gt; variable:&lt;/div&gt;&lt;br /&gt;&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace; font-size: x-small;"&gt;public function setDirection(direction:int):void&lt;br /&gt;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;newDirection = direction;&lt;br /&gt;}&lt;/div&gt;&lt;br /&gt;&lt;div style="text-align: justify;"&gt;Implementation of &lt;b&gt;move&lt;/b&gt; function has been completely changed and is now almost hundred lines long. I will not show complete source code here, I will try to explain how it works on the section, that moves snake in northern direction. You can find complete source code in Snake.as file in &lt;a href="http://bgrandovec.hostzi.com/Files/SnakesAdventure_P16.zip"&gt;project&lt;/a&gt; package file.&lt;/div&gt;&lt;br /&gt;&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace; font-size: x-small;"&gt;public function move():void&lt;br /&gt;{    &lt;br /&gt;&amp;nbsp;&amp;nbsp;partPosition.pop();&lt;br /&gt;&amp;nbsp;&amp;nbsp;partDirection.pop();&lt;br /&gt;&amp;nbsp;&amp;nbsp;partPhase.pop();&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;var position:Point = partPosition[0];&lt;br /&gt;&amp;nbsp;&amp;nbsp;var phase:int = partPhase[0];    &lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;switch (direction)&lt;br /&gt;&amp;nbsp;&amp;nbsp;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;case NORTH:&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if ((newDirection != direction) &amp;amp;&amp;amp; (phase == 0))      &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{                &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;direction = newDirection;          &lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if (direction == EAST)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;partPosition.unshift(new Point(position.x + 7,position.y + 8));&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;else&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;partPosition.unshift(new Point(position.x - 6,position.y + 8)); &lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;partPhase.unshift(0);  &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;else&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;partPosition.unshift(new Point(position.x,position.y + SPEED));             &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;partPhase.unshift(((phase - 1) &amp;lt; 0 ? 8 : phase - 1)  % 9);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;break;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;.&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;.&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;.&lt;br /&gt;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;partDirection.unshift(direction);&lt;br /&gt;}  &lt;/div&gt;&lt;br /&gt;&lt;div style="text-align: justify;"&gt;Function first removes (pop) data for the last part of the snakes body from all Arrays, position and phase value of leading body part is stored to temporary variables.&lt;br /&gt;&lt;br /&gt;In case the snake moves in the northern direction, it checks if value of &lt;b&gt;newDirection&lt;/b&gt; variable is different from value of &lt;b&gt;direction&lt;/b&gt; variable, which means that player recently changed the direction of the snake. When &lt;b&gt;phase&lt;/b&gt; value of leading part equals 0, direction of movement can change. Position of new part is not increased by four in vertical direction, but is changed according to size of the image that fills the gap between two parts with different directions. Phase value of new part is set to zero.&lt;br /&gt;&lt;br /&gt;If direction of movement hasn't changed, position of new part is increased by four (SPEED) in vertical direction. Phase value of new part is decreased by one or set to 8 if previous value was zero. Finally, direction of new part is inserted at the beginning of Array.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Implementation of drawing&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;The &lt;b&gt;draw&lt;/b&gt; function has become much more complicated. Now we have to use different parts of the source image, to display head, tail and body. Again, I will show only part of the drawing routine and explain how it works. Complete source code of &lt;b&gt;draw&lt;/b&gt; function can be found in Snake.as file in &lt;a href="http://bgrandovec.hostzi.com/Files/SnakesAdventure_P16.zip"&gt;project&lt;/a&gt; package file.&lt;/div&gt;&lt;br /&gt;&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace; font-size: x-small;"&gt;[Embed(source="../Images/Snake.png")] private var snakeImg:Class;&lt;br /&gt;&lt;br /&gt;private var bitmap:BitmapData = null;&lt;br /&gt;&lt;br /&gt;private var northHeadOffset:Array = new Array(0,2,3,3,1,-1,-3,-3,-2);&lt;br /&gt;... &lt;br /&gt;&lt;br /&gt;public function draw(screenBuffer:BitmapData,visible:Rectangle):void&lt;br /&gt;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;if (bitmap == null)&lt;br /&gt;&amp;nbsp;&amp;nbsp;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;bitmap = new BitmapData(96,80,true,0x00000000);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;bitmap.draw(new snakeImg());&lt;br /&gt;&amp;nbsp;&amp;nbsp;}    &lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;for (var i:int = partPosition.length - 1; i &amp;gt;= 0; i--)&lt;br /&gt;&amp;nbsp;&amp;nbsp;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;var pos:Point = partPosition[i];&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;var direction:int = partDirection[i];&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;var phase:int = partPhase[i];             &lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if (i == 0) //head&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{        &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;phase = partPhase[1];         &lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;switch (direction)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;case NORTH:         &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;screenBuffer.copyPixels(bitmap,&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;new Rectangle(38,51,15,17),&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;new Point(pos.x - 7 + northHeadOffset[phase],visible.y - pos.y - 13)); &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;break;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;...&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}                    &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;else&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if (i == partPosition.length - 1) //tail&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{        &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;switch (direction)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;case NORTH:         &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;screenBuffer.copyPixels(bitmap,&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;amp;nbspnew Rectangle(80,2,11,10),&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;amp;nbspnew Point(pos.x - 5 + northHeadOffset[phase], visible.y - pos.y - 3)); &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;break;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;...&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}                    &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}        &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;else  //body&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if ((direction == EAST) || (direction == WEST))&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;screenBuffer.copyPixels(bitmap,&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;new Rectangle(18 + phase * 4,0,4,19),&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;new Point(pos.x - 2,visible.y - pos.y - 9));&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;else          &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;screenBuffer.copyPixels(bitmap,&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;new Rectangle(0,18 + phase * 4,19,4),&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;new Point(pos.x - 9,visible.y - pos.y - 2));&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; var prevDirection:int = i &amp;lt; partPosition.length - 1 ? partDirection[i + 1] : direction;&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; if (prevDirection != direction)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; switch (prevDirection)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; case NORTH:&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if (direction == EAST)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;screenBuffer.copyPixels(bitmap,&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;new Rectangle(72,51,10,11),&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;new Point(pos.x - 12,visible.y - pos.y - 5));&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; else&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;screenBuffer.copyPixels(bitmap,&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;new Rectangle(82,51,10,11),&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;new Point(pos.x + 2,visible.y - pos.y - 3));&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; break;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ...&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;}  &lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;div style="text-align: justify;"&gt;Source code that embeds Snake.png and creates BitmapData object from the source image has not changed, only width and height of source image has been changed.&lt;br /&gt;&lt;br /&gt;Parts of the snake are now copied to screen buffer in reverse order: tail first, than body and finally the head. To display the head and tail in right direction, we have to use appropriate area of source image. Because the position of body changes vertically/horizontally, we need to adjust the position of the head and tail with predefined values from &lt;b&gt;northHeadOffset&lt;/b&gt; Array. Different parts of the body are displayed according to &lt;b&gt;phase&lt;/b&gt; value. &lt;br /&gt;&lt;br /&gt;Finally, the direction of previous part is compared to direction of the part in the process. If they have different direction, we have to fill the gap. Gap is filled with suitable part of the image in bottom right section of Snake.png.&lt;br /&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8678980820383323367-2946043953329790602?l=grandy-flexdev.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://grandy-flexdev.blogspot.com/feeds/2946043953329790602/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://grandy-flexdev.blogspot.com/2010/02/snake-advanced-version.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8678980820383323367/posts/default/2946043953329790602'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8678980820383323367/posts/default/2946043953329790602'/><link rel='alternate' type='text/html' href='http://grandy-flexdev.blogspot.com/2010/02/snake-advanced-version.html' title='Snake - advanced version'/><author><name>Grandy</name><uri>http://www.blogger.com/profile/13061370372593845090</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='29' height='32' src='http://4.bp.blogspot.com/_4Xe_fkP2r2A/StiN3kMzX2I/AAAAAAAAAAU/wWM-ILREdfw/S220/MySelf.png'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://1.bp.blogspot.com/_4Xe_fkP2r2A/S3LvWEJ0VZI/AAAAAAAAAC4/aJ5KjCuvTjo/s72-c/Snake.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8678980820383323367.post-2642509332226292490</id><published>2010-02-06T09:09:00.000-08:00</published><updated>2010-03-24T14:21:18.270-07:00</updated><title type='text'>Snake - simple version</title><content type='html'>&lt;div style="text-align: justify;"&gt;In this chapter we will work on the main character of the game - the Snake. We will create the simple version of the snake, that looks and acts similar to the snake in the original game. In the next chapter we are going to improve the appearance of the snake, everything else will remain the same.&lt;br /&gt;&lt;br /&gt;Before you continue reading, it is best that you start the game and see for yourself, what will be implemented throught this chapter. Control snake movement with mouse control: direction of movement is changed when mouse button is pressed, vector between mouse cursor and snake's head defines new direction. If snake runs out of the screen, just reload the page.&lt;br /&gt;&lt;br /&gt;&lt;div style="text-align: justify;"&gt;&lt;br /&gt;&lt;center&gt;&lt;br /&gt;&lt;table border="1"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td align="center"&gt;&lt;embed align="center" height="480" src="http://bgrandovec.hostzi.com/Files/SnakesAdventure_P15.swf" type="application/x-shockwave-flash" width="480"&gt;&lt;/embed&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/center&gt;&lt;/div&gt;&lt;br /&gt;&lt;b&gt;Snake class&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;ActionScript is very powerful object oriented programming language and to reach its full potential, you have to use custom classes whenever possible. Maybe it would be better if we used custom classes earlier in this tutorial, for example: for implementation of state automaton, we could create custom classes for all states. Anyway, it is time to create our first custom class named Snake. All functionality, that concerns snake, will be implemented in this class and exposed via public methods.&lt;br /&gt;&lt;br /&gt;Before we create Snake class we need a package that will contain this class (and other classes for this project). This is very simple, just create new folder inside project root folder and name it Classes.&lt;br /&gt;&lt;br /&gt;Before we can use class from this package, we have to import it. Add this  statement to other import statement at the top of SnakesAdventure.as file:&lt;/div&gt;&lt;br /&gt;&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace; font-size: x-small;"&gt;import Classes.*;&lt;/div&gt;&lt;br /&gt;&lt;div style="text-align: justify;"&gt;Create new file inside Classes folder, name it Snake.as and copy the following section into this file:&lt;/div&gt;&lt;br /&gt;&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace; font-size: x-small;"&gt;package Classes&lt;br /&gt;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;import flash.geom.*; &lt;br /&gt;&amp;nbsp;&amp;nbsp;import flash.display.*; &lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;public class Snake&lt;br /&gt;&amp;nbsp;&amp;nbsp;{&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;}&lt;/div&gt;&lt;br /&gt;&lt;div style="text-align: justify;"&gt;Package instruction in the first line defines to what package all classes inside the block belong to. Two import statements define external packages that will be used in this source file. Finally, Snake class is defined.&lt;br /&gt;&lt;br /&gt;Implementation of Snake class will be quite short, but will require a lot more explanation. We will implement class functionality step by step, all the code in the following examples belongs inside Snake class block.&lt;br /&gt;&lt;br /&gt;There is no rule how the implementation of custom class should look like, but developers usually put public constants, enumerations and variables at the beginning of class. Put these constants into Snake class:&lt;/div&gt;&lt;br /&gt;&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace; font-size: x-small;"&gt;public static const SPEED:int       = 8;  &lt;br /&gt;public static const NORTH:int       = 1;&lt;br /&gt;public static const EAST:int        = 2;&lt;br /&gt;public static const SOUTH:int       = 3;&lt;br /&gt;public static const WEST:int        = 4; &lt;/div&gt;&lt;br /&gt;&lt;div style="text-align: justify;"&gt;SPEED constant defines the speed of snake's movement in pixels (per frame). Constants NORTH, EAST, SOUTH and WEST will be used in conjunction with direction of snake's movement.&lt;br /&gt;&lt;br /&gt;We need two variables to describe snake's movement: position and direction; speed of the movement is constant (8 pixels). Snake body consist from many particles,  current position of each particle will be kept inside its own Point object, all Point object will be stored inside Array.&lt;/div&gt;&lt;br /&gt;&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace; font-size: x-small;"&gt;private var direction:int = NORTH;  &lt;br /&gt;private var partPosition:Array = new Array();&lt;/div&gt;&lt;br /&gt;&lt;div style="text-align: justify;"&gt;When Snake object is instantiated, &lt;b&gt;direction&lt;/b&gt; variable is set to NORTH, at the beginning of each stage snake starts to move in northern direction. Definition of &lt;b&gt;partPosition&lt;/b&gt; Array does not define particle positions, they will be set in constructor. Both variables are private, and can be changed only from inside this class.&lt;br /&gt;&lt;br /&gt;Constructor is class function, that is executed during creation of the object. Snake class constructor requires three parameters:&lt;br /&gt;&lt;br /&gt;- &lt;b&gt;xPos&lt;/b&gt;: horizontal position of first particle (head)&lt;br /&gt;- &lt;b&gt;yPos&lt;/b&gt;: vertical position of first particle (head)&lt;br /&gt;- &lt;b&gt;length&lt;/b&gt;: number of particles that represent snakes body&lt;/div&gt;&lt;br /&gt;&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace; font-size: x-small;"&gt;public function Snake(xPos:int,yPos:int,length:int) &lt;br /&gt;{      &lt;br /&gt;&amp;nbsp;&amp;nbsp;for (var i:int = 0; i &amp;lt; length; i++)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;partPosition.push(new Point(xPos,yPos - i * SPEED));&lt;br /&gt;} &lt;/div&gt;&lt;br /&gt;&lt;div style="text-align: justify;"&gt;Constructor creates as many new Point objects as &lt;b&gt;length&lt;/b&gt; parameter requires, &lt;b&gt;push&lt;/b&gt; method adds this newly created object to the end of Array. First object (index 0) will represent the head.&lt;br /&gt;&lt;br /&gt;Horizontal position of each particle equals value of &lt;b&gt;xPos&lt;/b&gt; parameter, vertical position of head equals value of &lt;b&gt;yPos&lt;/b&gt; parameter. Vertical position of each following particle is decreased by eight (SPEED). When the game starts, particles of snake body are on vertical line, particles are divided by eight pixels.&lt;br /&gt;&lt;br /&gt;There is one thing about vertical positions of particles, that might confuse you. Vertical position of particles are decreasing from head to tail, because we are using different coordinate system that we used for drawing into screen buffer. Position (0,0) in screen buffer represents top-left corner, position (479,479) represent lower-right corner. We are using vertically inverted coordinate system for game mechanic: position (0,0) is lower-left corner and position (479,479) is top-right corner. Currently, there isn't any benefit from this approach, in fact, it will require some additional work in drawing routines, but will make life much easier when we start implementing scrolling.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Snake object&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;Now, that we have Snake class defined, we can create Snake object. Add declaration into Game.as:&lt;/div&gt;&lt;br /&gt;&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace; font-size: x-small;"&gt;private var snake:Snake = null;&lt;/div&gt;&lt;br /&gt;&lt;div style="text-align: justify;"&gt;Object will be instantiated in New_Game function:&lt;/div&gt;&lt;br /&gt;&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace; font-size: x-small;"&gt;snake = new Snake(SCREEN_WIDTH / 2,SCREEN_HEIGHT / 3,10);  &lt;/div&gt;&lt;br /&gt;&lt;div style="text-align: justify;"&gt;New_Game function creates Snake object, that represents snake that has ten particles and its head is positioned slightly below the centre of the screen. If you compile and run the game at this point, you will not see the snake. Of course, we have to first implement functionality, that actually displays particles in screen buffer.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Drawing particles&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;Before we start with implementation of drawing routine, add the call of Snake.draw method in Draw_Game function, place it right after the code that colors screen buffer in green (screenBuffer.fillRect...):&lt;/div&gt;&lt;br /&gt;&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace; font-size: x-small;"&gt;if (snake != null)&lt;br /&gt;&amp;nbsp;&amp;nbsp;snake.draw(screenBuffer,new Rectangle(0,SCREEN_HEIGHT,SCREEN_WIDTH,SCREEN_HEIGHT)); &lt;/div&gt;&lt;br /&gt;&lt;div style="text-align: justify;"&gt;Function &lt;b&gt;draw&lt;/b&gt; from Snake class requires two parameters:&lt;br /&gt;- BitmapData object, where the drawing will occur&lt;br /&gt;- rectangle that represents visible area of the game. This functionality will be implemented in following chapters.&lt;br /&gt;&lt;br /&gt;Add implementation of &lt;b&gt;draw&lt;/b&gt; function into Snake.as file:&lt;/div&gt;&lt;br /&gt;&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace; font-size: x-small;"&gt;[Embed(source="../Images/Snake.png")] private var snakeImg:Class;&lt;br /&gt;&lt;br /&gt;private var bitmap:BitmapData = null;    &lt;br /&gt;&lt;br /&gt;public function draw(screenBuffer:BitmapData,visible:Rectangle):void&lt;br /&gt;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;if (bitmap == null)&lt;br /&gt;&amp;nbsp;&amp;nbsp;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;bitmap = new BitmapData(24,12,true,0x00000000);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;bitmap.draw(new snakeImg());&lt;br /&gt;&amp;nbsp;&amp;nbsp;}    &lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;for (var i:int; i &amp;lt; partPosition.length; i++)&lt;br /&gt;&amp;nbsp;&amp;nbsp;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;var pos:Point = partPosition[i];&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;screenBuffer.copyPixels(bitmap,&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;new Rectangle((i % 2) * 12,0,12,12),&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;new Point(pos.x - 6,visible.y - pos.y - 6));&lt;br /&gt;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;}&lt;/div&gt;&lt;br /&gt;&lt;div style="text-align: justify;"&gt;Image file Snake.png will be used to draw particles and can be found inside Images folder in &lt;a href="http://bgrandovec.hostzi.com/Files/SnakesAdventure_P15.zip"&gt;project&lt;/a&gt; package. There are two version of particle, light and dark. White version will be used for even (index 0,2,4...) particles, grey for odd. This will make snake look less boring.&lt;br /&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://3.bp.blogspot.com/_4Xe_fkP2r2A/S3BJQ4O1MLI/AAAAAAAAACw/MhIQqb1CS7U/s1600-h/Snake.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://3.bp.blogspot.com/_4Xe_fkP2r2A/S3BJQ4O1MLI/AAAAAAAAACw/MhIQqb1CS7U/s320/Snake.png" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;To use this image, we have to perform standard procedure: embed the image, create BitmapData object, and copy source image into it. Actual drawing is performed inside &lt;b&gt;for&lt;/b&gt; loop, value of &lt;b&gt;i&lt;/b&gt; variable decides which version of particle will be painted. Head (0) is always light, next particle is dark, light, dark, light...&lt;br /&gt;&lt;br /&gt;To display particles on correct positions, we have to invert its vertical position (visible.y - pos.y). This is because of the difference between coordinate system for the game mechanic and screen buffer.&lt;br /&gt;&lt;br /&gt;Size of each particle image is 12x12 pixels, distance between particles is only eight pixels (SPEED), that is why particles are overlapping. Positions stored inside &lt;b&gt;partPosition&lt;/b&gt; array represent centre of each particle, to display particle image correctly, we have to move the location where pixels are copied, by half of the source image size (-6,-6).&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Snake movement&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;We need to implement four functions, that will allow us to control snake movement. All functions belong to Snake class:&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace; font-size: x-small;"&gt;public function getPosition():Point&lt;br /&gt;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;return partPosition[0];&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;public function getDirection():int&lt;br /&gt;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;return direction;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;public function setDirection(direction:int):void&lt;br /&gt;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;this.direction = direction;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;public function move():void&lt;br /&gt;{    &lt;br /&gt;&amp;nbsp;&amp;nbsp;partPosition.pop();&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;var position:Point = partPosition[0]; &lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;switch (direction)&lt;br /&gt;&amp;nbsp;&amp;nbsp;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;case NORTH:&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;partPosition.unshift(new Point(position.x,position.y + SPEED));  &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;break;&lt;br /&gt;&amp;nbsp;&amp;nbsp;case EAST:&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;partPosition.unshift(new Point(position.x + SPEED,position.y));               &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;break;&lt;br /&gt;&amp;nbsp;&amp;nbsp;case SOUTH:&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;partPosition.unshift(new Point(position.x,position.y - SPEED));   &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;break;&lt;br /&gt;&amp;nbsp;&amp;nbsp;case WEST: &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;partPosition.unshift(new Point(position.x - SPEED,position.y));&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;break;&lt;br /&gt;&amp;nbsp;&amp;nbsp;}      &lt;br /&gt;} &lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;div style="text-align: justify;"&gt;- &lt;b&gt;getPosition&lt;/b&gt; returns position of the snake, in fact position of the first particle (head)&lt;br /&gt;- &lt;b&gt;getDirection&lt;/b&gt; returns value of &lt;b&gt;direction&lt;/b&gt; variable&lt;br /&gt;- &lt;b&gt;setDirection&lt;/b&gt; sets new value to &lt;b&gt;direction&lt;/b&gt; variable&lt;br /&gt;- &lt;b&gt;move&lt;/b&gt; actually performs movement. Last particle - tail is removed (pop) and new one is inserted (unshift) at the beginning of the queue - head. Position of new particle is calculated from previous position of the head and direction of movement. When snake moves north, vertical position is increased by eight pixels (SPEED), when it moves south position is decreased by same value. Movement in east/west direction increases/decreases horizontal position.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Controlling snake movement&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;Now we can use these functions to update and control movement of the snake in the source code inside Game.as file. First we will update position of the snake once per frame. At the end of &lt;b&gt;switch&lt;/b&gt; statement in Draw_Game function add new &lt;b&gt;case&lt;/b&gt; condition:&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace; font-size: x-small;"&gt;case GAME_PLAYED:        &lt;br /&gt;&amp;nbsp;&amp;nbsp;if (snake != null)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;snake.move();&lt;br /&gt;&amp;nbsp;&amp;nbsp;break;   &lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;div style="text-align: justify;"&gt;If you start the game at this point, you won't be able to control the snake movement. Snake will move only in default direction, which is the northern direction. &lt;br /&gt;&lt;br /&gt;We will control movement of the snake from MouseDown_Game function. Add new condition to &lt;b&gt;switch&lt;/b&gt; block inside MouseDown_Game function:&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace; font-size: x-small;"&gt;case GAME_PLAYED:&lt;br /&gt;&amp;nbsp;&amp;nbsp;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;my = SCREEN_HEIGHT - my;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;var position:Point = snake.getPosition();&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;var direction:int = snake.getDirection();      &lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if ((Math.abs(mx - position.x) &gt; Snake.SPEED) || &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;(Math.abs(my - position.y) &gt; Snake.SPEED))&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if (Math.abs(mx - position.x) &gt; Math.abs(my - position.y))&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{ //check east/west&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if ((direction == Snake.NORTH) || (direction == Snake.SOUTH))        &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if (mx - position.x &gt; 0)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;snake.setDirection(Snake.EAST);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;else&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;snake.setDirection(Snake.WEST);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;else&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{ //check south/north&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if ((direction == Snake.EAST) || (direction == Snake.WEST))            &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if (my - position.y &gt; 0)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;snake.setDirection(Snake.NORTH);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;else&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;snake.setDirection(Snake.SOUTH);        &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&amp;nbsp;&amp;nbsp;break;    &lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;div style="text-align: justify;"&gt;This code is executed when player pushes the mouse button. Vertical position of mouse cursor is flipped, because the game uses different coordinate system. Snake's position and direction are stored into temporary variables.&lt;br /&gt;&lt;br /&gt;Mouse cursor must be positioned more than eight (Snake.SPEED) pixels away from the head, otherwise direction cannot change.&lt;br /&gt;&lt;br /&gt;If absolute horizontal distance between mouse cursor and head of the snake is greater that absolute vertical distance, direction can change to east or west only. This happens only if snake is currently moving in northern or southern direction.&lt;br /&gt;&lt;br /&gt;If absolute vertical distance between mouse cursor and head of the snake is greater that absolute horizontal distance, direction can change to north or south, but only if snake is currently moving in eastern or western direction.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Fine tuning&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;If you compile and start the game you will be able to control the movement of the snake, but most probably snake will soon run out of the screen, because it moves way too fast. Game runs at 24 frames per second (by default), and snake moves by eight pixels each frame, which makes at total 192 pixels per second. Snake needs only 2.5 sec to travel from one side of the frame to another.&lt;br /&gt;&lt;br /&gt;You can decrease the value of SPEED constant in Snake class and snake will move slowly, but particles will overlap even more and snake will look ugly. &lt;br /&gt;&lt;br /&gt;I am using another solution: snake movement is updated once per two frame updates. This makes snake move 50% slower, but movement looks much less fluent. This solution was implemented in Game.as file. I made new global variable &lt;b&gt;frameCount&lt;/b&gt;: &lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace; font-size: x-small;"&gt;private var frameCount:int = 0;&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;div style="text-align: justify;"&gt;Value of variable is increased once per frame, at the beginning of Draw_Game function.&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace; font-size: x-small;"&gt;frameCount++; &lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;div style="text-align: justify;"&gt;Code that updates position of the snake is changed to:&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace; font-size: x-small;"&gt;if ((snake != null) &amp;&amp; (frameCount % 2 == 0))&lt;br /&gt;&amp;nbsp;&amp;nbsp;snake.move();&lt;br /&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8678980820383323367-2642509332226292490?l=grandy-flexdev.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://grandy-flexdev.blogspot.com/feeds/2642509332226292490/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://grandy-flexdev.blogspot.com/2010/02/snake-simple-version.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8678980820383323367/posts/default/2642509332226292490'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8678980820383323367/posts/default/2642509332226292490'/><link rel='alternate' type='text/html' href='http://grandy-flexdev.blogspot.com/2010/02/snake-simple-version.html' title='Snake - simple version'/><author><name>Grandy</name><uri>http://www.blogger.com/profile/13061370372593845090</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='29' height='32' src='http://4.bp.blogspot.com/_4Xe_fkP2r2A/StiN3kMzX2I/AAAAAAAAAAU/wWM-ILREdfw/S220/MySelf.png'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://3.bp.blogspot.com/_4Xe_fkP2r2A/S3BJQ4O1MLI/AAAAAAAAACw/MhIQqb1CS7U/s72-c/Snake.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8678980820383323367.post-1980356788810300965</id><published>2010-02-03T09:45:00.000-08:00</published><updated>2010-03-24T14:09:50.960-07:00</updated><title type='text'>Stage one</title><content type='html'>&lt;div style="text-align: justify;"&gt;We are not ready to begin development of the first stage of the game, yet. In this chapter we will create two labels, which will be displayed at the beginning of each stage. One will show the number of current stage at the top and second one "Press mouse button when ready" at the bottom. We will also add some code, that will come in handy later, when we start working on gameplay.&lt;br /&gt;&lt;br /&gt;I add two new images in the project that will be used in the implementation, both images have five different levels of opacity (from 0.2 to 1.0). Images can be found in Images folder in &lt;a href="http://bgrandovec.hostzi.com/Files/SnakesAdventure_P14.zip"&gt;project&lt;/a&gt; package for this chapter.&lt;br /&gt;&lt;br /&gt;First image will be used to display "Stage XX" label, XX is number of current stage. Image contains Stage string and digits from 0 to 9. With those ten digits we can display all natural numbers, but we only need to display numbers from 01 to the number of last stage available in the game. Stage sign will be copied into screen buffer in three steps:&lt;br /&gt;&lt;br /&gt;- stage text&lt;br /&gt;- integer number of current stage divided by 10 &lt;br /&gt;- remainder of current stage divided by 10 &lt;br /&gt;&lt;br /&gt;Transparent parts of the image will be used to implement smooth transition between visible and hidden sign (and vice versa). &lt;/div&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://2.bp.blogspot.com/_4Xe_fkP2r2A/S2xZU7dEzWI/AAAAAAAAACg/ZpRINXjDP6M/s1600-h/StageLabel.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="181" src="http://2.bp.blogspot.com/_4Xe_fkP2r2A/S2xZU7dEzWI/AAAAAAAAACg/ZpRINXjDP6M/s400/StageLabel.png" width="400" /&gt;&lt;/a&gt;&amp;nbsp;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;Second image will be used to display the blinking text "Press mouse button when ready". Transparent parts of the image will be used to implement smooth transition between visible and hidden label (and vice versa). &lt;/div&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&amp;nbsp;&lt;a href="http://4.bp.blogspot.com/_4Xe_fkP2r2A/S2xZfh3j3mI/AAAAAAAAACo/ySZ2IF6mjhw/s1600-h/StageReady.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="320" src="http://4.bp.blogspot.com/_4Xe_fkP2r2A/S2xZfh3j3mI/AAAAAAAAACo/ySZ2IF6mjhw/s320/StageReady.png" width="307" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;&lt;div style="text-align: justify;"&gt;Labels will be displayed as long as mouse button is not pressed. In &lt;a href="http://grandy-flexdev.blogspot.com/2010/02/let-game-begin.html"&gt;previous chapter&lt;/a&gt; we implemented game state automaton and defined four states. Sign will become visible in GAME_FADE_IN state, GAME_START state will be active as long as mouse button is not pressed. When mouse button is pressed, GAME_STARTED state becomes active, and text start to slowly disappear.&lt;br /&gt;&lt;br /&gt;OK, let's start coding. Open Game.as and add definition of two variables to other variable definitions:&lt;/div&gt;&lt;br /&gt;&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace; font-size: x-small;"&gt;private var newState:int = 0;&lt;br /&gt;&lt;br /&gt;private var level:int = 0;&lt;/div&gt;&lt;br /&gt;&lt;div style="text-align: justify;"&gt;Usage of &lt;b&gt;newState&lt;/b&gt; variable will be explained later, &lt;b&gt;level&lt;/b&gt; variable will contain the number of active stage/level. We will set this variable to 1 when player select &lt;b&gt;new game&lt;/b&gt; option in game menu. Add this line at the beginning of New_Game function:&lt;/div&gt;&lt;br /&gt;&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace; font-size: x-small;"&gt;level = 1;&lt;/div&gt;&lt;br /&gt;&lt;div style="text-align: justify;"&gt;Implementation of Draw_Game function will require a little bit more work and explanation. Add this piece of code to Draw_Game:&lt;/div&gt;&lt;br /&gt;&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace; font-size: x-small;"&gt;gameTime += elapsedTime;&lt;br /&gt;&lt;br /&gt;screenBuffer.fillRect(new Rectangle(0,0,SCREEN_WIDTH,SCREEN_HEIGHT),0xFF406020);  &lt;/div&gt;&lt;br /&gt;&lt;div style="text-align: justify;"&gt;In the first line we count the time (in second) since the current game state become active. Value is increased by time interval between previous and current frame. The &lt;b&gt;fillRect&lt;/b&gt; method paints whole area of screen buffer in green colour. This is just temporary, we will remove this line when we start implementing scrolling background. Until then, green background will serve us better than default black background. &lt;br /&gt;&lt;br /&gt;&lt;b&gt;Function Draw_StageSign&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;Draw_StageSign function will be used to display both signs, implementation is quite long, but don't let it scare you off, there is nothing you haven't seen before, if you followed this tutorial from the beginning. Add Draw_StageSign function to Game.as file:&lt;/div&gt;&lt;br /&gt;&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace; font-size: x-small;"&gt;private var stageLabelBitmap:BitmapData = null;&lt;br /&gt;private var stageReadyBitmap:BitmapData = null;&lt;br /&gt;&lt;br /&gt;private function Draw_StageSign(stageOpacity:Number,readyOpacity:Number):void&lt;br /&gt;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;if (stageLabelBitmap == null)&lt;br /&gt;&amp;nbsp;&amp;nbsp;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;stageLabelBitmap = new BitmapData(350,160,true,0x00000000);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;stageLabelBitmap.draw(new stageLabelImg());&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;stageReadyBitmap = new BitmapData(240,250,true,0x00000000);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;stageReadyBitmap.draw(new stageReadyImg());&lt;br /&gt;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;if (stageOpacity &amp;gt; 0.15)   &lt;br /&gt;&amp;nbsp;&amp;nbsp;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;var yPos:int = 0;&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if (stageOpacity &amp;lt; 0.25)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;yPos = 128;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;else&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if (stageOpacity &amp;lt; 0.45)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;yPos = 96;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;else&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if (stageOpacity &amp;lt; 0.45)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;yPos = 64;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;else&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if (stageOpacity &amp;lt; 0.55)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;yPos = 32;&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;screenBuffer.copyPixels(stageLabelBitmap,&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;new Rectangle(0, yPos, 100, 32),&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;new Point(SCREEN_WIDTH / 2 - 80,SCREEN_HEIGHT / 2 - 120));&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;screenBuffer.copyPixels(stageLabelBitmap,&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;new Rectangle(int(level / 10) * 24 + 102, yPos, 24, 32),&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;new Point(SCREEN_WIDTH / 2 + 30,SCREEN_HEIGHT / 2 - 120));&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;screenBuffer.copyPixels(stageLabelBitmap,&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;new Rectangle((level % 10) * 24 + 102, yPos, 24, 32),&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;new Point(SCREEN_WIDTH / 2 + 54,SCREEN_HEIGHT / 2 - 120));&lt;br /&gt;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;if (readyOpacity &amp;gt; 0.15)   &lt;br /&gt;&amp;nbsp;&amp;nbsp;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;var yPos2:int = 0;&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if (readyOpacity &amp;lt; 0.25)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;yPos2 = 200;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;else     &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if (readyOpacity &amp;lt; 0.45)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;yPos2 = 150;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;else&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if (readyOpacity &amp;lt; 0.45)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;yPos2 = 100;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;else&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if (readyOpacity &amp;lt; 0.55)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;yPos2 = 50;&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;screenBuffer.copyPixels(stageReadyBitmap,&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;new Rectangle(0, yPos2, 240, 50),&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;new Point(SCREEN_WIDTH / 2 - 120,SCREEN_HEIGHT / 2 - 50));&lt;br /&gt;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;} &lt;/div&gt;&lt;br /&gt;&lt;div style="text-align: justify;"&gt;Function requires two parameters, first parameter is opacity of "Stage XX" label, second parameter is opacity of "Press mouse button when ready" label. When the function is executed first time, both BitmapData objects are created from embedded images. Object &lt;b&gt;stageLabelBitmap&lt;/b&gt; contains content of StageLabel.png, &lt;b&gt;stageReadyBitmap&lt;/b&gt; contains content of StageReady.png.&lt;br /&gt;&lt;br /&gt;Second block of code executes only when value of &lt;b&gt;stageOpacity&lt;/b&gt; is greater than 0.15, otherwise "Stage XX" label is not displayed. Variable &lt;b&gt;yPos&lt;/b&gt; contains the value of vertical position in source image. Values are a little bit modified according to opacity of labels in source image. Height of each label in the source image is 32, that is why the values 0, 32, 64, 96 or 128 are set to &lt;b&gt;yPos&lt;/b&gt;. &lt;br /&gt;&lt;br /&gt;First &lt;b&gt;copyPixel&lt;/b&gt; function copies part of source image that contains Stage label, width of the rectangle is hundred pixels. Top left pixel of the source image is copied 80 pixels to the left and 120 above the centre of screen buffer.&lt;br /&gt;&lt;br /&gt;Both numbers are copied at the same vertical position, horizontal position is set on the right side of screen buffer, that is why complete label appears horizontally centred. Digits in the source image start at column 102, width of each digit is 24 pixels. To display digit 0, we set horizontal position in source image to 102 + 24 * 0 = 102, to display digit 4 we use value 102 + 24 * 4 = 192. Value of both digits is calculated from &lt;b&gt;level&lt;/b&gt; variable. First digit is result of division of  &lt;b&gt;level&lt;/b&gt; by 10, second digit is reminder of same division.&lt;br /&gt;&lt;br /&gt;Last block of code displays "Press mouse button when ready" text with level of opacity required by &lt;b&gt;readyOpacity&lt;/b&gt; parameter. We use same approach that we used to display "Stage" text, except this time we use different source image, where labels are 50 pixels apart (vertically).&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Press mouse button when ready&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;When mouse button is pressed, GAME_START state ends and GAME_STARTED state becomes active and both labels start to disappear. Because the "Press mouse button when ready" label is blinking during the GAME_START state, we have to wait until label is fully opaque, before we change the state. We will store value of new state into  &lt;b&gt;newState&lt;/b&gt; variable when mouse button is pressed and Draw_Game will change the state, when time is right. Replace the current version MouseDown_Game function with this one:&lt;/div&gt;&lt;br /&gt;&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace; font-size: x-small;"&gt;private function MouseDown_Game(event:MouseEvent):void  &lt;br /&gt;{ &lt;br /&gt;&amp;nbsp;&amp;nbsp;var mx:int = event.localX;&lt;br /&gt;&amp;nbsp;&amp;nbsp;var my:int = event.localY;&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;switch (gameState)&lt;br /&gt;&amp;nbsp;&amp;nbsp;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;case GAME_START:  &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;newState = GAME_STARTED;   &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;break;&lt;br /&gt;&amp;nbsp;&amp;nbsp;} &lt;br /&gt;} &lt;/div&gt;&lt;br /&gt;&lt;div style="text-align: justify;"&gt;&lt;b&gt;Function Draw_Game part II&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;Now, that we have Draw_StageSign function implemented, it's time that we put it in use. Draw_StageSign will be called only when game states GAME_FADE_IN, GAME_START and GAME_STARTED are active. Put the following &lt;b&gt;switch&lt;/b&gt; block at the end of Draw_Game function:&lt;/div&gt;&lt;br /&gt;&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace; font-size: x-small;"&gt;switch (gameState)&lt;br /&gt;{&lt;br /&gt;case GAME_FADE_IN:  &lt;br /&gt;&amp;nbsp;&amp;nbsp;Draw_StageSign(gameTime,gameTime);&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;Apply_FadeEffect(1 - gameTime); &lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;if (gameTime &amp;gt;= 1)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;ChangeState_Game(GAME_START);       &lt;br /&gt;&amp;nbsp;&amp;nbsp;break;&lt;br /&gt;case GAME_START:&lt;br /&gt;&amp;nbsp;&amp;nbsp;var fracTime:Number = gameTime - int(gameTime);&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;Draw_StageSign(1,int(gameTime + 1) % 2 == 0 ? fracTime : 1 - fracTime);&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;if ((newState == GAME_STARTED) &amp;amp;&amp;amp;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;(int(gameTime + 1) % 2 == 0 ? fracTime &amp;gt; 0.55 : fracTime &amp;lt; 0.55)) &lt;br /&gt;&amp;nbsp;&amp;nbsp;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;ChangeState_Game(GAME_STARTED);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;newState = 0;&lt;br /&gt;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&amp;nbsp;&amp;nbsp;break;&lt;br /&gt;case GAME_STARTED:&lt;br /&gt;&amp;nbsp;&amp;nbsp;Draw_StageSign(1 - gameTime,1 - gameTime);&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;if (gameTime &amp;gt;= 1)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;ChangeState_Game(GAME_PLAYED);&lt;br /&gt;&amp;nbsp;&amp;nbsp;break;&lt;br /&gt;}   &lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;div style="text-align: justify;"&gt;GAME_FADE_IN state is active for one second. Within this second, both labels start to appear, but it is hard to notice the effect, because fade-in effect is applied over complete screen buffer. Values for Draw_StageSign parameters can range from 0.0 (not visible) to 1.0 (visible). After one second, labels are fully visible and GAME_START state becomes active.&lt;br /&gt;&lt;br /&gt;GAME_START state is active until mouse button is pressed. Value of &lt;b&gt;gameTime&lt;/b&gt; variable increases over time, variable &lt;b&gt;fracTime&lt;/b&gt; has the fractional part of &lt;b&gt;gameTime&lt;/b&gt; value. For example when value of &lt;b&gt;gameTime&lt;/b&gt; is 3.75 (seconds) value of &lt;b&gt;fracTime&lt;/b&gt; is 0.75.&lt;br /&gt;&lt;br /&gt;During GAME_START state, Stage label is visible all the time, first parameter in Draw_StageSign function call is set to 1. On the other hand "Press mouse button..." label is blinking all the time. On the odd seconds (integer value of &lt;b&gt;gameTime&lt;/b&gt; variable is odd) label slowly disappears, on the even seconds it is becoming visible again.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;if&lt;/b&gt; statement checks whether &lt;b&gt;newState&lt;/b&gt; variable is set (mouse button was pressed) and when blinking label becomes fully visible, changes the state to GAME_STARTED. This state is active for one second, during this time both labels slowly disappear.&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;div style="text-align: justify;"&gt;&lt;center&gt;&lt;br /&gt;&lt;table border="1"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td align="center"&gt;&lt;embed align="center" height="480" src="http://bgrandovec.hostzi.com/Files/SnakesAdventure_P14.swf" type="application/x-shockwave-flash" width="480"&gt;&lt;/embed&gt;&lt;br /&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/center&gt;&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;div style="text-align: justify;"&gt;You can set different values to &lt;b&gt;level&lt;/b&gt; variable in New_Game function, to see how those number look like. Just don't forget to set the value back to 1, when you are done.&lt;br /&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8678980820383323367-1980356788810300965?l=grandy-flexdev.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://grandy-flexdev.blogspot.com/feeds/1980356788810300965/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://grandy-flexdev.blogspot.com/2010/02/stage-one.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8678980820383323367/posts/default/1980356788810300965'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8678980820383323367/posts/default/1980356788810300965'/><link rel='alternate' type='text/html' href='http://grandy-flexdev.blogspot.com/2010/02/stage-one.html' title='Stage one'/><author><name>Grandy</name><uri>http://www.blogger.com/profile/13061370372593845090</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='29' height='32' src='http://4.bp.blogspot.com/_4Xe_fkP2r2A/StiN3kMzX2I/AAAAAAAAAAU/wWM-ILREdfw/S220/MySelf.png'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://2.bp.blogspot.com/_4Xe_fkP2r2A/S2xZU7dEzWI/AAAAAAAAACg/ZpRINXjDP6M/s72-c/StageLabel.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8678980820383323367.post-1717874516070939972</id><published>2010-02-01T09:02:00.001-08:00</published><updated>2010-03-24T14:01:17.444-07:00</updated><title type='text'>Let the game begin</title><content type='html'>&lt;div style="text-align: justify;"&gt;If you followed this tutorial from beginning, you should know everything you need to know, to develop your own game. At least from technical point of view. So far we learned how to compile program from the source code, how to display images and play sounds. We also implemented double buffering, mouse event handler and even few simple animations. More than enough to create simple games, if you know how to make them. &lt;br /&gt;&lt;br /&gt;Game development can be quite simple or very hard, depends of the type and quality of the game. Snake, Tetris, Space invaders... clones are relatively simple to create and convenient for game development beginners. First person shooters, strategies, MMO's... usually require more that one person to make and a lot of hard work, experience, money.&lt;br /&gt;&lt;br /&gt;Anyway, from now on we will focus mostly on development of the game. But you most probably wonder, what kind of game are we going to make here.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Snake's Adventure???&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;Snake's Adventure will be the clone of the classic Snake game with some advanced features. Snake is one of the most popular games of all times, you can read all about the original and clones on &lt;a href="http://en.wikipedia.org/wiki/Snake_%28video_game%29"&gt;Wikipedia&lt;/a&gt;. If you have never played the game before, I recommend that you do, because: &lt;br /&gt;- it will help you better understand this tutorial&lt;br /&gt;- it is fun.&lt;br /&gt;&lt;br /&gt;Snake's Adventure will have all the features of the original: player will control the snake, that is constantly moving, and try to pick up all available food. When food is picked up, snake will grow longer, when snake's head hits the obstacle, screen edge or its own body, its game over.&lt;br /&gt;&lt;br /&gt;The game will be also quite different from original. Player will control snake movement with the mouse. Snake will move on the terrain with different obstacles and it will constantly scroll up. If the food is not picked up by the time it disappears form the bottom of screen, it is game over, too.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;What's the plan?&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;First we will make few adjustments in game menu and create game state automaton. Not much new here, but it has to be done.&lt;br /&gt;&lt;br /&gt;Then we will implement Snake class, the drawing routine here will be most probably the hardest thing to understand. But it will look cool. Functionality, that controls movement of the snake, comes next. Here we will also learn how to create custom mouse cursor.&lt;br /&gt;&lt;br /&gt;Next on the menu is - food: drawing, positioning, collision detection, scoring system.... I saved the best/hardest for the last: terrain, obstacles and scrolling.&lt;br /&gt;&lt;br /&gt;At the end, we will implement settings menu, load/store setting, learn how to play music... and polish the game a little bit. I will also give you some advices how and where to publish the game. &lt;br /&gt;&lt;br /&gt;&lt;b&gt;Start new game&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;Currently, selected &lt;b&gt;new game&lt;/b&gt; option in game menu, doesn't change state of the program when title screen fades out. Instead it resets game menu state automaton and after few seconds game menu is active again. Let's fix this.&lt;br /&gt;&lt;br /&gt;Add new definition in GameMenu.as behind definition of &lt;b&gt;pressedOption&lt;/b&gt; variable:&lt;/div&gt;&lt;br /&gt;&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace; font-size: x-small;"&gt;private var selectedOption:int = -1;&lt;/div&gt;&lt;br /&gt;&lt;div style="text-align: justify;"&gt;Value of variable will be set, when player releases mouse button over the selected option. Change &lt;b&gt;switch&lt;/b&gt; block in MouseUp_GameMenu function to:&lt;/div&gt;&lt;br /&gt;&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace; font-size: x-small;"&gt;switch (gameMenuState)&lt;br /&gt;{&lt;br /&gt;case GAMEOPTIONS_WAIT:  &lt;br /&gt;&amp;nbsp;&amp;nbsp;switch (pressedOption)&lt;br /&gt;&amp;nbsp;&amp;nbsp;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;case OPTION_NEW_GAME:    &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;selectedOption = OPTION_NEW_GAME;      &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;ChangeState_GameMenu(GAMEOPTIONS_OUT);      &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;break;&lt;br /&gt;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&amp;nbsp;&amp;nbsp;break;&lt;br /&gt;} &lt;/div&gt;&lt;br /&gt;&lt;div style="text-align: justify;"&gt;This may look unnecessary to you right now, because &lt;b&gt;new game&lt;/b&gt; is the only option that changes the state of game menu. We will need it later when we implement behaviour of other two options.&lt;br /&gt;&lt;br /&gt;Finally, we have to change the state of the program to GAME, but not before the title screen fades out. Replace the line:&lt;/div&gt;&lt;br /&gt;&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace; font-size: x-small;"&gt;ChangeState_GameMenu(TITLE_SHOW);&lt;/div&gt;&lt;br /&gt;&lt;div style="text-align: justify;"&gt;at the bottom of Draw_GameMenu function with:&lt;/div&gt;&lt;br /&gt;&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace; font-size: x-small;"&gt;switch (selectedOption)&lt;br /&gt;{&lt;br /&gt;case OPTION_NEW_GAME:&lt;br /&gt;&amp;nbsp;&amp;nbsp;state = GAME;&lt;br /&gt;&amp;nbsp;&amp;nbsp;New_Game();&lt;br /&gt;&amp;nbsp;&amp;nbsp;break;&lt;br /&gt;}&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;div style="text-align: justify;"&gt;This code ends the GAME_MENU state and actives GAME state. New_Game function will take care of game initialization, currently this function is not defined. This will be our next task. &lt;br /&gt;&lt;br /&gt;&lt;b&gt;Game.as&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;This file is already part of the project, we made it in &lt;a href="http://grandy-flexdev.blogspot.com/2010/01/thinking-ahead.html"&gt;chapter 9&lt;/a&gt;. If you open the file, you can see that it is pretty much empty. It contains four functions without implementation, all of them are called from event handler routines implemented in SnakesAdventure.as: &lt;br /&gt;&lt;br /&gt;- Draw_Game is called from Draw function (on &lt;b&gt;ENTER_FRAME&lt;/b&gt; event)&lt;br /&gt;- MouseDown_Game is called from MouseDown function (on &lt;b&gt;MOUSE_DOWN&lt;/b&gt; event)&lt;br /&gt;- MouseUp_Game is called from MouseUp function (on &lt;b&gt;MOUSE_UP&lt;/b&gt; event)&lt;br /&gt;- MouseMoved_Game is called from MouseMoved function (on &lt;b&gt;MOUSE_MOVE&lt;/b&gt; event)&lt;br /&gt;&lt;br /&gt;Before we start implementing all those functions, we have to make some preparations.&lt;br /&gt;&lt;br /&gt;We already implemented state automaton twice: in activation screen and game menu. Game state automaton will require a lot more different sub-states, but for now we will define only four and add new state, when it is required:&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace; font-size: x-small;"&gt;private static const GAME_FADE_IN:int        = 1;&lt;br /&gt;private static const GAME_START:int          = 2;&lt;br /&gt;private static const GAME_STARTED:int        = 3;&lt;br /&gt;private static const GAME_PLAYED:int         = 4;&lt;br /&gt;&lt;br /&gt;private var gameState:int = GAME_FADE_IN;&lt;br /&gt;private var gameTime:Number = 0;&lt;br /&gt;&lt;br /&gt;private function ChangeState_Game(newState:int):void&lt;br /&gt;{  &lt;br /&gt;&amp;nbsp;&amp;nbsp;gameState = newState;&lt;br /&gt;&amp;nbsp;&amp;nbsp;gameTime = 0;&lt;br /&gt;}&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;div style="text-align: justify;"&gt;This should look very familiar to you, because similar functionality was already implemented in Activation.as and GameMenu.as. We defined four different constants, one for each state. Variable &lt;b&gt;gameState&lt;/b&gt; contains value of active sub-state, variable &lt;b&gt;gameTime&lt;/b&gt; contains number of seconds since sub-state was activated. Function &lt;b&gt;ChangeState_Game&lt;/b&gt; will be used to change active sub-state.&lt;br /&gt;&lt;br /&gt;In Draw_GameMenu function (GameMenu.as) we added a call to undefined function and this was the reason why program did not compile anymore. &lt;b&gt;New_Game&lt;/b&gt; function will take care of game initialization, but right now we have nothing to initialize. Implementation just sets the GAME_FADE_IN game state:&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace; font-size: x-small;"&gt;private function New_Game():void&lt;br /&gt;{  &lt;br /&gt;&amp;nbsp;&amp;nbsp;ChangeState_Game(GAME_FADE_IN);&lt;br /&gt;}&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;div style="text-align: justify;"&gt;Finally, the code compiles without errors. As usual, complete package for this chapter can be download &lt;a href="http://bgrandovec.hostzi.com/Files/SnakesAdventure_P13.zip"&gt;here&lt;/a&gt;.&lt;br /&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8678980820383323367-1717874516070939972?l=grandy-flexdev.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://grandy-flexdev.blogspot.com/feeds/1717874516070939972/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://grandy-flexdev.blogspot.com/2010/02/let-game-begin.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8678980820383323367/posts/default/1717874516070939972'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8678980820383323367/posts/default/1717874516070939972'/><link rel='alternate' type='text/html' href='http://grandy-flexdev.blogspot.com/2010/02/let-game-begin.html' title='Let the game begin'/><author><name>Grandy</name><uri>http://www.blogger.com/profile/13061370372593845090</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='29' height='32' src='http://4.bp.blogspot.com/_4Xe_fkP2r2A/StiN3kMzX2I/AAAAAAAAAAU/wWM-ILREdfw/S220/MySelf.png'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8678980820383323367.post-5548002343231005456</id><published>2010-01-22T10:55:00.000-08:00</published><updated>2010-03-24T13:49:22.425-07:00</updated><title type='text'>Playing sound effects</title><content type='html'>&lt;div style="text-align: justify;"&gt;Sound effects in the game have a huge impact on the players experience. Playing sound effects with Action Script is simple, creating good sound effects is not. If you don't know how to make good sound effects for your game (like me), do not worry. You can find a lot quality sound effect on the internet for free or very small price.&lt;br /&gt;&lt;br /&gt;In this chapter I will explain only the basics of how to play sound effects. I made three sounds effects and you can find them in Sounds folder in the &lt;a href="http://bgrandovec.hostzi.com/Files/SnakesAdventure_P12.zip"&gt;project&lt;/a&gt; package for this chapter. All three files are in MP3 format, because Sound class, which will be used to play sound effects, supports only MP3 files. MP3 format is great for web games, because file size is small. Size of all three files together is only 90KB.&lt;br /&gt;&lt;br /&gt;If you start the SnakesAdventure, embedded below, you can hear OptionSelected.mp3 played after mouse button click. OptionsIn.mp3 is played while the game options move from the left side to the centre. OptionsOut.mp3 is played while the game options move from the centre to the right side of the screen.&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;div style="text-align: justify;"&gt;&lt;center&gt;&lt;br /&gt;&lt;table border="1"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td align="center"&gt;&lt;embed align="center" height="480" src="http://bgrandovec.hostzi.com/Files/SnakesAdventure_P12.swf" type="application/x-shockwave-flash" width="480"&gt;&lt;/embed&gt;&lt;br /&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/center&gt;&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;div style="text-align: justify;"&gt;Complete source code, which takes care of embedding sound files and playing sound effects, is in the file Sounds.as. At the beginning of the file are three definitions of constants, one for each sound effect. Value of variable &lt;b&gt;soundVolume&lt;/b&gt; controls volume of played sound effect, volume can range from 0.0 (silent) to 1.0 (max volume).&lt;br /&gt;&lt;br /&gt;All three sound files are embedded the same way we embedded all images from Images folder. &lt;br /&gt;&lt;br /&gt;Function PlaySound plays one sound effect, value of &lt;b&gt;type&lt;/b&gt; parameter defines which sound effect will be played. On the basis of &lt;b&gt;type&lt;/b&gt; parameter appropriate Sound object is made. We use Sound class &lt;b&gt;play&lt;/b&gt; function to play sound effects. This function requires three parameters:&lt;br /&gt;- initial position (in milliseconds) at which playback start&lt;br /&gt;- the number of times a sound loops back to the startTime value before the sound channel stops playback&lt;br /&gt;- SoundTransform object assigned to the sound channel&lt;br /&gt;&lt;br /&gt;We will play all files from beginning and they won't loop. Only volume of the played sound effect will be adjusted. With SoundTransform object you can also adjust panning of played sound.&lt;br /&gt;&lt;br /&gt;Initial value of &lt;b&gt;soundVolume&lt;/b&gt; variable is 0.7, you can adjust this value as you will. So far, value remains unchanged during the game execution. Later, when we implement settings menu, player will be able to adjust sound volume with the slider.&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace; font-size: x-small;"&gt;private static const OPTIONSIN_SOUND:int      = 1;&lt;br /&gt;private static const OPTIONSOUT_SOUND:int     = 2;&lt;br /&gt;private static const OPTIONSELECTED_SOUND:int = 3;&lt;br /&gt;&lt;br /&gt;private var soundVolume:Number = 0.7;&lt;br /&gt;&lt;br /&gt;[Embed(source="Sounds/OptionsIn.mp3")] private var optionsInSnd:Class;&lt;br /&gt;[Embed(source="Sounds/OptionsOut.mp3")] private var optionsOutSnd:Class;&lt;br /&gt;[Embed(source="Sounds/OptionSelected.mp3")] private var optionSelectedSnd:Class;&lt;br /&gt;&lt;br /&gt;private function PlaySound(type:int) : void&lt;br /&gt;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;var sfx:Sound = null;&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;switch (type)&lt;br /&gt;&amp;nbsp;&amp;nbsp;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;case OPTIONSIN_SOUND:&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;sfx = new optionsInSnd() as Sound;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;break;&lt;br /&gt;&amp;nbsp;&amp;nbsp;case OPTIONSOUT_SOUND:&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;sfx = new optionsOutSnd() as Sound;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;break;&lt;br /&gt;&amp;nbsp;&amp;nbsp;case OPTIONSELECTED_SOUND:&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;sfx = new optionSelectedSnd() as Sound;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;break;   &lt;br /&gt;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;if (sfx != null)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;sfx.play(0,0,new SoundTransform(soundVolume));&lt;br /&gt;}&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;div style="text-align: justify;"&gt;We have all we need to play the sound effects. Let's use PlaySound function in Activation.as and GameMenu.as files.&lt;br /&gt;&lt;br /&gt;In Activation.as we will call PlaySound when mouse button is pressed. We did not handle mouse down event in Activation.as so far, that is why we have to create MouseDown_Activation function and call it from MouseDown function in SnakesAdventure.as if ACTIVATION state is active.&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace; font-size: x-small;"&gt;private function MouseDown_Activation(event:MouseEvent):void  &lt;br /&gt;{ &lt;br /&gt;&amp;nbsp;&amp;nbsp;if (activationState == ACTIVATION_WAIT)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;PlaySound(OPTIONSELECTED_SOUND);  &lt;br /&gt;}&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;div style="text-align: justify;"&gt;There is a lot more new code in GameMenu.as. ChangeState_GameMenu function is new here and it is called whenever game menu state changes. Before that, we changed the state by changing variable &lt;b&gt;gameMenuState&lt;/b&gt; and setting &lt;b&gt;gameMenuTime&lt;/b&gt; to zero. ChangeState_GameMenu function does the same, but before that it checks if GAMEOPTIONS_IN or GAMEOPTIONS_OUT is becoming active and plays suitable sound effect.&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace; font-size: x-small;"&gt;private function ChangeState_GameMenu(newState:int):void&lt;br /&gt;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;switch(newState)&lt;br /&gt;&amp;nbsp;&amp;nbsp;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;case GAMEOPTIONS_IN: &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;PlaySound(OPTIONSIN_SOUND);  &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;break;&lt;br /&gt;&amp;nbsp;&amp;nbsp;case GAMEOPTIONS_OUT:&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;PlaySound(OPTIONSOUT_SOUND);  &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;break;&lt;br /&gt;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;gameMenuState = newState;&lt;br /&gt;&amp;nbsp;&amp;nbsp;gameMenuTime = 0;&lt;br /&gt;}&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;div style="text-align: justify;"&gt;PlaySound function call has also been put in MouseDown_GameMenu function, but sound effect is played only when player clicks inside game option area.&lt;br /&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8678980820383323367-5548002343231005456?l=grandy-flexdev.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://grandy-flexdev.blogspot.com/feeds/5548002343231005456/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://grandy-flexdev.blogspot.com/2010/01/playing-sound-effects.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8678980820383323367/posts/default/5548002343231005456'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8678980820383323367/posts/default/5548002343231005456'/><link rel='alternate' type='text/html' href='http://grandy-flexdev.blogspot.com/2010/01/playing-sound-effects.html' title='Playing sound effects'/><author><name>Grandy</name><uri>http://www.blogger.com/profile/13061370372593845090</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='29' height='32' src='http://4.bp.blogspot.com/_4Xe_fkP2r2A/StiN3kMzX2I/AAAAAAAAAAU/wWM-ILREdfw/S220/MySelf.png'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8678980820383323367.post-9136291625240350162</id><published>2010-01-19T10:03:00.000-08:00</published><updated>2010-03-24T13:45:41.987-07:00</updated><title type='text'>Simple animations</title><content type='html'>&lt;div style="text-align: justify;"&gt;Animation is the sequence of images that creates an illusion of movement. Single image, displayed on various positions, can also create an illusion of movement. We already used both techniques in chapter &lt;a href="http://grandy-flexdev.blogspot.com/2010/01/implementing-keyboard-handler.html"&gt;8. Handling mouse events&lt;/a&gt;. If you remember, we are displaying two different images for background of selected and not selected option. We also set the location of selected background one pixel lower.&lt;br /&gt;&lt;br /&gt;In this chapter we will implement three different algorithms that perform animations and use them in activation screen and game menu. Before we begin, I suggest you start the game below and see for yourself, how they work. &lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;div style="text-align: justify;"&gt;&lt;center&gt;&lt;br /&gt;&lt;table border="1"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td align="center"&gt;&lt;embed align="center" height="480" src="http://bgrandovec.hostzi.com/Files/SnakesAdventure_P11.swf" type="application/x-shockwave-flash" width="480"&gt;&lt;/embed&gt;&lt;br /&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/center&gt;&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;div style="text-align: justify;"&gt;You should also &lt;a href="http://bgrandovec.hostzi.com/Files/SnakesAdventure_P11.zip"&gt;download&lt;/a&gt; project files for this chapter, because complete content of source files will help you better understand how algorithms work.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Fade effect&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;Fade effect is transition between original image and fully black image (fade out) or vice versa (fade in). In current version of Snake's Adventure this effect is applied right after program starts and after &lt;b&gt;New game&lt;/b&gt; option is selected.&lt;br /&gt;&lt;br /&gt;Fade effect is implemented in function Apply_FadeEffect in file Effects.as, which has to be included in main project source file (SnakesAdventure.as) before function can be used. &lt;br /&gt;&lt;br /&gt;&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace; font-size: x-small;"&gt;private var fadeEffectBitmap:BitmapData = null;&lt;br /&gt;&lt;br /&gt;private function Apply_FadeEffect(factor:Number):void&lt;br /&gt;{                          &lt;br /&gt;&amp;nbsp;&amp;nbsp;if (fadeEffectBitmap == null)&lt;br /&gt;&amp;nbsp;&amp;nbsp;{   &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;fadeEffectBitmap = new BitmapData(SCREEN_WIDTH,SCREEN_HEIGHT,true,0x00000000);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;fadeEffectBitmap.draw(new fadeEffectImg()); &lt;br /&gt;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;if (factor &amp;gt; 0.95)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;factor = 0.95;&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;for (var i:int = 0; i &amp;lt; 20; i++)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;screenBuffer.copyPixels(fadeEffectBitmap,&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;new Rectangle(0, (int)(factor * 20)  * 24, SCREEN_WIDTH, 24),&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;new Point(0,i * 24)); } &lt;br /&gt;&lt;/div&gt;&lt;br /&gt;Apply_FadeEffect requires one numeric parameter, values can range between 0 and 1. This value defines how much blackness is applied to screen buffer. Levels of blackness are defined in the FadeEffect.png. This image is fully black, but transparency increases from top to bottom. Transparency at the top is 0.05 and at the bottom 1. There are twenty different levels of transparency in this image that increases by factor 0.05. Height of each area is 24 pixels (20 x 24 = 480).&lt;br /&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://1.bp.blogspot.com/_4Xe_fkP2r2A/S1dkIXjOzLI/AAAAAAAAACY/XkteNCYj71w/s1600-h/FadeEffect.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://1.bp.blogspot.com/_4Xe_fkP2r2A/S1dkIXjOzLI/AAAAAAAAACY/XkteNCYj71w/s320/FadeEffect.png" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;Appropriate area of source image is calculated from value of &lt;b&gt;factor&lt;/b&gt; parameter. This part of source image is copied into screen buffer twenty times (from top to bottom).&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Splitting activation banner&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;When activation mode is active and mouse button is released, the banner at the bottom of the &lt;b&gt;gamePanel&lt;/b&gt; splits in two. Left part starts to move in the left direction, right part in the right direction. They move at the constant speed until they disappear from the panel.&lt;br /&gt;&lt;br /&gt;Before we focus on algorithm itself, let me explain some changes, that were made in Activation.as file.&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace; font-size: x-small;"&gt;private static const ACTIVATION_SHOW:int = 1;&lt;br /&gt;private static const ACTIVATION_WAIT:int = 2;&lt;br /&gt;private static const ACTIVATION_HIDE:int = 3;&lt;br /&gt;&lt;br /&gt;private var activationState:int = ACTIVATION_SHOW;&lt;br /&gt;private var activationTime:Number = 0;&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;div style="text-align: justify;"&gt;We need another state automaton, that will be active while program is in ACTIVATION state. Variable &lt;b&gt;activationState&lt;/b&gt; has the value of currently active sub-state, constants ACTIVATION_SHOW/WAIT/HIDE define all possible sub-states.&lt;br /&gt;&lt;br /&gt;Variable &lt;b&gt;activationTime&lt;/b&gt; will be used as the time counter (in seconds) of currently active sub-state.&lt;br /&gt;&lt;br /&gt;Below you can see that implementation of Draw_Activation function has been completely changed:&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace; font-size: x-small;"&gt;private function Draw_Activation(ellapsedTime:Number):void&lt;br /&gt;{   &lt;br /&gt;&amp;nbsp;&amp;nbsp;activationTime += ellapsedTime;&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;Draw_TitleScreen();&lt;br /&gt;&amp;nbsp;&amp;nbsp;Draw_ActivationBanner();  &lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;switch (activationState)&lt;br /&gt;&amp;nbsp;&amp;nbsp;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;case ACTIVATION_SHOW:    &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Apply_FadeEffect(1 - activationTime); &lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if (activationTime &gt;= 1)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;activationState = ACTIVATION_WAIT;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;activationTime = 0;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;break;&lt;br /&gt;&amp;nbsp;&amp;nbsp;case ACTIVATION_WAIT:&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;break;    &lt;br /&gt;&amp;nbsp;&amp;nbsp;case ACTIVATION_HIDE:    &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if (activationTime &gt;= 1)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;state = GAME_MENU;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;gameMenuState = GAMEOPTIONS_IN;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;} &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;break;  &lt;br /&gt;&amp;nbsp;&amp;nbsp;}    &lt;br /&gt;}&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;div style="text-align: justify;"&gt;First, value of &lt;b&gt;activationTime&lt;/b&gt; is increased by time interval between previous and current frame. Next, title screen and activation banner are drawn and at the end code, specific for active sub-state, is executed.&lt;br /&gt;&lt;br /&gt;ACTIVATION_SHOW state applies fade-in effect to screen buffer and lasts one second. After one second ACTIVATION_WAIT state becomes active and stays active until mouse button is released. &lt;br /&gt;&lt;br /&gt;MouseUp_Activation function from previous chapter changed the value of global &lt;b&gt;state&lt;/b&gt; variable to GAME menu. New version set the value of &lt;b&gt;activationState&lt;/b&gt; variable to ACTIVATION_HIDE and resets &lt;b&gt;activationTime&lt;/b&gt; counter to zero.&lt;br /&gt;&lt;br /&gt;ACTIVATION_HIDE state is also active for only one seconds. In this time, split banner animation is displayed. After one second global &lt;b&gt;state&lt;/b&gt; variable is set to GAME menu and &lt;b&gt;gameMenuState&lt;/b&gt; variable is set to GAMEOPTIONS_IN. Variable gameMenuState and constant GAMEOPTIONS_IN were also introduced in this chapter and will be explained later.&lt;br /&gt;&lt;br /&gt;Previous version of Draw_ActivationBanner function drew activation banner into screen buffer in one step. New version draws activation banner in two steps, first the left side of the image and then right side. If ACTIVATION_HIDE state is not active, banner looks the same as before. But inside one second, while state is active, value of variable &lt;b&gt;xPos&lt;/b&gt; increases from 0 (at the beginning) to 300 (add the end). This value is subtracted from horizontal position of left part of the banner, and added to horizontal position of the right part.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Moving game options&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;In this version of Snake's Adventure, game options are not visible right after &lt;b&gt;game menu&lt;/b&gt; state becomes active. Now they come from left side of the &lt;b&gt;gamePanel&lt;/b&gt; and move in the right direction.  When they reach the centre, movements stops and options become active. When &lt;b&gt;new game&lt;/b&gt; option is selected, all three options move to the right until they disappear. &lt;br /&gt;&lt;br /&gt;Implementation of this animation also not require any additional images and does not distinguish much from activation banner animation. But there has been some changes in the source code in file GameMenu.as, that has to be mentioned. &lt;br /&gt;&lt;br /&gt;Another state automaton has been implemented here with the same purpose as state automaton implemented in Activation.as.&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace; font-size: x-small;"&gt;private static const TITLE_SHOW:int       = 1;&lt;br /&gt;private static const GAMEOPTIONS_IN:int   = 2;&lt;br /&gt;private static const GAMEOPTIONS_WAIT:int = 3;&lt;br /&gt;private static const GAMEOPTIONS_OUT:int  = 4;&lt;br /&gt;private static const TITLE_HIDE:int       = 5;&lt;br /&gt;&lt;br /&gt;private var gameMenuState:int = TITLE_SHOW;&lt;br /&gt;private var gameMenuTime:Number = 0;&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;div style="text-align: justify;"&gt;Not a lot different, as you can see, but this time state automaton has five possible states.&lt;br /&gt;&lt;br /&gt;While TITLE_SHOW state is active, fade-in effect is applied to screen buffer. After one second GAMEOPTIONS_IN state becomes active. &lt;br /&gt;&lt;br /&gt;GAMEOPTIONS_IN state also lasts one seconds and within this seconds, game options move from the left side of &lt;b&gt;gamePanel&lt;/b&gt; to the centre. When they reach the centre, GAMEOPTIONS_WAIT state becomes active.&lt;br /&gt;&lt;br /&gt;While GAMEOPTIONS_WAIT state is active, program waits for mouse movement and mouse buttons events and behaves the same way as previous version of Snake's Adventure. Only this time, selection of &lt;b&gt;new game&lt;/b&gt; option activates GAMEOPTIONS_OUT state.&lt;br /&gt;&lt;br /&gt;GAMEOPTIONS_OUT state lasts one seconds and within this seconds, game options move from the centre of &lt;b&gt;gamePanel&lt;/b&gt; to the right, until they completely disappear. Now TITLE_HIDE state becomes active and fade-out effect is applied for one second.&lt;br /&gt;&lt;br /&gt;When the fade-out effect reaches the end and &lt;b&gt;gamePanel&lt;/b&gt; becomes completely black, program should activate GAME state and new game would begin. Activation of GAME state is pointless at the moment, because we have not work on the game, yet. Instead TITLE_SHOW state becomes active, title screen becomes visible again and game options show up.&lt;br /&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8678980820383323367-9136291625240350162?l=grandy-flexdev.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://grandy-flexdev.blogspot.com/feeds/9136291625240350162/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://grandy-flexdev.blogspot.com/2010/01/simple-animations.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8678980820383323367/posts/default/9136291625240350162'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8678980820383323367/posts/default/9136291625240350162'/><link rel='alternate' type='text/html' href='http://grandy-flexdev.blogspot.com/2010/01/simple-animations.html' title='Simple animations'/><author><name>Grandy</name><uri>http://www.blogger.com/profile/13061370372593845090</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='29' height='32' src='http://4.bp.blogspot.com/_4Xe_fkP2r2A/StiN3kMzX2I/AAAAAAAAAAU/wWM-ILREdfw/S220/MySelf.png'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://1.bp.blogspot.com/_4Xe_fkP2r2A/S1dkIXjOzLI/AAAAAAAAACY/XkteNCYj71w/s72-c/FadeEffect.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8678980820383323367.post-6217791127482159303</id><published>2010-01-18T10:00:00.000-08:00</published><updated>2010-03-24T13:37:42.619-07:00</updated><title type='text'>Embedding into web page</title><content type='html'>&lt;div style="text-align: justify;"&gt;There are many ways to distribute games made with Flex. You can create standalone executable, but most probably you wish to publish your game on your website or submit it to one or more game portals.&lt;br /&gt;&lt;br /&gt;In theory, your game will behave the same when played as standalone or from inside another application (web browser). In practice, there are some minor differences. One important difference for game developers is focus management, which can cause some problems, if game supports keyboard controls. Snake's Adventure will support only mouse controls, but if you wish support keyboard controls in your game, you will have to take care of focus management.&lt;br /&gt;&lt;br /&gt;As you can see in previous chapter, I embedded SnakesAdventure.swf for the first time. On the Internet you can find a lot of (different) examples, how to embed SWF files into web page. I am using following HTML tag on this pages:&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace; font-size: x-small;"&gt;&amp;lt;embed pluginspage="http://www.macromedia.com/go/getflashplayer" quality="high" src="SnakesAdventure.swf" type="application/x-shockwave-flash" width="480" height="480"&amp;gt;&amp;lt;/embed&amp;gt;&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;div style="text-align: justify;"&gt;There is one more thing you should be aware of, if you wish to submit your game on portals, web pages... Your game should not start right after it is loaded, embedded games usually have starting screen, where you have to click to start the game. This may seem unnecessary if there is only one game on the page, but it prevents chaos in case there are many games on the page.&lt;br /&gt;&lt;br /&gt;In this chapter, we will implement activation mode, that will display the same title screen, that we use in the game menu, in the background. On the lower part of the frame will be the banner that says "Press mouse click to start the game". Activation mode will be active until mouse button is released.&lt;br /&gt;&lt;br /&gt;First we have to check if game is running as embedded or not. In case it is, we will start the program in activation state otherwise &lt;b&gt;game menu&lt;/b&gt; state will remain active. ExternalInterface class contains property &lt;b&gt;available&lt;/b&gt; that tell us if program is embedded. Before we can use it, we have to add import statement at the top of SnakesAdventure.as:&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace; font-size: x-small;"&gt;import flash.external.ExternalInterface; &lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;div style="text-align: justify;"&gt;Add new constant to other state constants:&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace; font-size: x-small;"&gt;private static const ACTIVATION:int       = 0;&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;div style="text-align: justify;"&gt;Inside &lt;b&gt;Init&lt;/b&gt; function we will check if game is embedded and in case it is, we will set &lt;b&gt;state&lt;/b&gt; variable value to ACTIVATION. Otherwise &lt;b&gt;state&lt;/b&gt; variable value will remain unchanged and program will display game menu at the beginning.&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace; font-size: x-small;"&gt;if (ExternalInterface.available)&lt;br /&gt;&amp;nbsp;&amp;nbsp;state = ACTIVATION;&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;div style="text-align: justify;"&gt;We will put source code for ACTIVATION state into its own file: Activation.as. Create empty file with that name and copy following source code:&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace; font-size: x-small;"&gt;private function Draw_Activation(elapsedTime:Number):void&lt;br /&gt;{    &lt;br /&gt;&amp;nbsp;&amp;nbsp;Draw_TitleScreen();&lt;br /&gt;&amp;nbsp;&amp;nbsp;Draw_ActivationBanner();    &lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;private var activationBannerBitmap:BitmapData = null;&lt;br /&gt;&lt;br /&gt;private function Draw_ActivationBanner():void&lt;br /&gt;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;if (activationBannerBitmap == null)&lt;br /&gt;&amp;nbsp;&amp;nbsp;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;activationBannerBitmap = new BitmapData(SCREEN_WIDTH,36,true,0x00000000);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;activationBannerBitmap.draw(new activationBannerImg());&lt;br /&gt;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;screenBuffer.copyPixels(activationBannerBitmap,&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;new Rectangle(0, 0, SCREEN_WIDTH , 36),&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;new Point(0,400));                        &lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;private function MouseUp_Activation(event:MouseEvent):void  &lt;br /&gt;{ &lt;br /&gt;&amp;nbsp;&amp;nbsp;state = GAME_MENU;&lt;br /&gt;}&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;div style="text-align: justify;"&gt;Nothing new here, that we have not seen in previous chapters.&lt;br /&gt;&lt;br /&gt;Draw_Activation function is called from Draw function in SnakesAdventure.as when ACTIVATION state is active. It first calls Draw_TitleScreen from GameMenu.as that draws title screen image. Then it displays activation banner by calling Draw_ActivationBanner implemented bellow. Code from Draw_ActivationBanner is similar to other functions that draw image into screen buffer. Size of my version of banner is 480x36 pixels, if you made your version, adjust the size in the Rectangle.&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://2.bp.blogspot.com/_4Xe_fkP2r2A/S1S5N9pMZlI/AAAAAAAAACQ/dGFsFMuMGqc/s1600-h/ActivationBanner.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://2.bp.blogspot.com/_4Xe_fkP2r2A/S1S5N9pMZlI/AAAAAAAAACQ/dGFsFMuMGqc/s400/ActivationBanner.png" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;div style="text-align: justify;"&gt;MouseUp_Activation will be called from MouseUp function implemented in SnakesAdventure.as when ACTIVATION state is active. When user releases mouse button, MouseUp_Activation will change active state of the program to GAME_MENU and consequently, game menu will show up. We don't have to check MouseDown/Moved events here.&lt;br /&gt;&lt;br /&gt;Of course we must not forget to embed banner image into executable. Add this line to Images.as:&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace; font-size: x-small;"&gt;[Embed(source="Images/ActivationBanner.png")] private var activationBannerImg:Class;&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;div style="text-align: justify;"&gt;In SnakesAdventure.as we have to add another include stetement:&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace; font-size: x-small;"&gt;include "Activation.as";&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;div style="text-align: justify;"&gt;We also have to add another &lt;b&gt;case&lt;/b&gt; in switch statement of Draw function:&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace; font-size: x-small;"&gt;case ACTIVATION:&lt;br /&gt;&amp;nbsp;&amp;nbsp;Draw_Activation(elapsedTime);&lt;br /&gt;&amp;nbsp;&amp;nbsp;break;  &lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;div style="text-align: justify;"&gt;and MouseUp function:&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace; font-size: x-small;"&gt;case ACTIVATION:&lt;br /&gt;&amp;nbsp;&amp;nbsp;MouseUp_Activation(event);&lt;br /&gt;&amp;nbsp;&amp;nbsp;break;  &lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;div style="text-align: justify;"&gt;That's it. There is, of course, project package for this chapter available for &lt;a href="http://bgrandovec.hostzi.com/Files/SnakesAdventure_P10.zip"&gt;download&lt;/a&gt;. If you build SnakesAdventure.swf on your computer and start it from Flash player, you will not see activation screen that is visible in the embedded version below. &lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;div style="text-align: justify;"&gt;&lt;center&gt;&lt;br /&gt;&lt;table border="1"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td align="center"&gt;&lt;embed align="center" height="480" src="http://bgrandovec.hostzi.com/Files/SnakesAdventure_P10.swf" type="application/x-shockwave-flash" width="480"&gt;&lt;/embed&gt;&lt;br /&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/center&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8678980820383323367-6217791127482159303?l=grandy-flexdev.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://grandy-flexdev.blogspot.com/feeds/6217791127482159303/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://grandy-flexdev.blogspot.com/2010/01/embedding-into-web-page.html#comment-form' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8678980820383323367/posts/default/6217791127482159303'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8678980820383323367/posts/default/6217791127482159303'/><link rel='alternate' type='text/html' href='http://grandy-flexdev.blogspot.com/2010/01/embedding-into-web-page.html' title='Embedding into web page'/><author><name>Grandy</name><uri>http://www.blogger.com/profile/13061370372593845090</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='29' height='32' src='http://4.bp.blogspot.com/_4Xe_fkP2r2A/StiN3kMzX2I/AAAAAAAAAAU/wWM-ILREdfw/S220/MySelf.png'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://2.bp.blogspot.com/_4Xe_fkP2r2A/S1S5N9pMZlI/AAAAAAAAACQ/dGFsFMuMGqc/s72-c/ActivationBanner.png' height='72' width='72'/><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8678980820383323367.post-3791579750790886796</id><published>2010-01-11T09:51:00.001-08:00</published><updated>2010-03-24T13:38:10.864-07:00</updated><title type='text'>Thinking ahead</title><content type='html'>&lt;div style="text-align: justify;"&gt;If you are reading this tutorial, you most probably wish to learn how to create games with Flex. The reason why we were working on the game menu so far, is because it is easier to learn the basics on simple things. Eventually, we will start development of the game itself, that is why we have to be prepared. We need to somehow separate game menu functionality from the functionality of the game. First we will implement &lt;b&gt;state automaton&lt;/b&gt; and then break SnakesAdventure.as into three files.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;State automaton&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;State automaton or state machine is a model composed of a number of states. At the moment our program has only one state, we will simply name it &lt;b&gt;game menu&lt;/b&gt;. Let's pretend that we already implemented first stage of the game. When the player chooses &lt;b&gt;new game&lt;/b&gt; option, new state becomes active. We will call this state &lt;b&gt;game&lt;/b&gt;.&lt;br /&gt;&lt;br /&gt;Why is this important? Let me give you an example. In previous chapter we implemented mouse handler which will be active in both states. In &lt;b&gt;game menu&lt;/b&gt;, functions MouseDown/Up/Move control the behaviour of game options when mouse cursor is positioned over or away from label area. When the program will be in the &lt;b&gt;game&lt;/b&gt; state, tasks of all three functions will be completely different. That is why we need to know the state of program at the moment the event occurs and execute the right code.&lt;br /&gt;&lt;br /&gt;For state management we need only one variable, initialized with the value of the state at the start of the program. Each state will be defined with one constant value. Put the following definitions to other definitions in SnakesAdventure.as:&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace; font-size: x-small;"&gt;private static const GAME_MENU:int        = 1;&lt;br /&gt;private static const GAME:int             = 2;&lt;br /&gt;&lt;br /&gt;private var state:int = GAME_MENU;&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;div style="text-align: justify;"&gt;&lt;b&gt;Breaking the code&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;At the moment source code of the project is split in two files: Images.as and SnakesAdventure.as. Images.as contains only few definitions of embedded images. On the other hand, SnakesAdventure.as is growing with each chapter - my version already is almost 150 lines long. This should not be a problem for now, but in the future file size will grow with each new implemented feature and source code in the file will soon become a mess. From my experience, it is better to keep the source code clean from the beginning.&lt;br /&gt;&lt;br /&gt;That is why we will now split content of SnakesAdventure.as into three files: SnakesAdventure.as, GameMenu.as and Game.as. I suggest you &lt;a href="http://bgrandovec.hostzi.com/Files/SnakesAdventure_P9.zip"&gt;download&lt;/a&gt; my version of the project and briefly review all three files. I will try to explain what and why has been changed.&lt;br /&gt;&lt;br /&gt;First I made two empty files: GameMenu.as and Game.as. Then I added include statements for both files into SnakesAdventure.as (line 7 and 8). From now on both files are included in compilation process.&lt;br /&gt;&lt;br /&gt;I moved the code, specific to game menu from SnakesAdventure.as, into GameMenu.as:&lt;br /&gt;- definitions of OPTION_ constants&lt;br /&gt;- definition of variables pressedOption, titleScreenBitmap, gameOptionsBitmap and gameOptionBackgroundBitmap&lt;br /&gt;- Draw_TitleScreen function&lt;br /&gt;- Draw_GameOptions function&lt;br /&gt;&lt;br /&gt;Then I moved the content of Draw function (SnakesAdventure.as) into new function Draw_GameMenu in GameMenu.as. I did the same with MouseDown/Up/Moved, new functions in GameMenu.as now have names MouseDown_GameMenu, MouseUp_GameMenu and MouseMoved_GameMenu.&lt;br /&gt;&lt;br /&gt;We don't have any code as far as game is concerned, that is why file Game.as is very short. Only four functions with empty bodies are inside this file: Draw_Game, MouseDown_Game, MouseUp_Game, MouseMoved_Game. This functions will be executed when events occur while the program is in the &lt;b&gt;game&lt;/b&gt; state. We will implement this functions in the following chapters, but for now they are here to better illustrate the situation.&lt;br /&gt;&lt;br /&gt;SnakesAdventure.as from now on contains only variables and constants that are common to all three files or specific to code in this file. Init and UpdateFrame are the same as before, but Draw, MouseDown, MouseUp and MouseDown have been changed completely.&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace; font-size: x-small;"&gt;private function Draw(elapsedTime:Number):void&lt;br /&gt;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;switch (state)&lt;br /&gt;&amp;nbsp;&amp;nbsp;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;case GAME_MENU:&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Draw_GameMenu(elapsedTime);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;break;&lt;br /&gt;&amp;nbsp;&amp;nbsp;case GAME:&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Draw_Game(elapsedTime);  &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;break;   &lt;br /&gt;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;private function MouseDown(event:MouseEvent):void  &lt;br /&gt;{ &lt;br /&gt;&amp;nbsp;&amp;nbsp;switch (state)&lt;br /&gt;&amp;nbsp;&amp;nbsp;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;case GAME_MENU:&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;MouseDown_GameMenu(event);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;break;&lt;br /&gt;&amp;nbsp;&amp;nbsp;case GAME:&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;MouseDown_Game(event);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;break;&lt;br /&gt;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;} &lt;br /&gt;&lt;br /&gt;private function MouseUp(event:MouseEvent):void  &lt;br /&gt;{ &lt;br /&gt;&amp;nbsp;&amp;nbsp;switch (state)&lt;br /&gt;&amp;nbsp;&amp;nbsp;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;case GAME_MENU:&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;MouseUp_GameMenu(event);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;break;&lt;br /&gt;&amp;nbsp;&amp;nbsp;case GAME:&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;MouseUp_Game(event);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;break;&lt;br /&gt;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;private function MouseMoved(event:MouseEvent):void  &lt;br /&gt;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;switch (state)&lt;br /&gt;&amp;nbsp;&amp;nbsp;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;case GAME_MENU:&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;MouseMoved_GameMenu(event);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;break;&lt;br /&gt;&amp;nbsp;&amp;nbsp;case GAME:&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;MouseMoved_Game(event);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;break;&lt;br /&gt;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;}&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;div style="text-align: justify;"&gt;As you can see, all four functions looks very similar. They just check current state of the program and call appropriate function.&lt;br /&gt;&lt;br /&gt;We have made some huge changes in the source code of the project and now we are set to implement new features. In spite of all this changes, program behaves exactly the same as it did before. You can verify this with embedded SWF below.&lt;br /&gt;&lt;br /&gt;&lt;center&gt;&lt;table border="1"&gt;&lt;tr&gt;&lt;td align="center"&gt;&lt;embed height="480" src="http://bgrandovec.hostzi.com/Files/SnakesAdventure_P9.swf" type="application/x-shockwave-flash" width="480" align="center"&gt;&lt;/embed&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/center&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8678980820383323367-3791579750790886796?l=grandy-flexdev.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://grandy-flexdev.blogspot.com/feeds/3791579750790886796/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://grandy-flexdev.blogspot.com/2010/01/thinking-ahead.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8678980820383323367/posts/default/3791579750790886796'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8678980820383323367/posts/default/3791579750790886796'/><link rel='alternate' type='text/html' href='http://grandy-flexdev.blogspot.com/2010/01/thinking-ahead.html' title='Thinking ahead'/><author><name>Grandy</name><uri>http://www.blogger.com/profile/13061370372593845090</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='29' height='32' src='http://4.bp.blogspot.com/_4Xe_fkP2r2A/StiN3kMzX2I/AAAAAAAAAAU/wWM-ILREdfw/S220/MySelf.png'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8678980820383323367.post-3319219717279368981</id><published>2010-01-10T10:59:00.001-08:00</published><updated>2010-03-24T13:25:29.077-07:00</updated><title type='text'>Handling mouse events</title><content type='html'>&lt;div style="text-align: justify;"&gt;In the previous chapter we focused mostly on drawing of game options, but in this chapter we will make some changes, so that game options will work like buttons.&lt;br /&gt;&lt;br /&gt;To accomplish this, we have to instruct the application to let us know when mouse is moved or its buttons are pressed/released, and respond accordingly. This is called mouse event handling. Event handling plays important role in Flex development and if you would like to learn more about events and event handling, check this tutorial from &lt;a href="http://livedocs.adobe.com/flex/3/html/index.html"&gt;Adobe Flex live Docs&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;We will add three event handlers to &lt;b&gt;gamePanel&lt;/b&gt;: mouseDown, mouseUp and mouseMove. Change &lt;b&gt;mx:Canvas&lt;/b&gt; tag in SnakesAdventure.mxml like this:&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace; font-size: x-small;"&gt;&amp;lt;mx:Canvas id="gamePanel" x="0" y="0" width="100%" height="100%" mouseDown="MouseDown(event)" mouseUp="MouseUp(event)" mouseMove="MouseMoved(event)/&amp;gt;&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;div style="text-align: justify;"&gt;Within a single line, we instruct the application to execute: &lt;br /&gt;- MouseDown function when any mouse button is pressed&lt;br /&gt;- MouseUp function when any mouse button is released&lt;br /&gt;- MouseMoved function when mouse is moved&lt;br /&gt;&lt;br /&gt;All three functions will be implemented in file SnakesAdventure.as, but first we will make some changes in the file that will make implementation of options behaviour a little bit easier. Add three new constants after SCREEN_WIDTH and SCREEN_HEIGHT constants:&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace; font-size: x-small;"&gt;private static const OPTION_NEW_GAME:int  = 0;&lt;br /&gt;private static const OPTION_CONTINUE:int  = 1;&lt;br /&gt;private static const OPTION_SETTINGS:int  = 2;&lt;br /&gt;&lt;br /&gt;private var pressedOption:int = -1;&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;div style="text-align: justify;"&gt;We assigned one constant value for each option in game menu. We also defined new variable &lt;b&gt;pressedOption&lt;/b&gt;, where we will keep index of pressed option. At the beginning no option is pressed, that's why we assigned the variable value -1.&lt;br /&gt;&lt;br /&gt;We will used three new constants in the block of code bellow, where we will simplify code that draws game options. Replace the code with existing code that draws game options (function Draw_GameOptions).&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace; font-size: x-small;"&gt;for (var i:int = OPTION_NEW_GAME; i &amp;lt;= OPTION_SETTINGS; i++)&lt;br /&gt;{&lt;br /&gt;&amp;nbsp; var srcY:int = pressedOption == i ? 160 : 80;&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;if (i == OPTION_CONTINUE)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;srcY = 0;&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;screenBuffer.copyPixels(gameOptionBackgroundBitmap,&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;new Rectangle(0, srcY, 340, 80),&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;new Point(70,235 + i * 70 + (pressedOption == i ? 1 : 0)));&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;switch (i)&lt;br /&gt;&amp;nbsp;&amp;nbsp;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;case OPTION_NEW_GAME:&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;srcY = 0;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;break;&lt;br /&gt;&amp;nbsp;&amp;nbsp;case OPTION_CONTINUE:&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;srcY = 100;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;break;&lt;br /&gt;&amp;nbsp;&amp;nbsp;case OPTION_SETTINGS:&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;srcY = 150;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;break;&lt;br /&gt;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;screenBuffer.copyPixels(gameOptionsBitmap,&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; new Rectangle(0, srcY, 260, 50),&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; new Point(110,250 + i * 70 + (pressedOption == i ? 1 : 0))); } &lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;div style="text-align: justify;"&gt;In previous version we had six copies of &lt;b&gt;copyPixel&lt;/b&gt; commands, three for background and three for labels. In this version we have just two, because we put the drawing code inside loop with three iterations, one for each option. In both commands we check if option is pressed and if it is, we draw background and label one pixel lower. We also use background image that is a little bit smaller and has white glow around.&lt;br /&gt;&lt;br /&gt;Now we can finally handle mouse events. We will implement three functions:&lt;br /&gt;- MouseDown will check if mouse click occurred inside any option and in case it was, set the index of option to &lt;b&gt;pressedOption&lt;/b&gt; variable&lt;br /&gt;- MouseUp resets the value of &lt;b&gt;pressedOption&lt;/b&gt;&lt;br /&gt;- MouseMoved, checks if mouse cursor left the area of pressed option and resets the value of &lt;b&gt;pressedOption&lt;/b&gt;&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace; font-size: x-small;"&gt;private function MouseDown(event:MouseEvent):void  &lt;br /&gt;{ &lt;br /&gt;&amp;nbsp;&amp;nbsp;var mx:int = event.localX;&lt;br /&gt;&amp;nbsp;&amp;nbsp;var my:int = event.localY;&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;for (var i:int = OPTION_NEW_GAME; i &amp;lt;= OPTION_SETTINGS; i++)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if (i != OPTION_CONTINUE)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if ((mx &amp;gt;= 110) &amp;amp;&amp;amp; (mx &amp;lt; 370) &amp;amp;&amp;amp; (my &amp;gt;= 250 + i * 70) &amp;amp;&amp;amp; (my &amp;lt; 300 + i * 70))&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;pressedOption = i;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;private function MouseUp(event:MouseEvent):void&lt;br /&gt;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;var mx:int = event.localX;&lt;br /&gt;&amp;nbsp;&amp;nbsp;var my:int = event.localY;&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;pressedOption = -1;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;private function MouseMoved(event:MouseEvent):void&lt;br /&gt;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;var mx:int = event.localX;&lt;br /&gt;&amp;nbsp;&amp;nbsp;var my:int = event.localY;&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;for (var i:int = OPTION_NEW_GAME; i &amp;lt;= OPTION_SETTINGS; i++)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if (pressedOption == i)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if ((mx &amp;lt; 110) || (mx &amp;gt; 370) || (my &amp;lt; 250 + i * 70) || (my &amp;gt; 300 + i * 70))&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;pressedOption = -1; &lt;br /&gt;}&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;div style="text-align: justify;"&gt;In each function we first set position of mouse cursor to local variables.&lt;br /&gt;&lt;br /&gt;MouseDown loops through all options and in case it is not &lt;b&gt;continue&lt;/b&gt; option (because it is currently disabled) checks if mouse cursor is inside area, where option label is drawn. In case it is, &lt;b&gt;pressedOption&lt;/b&gt; variable gets the value of option index. Consequently, program will draw option with same index as &lt;b&gt;pressedOption&lt;/b&gt; variable value differently. Different (slightly smaller) background image will be used for drawing and option will be located one pixel lower. While the user holds the mouse button, option will be pressed.&lt;br /&gt;&lt;br /&gt;MouseUp is called when mouse button is released. Value of &lt;b&gt;pressedOption&lt;/b&gt; is set to -1, even if it was already -1. But if it was not, consequently, program will draw option with default background and it will appear like option was released.&lt;br /&gt;&lt;br /&gt;MouseMoved also resets value of &lt;b&gt;pressedOption&lt;/b&gt; to -1, but only if mouse cursor left the pressed option area.&lt;br /&gt;&lt;br /&gt;Complete project with source files and content files is available for &lt;a href="http://bgrandovec.hostzi.com/Files/SnakesAdventure_P8.zip"&gt;download&lt;/a&gt; as usual.&lt;br /&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8678980820383323367-3319219717279368981?l=grandy-flexdev.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://grandy-flexdev.blogspot.com/feeds/3319219717279368981/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://grandy-flexdev.blogspot.com/2010/01/implementing-keyboard-handler.html#comment-form' title='4 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8678980820383323367/posts/default/3319219717279368981'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8678980820383323367/posts/default/3319219717279368981'/><link rel='alternate' type='text/html' href='http://grandy-flexdev.blogspot.com/2010/01/implementing-keyboard-handler.html' title='Handling mouse events'/><author><name>Grandy</name><uri>http://www.blogger.com/profile/13061370372593845090</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='29' height='32' src='http://4.bp.blogspot.com/_4Xe_fkP2r2A/StiN3kMzX2I/AAAAAAAAAAU/wWM-ILREdfw/S220/MySelf.png'/></author><thr:total>4</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8678980820383323367.post-8528599515509066018</id><published>2009-11-20T06:13:00.000-08:00</published><updated>2010-03-25T09:00:38.238-07:00</updated><title type='text'>Implementing game options</title><content type='html'>&lt;div style="text-align: justify;"&gt;Game menu will be displayed on the lower part of of the frame and will have only three options: &lt;br /&gt;- new game: start new game from the beginning&lt;br /&gt;- continue: resume playing the game in progress&lt;br /&gt;- settings: display game settings&lt;br /&gt;&lt;br /&gt;Each option requires one image, but "continue" option can also be disabled (when there is no game in progress) and requires one extra image. As you can see on the picture bellow, all labels were put in one file. To draw required option, we will have to set appropriate source area for &lt;b&gt;copyPixel&lt;/b&gt; function. If you are making your own version of options, you can, put each image into its own file, but you will have to make few adjustments in the source code.&lt;br /&gt;&lt;br /&gt;If you wish to use my version anyway, &lt;a href="http://bgrandovec.hostzi.com/Files/SnakesAdventure_P7.zip"&gt;download&lt;/a&gt; project for this chapter and copy GameOptions.png from Images folder into your own project folder. Unfortunately, downloading image directly from this page is not recommended, because transparency of the image is not preserved.&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://1.bp.blogspot.com/_4Xe_fkP2r2A/S0Yo3M6g8mI/AAAAAAAAABQ/chPmQWyWtFk/s1600-h/GameOptions.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://1.bp.blogspot.com/_4Xe_fkP2r2A/S0Yo3M6g8mI/AAAAAAAAABQ/chPmQWyWtFk/s200/GameOptions.png" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;div style="text-align: justify;"&gt;When your or my version of GameOptions.png is stored inside Images folder, embed it the same way as we did TitleScreen.png in the &lt;a href="http://grandy-flexdev.blogspot.com/2009/11/displaying-title-screen.html"&gt;chapter 6&lt;/a&gt;. Add this line at the end of file Images.as:&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace; font-size: x-small;"&gt;[Embed(source="Images/GameOptions.png")] private var gameOptionsImg:Class;&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;div style="text-align: justify;"&gt;Draw_GameOptions function that paints all three options in screen buffer does not look much different from Draw_TitleScreen function we implemented in &lt;a href="http://grandy-flexdev.blogspot.com/2009/11/displaying-title-screen.html"&gt;chapter 6&lt;/a&gt;. Put the following piece of code at the end of SnakesAdventure.as file:&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace; font-size: x-small;"&gt;private var gameOptionsBitmap:BitmapData = null;&lt;br /&gt;&lt;br /&gt;private function Draw_GameOptions():void&lt;br /&gt;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;if (gameOptionsBitmap == null)&lt;br /&gt;&amp;nbsp;&amp;nbsp;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;gameOptionsBitmap = new BitmapData(260,200,true,0x00000000);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;gameOptionsBitmap.draw(new gameOptionsImg());&lt;br /&gt;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;screenBuffer.copyPixels(gameOptionsBitmap,&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;new Rectangle(0, 0, 260, 50),&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;new Point(110,250));&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;screenBuffer.copyPixels(gameOptionsBitmap,&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;new Rectangle(0, 50, 260, 50),&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;new Point(110,320));&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;screenBuffer.copyPixels(gameOptionsBitmap,&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;new Rectangle(0, 150, 260, 50),&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;new Point(110,390));&lt;br /&gt;}&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;div style="text-align: justify;"&gt;As before we first check if Bitmap object was already created and if it was not, we create it.&lt;br /&gt;This time we have specified fourth parameters in BitmapData constructor and set it to &lt;b&gt;0x00000000&lt;/b&gt; (set all bits in the bitmap to zero). By default all bits are set to one (non-transparent white colour), but they have to be set to zero for transparent images, otherwise transparency channel of original image is lost.&lt;br /&gt;&lt;br /&gt;Three calls of copyPixels function draw all three options into screen buffer. In my version of GameOptions.png width and height of each option is 260x50 pixels, that is why size of each rectangle area is also 260x50 pixels.&lt;br /&gt;&lt;br /&gt;First call draws &lt;b&gt;new game&lt;/b&gt; option slightly bellow the centre of the frame. To set the correct position, you specify location (third parameter) of the upper-left corner (not the centre) where the copy of source bitmap begins. That is why you have to subtract centre position of the source bitmap from destination location. If you wish to place &lt;b&gt;new game&lt;/b&gt; option in the centre of the frame (remember, frame size is 480x480 pixels so the centre is at 240,240), substract 130 from horizontal position and 25 from vertical (130,25 is the centre of the each option bitmap area). Position 110,215 will draw the &lt;b&gt;new game&lt;/b&gt; option in the centre of the frame. Because in my version of title screen game, the title text is very big, I had to move &lt;b&gt;new game&lt;/b&gt; option slightly bellow the centre of the frame, by setting vertical position to 255.&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://4.bp.blogspot.com/_4Xe_fkP2r2A/S0ZKI86E6qI/AAAAAAAAABY/ccVag6wJVkY/s1600-h/GameMenu.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://4.bp.blogspot.com/_4Xe_fkP2r2A/S0ZKI86E6qI/AAAAAAAAABY/ccVag6wJVkY/s320/GameMenu.png" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;div style="text-align: justify;"&gt;Second call of &lt;b&gt;copyPixels&lt;/b&gt; function draws the (enabled) &lt;b&gt;continue&lt;/b&gt; option. We use the same bitmap here, but we have to specify different source area rectangle and different location in the screen buffer. Source area is 50 pixels bellow &lt;b&gt;new game&lt;/b&gt; option (vertical position set to 50) and the vertical location in the screen buffer is increased by 70 pixels. As you can see on the picture above, vertical gap between first and second option is a little bit bigger (extra 20 pixels) than on the original image.&lt;br /&gt;&lt;br /&gt;Last call of &lt;b&gt;copyPixels&lt;/b&gt; function draws the &lt;b&gt;settings&lt;/b&gt; option. Source image area is set to the bottom of the image (vertically from pixel 150-199) and location on the screen buffer is set 70 pixels bellow &lt;b&gt;continue&lt;/b&gt; option.&lt;br /&gt;&lt;br /&gt;To actually draw game options, you have to add Draw_GameOptions function call into Draw function, after Draw_TitleScreen(). Don't insert it before Draw_TitleScreen(), because in that case title screen will be drawn over game menu options.&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;div style="text-align: justify;"&gt;&lt;b&gt;Options background&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;If you have my version of &lt;a href="http://bgrandovec.hostzi.com/Files/SnakesAdventure_P7.zip"&gt;project&lt;/a&gt; for this chapter on your disk, you probably noticed GameOptionBackground.png file in Images folder. This file has three versions of options background, one for disabled, one for enabled and one for selected option. Maybe the second and third background image look the same, but selected one is a little bit smaller and has white glow. &lt;br /&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://2.bp.blogspot.com/_4Xe_fkP2r2A/S1CzyIdPAxI/AAAAAAAAACI/dJj1KmHCBD0/s1600-h/GameOptionBackground.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://2.bp.blogspot.com/_4Xe_fkP2r2A/S1CzyIdPAxI/AAAAAAAAACI/dJj1KmHCBD0/s200/GameOptionBackground.png" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;div style="text-align: justify;"&gt;Before we implement the code that paints background of the game options, we have to do all the stuff we did for title screen and game options image: &lt;br /&gt;&lt;br /&gt;- embed (file Images.as): &lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace; font-size: x-small; text-align: left;"&gt;[Embed(source="Images/GameOptionsBackground.png")] private var gameOptionBackgroundImg:Class;&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;div style="text-align: justify;"&gt;- define: (file SnakesAsventure.as) add the line after definition of &lt;b&gt;gameOptionsBitmap&lt;/b&gt; variable:&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace; font-size: x-small;"&gt;private var gameOptionBackgroundBitmap:BitmapData = null;&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;div style="text-align: justify;"&gt;- create: (file SnakesAsventure.as) insert this piece of code into &lt;b&gt;Draw_GameOptions&lt;/b&gt; function, before or after the code that creates &lt;b&gt;gameOptionsBitmap&lt;/b&gt; object. The only thing that matters is that object is created before it is used.&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace; font-size: x-small;"&gt;if (gameOptionBackgroundBitmap == null)&lt;br /&gt;{   &lt;br /&gt;&amp;nbsp;&amp;nbsp;gameOptionBackgroundBitmap = new BitmapData(340,240,true,0x00000000);&lt;br /&gt;&amp;nbsp;&amp;nbsp;gameOptionBackgroundBitmap.draw(new gameOptionBackgroundImg());    &lt;br /&gt;}&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;div style="text-align: justify;"&gt;Now we are ready to implement the code that actually paints background of game options. As you can see on the picture, each option has its own background, enabled options has different background than disabled. We will also change the code that paints &lt;b&gt;continue&lt;/b&gt; option, so that the grey (disabled) label is drawn instead of blue one.&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://2.bp.blogspot.com/_4Xe_fkP2r2A/S0-Es0a1njI/AAAAAAAAACA/QaLamZX_iHc/s1600-h/GameMenu2.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://2.bp.blogspot.com/_4Xe_fkP2r2A/S0-Es0a1njI/AAAAAAAAACA/QaLamZX_iHc/s320/GameMenu2.png" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;div style="text-align: justify;"&gt;Insert the code bellow into Draw_GameOptions function, before the code that paints options labels.&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace; font-size: x-small;"&gt;screenBuffer.copyPixels(gameOptionBackgroundBitmap,&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;new Rectangle(0, 80, 340, 80),&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;new Point(70,235));&lt;br /&gt;&lt;br /&gt;screenBuffer.copyPixels(gameOptionBackgroundBitmap,&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;new Rectangle(0, 0, 340, 80),&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;new Point(70,305));&lt;br /&gt;&lt;br /&gt;screenBuffer.copyPixels(gameOptionBackgroundBitmap,&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;new Rectangle(0, 80, 340, 80),&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;new Point(70,375));&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;div style="text-align: justify;"&gt;As you can see, this block of code is similar to one that draws the labels. There are, of course three differences: different source bitmap is used, different source areas are set and locations are slightly different.&lt;br /&gt;&lt;br /&gt;Background image is 60 pixels wider and 30 pixels higher than labels, that's why the location in &lt;b&gt;copyPixel&lt;/b&gt; function has to be set 30 pixels left and 15 up from label. Vertical offset between backgrounds is the same as offset between labels.&lt;br /&gt;&lt;br /&gt;To display disabled &lt;b&gt;continue&lt;/b&gt; option, we have to make a minor change in the code that paints &lt;b&gt;continue&lt;/b&gt; option. Change vertical position in the source area rectangle from 50 to 100.&lt;br /&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8678980820383323367-8528599515509066018?l=grandy-flexdev.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://grandy-flexdev.blogspot.com/feeds/8528599515509066018/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://grandy-flexdev.blogspot.com/2009/11/implementing-menu-options.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8678980820383323367/posts/default/8528599515509066018'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8678980820383323367/posts/default/8528599515509066018'/><link rel='alternate' type='text/html' href='http://grandy-flexdev.blogspot.com/2009/11/implementing-menu-options.html' title='Implementing game options'/><author><name>Grandy</name><uri>http://www.blogger.com/profile/13061370372593845090</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='29' height='32' src='http://4.bp.blogspot.com/_4Xe_fkP2r2A/StiN3kMzX2I/AAAAAAAAAAU/wWM-ILREdfw/S220/MySelf.png'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://1.bp.blogspot.com/_4Xe_fkP2r2A/S0Yo3M6g8mI/AAAAAAAAABQ/chPmQWyWtFk/s72-c/GameOptions.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8678980820383323367.post-9195578389372695608</id><published>2009-11-16T04:53:00.000-08:00</published><updated>2010-03-23T12:40:04.391-07:00</updated><title type='text'>Displaying the title screen</title><content type='html'>&lt;div style="text-align: justify;"&gt;We have done a lot of work by now, but still there is nothing going on. It is time to add some graphics. First we will implement title screen and meanwhile explore basics of graphics programming in Flex.&lt;br /&gt;&lt;br /&gt;Title screen will be displayed as soon as the game starts. I've made simple picture for the title screen background, but I bet you can do better picture yourself, just make sure it has the same size as game frame. If you wish to use my picture anyway, &lt;a href="http://bgrandovec.hostzi.com/Files/SnakesAdventure_P6.zip"&gt;download&lt;/a&gt; complete project for this chapter. Title screen image can be found inside Images directory, under the name TitleScreen.png.&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://3.bp.blogspot.com/_4Xe_fkP2r2A/SwFM6dgmenI/AAAAAAAAAA4/fLuYCnwO3EM/s1600/TitleScreen.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://3.bp.blogspot.com/_4Xe_fkP2r2A/SwFM6dgmenI/AAAAAAAAAA4/fLuYCnwO3EM/s320/TitleScreen.png" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;div style="text-align: justify;"&gt;&lt;br /&gt;&lt;b&gt;Embedding image into SWF file&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;We will embed all content files into SWF files, which will make distribution of the game easier. Embedded files become part of the SWF file during the compilation process. Alternative approach, that we won't use, is to load external content files at runtime from disk, web... &lt;br /&gt;&lt;br /&gt;There are three things we have to do, to embed the title screen image into SWF file. First you need image file inside project folder. Put the TitleScreen.png into Images folder under project root.&lt;br /&gt;&lt;br /&gt;Next, create empty file in text editor and add this line of code at the beginning:&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace; font-size: x-small;"&gt;[Embed(source="Images/TitleScreen.png")] private var titleScreenImg:Class;&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;div style="text-align: justify;"&gt;and save file into project folder under the name Images.as. In this file we defined new class that represents content file. &lt;br /&gt;&lt;br /&gt;Now we have to include Images.as into SnakesAdventure.as. Add the following line under the import statements at the beginning of the file:&lt;br /&gt;&lt;br /&gt;&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace; font-size: x-small;"&gt;include "Images.as";&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;At this point you can recompile the application, but before you do, check the size of SnakesAdventure.swf file. When compilation is complete, size of new SnakesAdventure.swf file should increase according to the size of embedded image file. In my case size, where TitleScreen.png file is almost 130KB, but size of SWF is increased by more than 150KB. I also experienced slight increase of compilation time. Anyway, increase of SWF file size indicates that image file was successfully embedded into application.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Displaying the image&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;There are many different ways to display images in ActionScript. Performance in game development is crucial, that is why we will use fastest approach. For every image, we will create new BitmapData object and copy content of embedded image into it. This way we can use copyPixels routine to copy pixels directly from image into screen buffer. You can find all you need to know  about &lt;a href="http://livedocs.adobe.com/flex/2/langref/flash/display/BitmapData.html#copyPixels()"&gt;copyPixels&lt;/a&gt; function in Flex online reference manual.&lt;br /&gt;&lt;br /&gt;Open SnakesAdventure.as in text editor and add the following source code at the end of the file:&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace; font-size: x-small;"&gt;private var titleScreenBitmap:BitmapData = null;&lt;br /&gt;&lt;br /&gt;private function Draw_TitleScreen():void&lt;br /&gt;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;if (titleScreenBitmap == null)&lt;br /&gt;&amp;nbsp;&amp;nbsp;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;titleScreenBitmap = new BitmapData(SCREEN_WIDTH,SCREEN_HEIGHT);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;titleScreenBitmap.draw(new titleScreenImg()); &lt;br /&gt;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;screenBuffer.copyPixels(titleScreenBitmap, &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;new Rectangle(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT),&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;new Point(0,0)); &lt;br /&gt;}&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;div style="text-align: justify;"&gt;In the first line we declared global variable titleScreenBitmap. This variable will be the reference to BitmapData object with copy of embedded title screen image. The reference will be set when the object is create, null value indicates that variable does not have reference yet.&lt;br /&gt;&lt;br /&gt;In the first line of Draw_TitleScreen function we check if titleScreenBitmap already has reference. If not (null), object was not made yet, so we have to create it first. In constructor of BitmapData we have to specify image size, that is same as game frame size, so we can safely use SCREEN_WIDTH and SCREEN_HEIGHT constants. Next line of code creates embedded title screen image object and copies content of image into BitmapData object. Now we have copy of embedded image that we can use.&lt;br /&gt;&lt;br /&gt;Last instruction copies pixels from image copy on the screen buffer and eventually on the &lt;b&gt;gamePanel&lt;/b&gt;. As you can see, &lt;b&gt;copyPixels&lt;/b&gt; routine requires at least three parameters defined:&lt;br /&gt;- source bitmap image&lt;br /&gt;- area of source image that will be copied. Area is defined with Rectangle object. First two parameters represent top left pixel in source image, last two represent width and height of area&lt;br /&gt;- top left position on destination image (in our case screen buffer) where pixels will be copied.&lt;br /&gt;&lt;br /&gt;In our case, title screen image and screen buffer have equal size and we have to copy all 480x480 pixels from source image into the buffer of the same size.&lt;br /&gt;&lt;br /&gt;Now that we implement Draw_TitleScreen function, we have to call it. Insert this line into &lt;b&gt;Draw&lt;/b&gt; function:&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace; font-size: x-small;"&gt;Draw_TitleScreen();&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;div style="text-align: justify;"&gt;Recompile the project and open SnakesAdventure.swf again. If you did everything right, you should see the title screen image displayed right after the application starts.&lt;br /&gt;&lt;br /&gt;In case you have trouble understanding the code so far, I recommend that you take some time and experiment on the existing code. Change values of source image area  or destination position in &lt;b&gt;copyPixel&lt;/b&gt; function call, use different images for the background... Just don't forget to recompile and rerun after you make changes.&lt;br /&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8678980820383323367-9195578389372695608?l=grandy-flexdev.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://grandy-flexdev.blogspot.com/feeds/9195578389372695608/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://grandy-flexdev.blogspot.com/2009/11/displaying-title-screen.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8678980820383323367/posts/default/9195578389372695608'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8678980820383323367/posts/default/9195578389372695608'/><link rel='alternate' type='text/html' href='http://grandy-flexdev.blogspot.com/2009/11/displaying-title-screen.html' title='Displaying the title screen'/><author><name>Grandy</name><uri>http://www.blogger.com/profile/13061370372593845090</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='29' height='32' src='http://4.bp.blogspot.com/_4Xe_fkP2r2A/StiN3kMzX2I/AAAAAAAAAAU/wWM-ILREdfw/S220/MySelf.png'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://3.bp.blogspot.com/_4Xe_fkP2r2A/SwFM6dgmenI/AAAAAAAAAA4/fLuYCnwO3EM/s72-c/TitleScreen.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8678980820383323367.post-8418793449196357922</id><published>2009-11-10T06:06:00.000-08:00</published><updated>2011-05-19T23:41:14.104-07:00</updated><title type='text'>Game initialization</title><content type='html'>&lt;div style="text-align: justify;"&gt;&lt;b&gt;Init&lt;/b&gt; function, declared in SnakesAdventure.as (&lt;a href="http://grandy-flexdev.blogspot.com/2009/11/basics-of-flex-development.html"&gt;chapter 3&lt;/a&gt;) is executed right after application initialization phase is complete. &lt;b&gt;Init&lt;/b&gt; function will perform all necessary steps, before game execution starts.&lt;br /&gt;&lt;br /&gt;But first, lets define all external packages and classes that will be used inside this source file. All external classes that we use, even if they are part of Flex SDK, have to be imported before we can use them. With import we can define separate classes (flash.display.BitmapData) or complete package (flash.display.*). Put the following code at the beginning of SnakeAdventure.as:&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace; font-size: x-small;"&gt;import flash.display.*; &lt;br /&gt;import flash.events.*;&lt;br /&gt;import mx.events.*;&lt;br /&gt;import mx.controls.*;&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;div style="text-align: justify;"&gt;Next we will define two constant values that will be used often inside this source code file. Insert following constant definitions after import statements. &lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace; font-size: x-small;"&gt;private static const SCREEN_WIDTH:int          = 480;&lt;br /&gt;private static const SCREEN_HEIGHT:int         = 480;&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;div style="text-align: justify;"&gt;This two constants have the value of gamePanel width and height. Actual size of frame is defined in SnakeAdventure.mxml. If you plan to change frame size for your own version of the game, you should change frame width and height values in both files.&lt;br /&gt;&lt;br /&gt;We also need one global variable, that will indicate if initialization phase is already completed. Lets name this variable &lt;b&gt;initializationComplete&lt;/b&gt; and set its value to false:&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace; font-size: x-small;"&gt;private var initializationCompleted:Boolean = false;&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;div style="text-align: justify;"&gt;Now we can focus on game inititialization itself. &lt;br /&gt;&lt;br /&gt;&lt;b&gt;Creation of global screen buffer&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;Screen buffer is BitmapData object that let us directly manipulate pixel data. We will draw all visible graphics into screen buffer first and then copy it on gamePanel. Screen buffer has exactly the same size as application frame (480x480 pixels). &lt;br /&gt;&lt;br /&gt;First we need global variable, that will keep the reference to screen buffer, after we create it. Put the definition of variable after &lt;b&gt;initializationComplete&lt;/b&gt;:&lt;br /&gt;&lt;br /&gt;&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace; font-size: x-small;"&gt;private var screenBuffer:BitmapData = null;&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;Insert this piece of code, that creates screen buffer, into Init function:&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace; font-size: x-small;"&gt;screenBuffer = new BitmapData(SCREEN_WIDTH, SCREEN_HEIGHT, false, 0x00000000);&lt;br /&gt;&lt;br /&gt;initializationCompleted = true;  &lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;div style="text-align: justify;"&gt;BitmapData constructor has four parameters defined: width and height of bitmap, transparency is set to false and colour is set to black.&lt;br /&gt;&lt;br /&gt;Value of variable &lt;b&gt;initializationCompleted&lt;/b&gt; is set to true at the end of &lt;b&gt;Init&lt;/b&gt; function, and indicates that application initialized has finished.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Implementation of UpdateFrame&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;Before we start drawing visible graphics on gamePanel, we need to know when is the application ready to display new frame. We also need to know how much time has passed since previous frame. &lt;br /&gt;&lt;br /&gt;Event &lt;b&gt;ENTER_FRAME&lt;/b&gt;, dispatched by application will tell us, when we can start drawing graphics on gamePanel. Replace existing &lt;b&gt;UpdateFrame&lt;/b&gt; function definition in file SnakesAdventure.as with this block of code.&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace; font-size: x-small;"&gt;private var prevTime:Date = null;&lt;br /&gt;&lt;br /&gt;private function UpdateFrame():void&lt;br /&gt;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;if (!initializationCompleted)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return;&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;var currTime:Date = new Date();&lt;br /&gt;&amp;nbsp;&amp;nbsp;var elapsedTime:Number = 0; &lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;if (prevTime != null) &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;elapsedTime = (currTime.getTime() - prevTime.getTime()) / 1000.0;&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;Draw(elapsedTime);&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;gamePanel.graphics.clear();    &lt;br /&gt;&amp;nbsp;&amp;nbsp;gamePanel.graphics.beginBitmapFill(screenBuffer, null, false, false);&lt;br /&gt;&amp;nbsp;&amp;nbsp;gamePanel.graphics.drawRect(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT);&lt;br /&gt;&amp;nbsp;&amp;nbsp;gamePanel.graphics.endFill(); &lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;private function Draw(ellapsedTime:Number):void&lt;br /&gt;{&lt;br /&gt;&lt;br /&gt;}&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;div style="text-align: justify;"&gt;In the first line we defined global variable &lt;b&gt;prevTime&lt;/b&gt; which will store the time when last UpdateFrame was executed.&lt;br /&gt;&lt;br /&gt;In &lt;b&gt;UpdateFrame&lt;/b&gt; function we first check if execution of Init function was completed successfuly. In case it was, we calculate time between previous and current frame. If time of previous frame is not set, we set &lt;b&gt;elapsedTime&lt;/b&gt; variable to zero. Elapsed time between frames is measured in seconds.&lt;br /&gt;&lt;br /&gt;Then we call &lt;b&gt;Draw&lt;/b&gt; function which is defined after &lt;b&gt;UpdateFrame&lt;/b&gt; function. &lt;b&gt;Draw&lt;/b&gt; function does nothing at the moment.&lt;br /&gt;&lt;br /&gt;At the end, content of screen buffer is copied on &lt;b&gt;gamePanel&lt;/b&gt;.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Putting it all together&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;If you followed instructions and insert all the pieces of code on the right place, current version of SnakesAdventure.as should look like this:&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace; font-size: x-small;"&gt;import flash.display.*; &lt;br /&gt;import flash.events.*;&lt;br /&gt;import mx.events.*;&lt;br /&gt;import mx.controls.*;&lt;br /&gt;&lt;br /&gt;private static const SCREEN_WIDTH:int          = 480;&lt;br /&gt;private static const SCREEN_HEIGHT:int         = 480; &lt;br /&gt;&lt;br /&gt;private var initializationCompleted:Boolean = false;&lt;br /&gt;private var screenBuffer:BitmapData = null;&lt;br /&gt;&lt;br /&gt;public function Init():void &lt;br /&gt;{ &lt;br /&gt;&amp;nbsp;&amp;nbsp;screenBuffer = new BitmapData(SCREEN_WIDTH, SCREEN_HEIGHT, false, 0x00000000);&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;initializationCompleted = true;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;private var prevTime:Date = null;&lt;br /&gt;&lt;br /&gt;private function UpdateFrame():void&lt;br /&gt;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;if (!initializationCompleted)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return;&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;var currTime:Date = new Date();&lt;br /&gt;&amp;nbsp;&amp;nbsp;var elapsedTime:Number = 0; &lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;if (prevTime != null) &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;elapsedTime = (currTime.getTime() - prevTime.getTime()) / 1000.0;&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;Draw(elapsedTime);&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;gamePanel.graphics.clear();    &lt;br /&gt;&amp;nbsp;&amp;nbsp;gamePanel.graphics.beginBitmapFill(screenBuffer, null, false, false);&lt;br /&gt;&amp;nbsp;&amp;nbsp;gamePanel.graphics.drawRect(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT);&lt;br /&gt;&amp;nbsp;&amp;nbsp;gamePanel.graphics.endFill(); &lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;private function Draw(elapsedTime:Number):void&lt;br /&gt;{&lt;br /&gt;&lt;br /&gt;}&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;div style="text-align: justify;"&gt;Of course you can also &lt;a href="http://bgrandovec.hostzi.com/Files/SnakesAdventure_P5.zip"&gt;download&lt;/a&gt; complete project for this chapter.&lt;br /&gt;&lt;br /&gt;If you recompile and execute SWF file, you can see that nothing has changed. The difference is, that this time black background is consequence of screen buffer that is painted on the &lt;b&gt;gamePanel&lt;/b&gt;. In previous chapter, it was &lt;b&gt;backgroundColor&lt;/b&gt; attribute of Application object, that set background colour to black. If you change &lt;b&gt;backgroundColor&lt;/b&gt; attribute to red, you will still see black background.&lt;br /&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8678980820383323367-8418793449196357922?l=grandy-flexdev.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://grandy-flexdev.blogspot.com/feeds/8418793449196357922/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://grandy-flexdev.blogspot.com/2009/11/game-initialization.html#comment-form' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8678980820383323367/posts/default/8418793449196357922'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8678980820383323367/posts/default/8418793449196357922'/><link rel='alternate' type='text/html' href='http://grandy-flexdev.blogspot.com/2009/11/game-initialization.html' title='Game initialization'/><author><name>Grandy</name><uri>http://www.blogger.com/profile/13061370372593845090</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='29' height='32' src='http://4.bp.blogspot.com/_4Xe_fkP2r2A/StiN3kMzX2I/AAAAAAAAAAU/wWM-ILREdfw/S220/MySelf.png'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8678980820383323367.post-7417105439630497059</id><published>2009-11-05T04:10:00.001-08:00</published><updated>2010-03-24T13:13:58.186-07:00</updated><title type='text'>Compiling and running</title><content type='html'>&lt;div style="text-align: justify;"&gt;Compilation process creates object files from source code and builds them together with content files (sounds, images...) into executable SWF file. In &lt;a href="http://grandy-flexdev.blogspot.com/2009/10/setting-up-project-environment.html"&gt;chapter 2 - Setting up project environment&lt;/a&gt; you can find build scripts for Windows and Linux with instructions how to execute build process. If you didn't follow the tutorial, you can &lt;a href="http://bgrandovec.hostzi.com/Files/SnakesAdventure_P4.zip"&gt;download&lt;/a&gt; package with all files made so far.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Compile&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;If you have all necessary files in project root directory (two source files and one build script), execute command &lt;b&gt;make.bat&lt;/b&gt; on Windows or &lt;b&gt;make&lt;/b&gt; on Linux. If all goes well, Flex compiler will report location and size of output file (SnakesAdventure.swf) after few seconds.&lt;br /&gt;&lt;br /&gt;One advice for developers on Linux: when you make changes in source and content files and then try to recompile, compiler refuses and reports: &lt;br /&gt;&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace; font-size: x-small;"&gt;&lt;br /&gt;make: Nothing to be done for `all'&lt;/div&gt;Compiler did not find any changes in source code (if you did not change SnakesAdventure.mxml) and assumes that existing SWF file is up-to-date. Execute &lt;b&gt;make clean&lt;/b&gt;, to remove existing SWF file, before &lt;b&gt;make&lt;/b&gt;.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Run&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;If you have SWF files associated with external application on your system, you can run SnakesAdventure.swf from file system browser. If not, you can run the SWF file with Flash player. Flash players for different systems can be found inside runtimes/player folders inside Flex SDK. Start Flash player, choose the Open option from File menu and select location of file SnakesAdventure.swf.&lt;br /&gt;&lt;br /&gt;You can also run SnakesAdventure.swf from your Internet browser, just make sure it has required Flash plug-in installed. You can enter the location of SWF file in navigation bar or select it with File/Open File option.&lt;br /&gt;&lt;br /&gt;When application starts, you will see an empty black frame. Black background colour was specified with backgroundColor attribute of mx:Application tag in SnakesAdventure.mxml. #000000 value represents black colour. If you would like to experiment with backgroundColor attribute, you can find more info about HTML colours &lt;a href="http://biega.com/colors.html"&gt;here&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;Now that we have project set up and we can compile and run the application, it is time to focus on development of game itself.&lt;br /&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8678980820383323367-7417105439630497059?l=grandy-flexdev.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://grandy-flexdev.blogspot.com/feeds/7417105439630497059/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://grandy-flexdev.blogspot.com/2009/11/compiling-and-running.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8678980820383323367/posts/default/7417105439630497059'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8678980820383323367/posts/default/7417105439630497059'/><link rel='alternate' type='text/html' href='http://grandy-flexdev.blogspot.com/2009/11/compiling-and-running.html' title='Compiling and running'/><author><name>Grandy</name><uri>http://www.blogger.com/profile/13061370372593845090</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='29' height='32' src='http://4.bp.blogspot.com/_4Xe_fkP2r2A/StiN3kMzX2I/AAAAAAAAAAU/wWM-ILREdfw/S220/MySelf.png'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8678980820383323367.post-8530223247453622063</id><published>2009-11-02T05:14:00.000-08:00</published><updated>2010-03-23T12:15:49.557-07:00</updated><title type='text'>Creating the application</title><content type='html'>&lt;div style="text-align: justify;"&gt;We will use two programming languages to write our game: &lt;b&gt;ActionScript&lt;/b&gt; and &lt;b&gt;MXML&lt;/b&gt;. In fact, we will use only small portion of MXML to define application and canvas object. User interface, game logic, event handling... will all be written in ActionScript.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;MXML&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;Flex developers use MXML language to define layout of user interface components and other non-visual aspects of an application. MXML is XML markup language, convenient for development of rich user interfaces. But games, usually, display user interface differently than desktop applications, that is why we will not code much in MXML. All we have to do is create one MXML file, that will define application tag and include main ActionScript source code file. OK, create empty file in text editor, copy code below and save file as SnakesAdventure.mxml in project root.&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace; font-size: x-small;"&gt;&amp;lt;?xml version="1.0"?&amp;gt;&lt;br /&gt;&amp;lt;mx:Application xmlns:mx="http://www.adobe.com/2006/mxml"&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;name="SnakesAdventure"&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;backgroundColor="#000000"&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;horizontalAlign="center"&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;creationComplete="Init();"&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;enterFrame="UpdateFrame();"&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;paddingLeft="0"&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;paddingTop="0"&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;paddingBottom="0"&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;paddingRight="0"&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;width="480" height="480"&amp;gt;&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;lt;mx:Script&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;lt;![CDATA[&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;include "SnakesAdventure.as";&lt;br /&gt;&amp;nbsp;&amp;nbsp;]]&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;lt;/mx:Script&amp;gt;&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;lt;mx:Canvas id="gamePanel" x="0" y="0" width="100%" height="100%"/&amp;gt;&lt;br /&gt;&amp;lt;/mx:Application&amp;gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;MXML source code files always start with XML declaration (line 1). In the second line is starting tag of root element mx:Application. mx:Application element contains several attributes (lines 3-12): &lt;b&gt;width&lt;/b&gt; and &lt;b&gt;height&lt;/b&gt; attributes define size of the application frame in pixels (480x480), &lt;b&gt;backgroundColor&lt;/b&gt; defines background colour of application frame. Attribute &lt;b&gt;creationComplete&lt;/b&gt; defines which function will be called after application initialization is complete. Attribute &lt;b&gt;enterFrame&lt;/b&gt; defines which function will be called when application is ready to draw new frame. We will implement both functions in ActionScript (SnakesAdventure.as).&lt;br /&gt;&lt;br /&gt;In mx:Script element (lines 14-18) we gave instruction to Flex compiler that file SnakesAdventure.as contains relevant source code and should be included into compilation process. &lt;br /&gt;&lt;br /&gt;mx:Canvas element (lines 18-20) creates panel with the name "gamePanel" inside application frame. Panel has exactly the same size as application frame and will display all visible graphics.&lt;br /&gt;&lt;br /&gt;You can find a lot more information about Flex components on &lt;a href="http://livedocs.adobe.com/flex/3/langref/"&gt;Adobe Flex live docs&lt;/a&gt;, for example &lt;a href="http://livedocs.adobe.com/flex/3/langref/mx/core/Application.html"&gt;Application class page&lt;/a&gt; contains list of all attributes you can define in mx:Application element.&lt;br /&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;If you try to execute build script again, compilation will fail and compiler will report the following error: &lt;/div&gt;&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace; font-size: x-small;"&gt;Unable to open included file: /home/user/myProjects/SnakesAdventure/SnakesAdventure.as&lt;br /&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;No worries, we will create missing SnakesAdventure.as file next.&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;div style="text-align: justify;"&gt;&lt;b&gt;ActionScript&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;With MXML you can easily define and position user interface controls, containers, services... of the application, but you cannot implement their custom behaviour.  To implement custom behaviour, we have to use another programming language: ActionScript. There are many ways to mix MXML code with ActionScript, in SnakesAdventure.mxml we embedded ActionScript (include statement) inside mx:Script tag.&lt;br /&gt;&lt;br /&gt;ActionScript is object-oriented procedural programming language, developed by Adobe. If you have prior experience with programming languages like Java, JavaScript, C#... you should become familiar with ActionScript in very short period of time.&lt;br /&gt;&lt;br /&gt;Now, let's create missing SnakesAdventure.as file. Create empty file in text editor and copy code below. Save the file as SnakesAdventure.as inside project root.&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace; font-size: x-small;"&gt;public function Init():void &lt;br /&gt;{ &lt;br /&gt;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;private function UpdateFrame():void&lt;br /&gt;{&lt;br /&gt;&lt;br /&gt;}&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;div style="text-align: justify;"&gt;If you remember, we set two function in mx:Application tag (file  SnakesAdventure.mxml) that will handle &lt;b&gt;creationComplete&lt;/b&gt; and &lt;b&gt;enterFrame&lt;/b&gt; events. We have to define both functions, otherwise compiler reports an error. Currently they have empty bodies, but we will implement them in following chapters.&lt;br /&gt;&lt;br /&gt;One more thing: if your text editor supports syntax highlighting, but ActionScript code is displayed as plain text anyway, I suggest you enable highlighting for JavaScript. &lt;br /&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8678980820383323367-8530223247453622063?l=grandy-flexdev.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://grandy-flexdev.blogspot.com/feeds/8530223247453622063/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://grandy-flexdev.blogspot.com/2009/11/basics-of-flex-development.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8678980820383323367/posts/default/8530223247453622063'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8678980820383323367/posts/default/8530223247453622063'/><link rel='alternate' type='text/html' href='http://grandy-flexdev.blogspot.com/2009/11/basics-of-flex-development.html' title='Creating the application'/><author><name>Grandy</name><uri>http://www.blogger.com/profile/13061370372593845090</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='29' height='32' src='http://4.bp.blogspot.com/_4Xe_fkP2r2A/StiN3kMzX2I/AAAAAAAAAAU/wWM-ILREdfw/S220/MySelf.png'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8678980820383323367.post-4726319581998897343</id><published>2009-10-26T07:48:00.000-07:00</published><updated>2010-03-23T12:08:12.809-07:00</updated><title type='text'>Setting up project environment</title><content type='html'>&lt;div style="text-align: justify;"&gt;In this chapter you will learn how to set up new project for the game development, without use of Flex Builder (creation of new project in Builder should be trivial). &lt;br /&gt;&lt;br /&gt;Inside the folder, where you keep your other projects, create new folder and name it &lt;b&gt;SnakesAdventure&lt;/b&gt;. For example, I keep my projects in c:\myProjects folder in Windows and /home/user/myProjects folder in Linux. SnakesAdventures folder is now the root folder of the project, later it will contain all scripts, images, sounds and source code files. If you would like to keep different file types in different folders, create folders &lt;b&gt;Classes&lt;/b&gt;, &lt;b&gt;Images&lt;/b&gt; and &lt;b&gt;Sounds&lt;/b&gt; inside project folder.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Build script&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;Now we will create new script file, that compiles all source code files and builds all content files into single SWF file. Open text editor, create empty file, copy content of the script for your system and follow the instructions. If you are Windows user, I recommend you do not edit source code and scripts in Windows Notepad, use advanced text editor that supports syntax highlighting (Notepad2, UltraEdit...).&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Build script for Windows&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;Enter correct path to compiler executable (mxmlc.exe) on your system and save file as Make.bat:&lt;br /&gt;&lt;/div&gt;&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace; font-size: x-small;"&gt;C:\PROGRA~1\Flex3\bin\mxmlc.exe SnakesAdventure.mxml&lt;br /&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;b&gt;Build script for Linux&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;Enter correct path to compiler executable in MXMLC definition and save file as Makefile:&lt;br /&gt;&lt;/div&gt;&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace; font-size: x-small;"&gt;MXMLC = ~Flex/bin/mxmlc&lt;br /&gt;MFLAGS = -benchmark&lt;br /&gt;&lt;br /&gt;TARGETS = SnakesAdventure.swf&lt;br /&gt;&lt;br /&gt;all: $(TARGETS)&lt;br /&gt;&lt;br /&gt;clean:&lt;br /&gt;$(RM) $(TARGETS)&lt;br /&gt;&lt;br /&gt;.SUFFIXES:    .mxml .swf&lt;br /&gt;.mxml.swf:&lt;br /&gt;&lt;br /&gt;$(MXMLC) $(MFLAGS) $&amp;lt;&lt;br /&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;b&gt;Execute the build script&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;On Windows: open Command Prompt, enter project root folder and start the script with command &lt;b&gt;make.bat&lt;/b&gt;. On Linux: open terminal, enter project root folder and start the script with command &lt;b&gt;make&lt;/b&gt;.&lt;br /&gt;&lt;br /&gt;Script execution should fail, because source file SnakesAdventure.mxml is not available, yet. Flex compiler reports following message on my system (Windows):&lt;br /&gt;&lt;/div&gt;&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace; font-size: x-small;"&gt;Error: unable to open 'SnakesAdventure.mxml'&lt;br /&gt;&lt;br /&gt;Use 'mxmlc -help' for information about using the command line.&lt;br /&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8678980820383323367-4726319581998897343?l=grandy-flexdev.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://grandy-flexdev.blogspot.com/feeds/4726319581998897343/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://grandy-flexdev.blogspot.com/2009/10/setting-up-project-environment.html#comment-form' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8678980820383323367/posts/default/4726319581998897343'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8678980820383323367/posts/default/4726319581998897343'/><link rel='alternate' type='text/html' href='http://grandy-flexdev.blogspot.com/2009/10/setting-up-project-environment.html' title='Setting up project environment'/><author><name>Grandy</name><uri>http://www.blogger.com/profile/13061370372593845090</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='29' height='32' src='http://4.bp.blogspot.com/_4Xe_fkP2r2A/StiN3kMzX2I/AAAAAAAAAAU/wWM-ILREdfw/S220/MySelf.png'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8678980820383323367.post-8770053468935378932</id><published>2009-10-23T05:54:00.000-07:00</published><updated>2010-03-23T12:04:03.068-07:00</updated><title type='text'>Before we begin</title><content type='html'>&lt;div style="text-align: justify;"&gt;Adobe Flex is open source development kit for development of rich web applications based on the Adobe Flash platform. Adobe Flex is free and available for Windows, Linux and Mac OS. On the other hand, Adobe Flex Builder - development environment for Flex, cost almost 250$. Don't worry, if you cannot afford it, you will be able to execute and modify all code samples from this tutorial anyway, but I do believe Flex Builder makes developer's life much easier.&lt;br /&gt;&lt;br /&gt;This tutorial will teach you how to create games with Flex step by step. Together we will create game called Snake's adventure - advanced version of classic Snake game. I will not lie to you, without any programming experience you will most likely have problems understanding the source code from this tutorial. You should at least have basic knowledge of one modern programming language. &lt;br /&gt;&lt;br /&gt;If you do not have Flex SDK (software development kit) already installed on your computer, you can &lt;a href="http://www.adobe.com/cfusion/entitlement/index.cfm?e=flex3sdk"&gt;download&lt;/a&gt; it from here. There is no installation package for current version (3.4) of SDK, you will have to manually extract content of downloaded file on your disk. Flex SDK contains bunch of tools and lots of samples, take your time and explore the content of SDK.&lt;br /&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8678980820383323367-8770053468935378932?l=grandy-flexdev.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://grandy-flexdev.blogspot.com/feeds/8770053468935378932/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://grandy-flexdev.blogspot.com/2009/10/before-we-begin.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8678980820383323367/posts/default/8770053468935378932'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8678980820383323367/posts/default/8770053468935378932'/><link rel='alternate' type='text/html' href='http://grandy-flexdev.blogspot.com/2009/10/before-we-begin.html' title='Before we begin'/><author><name>Grandy</name><uri>http://www.blogger.com/profile/13061370372593845090</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='29' height='32' src='http://4.bp.blogspot.com/_4Xe_fkP2r2A/StiN3kMzX2I/AAAAAAAAAAU/wWM-ILREdfw/S220/MySelf.png'/></author><thr:total>0</thr:total></entry></feed>
