<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Phil Peron &#187; gamedev</title>
	<atom:link href="http://philperon.com/tag/gamedev/feed/" rel="self" type="application/rss+xml" />
	<link>http://philperon.com</link>
	<description>Flash Platform Developer and Game Development Hobbyist</description>
	<lastBuildDate>Wed, 23 Jun 2010 15:30:53 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.9.2</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>Polygon Collision and the Separating Axis Theorem in ActionScript</title>
		<link>http://philperon.com/2010/06/23/polygon-collision/</link>
		<comments>http://philperon.com/2010/06/23/polygon-collision/#comments</comments>
		<pubDate>Wed, 23 Jun 2010 15:30:53 +0000</pubDate>
		<dc:creator>Phil</dc:creator>
				<category><![CDATA[actionscript]]></category>
		<category><![CDATA[game development]]></category>
		<category><![CDATA[gamedev]]></category>

		<guid isPermaLink="false">http://philperon.com/?p=667</guid>
		<description><![CDATA[I&#8217;ve been spending quite a bit of time on my latest game project which, like many other games, requires collision detection. Knowing that using brute force for broad-phase detection wasn&#8217;t an option, I implemented a spatial hash to partition the world&#8217;s game objects into manageable groups. At this point, I was ready to tackle the [...]]]></description>
			<content:encoded><![CDATA[<p>I&#8217;ve been spending quite a bit of time on my latest game project which, like many other games, requires collision detection. Knowing that using brute force for broad-phase detection wasn&#8217;t an option, I implemented a spatial hash to partition the world&#8217;s game objects into manageable groups. At this point, I was ready to tackle the narrow-phase portion and immediately sought to use a form of pixel-perfect collision I&#8217;ve grown to understand and use fairly well. Unfortunately, this type of detection is inappropriate for a lot of things and an avatar moving along a tile-based set is one of them. It can be fairly costly and is better suited for boolean-based tests. After trying to force this algorithm to do something it shouldn&#8217;t, I finally settled down and visited a form of collision I had known about for a while but had not the need to implement&#8230;until now.<br />
<span id="more-667"></span><br />
I&#8217;m not going to explain how the <a href="http://en.wikipedia.org/wiki/Separating_axis_theorem">Separating Axis Theorem (SAT)</a> works. There are <a href="http://www.google.com/search?sourceid=chrome&#038;ie=UTF-8&#038;q=Separating+Axis+Theorem">plenty of resources available</a> for that. Instead, I&#8217;m simply going to share with you the code that drives it and how you can use it in your own game.</p>
<p>Before we dive in, there&#8217;s something you should be aware of:</p>
<p><em>This code exists because it&#8217;s easier for me to prototype new things in ActionScript. That being said, there are certainly opportunities to improve performance and structure but I&#8217;m not interested in doing that here. I&#8217;ll address those issues and share the result when I port it over to my target platform in C#.</em></p>
<p>I&#8217;ve taken time to try and make things as easy as possible to use. I&#8217;m assuming you&#8217;re reading this because you need to leverage this functionality and want things to &#8220;just work&#8221;.</p>
<p>Here it is:</p>
<pre class="brush: jscript;">
// create a vector of points that express the first polygon.
var points1:Vector.&lt;Point&gt; = new Vector.&lt;Point&gt;();
points1.push(new Point(0, 0));
points1.push(new Point(50, 0));
points1.push(new Point(50, 50));
points1.push(new Point(0, 50));

// create the first polygon, adjust it's registration point and move it.
var polygon1:Polygon = new Polygon(points);
polygon1.offset = new Vector2D(polygon1.center.x, polygon1.center.y);
polygon1.translate(new Vector2D(50, 50));

// create a vector of points that express the second polygon.
var points2:Vector.&lt;Point&gt; = new Vector.&lt;Point&gt;();
points2.push(new Point(0, 0));
points2.push(new Point(100, 0));
points2.push(new Point(100, 100));
points2.push(new Point(0, 100));

// create the second polygon, adjust it's registration point and move it.
var polygon2:Polygon = new Polygon(points);
polygon2.offset = new Vector2D(polygon2.center.x, polygon2.center.y);
polygon2.translate(new Vector2D(200, 200));
</pre>
<p>At this point, there are two polygons ready to shake, rattle or roll. When you&#8217;d like to see whether or not they&#8217;re colliding, use the following:</p>
<pre class="brush: jscript;">
// define a container to hold a translation vector that can be altered by the collision.
var collisionResponseTranslation:Vector2D = new Vector2D();

// finally, discover whether or not a collision has occurred.
if(polygon1.isCollidingWith(polygon2, collisionResponseTranslation))
    polygon1.translate(collisionResponseTranslation);
</pre>
<p>That&#8217;s it! Here&#8217;s a demo that illustrates things a little better:</p>

<object classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000"
			id="fm_PolygonCollisionDemo_720443284"
			class="flashmovie"
			width="400"
			height="300">
	<param name="movie" value="/flash/PolygonCollisionDemo.swf" />
	<!--[if !IE]>-->
	<object	type="application/x-shockwave-flash"
			data="/flash/PolygonCollisionDemo.swf"
			name="fm_PolygonCollisionDemo_720443284"
			width="400"
			height="300">
	<!--<![endif]-->
		<a href="http://adobe.com/go/getflashplayer"><img src="http://www.adobe.com/images/shared/download_buttons/get_flash_player.gif" alt="Get Adobe Flash player" /></a><br />

	<!--[if !IE]>-->
	</object>
	<!--<![endif]-->
</object>
<p>Please keep in mind that <strong>this will only work for convex polygons</strong>. My game doesn&#8217;t merit getting as complex as the folks at <a href="http://www.metanetsoftware.com/technique/tutorialA.html">Metanet</a> did with <a href="http://www.thewayoftheninja.org/n.html">N</a> so until it that time, it&#8217;s pretty much complete.</p>
<p>You&#8217;ll find the demo and library source, <a href="http://philperon.com/files/PolygonCollisionDemo.zip">here</a>.</p>
<p>Good luck and happy coding!</p>
]]></content:encoded>
			<wfw:commentRss>http://philperon.com/2010/06/23/polygon-collision/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
		<item>
		<title>An Introduction to ElectroServer and PushButton Engine: Part Two</title>
		<link>http://philperon.com/2010/03/31/an-introduction-to-electroserver-and-pushbutton-engine-part-two/</link>
		<comments>http://philperon.com/2010/03/31/an-introduction-to-electroserver-and-pushbutton-engine-part-two/#comments</comments>
		<pubDate>Wed, 31 Mar 2010 10:11:48 +0000</pubDate>
		<dc:creator>Phil</dc:creator>
				<category><![CDATA[flash]]></category>
		<category><![CDATA[game development]]></category>
		<category><![CDATA[mmo]]></category>
		<category><![CDATA[ElectroServer]]></category>
		<category><![CDATA[gamedev]]></category>
		<category><![CDATA[PushButton Engine]]></category>

		<guid isPermaLink="false">http://philperon.com/?p=629</guid>
		<description><![CDATA[
In part one, the focus was on building the server logic for a multiplayer game. Now, we&#8217;ll get to work on a PushButton Engine client that will connect and communicate with ElectroServer. If you&#8217;re completely unaware of how PushButton Engine works, I&#8217;d urge you to spend some time checking out the documentation to get yourself [...]]]></description>
			<content:encoded><![CDATA[<p>
In <a href="http://philperon.com/2010/03/17/an-introduction-to-electroserver-and-pushbutton-engine-part-one/">part one</a>, the focus was on building the server logic for a multiplayer game. Now, we&#8217;ll get to work on a PushButton Engine client that will connect and communicate with ElectroServer. If you&#8217;re completely unaware of how PushButton Engine works, I&#8217;d urge you to spend some time checking out the <a href="http://pushbuttonengine.com/docs/">documentation </a>to get yourself up to speed.
</p>
<p>
Let&#8217;s get started!
</p>
<p><span id="more-629"></span></p>
<h2>The Client</h2>
<p>
The client we&#8217;re going to build is a fairly primitive one. It will connect to ElectroServer, spawn a knight player avatar and display anyone else that is connected as a black wizard. As players move around the area, their position will be broadcast across all connected clients and updated appropriately.
</p>
<p>
PushButton Engine lets the developer declare which objects they&#8217;d to use via an XML file (typically referred to as a &#8216;level file&#8217;). For the application developers among you, it will feel a lot like some of the Inversion of Control solutions that are available today. We&#8217;ll create one file that will declare common entities that are relevant across various game states and another that represents the primary game mode.
</p>
<h3>Defining the Game</h3>
<p><strong>File: /ESPBEDemo-client/assets/levels/common.xml</strong></p>
<pre class="brush: xml;">
&lt;?xml version=&quot;1.0&quot; encoding=&quot;utf-8&quot;?&gt;

&lt;!-- Define all the entities that will be used across game modes. --&gt;

&lt;things version=&quot;1&quot;&gt;

    &lt;!-- We need a spatial manager entity component to keep track of entities
    that have a spatial component and thus require a position be set. Like our
    soon-to-be-created avatars. --&gt;
    &lt;entity name=&quot;spatialManager&quot;&gt;
        &lt;component type=&quot;com.pblabs.rendering2D.BasicSpatialManager2D&quot; name=&quot;manager&quot; /&gt;
    &lt;/entity&gt;

    &lt;!-- Create a display object scene that will do the rendering for us. --&gt;
    &lt;entity name=&quot;scene&quot;&gt;
        &lt;component type=&quot;com.pblabs.rendering2D.DisplayObjectScene&quot; name=&quot;scene&quot;&gt;
            &lt;!-- Assign it a name --&gt;
            &lt;sceneViewName&gt;sceneView&lt;/sceneViewName&gt;
            &lt;!-- and set the scene position. --&gt;
            &lt;position&gt;
                &lt;x&gt;-400&lt;/x&gt;
                &lt;y&gt;-300&lt;/y&gt;
            &lt;/position&gt;
        &lt;/component&gt;
    &lt;/entity&gt;

    &lt;!-- Now add these two entities to a group so they can be instantiated conveniently. --&gt;
    &lt;group name=&quot;common&quot;&gt;
        &lt;objectReference name=&quot;spatialManager&quot; /&gt;
        &lt;objectReference name=&quot;scene&quot; /&gt;
      &lt;/group&gt;

&lt;/things&gt;
</pre>
<p>
We now have a spatial manager to handle the positioning of objects on the screen and a scene to render them to. Now let&#8217;s define the object we&#8217;ll need when our main game mode (or level) is loaded.
</p>
<p><strong>File: /ESPBEDemo-client/assets/levels/game.xml</strong></p>
<pre class="brush: xml;">
&lt;?xml version=&quot;1.0&quot; encoding=&quot;utf-8&quot;?&gt;

&lt;!-- Define all the objects that need to be available when this level is loaded --&gt;
&lt;things version=&quot;1&quot;&gt;

    &lt;!-- Create the player avatar. --&gt;
    &lt;template name=&quot;player&quot;&gt;
        &lt;!-- Create a sprite renderer to render the player avatar --&gt;
        &lt;component type=&quot;com.pblabs.rendering2D.SpriteRenderer&quot; name=&quot;sprite&quot;&gt;
            &lt;!-- Tell the sprite on what scene it should be rendered.
            (The 'scene' entity we created in common.xml.) --&gt;
            &lt;scene entityName=&quot;scene&quot; componentName=&quot;scene&quot;/&gt;
            &lt;!-- Define the location of the image file. --&gt;
            &lt;fileName&gt;../assets/images/player.png&lt;/fileName&gt;
            &lt;!-- Assign the layer index. --&gt;
            &lt;layerIndex&gt;1&lt;/layerIndex&gt;
            &lt;!-- Define where this sprite should be rendered. --&gt;
            &lt;positionProperty&gt;@spatial.position&lt;/positionProperty&gt;
        &lt;/component&gt;
        &lt;!-- This component allows the entity to be positioned on the screen. --&gt;
        &lt;component type=&quot;com.pblabs.rendering2D.SimpleSpatialComponent&quot; name=&quot;spatial&quot;&gt;
            &lt;!-- Make sure it knows where the spatial manager is (from common.xml). --&gt;
            &lt;spatialManager entityName=&quot;spatialManager&quot; /&gt;
            &lt;!-- And how large it should be. --&gt;
            &lt;size&gt;
                &lt;x&gt;48&lt;/x&gt;
                &lt;y&gt;48&lt;/y&gt;
            &lt;/size&gt;
        &lt;/component&gt;
        &lt;!-- Add a keyboard input component to accept user input. --&gt;
        &lt;component type=&quot;com.philperon.espbedemo.components.KeyboardInput&quot; name=&quot;keyboardInput&quot;&gt;
            &lt;!-- Assign W, A, S and D for player movement. --&gt;
            &lt;inputMap childType=&quot;com.pblabs.engine.core.InputKey&quot;&gt;
                &lt;up&gt;W&lt;/up&gt;
                &lt;down&gt;S&lt;/down&gt;
                &lt;left&gt;A&lt;/left&gt;
                &lt;right&gt;D&lt;/right&gt;
            &lt;/inputMap&gt;
        &lt;/component&gt;
        &lt;!-- Add a controller component to deal with how user input should be handled. --&gt;
        &lt;component type=&quot;com.philperon.espbedemo.components.PlayerController&quot; name=&quot;controller&quot;&gt;
            &lt;keyboardInput componentName=&quot;keyboardInput&quot; /&gt;
            &lt;spatial componentName=&quot;spatial&quot; /&gt;
        &lt;/component&gt;
    &lt;/template&gt;

    &lt;!-- Create the opponent avatar. --&gt;
    &lt;template name=&quot;opponent&quot;&gt;
        &lt;!-- Similar setup to that shown above. --&gt;
        &lt;component type=&quot;com.pblabs.rendering2D.SpriteRenderer&quot; name=&quot;sprite&quot;&gt;
            &lt;scene entityName=&quot;scene&quot; componentName=&quot;scene&quot;/&gt;
            &lt;fileName&gt;../assets/images/opponent.png&lt;/fileName&gt;
            &lt;layerIndex&gt;1&lt;/layerIndex&gt;
            &lt;positionProperty&gt;@mover.position&lt;/positionProperty&gt;
        &lt;/component&gt;
        &lt;!-- Add a component to handle interpolated movement based on position
        updates from the server. --&gt;
        &lt;component type=&quot;com.pblabs.rendering2D.Interpolated2DMoverComponent&quot; name=&quot;mover&quot;&gt;
            &lt;!-- How many degrees should be of the goal position before movement begins. --&gt;
            &lt;movementHeadingThreshold&gt;360&lt;/movementHeadingThreshold&gt;
            &lt;!-- Assign the spatial manager. --&gt;
            &lt;spatialManager entityName=&quot;spatialManager&quot; /&gt;
            &lt;!-- Tweak the movement speed slightly to give it a more natural look. --&gt;
            &lt;nudge&gt;1.2&lt;/nudge&gt;
            &lt;!-- Like the player avatar, define the size. --&gt;
            &lt;size&gt;
                &lt;x&gt;48&lt;/x&gt;
                &lt;y&gt;48&lt;/y&gt;
            &lt;/size&gt;
        &lt;/component&gt;
    &lt;/template&gt;

&lt;/things&gt;
</pre>
<p>
The game.xml file really starts to illustrate how powerful PushButton Engine can be once you wrap your head around a composition-style architecture. By writing small components that have a single primary duty, you can reuse them again and again in an unlimited number of entities. Game assembly then becomes a simple matter of defining the &#8220;recipe&#8221; that makes your game unique. It also opens up opportunities for game designers to have a hand in game development with only a limited knowledge of ActionScript.
</p>
<p>
Another group of items being referenced are the actual assets themselves. For this demonstration this includes the .xml level files and .png game graphics. We&#8217;ll place these in a group so they can be embedded and easily handled when the game initializes.
</p>
<p><strong>File: /ESPBEDemo-client/src/com/philperon/espbedemo/Resources.as</strong></p>
<pre class="brush: jscript;">
package com.philperon.espbedemo
{
    import com.pblabs.engine.PBE;
    import com.pblabs.engine.resource.ImageResource;
    import com.pblabs.engine.resource.ResourceBundle;
    import com.pblabs.engine.resource.XMLResource;

    import flash.display.Bitmap;
    import flash.utils.ByteArray;

    // Create a new resouce bundle to handle loading and registering
    // embedded resources.
    public class Resources extends ResourceBundle
    {
        // Add the level files we'll need.
        [Embed(source=&quot;../assets/levels/common.xml&quot;, mimeType=&quot;application/octet-stream&quot;)]
        public var Common:Class;

        [Embed(source=&quot;../assets/levels/game.xml&quot;, mimeType=&quot;application/octet-stream&quot;)]
        public var Game:Class;

        // And the graphics used to represent the game.
        [Embed(source=&quot;../assets/images/background.png&quot;)]
        public var BackgroundPNG:Class;

        [Embed(source=&quot;../assets/images/player.png&quot;)]
        public var PlayerPNG:Class;

        [Embed(source=&quot;../assets/images/opponent.png&quot;)]
        public var OpponentPNG:Class;

        public function Resources()
        {
            // When this class is instantiated, tell the resource manager to register the resources listed above.
            PBE.resourceManager.registerEmbeddedResource(&quot;../assets/levels/common.xml&quot;, XMLResource, new Common() as ByteArray);
            PBE.resourceManager.registerEmbeddedResource(&quot;../assets/levels/game.xml&quot;, XMLResource, new Game() as ByteArray);
            PBE.resourceManager.registerEmbeddedResource(&quot;../assets/images/background.png&quot;, ImageResource, new BackgroundPNG() as Bitmap);
            PBE.resourceManager.registerEmbeddedResource(&quot;../assets/images/player.png&quot;, ImageResource, new PlayerPNG() as Bitmap);
            PBE.resourceManager.registerEmbeddedResource(&quot;../assets/images/opponent.png&quot;, ImageResource, new OpponentPNG() as Bitmap);
        }
    }
}
</pre>
<p>
Now we have all the assets we&#8217;ll need to display our game. It&#8217;s time to start filling in some of the actual game logic that typically resides inside components. If you recall, we referenced a component to handle keyboard input and another to deal with how that input should be handled. Let&#8217;s start with our KeyboardInput component.
</p>
<p><strong>File: /ESPBEDemo-client/src/com/philperon/espbedemo/components/KeyboardInput.as</strong></p>
<pre class="brush: jscript;">
package com.philperon.espbedemo.components
{
    import com.pblabs.engine.core.InputMap;
    import com.pblabs.engine.entity.EntityComponent;

    // A component that handles keyboard input!
    public class KeyboardInput extends EntityComponent
    {
        // Define some variables to store keyboard input values.
        public var up:Number = 0.0;
        public var down:Number = 0.0;
        public var left:Number = 0.0;
        public var right:Number = 0.0;

        // getter and setter for the InputMap class that does the
        // real work here.
        public function get inputMap():InputMap
        {
            return _inputMap;
        }

        public function set inputMap(map:InputMap):void
        {
            // Store the input map in a private variable...
            _inputMap = map;

            // ...and map the actions we defined in game.xml to
            // the handlers.
            if (_inputMap != null)
            {
                _inputMap.mapActionToHandler(&quot;up&quot;, upHandler);
                _inputMap.mapActionToHandler(&quot;down&quot;, downHandler);
                _inputMap.mapActionToHandler(&quot;left&quot;, leftHandler);
                _inputMap.mapActionToHandler(&quot;right&quot;, rightHandler);
            }
        }

        // Finally, set up the handlers themselves.
        private function upHandler(value:Number):void
        {
            up = value;
        }

        private function downHandler(value:Number):void
        {
            down = value;
        }

        private function leftHandler(value:Number):void
        {
            left = value;
        }

        private function rightHandler(value:Number):void
        {
            right = value;
        }

        private var _inputMap:InputMap;
    }
}
</pre>
<p>
The game can now respond to keyboard input. We&#8217;re getting close to the core of our demo but need some way to ensure all these great resources make it on to the display list. For this purpose, we&#8217;ll use a subclass of BaseScreen that will be registered with a screen manager once we dive into the main game class.
</p>
<p><strong>File: /ESPBEDemo-client/src/com/philperon/espbedemo/GameScreen.as</strong></p>
<pre class="brush: jscript;">
package com.philperon.espbedemo
{
    import com.pblabs.engine.PBE;
    import com.pblabs.engine.debug.Logger;
    import com.pblabs.engine.resource.ImageResource;
    import com.pblabs.rendering2D.ui.SceneView;
    import com.pblabs.screens.BaseScreen;

    // Create a new screen class that will be registered with the
    // screen manager.
    public class GameScreen extends BaseScreen
    {
        // Declare a scene variable so we have something to actually
        // draw to.
        public var sceneView:SceneView;

        public function GameScreen()
        {
            super();

            // Create the scene view to match the same size as the .swf
            // and add to the display list.
            sceneView = new SceneView();
            sceneView.name = &quot;sceneView&quot;;
            sceneView.width = 800;
            sceneView.height = 600;
            addChild(sceneView);

            // Request that a background image be loaded on to the screen.
            // Pass in handlers to deal with a success or failure.
            PBE.resourceManager.load(&quot;../assets/images/background.png&quot;, ImageResource, imageLoadSuccessHandler, imageLoadFailedHandler);
        }

        // Once the image is loaded, send the bitmap data into a fill on
        // the Graphics instance of this display object.
        private function imageLoadSuccessHandler(imageResource:ImageResource):void
        {
            cacheAsBitmap = true;
            graphics.clear();
            graphics.beginBitmapFill(imageResource.image.bitmapData);
            graphics.drawRect(0, 0, imageResource.image.bitmapData.width, imageResource.image.bitmapData.height);
            graphics.endFill();
        }

        private function imageLoadFailedHandler(imageResource:ImageResource):void
        {
            Logger.print(this, &quot;Failed to load image '&quot; + imageResource.filename + &quot;'&quot;);
        }
    }
}
</pre>
<p>
We&#8217;re getting close. It&#8217;s time to wire up the PlayerController we added to the player entity in the game.xml file. This will contain all the logic needed to control the player&#8217;s avatar including sending the position updates to ElectroServer. Here we go&#8230;
</p>
<p><strong>File: /ESPBEDemo-client/src/com/philperon/espbedemo/components/PlayerController.as</strong></p>
<pre class="brush: jscript;">
package com.philperon.espbedemo.components
{
    import com.electrotank.electroserver4.ElectroServer;
    import com.electrotank.electroserver4.esobject.EsObject;
    import com.electrotank.electroserver4.message.request.PluginRequest;
    import com.pblabs.engine.PBE;
    import com.pblabs.engine.components.TickedComponent;
    import com.pblabs.rendering2D.SimpleSpatialComponent;

    import flash.geom.Point;

    // This represents the core logic for a player avatar.
    // It extends TickedComponent so we have access to game ticks.
    public class PlayerController extends TickedComponent
    {
        // Set how fast we'd like the player to move.
        public static const SPEED:uint = 100;

        // Declare a variable to hold the ElectroServer connection.
        public var connection:ElectroServer;
        // Make sure the player knows the current room and zone ids.
        public var currentRoomID:Number;
        public var currentZoneID:Number;
        // Create a handle to the KeyboardInput component we just created.
        public var keyboardInput:KeyboardInput;
        // As mentioned earlier, the spatial component manages position.
        public var spatial:SimpleSpatialComponent;
        // And of course, every player has a name.
        public var username:String;

        // The position buffer will ensure we're not sending updates if
        // the player hasn't moved.
        private var _positionBuffer:Point = new Point();

        public function PlayerController()
        {
            super();
        }

        // The onTick method that gets called every game tick.
        override public function onTick(deltaTime:Number):void
        {
            // Set the x and y velocity based on the keyboard input registered
            // from the KeyboardInput component.
            spatial.velocity.x = (keyboardInput.right - keyboardInput.left) * PlayerController.SPEED;
            spatial.velocity.y = (keyboardInput.down - keyboardInput.up) * PlayerController.SPEED;

            // Bounds check the player's movement. (Ideally, this would also be
            // enforced on the server but I'm trying to keep things as
            // simple as possible.)
            if(spatial.position.x &lt; 0 &amp;&amp; spatial.velocity.x &lt; 0 ||
                spatial.position.x &gt; 800 &amp;&amp; spatial.velocity.x &gt; 0)
                spatial.velocity.x = 0;

            if(spatial.position.y &lt; 0 &amp;&amp; spatial.velocity.y &lt; 0 ||
                spatial.position.y &gt; 600 &amp;&amp; spatial.velocity.y &gt; 0)
                spatial.velocity.y = 0;
        }

        // This fires when this component is added to an entity.
        override protected function onAdd():void
        {
            super.onAdd();
            // Schedule a position update task with the process manager.
            PBE.processManager.schedule(200, this, sendPosition);
        }

        // The function that's called when the task we just scheduled is due.
        public function sendPosition():void
        {
            // Check to make sure we've actually moved.
            if((spatial.x != _positionBuffer.x) || (spatial.y != _positionBuffer.y))
            {
                // If we have moved, create a new request to be sent back to the server
                var pr:PluginRequest = new PluginRequest();
                // Set the plugin name as well as the room and zone id
                // that we created in Part 1 of this tutorial.
                pr.setPluginName(&quot;GamePlugin&quot;);
                pr.setRoomId(currentRoomID);
                pr.setZoneId(currentZoneID);

                // Create an EsObject that will act as our message payload.
                var pos:EsObject = new EsObject();
                // Set the opcode (also found in Part 1)
                pos.setInteger(&quot;opcode&quot;, ESPBEDemo.STATE_UPDATE);
                // Make sure the server knows who it's coming from...
                pos.setString(&quot;name&quot;, username);
                // ...and what we're changing.
                pos.setNumber(&quot;x&quot;, spatial.x);
                pos.setNumber(&quot;y&quot;, spatial.y);
                // Add the payload to our plugin request.
                pr.setEsObject(pos);
                // Now send it on it's way.
                connection.send(pr);                

                // Push our current position into the buffer.
                _positionBuffer.x = spatial.x;
                _positionBuffer.y = spatial.y;
            }
            // Finally, schedule this task to run again.
            PBE.processManager.schedule(200, this, sendPosition);
        }
    }
}
</pre>
<p>
All the support classes are finished. Now to focus on the main game class that will set up the server connection and start our client.
</p>
<h3>A Series of Events</h3>
<p>
Much of what we&#8217;ll be looking at within our main game class is driven by events. Both PushButton Engine and the ElectroServer AS3 API expose events that help you drive your game logic. For a large project you may not want to bundle all your handlers in one place, but we do so here to make it easier to follow how the logic flows from game initialization, server connection and finally gameplay.
</p>
<p><strong>File: /ESPBEDemo-client/src/ESPBEDemo.as</strong></p>
<pre class="brush: jscript;">
package
{
    import com.electrotank.electroserver4.ElectroServer;
    import com.electrotank.electroserver4.entities.Protocol;
    import com.electrotank.electroserver4.entities.SearchCriteria;
    import com.electrotank.electroserver4.entities.UserVariable;
    import com.electrotank.electroserver4.esobject.EsObject;
    import com.electrotank.electroserver4.message.MessageType;
    import com.electrotank.electroserver4.message.event.ConnectionEvent;
    import com.electrotank.electroserver4.message.event.PluginMessageEvent;
    import com.electrotank.electroserver4.message.request.LoginRequest;
    import com.electrotank.electroserver4.message.request.PluginRequest;
    import com.electrotank.electroserver4.message.request.QuickJoinGameRequest;
    import com.electrotank.electroserver4.message.response.CreateOrJoinGameResponse;
    import com.electrotank.electroserver4.message.response.LoginResponse;
    import com.pblabs.engine.PBE;
    import com.pblabs.engine.core.TemplateManager;
    import com.pblabs.engine.entity.IEntity;
    import com.pblabs.engine.entity.PropertyReference;
    import com.pblabs.rendering2D.*;
    import com.pblabs.rendering2D.spritesheet.SpriteSheetComponent;
    import com.philperon.espbedemo.*;
    import com.philperon.espbedemo.components.*;

    import flash.display.Sprite;
    import flash.display.StageScaleMode;
    import flash.events.Event;
    import flash.geom.Point;

    // Set up our swf configuration
    [SWF(width=&quot;800&quot;, height=&quot;600&quot;, frameRate=&quot;60&quot;, backgroundColor=&quot;0x000000&quot;)]
    public class ESPBEDemo extends Sprite
    {
        // Define our game protocol here. This reflects the same values we set in
        // part one.
        public static const PLAYER_INIT:int = 1;
        public static const OPPONENT_ENTERED:int = 2;
        public static const STATE_UPDATE:int = 3;
        public static const PLAYER_LEFT:int = 4;

        // declare variable for the ElectroServer connection.
        private var _es:ElectroServer;
        // The room and zone ids.
        private var _roomID:Number = -1;
        private var _zoneID:Number = -1;
        // General properties on users.
        private var _userProps:EsObject;
        // The player name
        private var _name:String;
        // And a collection to hold opponents objects.
        private var _opponents:Object = {};
        // This will hold the type of game we're assigned to.
        private var _gameType:String;

        public function ESPBEDemo()
        {
            // Set the scale mode.
            stage.scaleMode = StageScaleMode.SHOW_ALL;

            // Register classes that we reference in our level files here.
            // This is so the compiler knows to include them.
            PBE.registerType(DisplayObjectRenderer);
            PBE.registerType(DisplayObjectScene);
            PBE.registerType(Interpolated2DMoverComponent);
            PBE.registerType(SimpleSpatialComponent);
            PBE.registerType(SpriteSheetComponent);
            PBE.registerType(SpriteRenderer);
            PBE.registerType(PlayerController);
            PBE.registerType(KeyboardInput);

            // Start PushButton Engine.
            PBE.startup(this);

            // Add our resources.
            PBE.addResources(new Resources());

            // And register the game screen we created earlier.
            PBE.screenManager.registerScreen(&quot;game&quot;, new GameScreen());

            // Set up a loaded handler so that we know when our common.xml file is ready to go.
            PBE.templateManager.addEventListener(TemplateManager.LOADED_EVENT, loadedHandler);
            PBE.templateManager.loadFile(&quot;../assets/levels/common.xml&quot;);
        }

        // The loadedHandler fires once the common.xml level file is loaded.
        private function loadedHandler(event:Event):void
        {
            // Clean up the listener.
            PBE.templateManager.removeEventListener(TemplateManager.LOADED_EVENT, loadedHandler);

            // Instantiate the &quot;common&quot; group we defined in common.xml. This ensures
            // the spatial manager and scene are ready and available.
            PBE.templateManager.instantiateGroup(&quot;common&quot;);

            // Now it's time to start the ElectroServer connection process.
            _es = new ElectroServer();
            // Set the protocol to binary for best performance.
            _es.setProtocol(Protocol.BINARY);
            // Wire up our listeners for connection...
            _es.addEventListener(MessageType.ConnectionEvent, &quot;onConnectionEvent&quot;, this);
            // ...login response...
            _es.addEventListener(MessageType.LoginResponse, &quot;onLoginResponse&quot;, this);
            // ...game joins...
            _es.addEventListener(MessageType.CreateOrJoinGameResponse, &quot;onCreateOrJoinGameResponse&quot;, this);
            // ...and finally, general plugin messages.
            _es.addEventListener(MessageType.PluginMessageEvent, &quot;onPluginMessageEvent&quot;, this);
            // Now, create the connection to the server.
            //(This assumes you're running the server locally.)
            _es.createConnection(&quot;127.0.0.1&quot;, 9899);
        }

        // Handle the connection response from the server.
        public function onConnectionEvent(event:ConnectionEvent):void
        {
            // If the connection is accepted...
            if (event.getAccepted()) {
                // ...generate a user name.
                _name = &quot;user&quot;+Math.round(10000*Math.random());
                // Create and send a login request to the server.
                var loginRequest:LoginRequest = new LoginRequest();
                loginRequest.setUserName(_name);
                _es.send(loginRequest);
            // Otherwise, throw an error.
            } else {
                throw new Error(&quot;Connection failed: &quot; + event.getEsError().getDescription());
            }
        }

        // This handles our login response from the server.
        public function onLoginResponse(event:LoginResponse):void
        {
            // Create a new search criteria instance. This is used
            // inside a join game request below.
            var criteria:SearchCriteria = new SearchCriteria();
            // Set the game type to match the name we defined in part one of the tutorial.
            criteria.setGameType(&quot;game&quot;);

            // Grab the first user variable sent from the server.
            var uservar:UserVariable = event.getUserVariables()[0];
            // Extract the EsObject value from the user variable.
            var esobj:EsObject = uservar.getValue();
            // Make sure we're looking at &quot;gameType&quot;.
            if(esobj.doesPropertyExist(&quot;gameType&quot;))
            {
                // ElectroServer 4 is not yet capable of adding a player to a game automatically
                // so we'll request it from the client side.
                //
                // Grab the game type.
                var mode:String = esobj.getString(&quot;gameType&quot;);
                // And create a new join game request.
                var request:QuickJoinGameRequest = new QuickJoinGameRequest();
                // Set the game type we just grabbed.
                request.setGameType(mode);
                // As well as the zone name.
                request.setZoneName(mode + &quot;Zone&quot;);
                // Finally, set the criteria and send the request back to the server.
                request.setSearchCriteria(criteria);
                _es.send(request);
            }
        }

        // When a game request response arrives from the server, enter this handler.
        public function onCreateOrJoinGameResponse(event:CreateOrJoinGameResponse):void
        {
            // Check to see if we've successfully joined.
            if(event.getSuccessful() == true)
            {
                // Make sure we have a &quot;type&quot;.
                if(event.getGameDetails().doesPropertyExist(&quot;type&quot;))
                {
                    // And set that here.
                    _gameType = event.getGameDetails().getString(&quot;type&quot;);

                    // Store a local reference to the room and zone id.
                    _roomID = event.getRoomId();
                    _zoneID = event.getZoneId();

                    // Tack a listener on to the TemplateManager to notify us when the next file is loaded.
                    PBE.templateManager.addEventListener(TemplateManager.LOADED_EVENT, gameLoadedHandler);
                    // Request that our game.xml file that defines our game is loaded.
                    PBE.templateManager.loadFile(&quot;../assets/levels/&quot; + _gameType + &quot;.xml&quot;);
                }
            }
            // Otherwise, throw an error.
            else
            {
                throw new Error(&quot;Could not join game: &quot; + event.getEsError().getDescription());
            }
        }

        // Jump in this handler once we've loaded our client game assets and are ready to begin.
        private function gameLoadedHandler(event:Event):void
        {
            // Head off to the screen we registered above in the constructor.
            PBE.screenManager.goto(_gameType);

            // Grab the player EsObject that was stored in the _userProps variable. (We'll find
            // out how _userProps got defined below.)
            var player:EsObject = _userProps.getEsObject(&quot;player&quot;);
            // And get the initial x and y location of the player. We do this now because
            // we finally are able to do something about it; Render it on-screen.
            var spawnPoint:Point = new Point(player.getNumber(&quot;x&quot;), player.getNumber(&quot;y&quot;));
            // Create a list of opponents that are already in-game.
            var opponentList:Array = _userProps.getEsObjectArray(&quot;playerlist&quot;);

            // Iterate over each opponent in the list.
            for(var i:uint = 0; i &lt; opponentList.length; i++)
            {
                // Access each opponent EsObject
                var oppObj:EsObject = EsObject(opponentList[i]);
                // Get it's name.
                var name:String = oppObj.getString(&quot;name&quot;);
                // And if the name exists...
                if(name != _name)
                {
                    // ...extract the current position...
                    var p:Point = new Point(oppObj.getNumber(&quot;x&quot;), oppObj.getNumber(&quot;y&quot;));
                    // ...and request that a new opponent avatar be spawned.
                    spawnOpponent(name, p);
                }
            }

            // Finally, don't forget to spawn the player's avatar.
            spawnPlayer(spawnPoint);
        }

        // Define what happens when an opponent avatar is created.
        private function spawnOpponent(name:String, spawnPoint:Point):void
        {
            // Based on the name, create a new entity passing in all the parameters
            // it needs to work properly.
            //
            // &quot;opponent&quot; is the name we gave to the template in game.xml. The &quot;@&quot; symbols
            // mean we're accessing a component of the entity template.
            _opponents[name] = PBE.makeEntity(&quot;opponent&quot;, {
                &quot;@mover.initialPosition&quot;:spawnPoint,
                &quot;@mover.translationSpeed&quot;:100,
                &quot;@controller.currentRoomID&quot;:_roomID,
                &quot;@controller.currentZoneID&quot;:_zoneID,
                &quot;@controller.username&quot;:name
            });
        }

        // Define what happens when a player avatar is created.
        private function spawnPlayer(spawnPoint:Point):void
        {
            // As mentioned above, create a new entity based on the &quot;player&quot;
            // template we defined in game.xml.
            PBE.makeEntity(&quot;player&quot;, {
                &quot;@spatial.position&quot;:spawnPoint,
                &quot;@controller.connection&quot;:_es,
                &quot;@controller.currentRoomID&quot;:_roomID,
                &quot;@controller.currentZoneID&quot;:_zoneID,
                &quot;@controller.username&quot;:_name
            });
        }

        // Define a handler to deal with messages coming in from the plugin.
        public function onPluginMessageEvent(event:PluginMessageEvent):void
        {
            // Get the EsObject from the event object.
            var eso:EsObject = event.getEsObject();
            // Grab the opcode.
            var opcode:int = eso.getInteger(&quot;opcode&quot;);
            // Set up some shared variables.
            var player:EsObject;
            var name:String = &quot;&quot;;

            // switch over the opcode being passed in.
            switch(opcode)
            {
                // When the player was first logged in, we received this message
                // from the server. If you were wondering, this is how _userProps
                // was defined.
                case PLAYER_INIT:
                    _userProps = eso;
                    break;
                // Each time an opponent enters, grab the player object and name and
                // spawn a new opponent avatar.
                case OPPONENT_ENTERED:
                    player = eso.getEsObject(&quot;player&quot;);
                    name = player.getString(&quot;name&quot;);
                    if(name != _name)
                        spawnOpponent(name, new Point(player.getNumber(&quot;x&quot;), player.getNumber(&quot;y&quot;)));
                    break;
                // The only state updates we're handling in this demo are position updates.
                // When they arrive, move the corresponding opponent.
                case STATE_UPDATE:
                    name = eso.getString(&quot;name&quot;);
                    if(name != _name)
                        moveOpponent(name, eso.getNumber(&quot;x&quot;), eso.getNumber(&quot;y&quot;));
                    break;
                // When a player leaves, request that they be removed from the game.
                case PLAYER_LEFT:
                    name = eso.getString(&quot;name&quot;);
                    removePlayerFromList(name);
                    break;
                // Die if we don't recognize an opcode.
                default:
                    throw new Error(&quot;Unknown opcode: &quot; + opcode);
            }
        }

        // Defines what takes place when the server tells us a player has left.
        private function removePlayerFromList(name:String):void
        {
            // Grab the entity reference to the player...
            var player:IEntity = _opponents[name];
            // ...and destroy it.
            player.destroy();
            // Finally, remove it from the collection.
            delete _opponents[name];
        }

        // Handles moving the opponent avatar on the screen.
        private function moveOpponent(username:String, moveX:Number, moveY:Number):void
        {
            // Grab the entity reference.
            var entity:IEntity = _opponents[username];
            // If it's not null, set a new goal position for the interpolated mover component.
            if(entity != null)
            {
                entity.setProperty(new PropertyReference(&quot;@mover.goalPosition&quot;), new Point(moveX, moveY));
            }
        }
    }
}
</pre>
<p>
That&#8217;s it! Make sure the server is started and fire up your newly created client. Click inside the swf and remember to use W, A, S and D (or whatever you chose to set inside the KeyboardInput component) and watch your avatar move. Now open up another browser window and point to the same location to see what happens when another client connects. You may want to play a bit with the &#8220;nudge&#8221; property of the Interpolated2DMoverComponent to get it feeling right but regardless, you&#8217;re off and running!
</p>
<h2>Next Steps</h2>
<p>
We covered a lot of ground in this tutorial and you may be wondering what the heck to do next. If you struggled a bit with some of the server-side stuff we covered in part one, I&#8217;d head over to the ElectroServer <a href="http://www.electro-server.com/forum/">forums</a> or <a href="http://es-wiki.com/index.php?title=Main_Page">wiki</a> and start looking at some of the great tutorials and references they&#8217;ve set up there. If you&#8217;d like to dive deeper into PushButton Engine, the <a href="http://pushbuttonengine.com/forum/">forums</a> are an excellent place to start learning as well as the <a href="http://pushbuttonengine.com/docs/">docs</a> and awesome IRC channel, #pbengine. Finally, if you&#8217;re ready to dig deeper into the world of multiplayer games, I&#8217;d urge you to start looking at some pieces that will be integral once you begin creating a production-grade system. Check out articles and tutorials for things like clock/time synchronization, dead reckoning, area of interest management, object state distribution and persistence. If you&#8217;re feeling especially brave, check out how we handle custom game protocol management using the <a href="http://github.com/pperon">Gliese Framework</a> for RedDwarf
</p>
<p>
If you&#8217;ve come this far, thank you. I appreciate your time and your visit. Now go make a great game!
</p>
<p><em><br />
You can download the source code covered in this post <a href="http://philperon.com/files/ESPBEDemo-client.zip">here</a>.<br />
</em></p>
]]></content:encoded>
			<wfw:commentRss>http://philperon.com/2010/03/31/an-introduction-to-electroserver-and-pushbutton-engine-part-two/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>An Introduction to ElectroServer and PushButton Engine: Part One</title>
		<link>http://philperon.com/2010/03/17/an-introduction-to-electroserver-and-pushbutton-engine-part-one/</link>
		<comments>http://philperon.com/2010/03/17/an-introduction-to-electroserver-and-pushbutton-engine-part-one/#comments</comments>
		<pubDate>Wed, 17 Mar 2010 17:07:57 +0000</pubDate>
		<dc:creator>Phil</dc:creator>
				<category><![CDATA[flash]]></category>
		<category><![CDATA[game development]]></category>
		<category><![CDATA[mmo]]></category>
		<category><![CDATA[ElectroServer]]></category>
		<category><![CDATA[gamedev]]></category>
		<category><![CDATA[PushButton Engine]]></category>

		<guid isPermaLink="false">http://philperon.com/?p=585</guid>
		<description><![CDATA[
There are many options available when deciding on which Flash engine or framework to use before development begins on your next single-player project. Should you decide to add multi-player capability, the list gets shorter. This is especially true if your game crosses over into the MMOG or Virtual World domains. Code reusability, game asset management [...]]]></description>
			<content:encoded><![CDATA[<p>
There are many options available when deciding on which Flash engine or framework to use before development begins on your next single-player project. Should you decide to add multi-player capability, the list gets shorter. This is especially true if your game crosses over into the MMOG or Virtual World domains. Code reusability, game asset management and premium performance are all key to successfully reaching that goal. PushButton Engine satisfies these criteria and more by offering a component-based architecture, dependency injection, a robust engine core and a strong community.
</p>
<p>
When deciding on which server technology to use it&#8217;s quite a different story. The list of viable options is much shorter. Scalability, maintainability, extensibility and price all come to mind when shopping around for the right product. The RedDwarf server (formerly Project Darkstar) is tempting due to it&#8217;s cost (free) but developers who are interested in simply writing their game code may become discouraged due to it&#8217;s steep learning curve. Enter, ElectroServer. When I recently started exploring ElectroTank&#8217;s flagship product, I was hooked on it&#8217;s highly-polished API and how dead-simple it was to get up and running. Couple that experience with it&#8217;s potential to scale to hundreds of thousands of simultaneous users and it&#8217;s difficult to find a better option.
</p>
<p><span id="more-585"></span></p>
<h3>Goals</h3>
<p>The goal of this tutorial is not to have you up and running with a full-blown, ready to ship product. Instead, the focus is on just how little you have to do to get something started. I hope it will help illustrate how powerful the combination of PushButton Engine and ElectroServer can be. Although introductory in nature, I believe you&#8217;ll see the incredible value merging these two great technologies can provide.</p>
<h3>Prerequisites</h3>
<p>I&#8217;m assuming you&#8217;re comfortable moving around an IDE or text editor, have some fairly advanced ActionScript skills, some Java experience and generally aren&#8217;t afraid to get your hands dirty. If you&#8217;ve never used ElectroServer or PushButton Engine, I would urge you at least check out their respective starter lessons to get you up to speed.</p>
<h2>The Server</h2>
<p>Before a client application can start a game, it needs something to connect to. ElectroServer is built on a plugin architecture which allows developers to easily extend it&#8217;s core functionality. Plugins can be scoped to the server, a room or a player. In this example, we&#8217;ll focus on server initialization, user login and finally the game logic itself. Let&#8217;s start digging into some code!</p>
<h3>Initialization</h3>
<p>Our first plugin is scoped to the server and is in charge of configuring the primary game plugin.</p>
<p><strong>File: /ESPBEDemo-server/src/com/philperon/espbedemo/plugins/InitPlugin.java</strong></p>
<pre class="brush: java;">
package com.philperon.espbedemo.plugins;

import com.electrotank.electroserver4.extensions.Plugin;
import com.electrotank.electroserver4.extensions.PluginLifeCycle;
import com.electrotank.electroserver4.extensions.api.PluginApi;
import com.electrotank.electroserver4.extensions.api.value.EsObject;
import com.electrotank.electroserver4.extensions.api.value.EsObjectRO;
import com.electrotank.electroserver4.extensions.api.value.ExtensionComponentConfiguration;
import com.electrotank.electroserver4.extensions.api.value.GameConfiguration;
import com.electrotank.electroserver4.extensions.api.value.RoomConfiguration;

// This is the plugin that gets everything started.
public class InitPlugin implements Plugin, PluginLifeCycle {

    // Define a private handle to the plugin api (used in the getter/setter below)
    private PluginApi api;

    // init is called when the object based on this class is instantiated.
    @Override
    public void init(EsObjectRO esObj) {

        // Create the plugin variable that will contain the plugin.
        ExtensionComponentConfiguration plugin = new ExtensionComponentConfiguration();

        // Define which extension the plugin will be associated with.
        plugin.setExtensionName(&quot;ESPBEDemo&quot;);
        // Set the handle which is how the plugin will be accessed when instantiated in a room.
        plugin.setHandle(&quot;GamePlugin&quot;);
        // Set the name that will be used to label this plugin in the Extension.xml file.
        plugin.setName(&quot;GamePlugin&quot;);

        // Create the room configuration for the room that will host the plugin.
        RoomConfiguration roomConfig = new RoomConfiguration();
        // Set the user connection limit.
        roomConfig.setCapacity(25);
        // Now add the plugin to the room configuration.
        roomConfig.addPlugin(plugin);

        // Create an ElectroServer object that will contain extra details that should be relayed to the user.
        EsObject gameDetails = new EsObject();
        // Set the type so that the client knows how to request access after it connects.
        gameDetails.setString(&quot;type&quot;, &quot;game&quot;);

        // Create a new game configuration instance.
        GameConfiguration gameConfig = new GameConfiguration();
        // Add the game details.
        gameConfig.setInitialGameDetails(gameDetails);
        // Add the room configuration we defined above to the game config object.
        gameConfig.setRoomConfiguration(roomConfig);
        // We're not interested in listening for room list updates in this demonstration...
        gameConfig.setReceivingRoomListUpdates(false);
        // ...or room variable updates.
        gameConfig.setReceivingRoomVariableUpdates(false);
        // Make sure we receive user list updates...
        gameConfig.setReceivingUserListUpdates(true);
        // ...as well as user variable updates.
        gameConfig.setReceivingUserVariableUpdates(true);
        // We're not interested in video events.
        gameConfig.setReceivingVideoEvents(false);
        // Finally, register our &quot;game&quot; using the game configuration object we just created.
        getApi().registerGameConfiguration(&quot;game&quot;, gameConfig);
    }

    @Override
    public PluginApi getApi() {
        return api;
    }

    @Override
    public void setApi(PluginApi api) {
        this.api = api;
    }

    @Override
    public void destroy() {
        // Clean up any loose ends.
    }

}
</pre>
<p>
That wraps up the initialization process. Before jumping into the game plugin, we&#8217;ll need to think about how user logins are handled.
</p>
<h3>Accepting User Logins</h3>
<p>
Event Handlers are another way the ElectroServer API allows you to extend functionality. At this point, the server is aware of the game plugin but we need some way to send this information to a connected client. This is where the LoginEventHandler comes into play.
</p>
<p><strong>File: /ESPBEDemo-server/src/com/philperon/espbedemo/handlers/LoginEventHandler.java</strong></p>
<pre class="brush: java;">
package com.philperon.espbedemo.handlers;

import com.electrotank.electroserver4.extensions.BaseLoginEventHandler;
import com.electrotank.electroserver4.extensions.ChainAction;
import com.electrotank.electroserver4.extensions.LoginContext;
import com.electrotank.electroserver4.extensions.api.value.EsObject;

// Like the other event handlers, there are base classes you extend to get started quickly.
public class LoginEventHandler extends BaseLoginEventHandler {

    // This method fires after a player logs in.
    public ChainAction executeLogin(LoginContext login) {

        // Create a new EsObject to hold values that will soon be passed to the client.
        EsObject uservars = new EsObject();

        // Set a gameType value to the name of our plugin, &quot;game&quot;.
        uservars.setString(&quot;gameType&quot;, &quot;game&quot;);

        // Add the user variables to the login context.
        login.addUserVariable(&quot;uservars&quot;, uservars);

        // And let the server know that all is well.
        return ChainAction.OkAndContinue;
    }
}
</pre>
<p>
Now, any time a user logs in, they will be sent the information they need to request access to the game. Ideally, the server would insert a player automatically but because that functionality is not yet available in the current version of ElectroServer, we&#8217;ll deal with that later on in the client code.
</p>
<h3>Writing the Game Plugin</h3>
<p>
Now to our server-side game code! The objective here is to listen for various player action events such as entering and exiting the game as well as moving around the game world.
</p>
<p><strong>File: /ESPBEDemo-server/src/com/philperon/espbedemo/plugins/GamePlugin.java</strong></p>
<pre class="brush: java;">
package com.philperon.espbedemo.plugins;

import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;

import com.electrotank.electroserver4.extensions.BasePlugin;
import com.electrotank.electroserver4.extensions.ChainAction;
import com.electrotank.electroserver4.extensions.api.value.EsObject;
import com.electrotank.electroserver4.extensions.api.value.EsObjectRO;
import com.electrotank.electroserver4.extensions.api.value.UserEnterContext;

// Extend the BasePlugin class to take advantage of the user events it exposes.
public class GamePlugin extends BasePlugin {

    // Define our game protocol...
    // Player enters
    private static final int PLAYER_INIT = 1;
    // Opponent enters
    private static final int OPPONENT_ENTERED = 2;
    // Player state changes
    private static final int STATE_UPDATE = 3;
    // Player leaves
    private static final int PLAYER_LEFT = 4;

    // Create a thread-safe map to store players currently in-game.
    private ConcurrentMap&lt;String,EsObject&gt; playerMap = new ConcurrentHashMap&lt;String,EsObject&gt;(25);

    // When the game initializes, turn on message queueing.
    @Override
    public void init(EsObjectRO esObj) {
        // This will send packaged messages five times per second.
        getApi().startQueue(200);
    }

    // Define what happens when a player enters the game.
    @Override
    public ChainAction userEnter(UserEnterContext context) {

        // Grab the user's name.
        String name = context.getUserName();

        // Create a new EsObject that will represent a player.
        // We're only concerned with their name and position in this demonstration.
        EsObject player = new EsObject();
        // Add their name.
        player.setString(&quot;name&quot;, name);
        // And their starting position.
        player.setNumber(&quot;x&quot;, 400);
        player.setNumber(&quot;y&quot;, 300);

        // Add the player to the room's player map.
        playerMap.put(name, player);

        // Create a EsObject to represent a new player message.
        EsObject uservars = new EsObject();
        // Add the opcode that represents a new player being initialized.
        uservars.setInteger(&quot;opcode&quot;, PLAYER_INIT);
        // Add the player object defined above.
        uservars.setEsObject(&quot;player&quot;, player);
        // Send the player list along so opponents can be properly rendered on the client.
        uservars.setEsObjectArray(&quot;playerlist&quot;, (EsObject[]) playerMap.values().toArray(new EsObject[playerMap.size()]));
        // And send the message privately to the user.
        getApi().sendPluginMessageToUser(context.getUserName(), uservars);

        // Now, define another player object for others to process.
        EsObject userObj = new EsObject();
        // Add the opcode for new opponents entering.
        userObj.setInteger(&quot;opcode&quot;, OPPONENT_ENTERED);
        // Add the player object.
        userObj.setEsObject(&quot;player&quot;, player);
        // And send the message to everyone in the room.
        getApi().sendPluginMessageToRoom(getApi().getZoneId(), getApi().getRoomId(), userObj);

        return ChainAction.OkAndContinue;
    }

    // Define what happens when a player leaves the game.
    @Override
    public void userExit(String name) {
        // Create a new message object.
        EsObject eso = new EsObject();
        // Add the opcode that represents a player leaving.
        eso.setInteger(&quot;opcode&quot;, PLAYER_LEFT);
        // Remove the player from the player map and add the name to the message.
        eso.setString(&quot;name&quot;, playerMap.remove(name).getString(&quot;name&quot;));
        // Now, send the message to the room notifying everyone that the player has left.
        getApi().sendPluginMessageToRoom(getApi().getZoneId(), getApi().getRoomId(), eso);
    }

    // Define what happens when a player sends a message to the room.
    @Override
    public void request(String userName, EsObjectRO requestParameters) {
        // If the user's message carries an opcode, process it.
        if(requestParameters.variableExists(&quot;opcode&quot;)) {
            // If the opcode represents a state update, update it here.
            if(requestParameters.getInteger(&quot;opcode&quot;) == STATE_UPDATE) {
                // Grab a handle of the player from the player map using it's name as a key.
                EsObject player = playerMap.get(userName);
                // And set it's new position.
                player.setNumber(&quot;x&quot;, requestParameters.getNumber(&quot;x&quot;));
                player.setNumber(&quot;y&quot;, requestParameters.getNumber(&quot;y&quot;));
            }
            // Finally, add the state update message to the message queue to be sent to
            // everyone in the room during the next 200ms cycle.
            getApi().sendQueuedPluginMessageToRoom(userName, requestParameters);
        }
    }

    // Clean up if and when the game plugin (room) is removed.
    @Override
    public void destroy() {
        getApi().stopQueue();
    }
}
</pre>
<p>
A quick note regarding message queueing. Due to limitations of the Flash Player and general good practice when designing a multi-player game, you don&#8217;t want to send a high number of messages per second. By wrapping up various messages per packet, the Flash Player remains happy and you still have enough information to render other players on the client adequately enough. I suggest 200 milliseconds per package here, but others might say that between 250 and 500 milliseconds is enough for anything outside a fast-twitch, action game. It really depends on your situation.
</p>
<h3>Deployment</h3>
<p>
Deploying a new ElectroServer is a snap. Simply define an extension.xml file, drop the relevant files in the server&#8217;s extension folder, restart the server and activate them. The Extension.xml file for this demonstration looks like this.
</p>
<p><strong>File: /ESPBEDemo-server/src/extension.xml</strong></p>
<pre class="brush: xml;">
&lt;?xml version=&quot;1.0&quot; encoding=&quot;utf-8&quot; ?&gt;
&lt;Extension&gt;

    &lt;!-- The name of our extension --&gt;
    &lt;Name&gt;ESPBEDemo&lt;/Name&gt;

    &lt;!-- Define all event handlers here. --&gt;
    &lt;EventHandlers&gt;
        &lt;LoginHandlers&gt;

            &lt;!-- Our login handler goes here. --&gt;
            &lt;LoginHandler&gt;

                &lt;!-- Define the name of the handle that will be used to access it --&gt;
                &lt;Handle&gt;LoginEventHandler&lt;/Handle&gt;

                &lt;!-- Define the type. We've been using Java but ActionScript 1 is also an option --&gt;
                &lt;Type&gt;Java&lt;/Type&gt;

                &lt;!-- Set the path to the actual login event handler class. --&gt;
                &lt;Path&gt;com.philperon.espbedemo.handlers.LoginEventHandler&lt;/Path&gt;

                &lt;/LoginHandler&gt;
        &lt;/LoginHandlers&gt;
    &lt;/EventHandlers&gt;

    &lt;!-- Define all plugins here --&gt;
    &lt;Plugins&gt;

        &lt;!-- First, the initialization plugin --&gt;
        &lt;Plugin&gt;
            &lt;Handle&gt;InitPlugin&lt;/Handle&gt;
            &lt;Type&gt;Java&lt;/Type&gt;
            &lt;Path&gt;com.philperon.espbedemo.plugins.InitPlugin&lt;/Path&gt;
        &lt;/Plugin&gt;

        &lt;!-- And then the game plugin --&gt;
        &lt;Plugin&gt;
            &lt;Handle&gt;GamePlugin&lt;/Handle&gt;
            &lt;Type&gt;Java&lt;/Type&gt;
            &lt;Path&gt;com.philperon.espbedemo.plugins.GamePlugin&lt;/Path&gt;
        &lt;/Plugin&gt;

&lt;/Plugins&gt;
&lt;/Extension&gt;
</pre>
<p>
Create two directories in [your electroserver install directory]/server/extenstions/ called, &#8220;ESPBEDemo&#8221; and &#8220;classes&#8221;. Copy the extension.xml file to the root of that directory and move the fully pathed .class files from your java project folder inside &#8220;classes&#8221;. When you&#8217;re finished you should have a structure that looks like this:
</p>
<p><em><br />
$EXTENSION_DIR/ESPBEDemo/extension.xml<br />
$EXTENSION_DIR/ESPBEDemo/classes/com/philperon/espbedemo/handlers/LoginEventHandler.class<br />
$EXTENSION_DIR/ESPBEDemo/classes/com/philperon/espbedemo/plugins/InitPlugin.class<br />
$EXTENSION_DIR/ESPBEDemo/classes/com/philperon/espbedemo/plugins/GamePlugin.class<br />
</em></p>
<p>
Now restart the server and activate the server level components, LoginEventHandler and InitPlugin by selecting &#8220;Extensions&#8221; from the top navigation bar in the ElectroServer admin interface and then, &#8220;Create New Server-level Component&#8221; on the left side of the page.
</p>
<p><img src="http://philperon.com/images/espbedemo/initPlugin.gif" alt="initPlugin definition" /></p>
<p>
Extension name should be the same as you created above (ESPBEDemo) and the name and handle fields should be &#8220;InitPlugin&#8221;. Once that&#8217;s saved, do the same for the LoginEventHandler.
</p>
<p><img src="http://philperon.com/images/espbedemo/loginEventHandler.gif" alt="LoginEventHandler definition" /></p>
<p>
Now restart ElectroServer. When it initializes, you should see something close to the following:
</p>
<p><img src="http://philperon.com/images/espbedemo/serverStart.gif" alt="server start screenshot" /></p>
<p>
Log back into the administration tool and check the extensions. If you expand the ESPBEDemo extension, it should look like this:
</p>
<p><img src="http://philperon.com/images/espbedemo/extensionDeployment.gif" alt="Extension deployment success" /></p>
<p>
Congrats! You&#8217;ve successfully built and deployed a Java extension for ElectroServer!
</p>
<p>
In part two, we&#8217;ll build the PBE client and connect it all together. Stay tuned!
</p>
<p>
<em><br />
You can download the source code covered in this post <a href="http://philperon.com/files/ESPBEDemo-server.zip">here</a>.<br />
</em>
</p>
<p>
<em>For more information on all things ElectroServer, check out their <a href="http://es-wiki.com">wiki</a> or visit their <a href="http://www.electro-server.com/forum/">forums</a>.</em></p>
]]></content:encoded>
			<wfw:commentRss>http://philperon.com/2010/03/17/an-introduction-to-electroserver-and-pushbutton-engine-part-one/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Starting Up PushButton Engine</title>
		<link>http://philperon.com/2009/05/29/starting-up-pushbutton-engine/</link>
		<comments>http://philperon.com/2009/05/29/starting-up-pushbutton-engine/#comments</comments>
		<pubDate>Fri, 29 May 2009 11:57:30 +0000</pubDate>
		<dc:creator>Phil</dc:creator>
				<category><![CDATA[flash]]></category>
		<category><![CDATA[game development]]></category>
		<category><![CDATA[gamedev]]></category>
		<category><![CDATA[PushButton Engine]]></category>

		<guid isPermaLink="false">http://philperon.com/?p=44</guid>
		<description><![CDATA[




PushButton Engine is an open-source Flash game engine from PushButton Labs, a group led by two of the Garage Games co-founders.
The plan behind PBE is to give away the engine source, sell a visual editor to help rapidly create games, offer a storefront for developers to sell their own PBE components and finally, make games [...]]]></description>
			<content:encoded><![CDATA[<div class="mceTemp">
<dl id="attachment_45" class="wp-caption alignleft" style="width: 190px;">
<dt class="wp-caption-dt"><a href="http://pushbuttonengine.com/"><img class="size-full wp-image-45" title="pbelogo" src="http://philperon.com/wp-content/uploads/2009/05/pbelogo.gif" alt="Pushbutton Engine" width="180" height="46" /></a></dt>
</dl>
</div>
<p><a title="PushButton Engine" href="http://pushbuttonengine.com/">PushButton Engine</a> is an open-source Flash game engine from <a title="PushButton Labs" href="http://pushbuttonlabs.com/">PushButton Labs</a>, a group led by two of the <a title="Garage Games" href="http://www.garagegames.com/">Garage Games</a> co-founders.</p>
<p>The plan behind PBE is to give away the engine source, sell a visual editor to help rapidly create games, offer a storefront for developers to sell their own PBE components and finally, make games themselves. Currently, the only thing available is the engine source and the ability to create (but not yet sell) PBE components.<span id="more-44"></span></p>
<h3>Starting It Up</h3>
<p>The <a title="PushButton Engine Source Code" href="http://code.google.com/p/pushbuttonengine/">PBE source</a> is hosted on Google Code so after a quick svn checkout, you have everything you need to get started. They offer an AIR app called the PushButton Engine Manager that helps manage projects. My hunch is that it will become a sort of PBE dashboard offering quick component purchases, news feeds and the like. With the manager you can open up the solution they offer which lets you peek at the demo games from the manager&#8217;s perspective. After setting the path to your Flex SDK of choice you generate your build files (Flex IDE and Ant) and you&#8217;re ready to go. I was pretty happy with this process. Everything went smoothly and I was able to fire up Ant and build the entire set of library swcs as well as the game demos.</p>
<h3>Pop the Hood</h3>
<p>PushButton Engine in it&#8217;s current state is not for the faint of heart. If you&#8217;ve only spent time in the Flash development world, the engine source and structure of a PBE game will come as a shock. At this point, I&#8217;d recommend reading the PBE <a title="PushButton Engine Manual" href="http://pushbuttonengine.com/docs/">manual</a> as it sheds some light on this strange and wonderful work. Even after finishing the manual you&#8217;ll need to keep an open mind as you work through your first game. The source itself doesn&#8217;t follow the coding conventions we&#8217;ve all grown accustomed to and the engine is still in development. The latter can be seen as a kind of moving target if you&#8217;re someone (like me) who prefers to keep their code up to date. I can recall two (maybe three) times where I had to stop production on my current project to refactor some code to work with the new engine updates. If this sort of activity doesn&#8217;t appeal to you I&#8217;d recommend waiting until the engine matures a little bit.</p>
<h3>Revving the Engine</h3>
<p>When I first generated a solution from the PBE Manager and created my first project there wasn&#8217;t a whole lot going on. I had to do a lot of manual editing of the pbelevel (an XML-based game definition file) to get it to compile and be happy. Even after that, there&#8217;s still quite a bit you need to do to draw an avatar on the screen. Not really a &#8220;push button&#8221; feel but I&#8217;m assuming this will improve and become a non-issue once the editor is complete. This is also where the forums really help out. <a href="http://coderhump.com/">Ben Garney</a>, the PB Labs &#8216;Coder&#8217; is an active participant and has helped me out on more than one occasion.</p>
<h3>Final Thoughts</h3>
<p>I like this engine. It&#8217;s been slow-moving at times but I&#8217;ve managed to accomplish what I set out to do and hope to eventually publish something to a site like Kongregate or New Grounds. It can certainly be frustrating at times but this has been one of the more rewarding coding experiences I&#8217;ve had in a while. I would urge any developer interested in developing games to check it out. It&#8217;s a wonderful opportunity to share your thoughts and give feedback during a time when it can have the most impact. Happy coding!</p>
]]></content:encoded>
			<wfw:commentRss>http://philperon.com/2009/05/29/starting-up-pushbutton-engine/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Review: Protecting Games</title>
		<link>http://philperon.com/2009/04/08/review-protecting-games/</link>
		<comments>http://philperon.com/2009/04/08/review-protecting-games/#comments</comments>
		<pubDate>Thu, 09 Apr 2009 03:03:19 +0000</pubDate>
		<dc:creator>Phil</dc:creator>
				<category><![CDATA[game development]]></category>
		<category><![CDATA[security]]></category>
		<category><![CDATA[gamedev]]></category>

		<guid isPermaLink="false">http://philperon.com/?p=23</guid>
		<description><![CDATA[With the arrival of online gambling, massively multiplayer games and services like XBox Live come a much larger audience and a widening demographic scope. These players have helped turn the game industry into a money-making behemoth. As large and popular as this industry has become it has done a surprisingly poor job of addressing the [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://www.amazon.com/Protecting-Games-Security-Developers-Publishers/dp/1584506709/ref=sr_1_1?ie=UTF8&amp;s=books&amp;qid=1239245662&amp;sr=8-1"><img src="/images/protecting-games.jpg" alt="Protecting Games" align="left" border="0" width="129" height="160" hspace="10" /></a>With the arrival of online gambling, massively multiplayer games and services like XBox Live come a much larger audience and a widening demographic scope. These players have helped turn the game industry into a money-making behemoth. As large and popular as this industry has become it has done a surprisingly poor job of addressing the darker side of gaming. <a href="http://www.amazon.com/Protecting-Games-Security-Developers-Publishers/dp/1584506709/ref=sr_1_1?ie=UTF8&amp;s=books&amp;qid=1239245662&amp;sr=8-1" title="Protecting Games by Steven Davis">Protecting Games by Steven Davis</a> of <a href="http://www.itglobalsecure.com/index.htm" title="IT GlobalSecure">IT GlobalSecure</a> attempts to solve this problem by shining a light on piracy, cheating, account theft, privacy, protecting children online and more.<span id="more-23"></span></p>
<p>Protecting Games is broken into four primary sections with piracy and cheating having the most obvious relevance. The latter two sections address social attacks from griefing to gold farming and finally a &#8220;Real World&#8221; section that seems to act as a catch-all covering relationships with third parties, real money transactions and even a brief chapter on terrorism.</p>
<p>The sections on piracy and cheating seem to make up the core of the book and carry with it interesting tips, anecdotes and in some cases psuedo-code that help illustrate a solution to the problem at hand. I actually walked away from these chapters feeling a bit depressed in regard to how monumental these security challenges are. It&#8217;s not that you&#8217;re left empty handed or unwarned. It&#8217;s just that you start to feel like you&#8217;re being attacked from all sides and quite frankly, you probably are. By this point in the book you&#8217;re ready for a change of pace and chapter 18 (which concludes the section on cheating) comes at the perfect time. Ironically for me, I was hoping for something different than the high score cheat case study which plagues many online Flash games and are of special interest to me. It&#8217;s only after devouring the chapter on network attacks that made me want to see more in that category.</p>
<p>What was most surprising was how <em>game design</em> can adversely affect security. By tweaking design documents early in the process there are some issues that can simply be mitigated instead of turning into real dollar problems that affect the integrity of the game and potentially turn away paying customers. Perhaps the author would consider changing the subtitle to &#8220;A Security Handbook for Game Developers, Designers and Publishers&#8221;. That being said, I should also mention that although the book is targeted toward those in the industry there&#8217;s incredibly useful information in this book for gamers and parents as well.</p>
<p>Protecting Games is an excellent security handbook albeit a slightly overwhelming one that deserves a place on the bookshelf of anyone involved in the process of creating games. It arms us with the knowledge we need to make the right choices while navigating through the process of not only an building an entertaining game but a secure one as well.</p>
<p><em>As a footnote, I was pleased to discover that Mr. Davis did not turn Protecting Games into a 398 page brochure for his SecurePlay products but kept a reasonably neutral perspective toward the topics covered.</em></p>
]]></content:encoded>
			<wfw:commentRss>http://philperon.com/2009/04/08/review-protecting-games/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>New Game Security Tome on the Horizon</title>
		<link>http://philperon.com/2008/12/03/new-game-security-tome-on-the-horizon/</link>
		<comments>http://philperon.com/2008/12/03/new-game-security-tome-on-the-horizon/#comments</comments>
		<pubDate>Wed, 03 Dec 2008 14:25:42 +0000</pubDate>
		<dc:creator>Phil</dc:creator>
				<category><![CDATA[game development]]></category>
		<category><![CDATA[security]]></category>
		<category><![CDATA[gamedev]]></category>

		<guid isPermaLink="false">http://philperon.com/?p=19</guid>
		<description><![CDATA[Steven Davis from PlayNoEvil just announced the completion of his new game security book, Protecting Games: A Security Handbook for Game Developers and Publishers available soon.
Congrats, Steven! Can&#8217;t wait to read it.
]]></description>
			<content:encoded><![CDATA[<p>Steven Davis from <a href="http://playnoevil.com/serendipity/">PlayNoEvil</a> just <a href="http://playnoevil.com/serendipity/index.php?/archives/2300-Good-News,-Bad-News-Protecting-Games-coming-out-Jan-20th,-416-pages!.html">announced </a>the completion of his new game security book, <a href="http://playnoevil.com/serendipity/exit.php?url_id=6428&amp;entry_id=2300">Protecting Games: A Security Handbook for Game Developers and Publishers</a> available soon.</p>
<p>Congrats, Steven! Can&#8217;t wait to read it.</p>
]]></content:encoded>
			<wfw:commentRss>http://philperon.com/2008/12/03/new-game-security-tome-on-the-horizon/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>State Machines in ActionScript</title>
		<link>http://philperon.com/2008/12/03/state-machines-in-actionscript/</link>
		<comments>http://philperon.com/2008/12/03/state-machines-in-actionscript/#comments</comments>
		<pubDate>Wed, 03 Dec 2008 12:53:18 +0000</pubDate>
		<dc:creator>Phil</dc:creator>
				<category><![CDATA[actionscript]]></category>
		<category><![CDATA[game development]]></category>
		<category><![CDATA[gamedev]]></category>

		<guid isPermaLink="false">http://philperon.com/?p=18</guid>
		<description><![CDATA[I love simple solutions to complex things. Squize&#8217;s post over at Gaming Your Way on State Machines in ActionScript explains an issue game developers often face that is elegantly handled with function pointers.
It&#8217;s been months since my last post (and coincidentally changing jobs) but I&#8217;d recently dusted off a grid-less rendering engine for 2d games [...]]]></description>
			<content:encoded><![CDATA[<p>I love simple solutions to complex things. Squize&#8217;s post over at <a href="http://blog.gamingyourway.com" title="Gaming Your Way">Gaming Your Way</a> on <a href="http://blog.gamingyourway.com/PermaLink,guid,8c079942-1647-4393-a7fc-fab8d014e24b.aspx" title="State Machines in ActionScript">State Machines in ActionScript</a> explains an issue game developers often face that is elegantly handled with function pointers.</p>
<p>It&#8217;s been months since my last post (and coincidentally changing jobs) but I&#8217;d recently dusted off a grid-less rendering engine for 2d games and was slightly disgusted with it core. It&#8217;s really not <em>that</em> bad. It works but the main loop gets a wee-bit lengthy and burns up cycles evaluating items that could possible be out of context at any given moment.</p>
<p>Using function pointers to create a state machine wraps this up nicely. Cheers, Squize!</p>
]]></content:encoded>
			<wfw:commentRss>http://philperon.com/2008/12/03/state-machines-in-actionscript/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Flash is SO Next-Gen</title>
		<link>http://philperon.com/2008/02/26/flash-is-so-next-gen/</link>
		<comments>http://philperon.com/2008/02/26/flash-is-so-next-gen/#comments</comments>
		<pubDate>Tue, 26 Feb 2008 12:33:43 +0000</pubDate>
		<dc:creator>Phil</dc:creator>
				<category><![CDATA[flash]]></category>
		<category><![CDATA[game development]]></category>
		<category><![CDATA[gamedev]]></category>

		<guid isPermaLink="false">http://philperon.com/?p=13</guid>
		<description><![CDATA[Raph Koster (think, Ultima) was quoted at this year&#8217;s GDC:
&#8220;I actually think Flash is the next-gen console in a lot of ways,&#8221; said Koster. &#8220;It&#8217;s pointing the way to the future more-so than the current generations of hardware, precisely because it is well on its way to becoming completely ubiquitous.&#8221;
He just made an entire community [...]]]></description>
			<content:encoded><![CDATA[<p>Raph Koster (think, Ultima) was quoted at this year&#8217;s GDC:</p>
<p>&#8220;I actually think Flash is the next-gen console in a lot of ways,&#8221; said Koster. &#8220;It&#8217;s pointing the way to the future more-so than the current generations of hardware, precisely because it is well on its way to becoming completely ubiquitous.&#8221;</p>
<p>He just made an entire community of Flash game developers feel very warm and fuzzy.</p>
<p>Check out the rest of the article <a href="http://www.gamesindustry.biz/content_page.php?aid=33498">here</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://philperon.com/2008/02/26/flash-is-so-next-gen/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>ActionScript 3 SGS Client Template</title>
		<link>http://philperon.com/2008/02/15/actionscript-3-sgs-client-template/</link>
		<comments>http://philperon.com/2008/02/15/actionscript-3-sgs-client-template/#comments</comments>
		<pubDate>Fri, 15 Feb 2008 20:20:02 +0000</pubDate>
		<dc:creator>Phil</dc:creator>
				<category><![CDATA[actionscript]]></category>
		<category><![CDATA[game development]]></category>
		<category><![CDATA[gamedev]]></category>

		<guid isPermaLink="false">http://philperon.com/?p=12</guid>
		<description><![CDATA[I&#8217;ve been playing with SGS lately and must admit, I freaking love it.
It&#8217;s free, GPL&#8217;d, has excellent documentation and just plain works. On top of all that, there&#8217;s even a full-fledged ActionScript 3 Client API available!
While working through the tutorials I found myself writing more than one flash client and decided I&#8217;d be better off [...]]]></description>
			<content:encoded><![CDATA[<p>I&#8217;ve been playing with <a href="http://www.projectdarkstar.com/">SGS</a> lately and must admit, I freaking love it.</p>
<p>It&#8217;s free, GPL&#8217;d, has excellent documentation and just plain works. On top of all that, there&#8217;s even a full-fledged <a href="https://darkstar-as-client.dev.java.net/">ActionScript 3 Client API</a> available!</p>
<p>While working through the tutorials I found myself writing more than one flash client and decided I&#8217;d be better off distilling them down to a single template. I think it&#8217;s a decent starting point for those &#8220;Hello World&#8221; demos and could potentially become the base for a full-blown, multi-user client application.</p>
<p>You can download the files, <a href="/files/as3_sgs_client_template.zip">here</a>.</p>
<p><em>Please let me know if you&#8217;re working on a Flash client for an SGS application. I&#8217;d love to hear about it!</em></p>
]]></content:encoded>
			<wfw:commentRss>http://philperon.com/2008/02/15/actionscript-3-sgs-client-template/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>MMO Money</title>
		<link>http://philperon.com/2008/02/15/mmo-money/</link>
		<comments>http://philperon.com/2008/02/15/mmo-money/#comments</comments>
		<pubDate>Fri, 15 Feb 2008 18:36:34 +0000</pubDate>
		<dc:creator>Phil</dc:creator>
				<category><![CDATA[mmo]]></category>
		<category><![CDATA[gamedev]]></category>

		<guid isPermaLink="false">http://philperon.com/?p=11</guid>
		<description><![CDATA[PlayNoEvil has a great post on how to make money running an MMO. Seven steps, easy to read and to the point. Right on.
Step 1 reflects a discussion my friend and I had recently on how Blizzard never planned on creating the behemoth that is WoW.
I highly recommend checking it out and the link to [...]]]></description>
			<content:encoded><![CDATA[<p>PlayNoEvil has a great <a href="http://playnoevil.com/serendipity/index.php?/archives/1907-How-to-Make-Money-running-an-MMO-Part-I.html">post</a> on how to make money running an MMO. Seven steps, easy to read and to the point. Right on.</p>
<p>Step 1 reflects a discussion my friend and I had recently on how Blizzard never <em>planned</em> on creating the behemoth that is WoW.</p>
<p>I highly recommend checking it out and the link to <a href="http://www.mmogchart.com/">MMOGCHART</a> is definitely worth bookmarking.</p>
]]></content:encoded>
			<wfw:commentRss>http://philperon.com/2008/02/15/mmo-money/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
