Search code examples
actionscript-3flashtimerloader

digital signage application (as3)


i'm trying to develop a digital signage application for the company i work for, with flash cs6. it is actually composed of two applications, one is server side, and other is installed on tv displays that have an integrated computer running windows xp. the server application is nothing but a form that an administrator uses to enter data that is stored in a mysql database through some php. that is working fine.

my problem is with the client that runs in the displays. the app is actually quite simple: there are "sections" of different sorts of information that it should load from the mysql tables, therefore loading text, image and videos that are all stored in the server. thing is the loaders run in parallel with timers. the timers are responsible for calling movieclips and frames, so that i don't need to animate everything in the timeline and the app keeps running from section to section in loop. and there is where i'm finding problems. i am not being able to find a proper way to program such loaders in a way that goes along well with the timers. so the final result is that images and videos are partially or never loaded, making the client app run in odd ways. here's an example of one of the sections of the app:

import flash.utils.Timer;
import flash.display.MovieClip;
import flash.events.Event;
import flash.events.TimerEvent;
import fl.transitions.*;
import fl.transitions.easing.*;


var randomNumber:Number = Math.random();
var xAnivItemRef:Number = 75;
var yAnivItemRef:Number = 140;
var anivArray:Array = new Array  ;
var endingTimer:Timer = new Timer(10000);
var loopTimer:Timer = new Timer(500);
var counter:uint = 0;
var fotosURL:String = "http://www.maxionline.com.br/maxi_sds/server/img/aniversariantes/";
var current_time = new Date();
var i:uint = 0;
var alphaTween:Tween;
var aniversariante_mc:MovieClip;
var numAniversariantes:uint;


endingTimer.addEventListener(TimerEvent.TIMER, leaveEvents);
loopTimer.addEventListener(TimerEvent.TIMER, loadAniv);


function setTitleMonth(event:Event = null)
{
          var month:String = current_time.getMonth();
          switch (month)
          {
                    case "0" :
                              anivTitle_mc.anivTitlePt2_mc.month_txt.text = "janeiro!";
                              break;


                    case "1" :
                              anivTitle_mc.anivTitlePt2_mc.month_txt.text = "fevereiro!";
                              break;


                    case "2" :
                              anivTitle_mc.anivTitlePt2_mc.month_txt.text = "março!";
                              break;


                    case "3" :
                              anivTitle_mc.anivTitlePt2_mc.month_txt.text = "abril!";
                              break;


                    case "4" :
                              anivTitle_mc.anivTitlePt2_mc.month_txt.text = "maio!";
                              break;


                    case "5" :
                              anivTitle_mc.anivTitlePt2_mc.month_txt.text = "junho!";
                              break;


                    case "6" :
                              anivTitle_mc.anivTitlePt2_mc.month_txt.text = "julho!";
                              break;


                    case "7" :
                              anivTitle_mc.anivTitlePt2_mc.month_txt.text = "agosto!";
                              break;


                    case "8" :
                              anivTitle_mc.anivTitlePt2_mc.month_txt.text = "setembro!";
                              break;


                    case "9" :
                              anivTitle_mc.anivTitlePt2_mc.month_txt.text = "outubro!";
                              break;


                    case "10" :
                              anivTitle_mc.anivTitlePt2_mc.month_txt.text = "novembro!";
                              break;


                    case "11" :
                              anivTitle_mc.anivTitlePt2_mc.month_txt.text = "dezembro!";
                              break;


                    default :
                              break;
          }
}


function anivSetup(event:Event = null):void
{
          var anivLoader:URLLoader = new URLLoader();
          anivLoader.dataFormat = URLLoaderDataFormat.TEXT;
          anivLoader.load(new URLRequest("http://www.maxionline.com.br/maxi_sds/client/dataRecoverAniv.php?_rand =" + randomNumber));
          anivLoader.addEventListener(Event.COMPLETE, getAnivData);
}


function getAnivData(evt:Event = null):void
{
          var anivDataStr:String = evt.target.data;
          var anivDataArray:Array = anivDataStr.split("&");
          var numItemsStr:String = anivDataArray[anivDataArray.length - 1].substr(5);
          var numItems:Number = Number(numItemsStr) * 4;
          numAniversariantes = numItems/4;
          anivDataArray.splice(anivDataArray.length - 1, 1);


          for (var i:uint=0; i<numItems; i++)
          {
                    anivArray.push(anivDataArray[i]);
          }
          loadAniv();
          anivMask_mc.gotoAndPlay("on");
          endingTimer.start();
          loopTimer.start();
}


function loadAniv(event:Event = null):void
{
          var aniversariante:anivItem_mc = new anivItem_mc();
          aniversariante.name = "aniversariante" + counter;

          if (numAniversariantes > 12)
          {
                    if (counter < 4)
                    {
                              aniversariante.y = yAnivItemRef + (220 * counter);
                              aniversariante.x = xAnivItemRef;
                    }
                    if (counter >= 4 && counter < 8)
                    {
                              aniversariante.y = yAnivItemRef + (220 * (counter - 4));
                              aniversariante.x = xAnivItemRef + 1355;
                    }
                    if (counter >= 8 && counter < 12)
                    {
                              aniversariante.y = yAnivItemRef + (220 * (counter - 8));
                              aniversariante.x = xAnivItemRef + 250;
                    }
                    if (counter >= 12 && counter < 16)
                    {
                              aniversariante.y = yAnivItemRef + (220 * (counter - 12));
                              aniversariante.x = xAnivItemRef + 895;
                    }
          }
          if (numAniversariantes > 8 && numAniversariantes <= 12)
          {
                    if (counter < 4)
                    {
                              aniversariante.y = yAnivItemRef + (220 * counter);
                              aniversariante.x = xAnivItemRef;
                    }
                    if (counter >= 4 && counter < 8)
                    {
                              aniversariante.y = yAnivItemRef + (220 * (counter - 4));
                              aniversariante.x = xAnivItemRef + 1355;
                    }
                    if (counter >= 8 && counter < 12)
                    {
                              aniversariante.y = yAnivItemRef + (220 * (counter - 8));
                              aniversariante.x = xAnivItemRef + 250;
                    }
          }
          if (numAniversariantes > 0 && numAniversariantes <= 8)
          {
                    if (counter < 4)
                    {
                              aniversariante.y = yAnivItemRef + (220 * counter);
                              aniversariante.x = xAnivItemRef + 200;
                    }
                    if (counter >= 4 && counter < 8)
                    {
                              aniversariante.y = yAnivItemRef + (220 * (counter - 4));
                              aniversariante.x = xAnivItemRef + 1150;
                    }
          }
          anivLoader_mc.addChild(aniversariante);
          aniversariante_mc = MovieClip(root).aniv_mc.anivLoader_mc.getChildByName("aniversariante" + counter);
          aniversariante_mc.anivName_txt.text = anivArray[i];
          aniversariante_mc.day_mc.anivDay_txt.text = anivArray[i + 1];


          var imgLoader:Loader = new Loader();
          imgLoader.load(new URLRequest(fotosURL + anivArray[i + 3]));
          imgLoader.contentLoaderInfo.addEventListener(ProgressEvent.PROGR ESS,imageLoading);
          imgLoader.contentLoaderInfo.addEventListener(Event.COMPLETE,imag eLoaded);


          var fadein:TransitionManager = new TransitionManager(aniversariante_mc);
          fadein.startTransition({type:Fade, direction:Transition.IN, duration:1, easing:Strong.easeOut});


          counter++;
          i = i + 4;


          if (i >= anivArray.length)
          {
                    loopTimer.stop();
                    loopTimer.removeEventListener(TimerEvent.TIMER, loadAniv);
          }
}


function leaveEvents(event:TimerEvent):void
{
          endingTimer.removeEventListener(TimerEvent.TIMER, leaveEvents);
          endingTimer.stop();
          anivMask_mc.gotoAndPlay("off");
          play();
}


function imageLoading(evt:ProgressEvent):void
{
          var loaded:Number = evt.bytesLoaded / evt.bytesTotal;
          updateProgress(loaded);
}


function updateProgress(vl:Number)
{
          aniversariante_mc.photo_mc.preloader_mc.loadingBar_mc.width = vl * aniversariante_mc.photo_mc.preloader_mc.loadingBar_mc.width;
}


function imageLoaded(event:Event):void
{
          var loadInfo:LoaderInfo = (event.target as LoaderInfo);
          aniversariante_mc.photo_mc.photoLoader_mc.addChild(loadInfo.cont ent);
}


anivSetup();
setTitleMonth();


stop();

the .fla can be downloaded here:

http://www.maxionline.com.br/maxi_sds/sds_client.fla

any advice would be greatly appreciated!


Solution

  • Stepping back and looking at the big picture ...

    I have built a digital signage type of application using Flash with content delivered from the server, currently starting its fourth year of updates. Some general thoughts in my opinion:

    1. Do not use the traditional Flash Timeline for the main flow of your program. Instead do everything programatically using Actionscript 3. This should eliminate some issues with things not displaying correctly but more importantly will allow greater scale-ability. This will also allow you greater control when plugging content in dynamically as well.

    2. Have a top level "Manager" class to manage the "Playlist" of content you will be looping. When content is done playing it should notify the "Manager" that is is done (or that it failed) so that the Manager can play the next content item right away. This will require adding Event Listeners and handlers where applicable, which in some cases may replace timers.

    3. Keep ALL your code in class files (ClassName.as) and organize them into folders (namespaces). Do not have ANY inline Actionscript that just sits on random keyframes. You can link library items to classes using the "Export to Actionscript" option.

    4. Keep your main class as small as possible, push as much code as possible out to separate class files.

    5. Most animations and tweens can be accomplished using packages from the TweenLite and TimelineMax family.

    6. Any animations like the one you have of the logo should be contained in its own MovieClip / Library Object / Class so you can easily plug it in anywhere. For your logo's animation you shouldn't have any problem using the traditional timeline to animate it if it is contained.

    7. Download all server content locally on the machine, then have Flash read it all locally. This should eliminate long waits for content, especially if the internet gets bogged down.

    8. Have a class for each content type (video, image slideshow, intro animation, etc...). This will allow you to plug in custom content.

    9. Use XML or JSON as much as possible.

    I hope that helps.