I never thought development of web games can be that simple until I started development of my first game with Adobe Flex. I made two games, without any prior experience with Action script, in only ten months: "Fitter" and "RGB".

I found many answers to my questions on different forums and web sites, and it is time to share my knowledge with Flex community.

Tuesday, November 10, 2009

Game initialization

Init function, declared in SnakesAdventure.as (chapter 3) is executed right after application initialization phase is complete. Init function will perform all necessary steps, before game execution starts.

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:

import flash.display.*;
import flash.events.*;
import mx.events.*;
import mx.controls.*;

Next we will define two constant values that will be used often inside this source code file. Insert following constant definitions after import statements.

private static const SCREEN_WIDTH:int = 480;
private static const SCREEN_HEIGHT:int = 480;

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.

We also need one global variable, that will indicate if initialization phase is already completed. Lets name this variable initializationComplete and set its value to false:

private var initializationCompleted:Boolean = false;

Now we can focus on game inititialization itself.

Creation of global screen buffer

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).

First we need global variable, that will keep the reference to screen buffer, after we create it. Put the definition of variable after initializationComplete:

private var screenBuffer:BitmapData = null;

Insert this piece of code, that creates screen buffer, into Init function:

screenBuffer = new BitmapData(SCREEN_WIDTH, SCREEN_HEIGHT, false, 0x00000000);

initializationCompleted = true;

BitmapData constructor has four parameters defined: width and height of bitmap, transparency is set to false and colour is set to black.

Value of variable initializationCompleted is set to true at the end of Init function, and indicates that application initialized has finished.

Implementation of UpdateFrame

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.

Event ENTER_FRAME, dispatched by application will tell us, when we can start drawing graphics on gamePanel. Replace existing UpdateFrame function definition in file SnakesAdventure.as with this block of code.

private var prevTime:Date = null;

private function UpdateFrame():void
{
  if (!initializationCompleted)
    return;

  var currTime:Date = new Date();
  var elapsedTime:Number = 0;

  if (prevTime != null)
    elapsedTime = (currTime.getTime() - prevTime.getTime()) / 1000.0;

  Draw(elapsedTime);

  gamePanel.graphics.clear();
  gamePanel.graphics.beginBitmapFill(screenBuffer, null, false, false);
  gamePanel.graphics.drawRect(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT);
  gamePanel.graphics.endFill();
}

private function Draw(ellapsedTime:Number):void
{

}

In the first line we defined global variable prevTime which will store the time when last UpdateFrame was executed.

In UpdateFrame 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 elapsedTime variable to zero. Elapsed time between frames is measured in seconds.

Then we call Draw function which is defined after UpdateFrame function. Draw function does nothing at the moment.

At the end, content of screen buffer is copied on gamePanel.

Putting it all together

If you followed instructions and insert all the pieces of code on the right place, current version of SnakesAdventure.as should look like this:

import flash.display.*;
import flash.events.*;
import mx.events.*;
import mx.controls.*;

private static const SCREEN_WIDTH:int = 480;
private static const SCREEN_HEIGHT:int = 480;

private var initializationCompleted:Boolean = false;
private var screenBuffer:BitmapData = null;

public function Init():void
{
  screenBuffer = new BitmapData(SCREEN_WIDTH, SCREEN_HEIGHT, false, 0x00000000);

  initializationCompleted = true;
}

private var prevTime:Date = null;

private function UpdateFrame():void
{
  if (!initializationCompleted)
    return;

  var currTime:Date = new Date();
  var elapsedTime:Number = 0;

  if (prevTime != null)
    elapsedTime = (currTime.getTime() - prevTime.getTime()) / 1000.0;

  Draw(elapsedTime);

  gamePanel.graphics.clear();
  gamePanel.graphics.beginBitmapFill(screenBuffer, null, false, false);
  gamePanel.graphics.drawRect(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT);
  gamePanel.graphics.endFill();
}

private function Draw(elapsedTime:Number):void
{

}

Of course you can also download complete project for this chapter.

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 gamePanel. In previous chapter, it was backgroundColor attribute of Application object, that set background colour to black. If you change backgroundColor attribute to red, you will still see black background.

2 comments:

  1. SourceAdventure.as?
    or SnakeAdventure.as?

    in the beginning of this chapter you mention SourceAdventure?

    ReplyDelete
  2. Ups, my mistake. It's SnakeAdventure.as

    ReplyDelete