Wednesday, March 30, 2011

Pausing a Flash game or movie detecting its focus

Pausing a Flash game or movie detecting its focus:

Sometimes we want our Flash game or movie to stop when the user is not playing/watching it.

It’s a feature blog readers ask me frequently, because once they read the post, often they need to reload the page to enjoy the demostrative Flash movie as it was already running before readers could see it.

Also, this is what happens to our Flash movies when they are switched from visible to invisible, according to Tinic Uro, Adobe engineer:

When SWF is visible:

  • SWF frame rates are limited and aligned to jiffies, i.e. 60 frames a second. (Note that Flash Playe 10.1 Beta 3 still has an upper limit of 120 which will be changed before the final release)
  • timers (AS2 Interval and AS3 Timers) are limited and aligned to jiffies.
  • local connections are limited and aligned to jiffies. That means a full round trip from one SWF to another will take at least 33 milliseconds. Some reports we get say it can be up to 40ms.
  • video is NOT aligned to jiffies and can play at any frame rate. This increases video playback fidelity.

When SWF is invisible:

  • SWF frame rate is clocked down to 2 frames/sec. No rendering occurs unless the SWF becomes visible again.
  • timers (AS2 Interval and AS3 Timers) are clocked down to 2 a second.
  • local connections are clocked down to 2 a second.
  • video is decoded (not rendered or displayed) using idle CPU time only.
  • For backwards compatibility reasons we override the 2 frames/sec frame rate to 8 frames/sec when audio is playing.

For all these reasons, it’s necessary to pause the Flash game or movie when the SWF itself is not focused.

AS3 provides us flash.events.Event.ACTIVATE which is dispatched when Flash Player or an AIR application gains operating system focus and becomes active,and flash.events.Event.DEACTIVATE dispatched when Flash Player or an AIR application loses operating system focus and is becoming inactive.

Using these two listeners, we can quickly create a simple movie with a circle moving from left to right and a pause screen to be added once the game needs to be paused.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
package {
 import flash.display.Sprite;
 import flash.events.Event;
 public class Main extends Sprite {
  private var circle:circleMc;// a simple circle we will move around
  private var pausedMovie:pausedMc;// the pause DisplayObject
  public function Main() {
   pausedMovie=new pausedMc();
   addChild(pausedMovie);
   circle=new circleMc();
   circle.y=100;
   circle.x=-50;
   addChild(circle);
   addEventListener(Event.ACTIVATE,onActivate);
   addEventListener(Event.DEACTIVATE,onDeactivate);
  }
  private function onActivate(e:Event):void {
   addEventListener(Event.ENTER_FRAME,onEnterFrm);
   removeChild(pausedMovie);
  }
  private function onDeactivate(e:Event):void {
   removeEventListener(Event.ENTER_FRAME,onEnterFrm);
   addChild(pausedMovie);
  }
  private function onEnterFrm(e:Event):void {
   circle.x++;
   if (circle.x>690) {
    circle.x=-50;
   }
  }
 }
}

It’s a very basic script, but it works as we expect:

Click on the movie to gain focus, and outside the movie to lose the focus, and see what happens.

Download the source code.

No comments:

Post a Comment