Wednesday, January 9, 2008

Configuring the Actionscript Client

Once your Flex project is working, you may want to know how to change the most important things in the code.

Look at the Config.as file.

package GameKit
{
public final class Config
{
public static var URL:String = "fireleg.com";
//public static var URL:String = "localhost";
public static var port:uint = 81;

public static var framesPerSecond:int = 24;

// Zero means we synchronize the world every frame.
// 1,2,3 means we count 1,2,3 frames before synching.
// This keeps your world looking smooth while the network
// can chill out a little bit.
public static var dampenNetSyncBy:int = 0;


If you are going to run the Java server on your own machine, then switch out my "fireleg.com" address with your test environment, probably "localhost".

I chose port 81 since it's one of those ports that almost everyone's firewall will allow through, but does not interfere with web servers.

The frames per second can be adjusted as needed for your game's performance.

And finally, you may not want to send a game message for every frame. Your game may be able to do just fine with only sending a particle update every nth frame.

For instance, a checkers game might only need a refresh 4 times per second. If you have framesPerSecond=16, you would set dampenNetSyncBy=4 to achieve your goal.

Now look at MXMLPong.mxml
mx:application mx="http://www.adobe.com/2006/mxml" layout="absolute" applicationcomplete="onAppComplete();"

This applicationcomplete event is different than many Actionscript examples you'll see. It actually waits until everything is created and avoids some serious errors. Be sure you use that exact function to launch your games framework.

Inside this function, we start the main game loop. Which is the heartbeat of the entire game:
private function onAppComplete():void
{
var framesPerSecond:int = GameKit.Config.framesPerSecond;
this.stage.scaleMode = StageScaleMode.NO_SCALE;
this.stage.align = StageAlign.TOP_LEFT;

game = new GameLoop(framesPerSecond, this);
This causes us to dive down into the GameLoop.as:

The MXMLPong file created the GameLoop object, which you can see is hungry for a sprite to display the game in.

 // sprite is the main container to display the game in
public function GameLoop(framesPerSecond:uint, sprite:Sprite) {
var refreshMillis:uint = 1000/framesPerSecond;


This function then calls the init function, which has one very important line of code:

gameTimer = new Timer(refreshMillis,0);
gameTimer.addEventListener(TimerEvent.TIMER, myLoop);


This kicks off the whole game at whatever frames per second you specified earlier, and will constantly call the myLoop() function.

Looking at myLoop(), you will see a whole checklist of things it tries to do again and again.

For instance, the first thing it does is check that a connection with the game server is made.

public function myLoop(timer:TimerEvent):void {
// this is that warmup time from the message sent above
if (!gameServer.connected || gameServer.msgCount < 1) {
trace("waiting for connection or first response...");
return;
}


You may think it's strange to keep "return"ing out of this function, but don't worry, it will be called many times until a connection is made.

Read through the rest of this function and you'll be on your way to understanding some of the code.

World.as contains the collision stuff.

Particle.as determines how the physical universe works in your game.

Commands.as is where you have to add how the network will pack/unpack the objects. It's a little ugly looking and you may just want to skip down to this part of the code:
 if (command != null && command.length > 1) {
if (command[0] == "place") { ...


Even then, my method requires hard-coded parsing of each element. I'm sure you may be able to improve this part of the code, but it's a very basic approach.

NetSynchronizer.as isn't used. I was probably thinking of making a generic way to avoid all the ugly parsing in commands.as. Ideally, there is probably a simple Flex way to package up any object.

The thing is, I want to be able to send a package with a header plus that AMF or whatever object. Obviously I just need a little more knowledge here so I can make use of the full Actionscript power.

NetworkConnection.as is super important. It takes care of the arbitrary protocol that I invented to speak with the Java server.

You will see all kinds of strange commands in there to join a group, send a message to your group or to everyone. This class is worth reading carefully once you're feeling good about the project.

You can see what's being sent back and forth by binding to these variables.

[Bindable] public var lastMessageIn:String; // from Server
[Bindable] public var lastMessageOut:String; // To Server


You may have noticed in the MXMLPong.mxml I put some text objects at the bottom of the screen to show you what is being said through NetworkConnection.as.

For those of you new to binding in Actionscript 3.0, just put something like this on your page:

<mx:Text x="315" y="482" text="{game.gameServer.lastMessageOut}" id="last_sent">
<mx:Text x="315" y="482" text="{game.gameServer.lastMessageIn}" id="last_in">

1 comment:

Anonymous said...

Who knows where to download XRumer 5.0 Palladium?
Help, please. All recommend this program to effectively advertise on the Internet, this is the best program!