Games Achievements My Kong Sign In

Multi-Screen Development: Best Practices

Recommendations for creating online gaming content for Flash Player 10.1

Compiled by Allen Ellison at Adobe (This document is a work in progress and is subject to change at any time)

High-Level Game Design Back to topics

Display Recommendations

Design for different screen sizes, screen orientations and display modes

  • Smart Phones
  • Web Tablets
  • Desktop

Observe minimum button sizes

Button sizes should be no smaller than .275 inches – which you should translate into pixels based on the devices DPI (pixel density).

The iPhone has a pixel density of 160, so .275 * 160 = 44 pixels

Whereas the Nexus One and the Motorola Droid have a pixel density of 240, so .275 * 240 = 66 pixels

Orientation Risks

You may or may not have control over whether or not the orientation of your content, relative to the device, changes – and you will only know about it after it has happened.

There are two viable solutions:

  • For landscape-biased content, put instructional graphics/text above and below the stage to instruct the user to rotate the phone to landscape orientation.

    For portrait-biased content, do the same to the left and right of the stage.

    If the scale is set to 'showall' (which it is by default), then the user should automatically see the instructions if the phone is oriented incorrectly.

  • Listen for an orientation event. If the content is re-oriented, then compensate by re-orienting and re-positioning your content. This won't work with all legacy content and the best way to accomplish this is to make sure that all of the game play elements exist within a 'shell' movie clip – that they’re not all top-level AS3 citizens. While in effect, this will counteract the browser-imposed re-orientation, it is not without its costs.

There are two fundamentally different display/interaction modes for Flash on mobile devices:

  • Embedded – content is likely to be more exposed to the potential for gesture ambiguity, D-PAD and trackball issues, as well as orientation and content sizing issues. This is the default display mode for Flash in the browser. Even if the user zooms into the Flash content, they will most likely be able to see some HTML content in the periphery.

  • Full Screen – similar to the same mode on the desktop, the user must initiate full-screen mode (by tapping a button within your movie). Flash will go full-screen, inform the user of the same (and some hint how to escape it (by hitting the back button) – but with the caveat that you basically can’t use the device’s keyboard (neither the physical keyboard nor its virtual one). In this display mode, only Flash content is displayed.

The user may inadvertently exit full-screen mode. Since game-play may become increasingly unpleasant in embedded mode, you might consider pausing the game.

  • My recommendation is that you present the game initially in the HTML context (you have relatively little choice here, as you can not automatically go into full-screen mode). This is a great opportunity for ad placement.
  • Once the user advances past the splash page (or alternatively, past the game instructions), you can, on a button click, go to full screen mode (assuming that AllowFullScreen="true" in the OBJECT/EMBED tag.
  • You can also make the content go full-screen automatically the first time the user attempts to interact with the content by setting the fullscreenOnSelection="true".

Taking into account the types of input devices that are available, and what's not available that you might be taking for granted.

  • Mobile devices typically don’t have a cursor and don’t natively support the concept of hovering, therefore any games that rely on a button’s “over” state, that use traditional hinting, or otherwise rely upon any type of “hover” functionality will need to be re-thought.
  • Keyboard: maybe
  • Cursor keys: maybe
  • Hold-to-repeat: maybe
  • Simultaneous keys: probably not
  • Accelerometer: only if mobile
  • Geo-location: not in the browser
  • Feedback options (haptic,lights,auditory,visual, cursor) – (haptic & lights probably not)
  • Screen - yes
  • Audio - yes
  • Haptic feedback – not available in the short-term window
  • Dedicated light indicators – probably not

Avoid Key.isDown() calls

Rendering Performance Back to topics

  • Hardware rendering automatically enabled if the device supports it without requiring gpu parameter. However specifying wmode=opaque or transparent will disable hardware rendering
  • Pixel Bender won't work if hardware rendering is not present
  • Use standard and alpha blend modes -- but avoid others, particularly layer
  • Avoid morphing shapes as these have to be re-tesselated on each frame (expensive)
  • Complex or finely articulated shapes are more expensive to render than large simple shapes
  • Avoid large changes in scale
  • Avoid over-drawing (when relying on hardware acceleration) although it's fine when rendering using software
  • Set background color of stage instead of putting a large rectangle in the background
  • Avoid default bitmap fill mode
  • Simplify vector graphics
  • Use CacheAsBitmap for content that doesn't change frequently
  • Avoid filters
  • Carefully picking bitmap sizes if content will need to be sized down&hellip
  • …but ideally, the content would always be 'right-sized'
  • Turn smoothing on if reducing image scale

Data Structure Management Back to topics

Old School Polygonal Data Structures (available as source)

Data Types

  • Array2
  • Array3
  • ArrayConvert
  • ArrayedQueue
  • ArrayedStack
  • BST
  • BinaryTreeNode
  • BitVector
  • Bits
  • Cloneable
  • Collection
  • Comparable
  • Compare
  • DLL
  • DLLNode
  • Graph
  • GraphArc
  • GraphNode
  • HashMap
  • Heap
  • Itr
  • LinkedStack
  • Prioritizable
  • PriorityQueue
  • SLL
  • SLLNode
  • Set
  • TreeBuilder
  • TreeNode
  • Vector
  • Visitable
  • BitMemory
  • ByteMemory
  • DoubleMemory
  • FloatMemory
  • IntMemory
  • MemoryAccess
  • MemoryArea
  • MemoryManager
  • ByteMemoryAccess
  • DoubleMemoryAccess
  • IntMemoryAccess
  • OutOfMemory
  • SegmentationFault
  • Factory
  • LinkedObjectPool
  • ObjectPool

Consider using polygonal labs data structures --highly optimized

Newer Highly-optimized polygonal data structures (only available as a SWC): http://code.google.com/p/polygonal/

Object Pooling: refer to http://lab.polygonal.de/2008/06/18/using-object-pools/

Game Logic, Event Notifications & Sequence Management Back to topics

There are two common performance sinkholes in Flash content:

  • onEnterFrame event listeners – it is not uncommon for there to be a lot of un-necessary processing that happens on each frame, which can quickly become very CPU expensive.
  • Timers – timers are also frequently abused. Try to keep the number of Timer objects to a minimum, be preferential to using them in objects that are likely to be around for a while (for example, shy away from creating a Timer class for each game avatar, as tempting as it might be). Challenge yourself to see if you can accomplish everything you need with a single Timer class instantiation.

Recommendations

  • Implement a Timer manager class
  • Single Timer instance
  • Multiple Timer subscriptions -- but guaranteed to fall on even boundaries.
  • Timer resolution is configurable
  • Organize timers in groups so that they can be suspended/resumed/destroyed as a group.
  • Consider replacing object-based event listeners with iteration loops.
  • Avoid using many timers
  • onEnterFrame vs. Timer
  • Dynamically throttling the frame rate
  • When animating multiple objects simultaneously, perform the delta operation as a single pass

    For example: in a re-make of the Asteroids game, you could create the ship and four big asteroids (n=5) -- placing a Timer object on each game object. When each Timer emitted a tick you could update the position of its parent. However, that results in [n] separate rendering events. It would be more efficient to make a single rendering pass in order of dependencies (if dependencies exist) updating all of the object positions and triggering just a single display refresh. This should result in a higher effective frame rate.

  • Consider using an open source Tween library, such as TweenLite or TweenMax
  • Use event notifications to react to keyboard events, don’t create loops that check to see if a certain key is pressed or not.

General Recommendations Back to topics

There are two common performance sinkholes in Flash content:

  • Perform and cache expensive/common calculations in advance -- for example, if a game's ship can exist in 8 different compass orientations and computational factors like gravitation, friction, etc. are static -- then you can create a single look-up table with 8 entries that contain a single integer/float that might be the result of a longer calculation:
    acceleration_factor = (Math.floor(Math.sin(angle)*grav_acceleration*object-mass*friction))
  • Hide objects by removing child
  • Use small display list
  • Replace static game elements that don't need to animate with a pre-rendered bitmap graphic
  • Use drawing API instead of Sprite
  • No significant penalty for MouseMove handlers that do nothing

Coding Recommendations Back to topics

Remember that the best practices for developing a game are not always going to agree with, and in fact will sometimes be in contradiction to best practices for other types of applications.

There is a natural tension that exists between some of the recommendations in this section that seek to optimize run-time efficiency and other, equally valid forms of efficiency, such as the amount of time it takes to write, troubleshoot, and maintain the code. Well-accepted OOP practices such as black-boxing functionality may have long-lasting payoff, but there is a small yet noticeable performance tax that results.

However, one best practice is always recommended, regardless – and that’s to use strict (or strongly-typed) AS3 in your projects. Not only does it make troubleshooting easier but because of the way Flash’s virtual engine works, strict AS3 code actually runs more efficiently than its counterpart AS2 or loosely-typed AS3.

Referencing

  • Eliminate weak references: e.g. asteroid["velocity"] should be asteroid.velocity;
  • Coerce untyped data (such as configuration data from an XML file) into the anticipated datatype before attempting to access
  • If using a data element more than a couple of times, use a local variable to bypass the cost of a lookup
  • Replace explicit or implicit Object datatype instantiations such as asteroid = {x:x_pos,y:y_pos}; with a more explicit class definition: asteroid = new Asteroid(x_pos,y_pos,asteroid_type)

Arrays

  • Use ByteArray instead of Array for byte/short/int values
  • If you store value objects in an array, coerce them back into the original value object class before attempting to access any of its members, for example, replace x_pos:int = asteroids[i].x; with x_pos:int = Asteroid(asteroids[i]).x;
  • Better yet, if all of the elements in an Array are the same data type or same class, then use the Vector class

Comparisons

  • Use bytes and bit operators to manage game object boolean states (canBeDestroyed, absorbsShot, activelyFiring, isCloaked, etc.)
  • Use hard-coded constants in lieu of the 'const' data type: while it decreases the readability/maintainability of the code, it is also more efficient.
    public var type:uint =3; instead of public const FORCEFIELD_TYPE:String="standardForceField"; as the latter form results in a string comparison (comparatively expensive)
  • Replace if (n % x == 0) with if (n & (x-1) == 0)
    note: not sure if this works with all possible values for x – might have to be multiples of 2?

Math

  • Use long-hand notations for functions such as Math.min(), Array.push(), Array.shift(), etc. to avoid the function call penalty:
    • replace var n=Math.abs(n) with if (n < 0) n = -n;
  • Use a++ (four times) or a+=4 in in lieu of a=a+4;
  • Use a=a-4 in lieu of a-- 4 times or a-=4;
  • Use multiply instead of division (b*.5 instead of b/2)
  • Shift left and shift right in cases where you need to multiple or divide by a power of 2
  • Coerce to uint instead of using Math.floor, and if appropriate int is even faster
  • Recast int calculations as Flash runtime will sometimes cause the outcome of calculations to become a Number.

    var x_pos:int;
    &hellip
    x_pos = x_pos * acceleration;

    should be

    var x_pos:int;
    &hellip
    x_pos = int(x_pos * acceleration);
  • Instead of

    y = Math.sin(Math.PI/180*i);

    use fast inline trigonometric functions

Iteration

  • Replace for loops with while loops. For example, instead of:

    for(var i:int=0;i<1000;i++) { data[i]=func(i);}

    do

    var i:int=0;
    while(i<1000) {
    data[i++] = func(i);
    }
  • Instead of

    var v1:Number=10;
    var v2:Number=20;
    var v3:Number=30;

    do

    var v1:Number=10, v2:Number=20, v3:Number=30;
  • Remember that removing a child from a display list (e.g. stage.removeChild(demon);) neither destroys the object nor does it stop the object from consuming resources. So adding and removing asteroid sprites that have an onEnterFrame listener or use a Timer() object may continue to consume resources until the timers are stopped/destroyed and you remove the EnterFrame listeners that may have been created, even if all explicit references to the object have been lost.
  • Replace anonymous function closures with method closures. That is, replace

    var f:Function = new function(event:Event) {trace("handler");}

    with

    function f(event:Event):void {
    trace("handler");
    }
  • haXe is a potential solution to the inherent conflict between performance and maintainability of a game: http://haxe.org/doc

HTML Considerations Back to topics

HTML game wrapper
  • Detect the device & flash player version – (refer to associated lobby template .html and associated .js files)
  • Deliver the appropriate swf if more than one SWF is available
  • Enable full-screen behavior by setting allowFullScreen="true"
  • Enable full-screen behavior automatically on first use interaction with content by setting fullscreenOnSelection="true" (does nothing if the full-screen behavior wasn't enabled)
  • Embed/object width/height behavior might be different depending on whether it's determined that it needs custom scaling behavior
  • Using mobile-specific meta tags (viewport)
  • Use JavaScript hook to detect re-orientation and full screen mode

At a minimum, your HTML files should contain:

  • Standard XML tag

    <?xml version="1.0" encoding="UTF-8"?>
  • Android-friendly mobile-specific mimetype declaration

    <!DOCTYPE html PUBLIC "-//WAPFORUM//DTD XHTML Mobile 1.0//EN" 
      "http://www.wapforum.org/DTD/xhtml-mobile10.dtd">
      <html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en">
        <head>
  • Android-friendly mobile-specific content type declaration

        <meta http-equiv="Content-Type"
        content="application/vnd.wap.xhtml+xml; charset=utf-8" />
  • What I've been using — not all of which is parsed by Android but by other phone platforms. However, notice the user-scalable attribute, which is understood by Android.

        <meta name="viewport" content="target-densitydpi=device-dpi,
          width=device-width, initial-scale=1.0,
          minimum-scale=1.0, maximum-scale=1.0, user-scalable=no"/>
  • This makes my life simpler in development (but obviously something to yank before going to production)

        <meta http-equiv="CACHE-CONTROL" content="NO-CACHE">
      </head>
      <body>
      </body>
    </html>
  • An example generic game wrapper:

    <object classid="clsid:d27cdb6e-ae6d-11cf-96b8-444553540000"
      codebase="http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=9,0,0,0"
      width="100%" height="100%"
      id="cheerleader480x854" align="middle" scale="noscale" salign="">
        <param name="allowScriptAccess" value="sameDomain" />
        <param name="allowFullScreen" value="true" />
        <param name="fullscreenOnSelection" value="true"/>
        <param name="movie" value="cheerleader480x854.swf" />
        <param name="quality" value="high" />
        <param name="bgcolor" value="#ffffff" />

        <embed src="cheerleader480x854.swf" quality="high"
        bgcolor="#ffffff" width="100%" height="100%"
        name="cheerleader480x854" align="middle"
        allowScriptAccess="sameDomain" allowFullScreen="true"
        fullscreenOnSelection="true" type="application/x-shockwave-flash"
        pluginspage="http://www.macromedia.com/go/getflashplayer" />
    </object>

Gaming Revenue Back to topics

How do you make money?
  1. Advertisements
    • Lobby Ads
    • Splash page banner ads
    • Pre-roll, mid-rolls and post-rolls
    • In-Game Marketing
    • Choosing between embedded game vs. full-screen
    • Ad Options when transforming a Flash game into an Android application
      • Banners
      • Interstitial ads
      • Overlays
      • Picture-in-a-picture
      • Pre-roll, mid-roll, post-roll
  2. App Purchase (AIR primarily)
  3. Micro-Transactions

Tips & Tricks Back to topics

Tip: When applying a blur filter with ActionScript, using values for blurX and blurY which are powers of two (such as 2, 4, 8, 16, and 32) can be computed faster and offer the benefit of a 20–30% performance improvement.

Once trick I learned while making some flash games is that a higher framerate on the fla file does not translate into smoother gameplay. In fact, you want the framerate as low as possible so that the main loop has adequate time to compute. I found a solid 18 fps actually looks better visually than an inconsistent 24-30 fps.

Following is from:
http://www.bigspaceship.com/blog/labs/flash-performance-tips-part-i/

Masks Are Bad
Well, they're not all bad. Masks can be exceptionally useful, as we all know by now. They're the #1 performance killer though. When you mask something, you force the player to decide what needs to be rendered and hidden every single frame. So how do you get around without masks? With a little bit of patience and tricky layering (such as making the background the foreground with a giant hole cut out for where your viewable area is) you'll be able to get the same end result without the performance hit.

Alpha PNGs and Video
Same deal as the masks. Sometimes it's unavoidable, but you're still asking the player to figure out what to render under the alpha. Sometimes we'll make an alpha video at half size and then scale it in Flash. You'd be surprised how good it still looks.

Oh, and with regards to alpha video: Try experimenting with PNG sequences in place of the alpha video. Video usually performs a little better, but its always worth looking into.

Frame Rate
Despite all discussions otherwise, there is no magic framerate. We use 25 or 30 because (as far as I know) we like it best. At some point we tested and determined one was slightly better than the other, but generally speaking this is not going to be the primary cause of a site running slow. I wouldn't generally advise going higher than 30 though, just because you're asking the player to render an awful lot awfully fast…

cacheAsBitmap and BitmapData
Where possible use cacheAsBitmap to rasterize vector items. You'll force Flash to draw the symbol one time and then never again. On the flip side, if you're scaling or rotating a symbol NEVER set it to cacheAsBitmap. Then you force Flash to render AND recapture the raster every frame, making the process slower instead of faster.

With sites like the Da Vinci Code and Nike Air, we would take a dynamic screenshot of the section, draw it into an empty movieclip and then manipulate the screenshot to animate it out. This is far, far faster than animating many elements out, or animating over top of many elements. I highly recommend this practice.

_visible is better than _alpha
_alpha = 0 and _visible = false are totally different things. Alpha determines the opacity of a clip. Visible determines whether or not the clip should actually be rendered by the player. If you're setting something all the way invisible, use the _visible property.

onEnterFrame and setInterval
When you're through with these processes, clear them from memory with onEnterFrame = null; and clearInterval(myInterval); respectively. Leaving these around when you're not using them is like leaving the telephone off the hook when you're done with a call.

Pre-define your math Got a sine wave you're about to draw? Is it the same sine wave every time? Hard code the numbers into an array. By doing the math for Flash, you're saving some complex processes in advance. I even experiment with using a Tween that I nextFrame() thru to get all of the entries into an array before hand.

Advanced Mobile Gaming Considerations Back to topics

Game Persistence

The following questions are obviously true for AIR, but it’s interesting to think about whether or not the same issues apply to in—browser content.

"What these results show is that people want mobile games to be 'pick up and play', and use them to fill time, as opposed to committing a large amount of time to playing them. It is therefore important that game designers facilitate this method of game playing, and make it easy to pick up and play games. The main elements of this are:"

  • Fast start up time (from app load to actually playing)
  • low number of extraneous menus to navigate before playing
  • app resumes from where it left off
  • app shuts down quickly, but doesn’t lose progress

-- http://www.stevebromley.com/blog/2009/10/23/mobile-games-should-start-quickly-lets-get-down-to-business/

Developers Players Support YouTube TikTok X (Twitter) LinkedIn
Join the conversation Join Discord
Terms of Service Privacy Policy Code of Conduct
© 2025 Kongregate