HOWTO: SharedObjects for Local Storage AS3

Using SharedObjects in Flash is very simple. Flash has SharedObjects that have been in the player since Flash6 when the introduction of Flash Communication Server which is now Flash Media Server which is releasing version 3 soon (also remote SharedObjects in Red5 is an open source RTMP media server that is based on Flash Media Server). So we can thank this release for SharedObjects, Camera objects, Audio, lots of the NetConnections, protocol enhancements and many other things. However to keep the tips simple we will just touch on the local usage and post a series of posts on these objects.

SharedObjects locally and remote have changed the way offline is thought about and are the backbone of many offline systems and prototypes. They have been influential in moving storage locally to remote in a lightweight AMF0 or AMF3 format.

SharedObject is in the flash.net namespace in AS3.

Here we show how to use the local version of a SharedObject to store data in the most simple form.

import flash.net.SharedObject;
var so:SharedObject = SharedObject.getLocal("userData");
so.data.username= "user1377";
so.data.pwdhash= "[hash] or pwd";
so.flush(); // writes changes to disk

You can see this is extremely simple to store data.Here we show how to use the local version of a SharedObject to retrieve data in the most simple form.

import flash.net.SharedObject;
var so:SharedObject = SharedObject.getLocal("userData");
var username:String = so.data.username;
var pwdhash:String = so.data.pwdhash;

That is it! In the most basic form SharedObjects are more simple than cookies and also are quite nice living outside the bounds of the cookies folder. If a user deletes all cookies it will not delete the SharedObjects. To delete SharedObjects you need to roght click on the Flash player, go to Settings and delete the objects there.You can store any type of data Flash supports from objects to numbers to strings in the SharedObject data.

import flash.net.SharedObject;
var so:SharedObject = SharedObject.getLocal("userData");
so.data.username= "user1377";
so.data.uid= new Number(1337);
var obj:Object = new Object();
obj.prop = "value";
so.data.userobj= obj;
so.flush(); // writes changes to disk

For large applications SharedObjects local are great because users can have their SharedObject space set to a high amount of space or unlmited for large offline type apps or more complex apps stored in a state object. It gets interesting when you pass this to the server in AMF or extremely compact AMF3 format to a remote stored object, via remoting, Shared Object events or any way you want to.We will be posting more on remote shared objects and some of the other tools such as Camera and Streams for AS3 over the coming weeks and deeper into the Sync Events for remote and local SOs.Sephiroth has a great Python tool to peer into the SOs on disk.

The first version of SharedObject Reader was written in python 2.2.
This new version is written in C# (C Sharp) as it’s now part of FlashDevelop editor.

Red5 also does this as well as many AMF kits.

Sync Events for SharedObject (as they change they launch a sync event)

Event object type: flash.events.SyncEvent
SyncEvent.type property = flash.events.SyncEvent.SYNC

Read more at adobe docs:

flash.net.SharedObject

Sample from AS3 docs showing usage

package {
    import flash.display.Sprite;
    import flash.events.MouseEvent;
    import flash.events.NetStatusEvent;
    import flash.net.SharedObject;
    import flash.net.SharedObjectFlushStatus;
    import flash.text.TextField;
    import flash.text.TextFieldAutoSize;
    import flash.text.TextFieldType;

    public class SharedObjectExample extends Sprite {

        private var mySo:SharedObject;

        public function SharedObjectExample() {
            buildUI();
            saveBtn.addEventListener(MouseEvent.CLICK, saveValue);
            clearBtn.addEventListener(MouseEvent.CLICK, clearValue);

            mySo = SharedObject.getLocal("application-name");
            output.appendText("SharedObject loaded...\n");
            output.appendText("loaded value: " + mySo.data.savedValue + "\n\n");
        }

         private function saveValue(event:MouseEvent):void {
            output.appendText("saving value...\n");
            mySo.data.savedValue = input.text;

            var flushStatus:String = null;
            try {
                flushStatus = mySo.flush(10000);
            } catch (error:Error) {
                output.appendText("Error...Could not write SharedObject to disk\n");
            }
            if (flushStatus != null) {
                switch (flushStatus) {
                    case SharedObjectFlushStatus.PENDING:
                        output.appendText("Requesting permission to save object...\n");
                        mySo.addEventListener(NetStatusEvent.NET_STATUS, onFlushStatus);
                        break;
                    case SharedObjectFlushStatus.FLUSHED:
                        output.appendText("Value flushed to disk.\n");
                        break;
                }
            }
            output.appendText("\n");
        }

        private function clearValue(event:MouseEvent):void {
            output.appendText("Cleared saved value...Reload SWF and the value should be \"undefined\".\n\n");
            delete mySo.data.savedValue;
        }

        private function onFlushStatus(event:NetStatusEvent):void {
            output.appendText("User closed permission dialog...\n");
            switch (event.info.code) {
                case "SharedObject.Flush.Success":
                    output.appendText("User granted permission -- value saved.\n");
                    break;
                case "SharedObject.Flush.Failed":
                    output.appendText("User denied permission -- value not saved.\n");
                    break;
            }
            output.appendText("\n");

            mySo.removeEventListener(NetStatusEvent.NET_STATUS, onFlushStatus);
        }

        // UI elements
        private var inputLbl:TextField;
        private var input:TextField;
        private var output:TextField;
        private var saveBtn:Sprite;
        private var clearBtn:Sprite;

        private function buildUI():void {
            // input label
            inputLbl = new TextField();
            addChild(inputLbl);
            inputLbl.x = 10;
            inputLbl.y = 10;
            inputLbl.text = "Value to save:";

            // input TextField
            input = new TextField();
            addChild(input);
            input.x = 80;
            input.y = 10;
            input.width = 100;
            input.height = 20;
            input.border = true;
            input.background = true;
            input.type = TextFieldType.INPUT;

            // output TextField
            output = new TextField();
            addChild(output);
            output.x = 10;
            output.y = 35;
            output.width = 250;
            output.height = 250;
            output.multiline = true;
            output.wordWrap = true;
            output.border = true;
            output.background = true;

            // Save button
            saveBtn = new Sprite();
            addChild(saveBtn);
            saveBtn.x = 190;
            saveBtn.y = 10;
            saveBtn.useHandCursor = true;
            saveBtn.graphics.lineStyle(1);
            saveBtn.graphics.beginFill(0xcccccc);
            saveBtn.graphics.drawRoundRect(0, 0, 30, 20, 5, 5);
            var saveLbl:TextField = new TextField();
            saveBtn.addChild(saveLbl);
            saveLbl.text = "Save";
            saveLbl.selectable = false;

            // Clear button
            clearBtn = new Sprite();
            addChild(clearBtn);
            clearBtn.x = 230;
            clearBtn.y = 10;
            clearBtn.useHandCursor = true;
            clearBtn.graphics.lineStyle(1);
            clearBtn.graphics.beginFill(0xcccccc);
            clearBtn.graphics.drawRoundRect(0, 0, 30, 20, 5, 5);
            var clearLbl:TextField = new TextField();
            clearBtn.addChild(clearLbl);
            clearLbl.text = "Clear";
            clearLbl.selectable = false;
        }
    }
}

3D Flash Perlin Noise Terrains with AS3 and Sandy

Rafajafar posted a great tutorial on 3D Flash Perlin Noise dynamic terrain generations with AS3 and Sandy.

Sandy is a flash 3d engine that has been out just a little longer than Papervision3D. The code for Sandy is very clear and it is a great engine. I have experimented with it and found it to be a bit slower it seems that papervision but it has great tools, including an extra 3ds file importer in addition to the Collada and ASE formats that most flash 3d engines support.

Using Perlin Noise is very common in 3d engines to draw large terrains and realistic terrains for 3d games or simulations. This technique makes it very easy to make dynamic terrains or randomly generated terrains, water effects, fire, clouds, whatever your need.

The demo has terrain generation class that can be used to build the dynamic terrain generation and the perlin noise material movement.

Samples using the TerrainCreator class to make different terrains. This could be used to also make level editors and other components of the game making pipeline in flash 3d.

//Water
ter = new TerrainCreator("MyTerrain", 1000000,
128, 9, 6000, 6000, 10,60,60, false,false, 15,
BitmapDataChannel.BLUE, false);

//Gentle Hills
ter = new TerrainCreator("MyTerrain", 10, 128, 9,
6000, 6000, 10,120,120, false,false, 15, 7, true);

//Smooth Hills
ter = new TerrainCreator("MyTerrain", 10, 128, 9,
6000, 6000, 10,120,120, true,true, 30, 7, true);

//Mountainous
ter = new TerrainCreator("MyTerrain", 30, 128, 3,
6000, 6000, 15,100,100, false,false, 10, 7, true);

Click here for the full tutorial and source files on 3D Flash Perlin Noise dynamic terrain generations with AS3 and Sandy.

Now if we could just fast forward 2-3 years on processor power and speed, or get hardware acceleration for Flash…

HOWTO: Using the ContextMenu in AS3 with FullScreen Mode As a Sample

Right clicking and other mouse support in flash is not really a shining star but in AS2/AS3 you *can* stuff the context menu with items. You can clear out all but Settings and About from the menu and stuff in other items that may pertain to a selected movieclip or the entire app you are building. This can be good when adding multiple functions into applications and for extra functions that you want to make available from a quick location such as full screen, selecting an item etc.

To enable a context menu for full screen capabilities take this example:

1) Make your document class of your AS3 Flash CS3 file to the class below.

package
{
import flash.display.*;
import flash.errors.*;
import flash.events.*;
import flash.filters.*;
import flash.geom.*;
import flash.net.*;
import flash.media.*;
import flash.ui.*;
import flash.utils.*;
import flash.xml.*;
public class FullScreenTest extends MovieClip
{
public function FullScreenTest()
{
// create the context menu, remove the built-in items,
// and add our custom items
var fullscreenCM:ContextMenu = new ContextMenu();
fullscreenCM.addEventListener(ContextMenuEvent.MENU_SELECT, onContextMenuHandler);
fullscreenCM.hideBuiltInItems();
var fs:ContextMenuItem = new ContextMenuItem("Show Full Screen" );
fs.addEventListener(ContextMenuEvent.MENU_ITEM_SELECT, onShowFullScreen);
fullscreenCM.customItems.push( fs );
var xfs:ContextMenuItem = new ContextMenuItem("Exit Full Screen");
xfs.addEventListener(ContextMenuEvent.MENU_ITEM_SELECT, onShowNormalScreen);
fullscreenCM.customItems.push( xfs );

// THIS ASSUMES YOU HAVE A MOVIECLIP IN THE LIBRARY
// THAT IS SET TO A CLASS NAMED 'mc' that inherits from MovieClip
var m:MovieClip = new mc();
m.contextMenu = fullscreenCM;
addChild(m);
}
// functions to enter and leave full screen mode
function onShowFullScreen(event:ContextMenuEvent):void
{
stage.displayState = StageDisplayState.FULL_SCREEN;
}
function onShowNormalScreen(event:ContextMenuEvent):void
{
stage.displayState = StageDisplayState.NORMAL;
}
// function to enable and disable the context menu items,
// based on what mode we are in.
function onContextMenuHandler(event:ContextMenuEvent):void
{
if (stage.displayState == StageDisplayState.NORMAL)
{
event.target.customItems[0].enabled = true; // show full screen button
event.target.customItems[1].enabled = false; // hide normal screen button
}
else
{
event.target.customItems[0].enabled = false; // hide full screen button
event.target.customItems[1].enabled = true; // shoe normal screen button
}
}
}
}

2) Now Export to HTML and be sure to change the exported parameters in the HTML file to allowFullScreen = true (for the fullscreen effect) and menu = true (for the ability to add in context menu items) to whatever library you use for embedding flash:

   'menu', 'true',
   'allowFullScreen', 'true'

OR if using HTML parameters

<param name="allowFullScreen" value="true" />
<param name="menu" value="true" />

You can view a sample here. (right click on the movie clip and ‘show full screen’, then ‘hide full screen’)

You can download a sample FlashCS3/AS3 version here.

If you want more information on fullscreen check here and here (downloadable sample and component).

HOWTO: Setup Orthographic Camera in Maya

We recently had a tutorial on making isometric assets for 3dsmax but this is the same tutorial for Maya. 

Orthographic cameras are again an isometric rendering that has no correct perspective, all edges are parallel, there is no vanishing point.  This is great for gaming or maps where you need the items at the bottom of the screen to be the same size as the items in the distance.

Many popular RTS or strategy games use this technique.  What it does is make it possible to create assets that can be exported and placed all over the game without the need to render at different distances.

Here’s the HOWTO to make Maya orthographic views for isometric gaming assets:

  1. Open your file in Maya (here is a great free one from turboquid.com). You will usually be in persp or perspective view.  If not go to Panels > Perspective > persp.
    Photo Sharing and Video Hosting at Photobucket
  2. Create a new camera by going to Create > Cameras > Create Camera and Aim (this creates a target camera rather than a free camera)
  3. Position the camera (not the camera aim) by using the move tool on the camera to get it at a 45 degree angle at the corner). Then make sure the camera aim is at the base of the object (if you places it at 0,0,0 then it should be all set).
  4. Select the Camera.
  5. Now go to Panels > Cameras > View through Selected
  6. You are now viewing through the camera. Photo Sharing and Video Hosting at Photobucket
  7. Usually you have to adjust it a bit here so get it so that the camera is pointed at the corner of the building with the move tools on the selected camera.  Since this is a camera with aim you only have to move the camera and not worry about rotation and aim.  I have my aim set to the bottom of the building.
  8. After you get the view right (you can manually set the angle at 45 degrees up and to the side or aim it manually) jump into the camera by selecting it with the list, Photo Sharing and Video Hosting at Photobucket then clicking Panels > View though Selected.
  9. To make it orthographic in the properties select the Orthographic panel, then check “Orthographic”.
    Photo Sharing and Video Hosting at Photobucket
  10. At this point it will proabably zoom in so you need to move the view by zooming in our out to make it fit. 
    Photo Sharing and Video Hosting at Photobucket
  11. Now your model is in orthographic or isometric view so you can export it out to your game. 
    Photo Sharing and Video Hosting at Photobucket
  12. The ideal solution is to create a maya scene and import all your buildings, cars, or other game assets in individually and then export them individually with the same light and direction/angle so you can piece it together in the game and take advantage of reuse and loading only areas being shown.Photo Sharing and Video Hosting at Photobucket

AS3 Random Number Generator

Polygonal Labs has an excellent random number generator.  There is an AS2 and AS3 version and it has much better random numbers tools such as seeds and ranges.

When developing games you often need a PRNG that, once initialized with a seed value, produces always the same sequence of random numbers after it. The Math.rand() function in Flash is a PRNG, but it doesn’t let you define a seed value (I think it’s picked randomly when the swf starts, but there isn’t much information about it) so another solution has to be found.

One of the best PRNGs is the Mersenne Twister algorithm, but in my opinion it’s total overkill for flash games (also slow and difficult to implement). However, after spending some time with google I found an interesting site explaining the implementation of the Park-Miller-Carta PRNG, which belongs to the group of Linear congruential generators (LCGs).

read more >>

Download & Usage

Park-Miller-Carta Pseudo-Random Number Generator:
AS2 Version
AS3 Version

First define a seed value (default is one) and then call nextInt() to get the next integer value, nextDouble() to get a floating point number between 0..1 and nextIntRange() or nextDoubleRange() to generate numbers within a certain range.

HOW TO: Setup an Orthographic Camera in 3dsMax9

{ draw logic } will be presenting HOWTOs every once in a while based on current projects or very simple, targeted actions in game development, programming, data design etc. 

Setup an Orthographic Camera in 3dsMax9

Axonometric Projection allows you to make flat Isometric game assets or views sometimes needed for maps layouts where false or flat 3D is used so you can see the items up close as well as you can see the items off in the distance. This view was common in the early sim citygames and many RPGs like Command and Conquer Red Alert (oh no not the blimps!). Photo Sharing and Video Hosting at Photobucket

Orthographic views are a camera setting that makes it so there is no vanishing point or correct perspective but instead parallel external lines. Sometimes this is key in scrolling 2d games or maps like I said but its also to help reuse assets over and over to create a better cache to pull from.  Orthographic viewscan also make flattening textures to be used in texturing in isometric games very simple.

To setup a camera in 3d Studio Max for orthographic renders follow these steps:

  1. Open up your file and get a perspective you want. Usually this is a diagonal 45 degree view or a 45 degree angle where 2/3 of one side shows and 1/3 of the other showsPhoto Sharing and Video Hosting at Photobucket
  2. Go to the perspective view and click in it. 
  3. Create a new camera by clicking CTRL+C. This will create a new ‘Camera01‘.
  4. Click C to jump into your new camera.
    Photo Sharing and Video Hosting at Photobucket
  5. As you can see this view has the perspective vanishing point and the lines on the outside of the model will eventually meet on the horizon.  For game assets this doesn’t always work when making an isometric or axonometric view.We want to make it an orthographic view so that there is a void of perspective and correct vanishing lines.
  6. To flatten this true perspective make sure the camera is still selected by clicking on the camera or by pressing ‘C’ (brings up all cameras as ‘P’ does the perspective view again) or selecting it from the object list.
  7.  Then under the modifiers tabs check the “Orthographic Projection” checkmark.Photo Sharing and Video Hosting at Photobucket 
  8. All done, now make a boatload more assets for your game/project!

See the difference in renders here:

True Perspective View:
Photo Sharing and Video Hosting at Photobucket

Orthographic View:
Photo Sharing and Video Hosting at Photobucket 

You can see that if the homes were to be stacked in rows where their walls are parallel (like the command and conquer screenshot above) the orthographic view is more suited for games or maps where you need to see all items the same size or scale. Click here to see a flash version of this that stretched full screen fluid flash.

Photo Sharing and Video Hosting at Photobucket

Here’s the MAX file source of the house. I used 3dsmax9 and built on a model I found online making it more cartoonish and simplistic/vector-like. For this tutorial some of the settings may be changed in your version but all 3d programs have this setting somewhere even if you are not using 3dsmax. 

Fluid Flash Layouts

Photo Sharing and Video Hosting at PhotobucketHere’s how to do Fluid Flash layouts quickly without Flex.

Fluid layouts are not new but fhard to come by documentation.

To create a Flash fluid layout, essentially what you do is create a Flash movie that is set to 100% in HTML/SWFObject/XHTML but scaling set to noScale. Then in the flash script you position each element as needed on a resize handler.

This works great for applications built in Flash that will need to scale such as an IDE, a word processor, an image editing programs or programs that might have floating panels and tools.

1) Make your flash movie HTML scaled to the browser:

If you are using deconcept’s excellent SWFObject (be sure to download it) then see this sample for the HTML embedding with js swfobject.

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">

<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">

<head>

<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />

<title>blipgames.com</title>

<script type="text/javascript" src="swfobject.js"></script>

<style type="text/css"> /* hide from ie on mac */

 html {

  height: 100%;

  overflow: hidden;

 }

#flashcontent {

  height: 100%;

 }

 /* end hide */

body {

  height: 100%;

  margin: 0;

  padding: 0;

}

</style>

</head>

<body>

 <div id="flashcontent">

  <strong>You need to upgrade your Flash Player</strong>

 </div>

<script type="text/javascript">

  // <![CDATA[

var so = new SWFObject("myMovie.swf", "myMovie", "100%", "100%", "8", "#efefef");

  so.addParam("scale", "noscale");

  so.write("flashcontent");

// ]]>

 </script>

</body>

</html>

2) Inside your flash code:

AS2

Stage.align = "TL"; // Top left align the stage

Stage.scaleMode = "noScale"; // Set noScale for containing stage.// CREATE A LISTENER OBJECTsizeListener = new Object();// ATTACH THE ON RESIZE EVENT TO THE LISTENERsizeListener.onResize = function()

{

// In the event call a method to move the items

// or, call each item here to be sized

movieToBeCentered._x = Stage.width/2;

movieToBeCentered._y = Stage.height/2;

movieToBeCentered._width = Stage.width * .5;

// add other movie clips to position...

};

// ADD THE LISTENER

Stage.addListener(sizeListener);

AS3

package

{

 import flash.display.*;

 import flash.events.*;

 import flash.utils.*;

public class AppMain extends MovieClip

 {

  public function AppMain()

  {

   stage.addEventListener(Event.RESIZE,onResize);

   stage.align = "TL"; // Top left align the stage

   stage.scaleMode = "noScale";  // items do not stretch to fit

  }
  public function onResize(event:Event)

  {

   // In the event call a method to move the items

   // or, call each item here to be sized

   movieToBeCentered.x = stage.width/2;

   movieToBeCentered.y = stage.height/2;

   movieToBeCentered.scaleX = stage.width * .5;

   // ... etc

  }

 }

}

This allows you to see easily how you can make a fluid layout in flash that scales with more of an alignment lock rather than the whole movie scaling.

A demo and toolkit will be available soon with an easy class library soon. For now you can go here to get a demo and source from the http://www.tutorio.com/tutorial/liquid-flash-layout site.