16 Replies Latest reply: May 14, 2012 9:30 AM by sinious RSS

    Ipad slowdown

    AnthonyAdb

      I'm working on an image gallery touch scrolling Ipad app and It needs to be able to scroll through a very big quantity of full screen jpg (1024x768 and possibly double size for Ipad3).

      The scrolling works fine with Tweenlite, my problem is when I load and unload Movieclips containing the images, the screen freeze for ~1/2 sec cutting off the scrolling animation.

      I'm using CacheAsBitmap, addChild and removeChildAt for every load and unload so I understand they all take some cpu for memory allocation etc ...

       

      So my question is :

      How can I load and unload images but still keep a smooth scrolling animation ?

      Is there any way to load in the background ?

       

      Any help would be appreciated

      Thx

        • 1. Re: Ipad slowdown
          sinious Community Member

          You could use Stage3D for mobile in AIR3.2 with Starling and improve your performance a huge amount. It means learning a lot but it will be worth it. Plus just moving images like a gallery is a trivial task for Starling.

           

          Otherwise, prior to Stage3D in AIR 3.2, to really make it as smooth as possible you're going to have to opt for a blitting technique. In a nutshell, you have a single bitmapdata that you draw the images into. Sounds complex but the performance is very good. However this technique relies 100% on the CPU which is nowhere near as fast as using Stage3D and Starling with the GPU. So you can have a Vector of sprites containing the images in your gallery and as the user moves their finger you simply keep running the copyPixels() method to draw the images into the bitmapdata.

           

          Here's a blitting engine and a quick demo that you can try for this but blitting itself isn't too complex.

           

          The bottom line is the display list works great on computers but devices are absolutely not computers. They're a mere fraction of the speed of a modern computer. So while the gallery will work silky smooth using a computer, it can perform intolerably slow on devices. You need to use techniques that maximize performance rather than try to use the standard display list or (far worse) the timeline for animation.

           

          BTW cacheAsBitmap can hurt you because devices have very little memory. Not only do they have low memory but the amount your app is allowed to use is very small. I probably wouldn't cacheAsBitmap those images. On a desktop computer I absolutely would, but not on a device.

          • 2. Re: Ipad slowdown
            AnthonyAdb Community Member

            Thanks Sinious,

            Stage3d sounds really nice and I'll probably have a longer look at it after this small project but for now blitting sounds easier ^__^

            I've had a look at blitMask (btw I was using TweenLite for the sliding) and here is what I have so far :

             

            package

            {

                      import flash.display.MovieClip;

                      import flash.events.MouseEvent;

                      import flash.events.Event;

             

                      import com.greensock.*;

                      import com.greensock.easing.*;

             

                      import flash.display.Bitmap;

                      import flash.display.BitmapData;

             

                      public class Gallery extends MovieClip

                      {

                                var offsetX:Number;

                                var blitMask:BlitMask;

                                var slideAnchor:MovieClip;

                                var slideAnchorTargetX:Number = 0;

                                var imageArray:Array = new Array(Catalogue_D_00, Catalogue_D_01, Catalogue_D_02);

                                var imageCurrentIndex:int = 0;

                                var imageOffsetX : Number = 0;

                                var imageWidth:Number = 768;

                                var mousedownX:Number;

             

            ////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////

             

                                public function Gallery()

                                {

                                          loadImage();

                                }

             

            ////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////

             

                                function loadImage():void

                                {

                                          if(slideAnchor == null)

                                          {

                                                    slideAnchor = new MovieClip();// creating the slide anchor to attach all images to it

                                                    this.addChildAt(slideAnchor, 0);

                                          }

             

                                          for(var i=0; i<imageArray.length; i++){

                                                    var mc:MovieClip = new imageArray[i];

                                                    slideAnchor.addChild(mc);

                                                    mc.x = imageOffsetX;

                                                    imageOffsetX += imageWidth;

                                                    mc.addEventListener(MouseEvent.MOUSE_DOWN, mouseDownHandler);

                                          }

             

                                          blitMask = new BlitMask(slideAnchor, 0, 0, 768, 1024, true);

                                          blitMask.disableBitmapMode();

                                }

             

            ////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////

             

                                function mouseDownHandler(e:MouseEvent):void

                                {

                                          TweenLite.killTweensOf(slideAnchor);

                                          mousedownX = this.mouseX;

                                          offsetX = slideAnchor.x - this.mouseX;

                                          e.currentTarget.addEventListener(MouseEvent.MOUSE_MOVE, mouseDragHandler);

                                          e.currentTarget.addEventListener( MouseEvent.MOUSE_UP, mouseUpHandler);

                                }

             

            ////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////

             

                                function mouseDragHandler(e:MouseEvent):void

                                {

                                          slideAnchor.x = this.mouseX + offsetX;

                                }

             

            ////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////

             

                                function mouseUpHandler(e:MouseEvent):void

                                {

                                          e.currentTarget.removeEventListener(MouseEvent.MOUSE_MOVE, mouseDragHandler);

                                          e.currentTarget.removeEventListener( MouseEvent.MOUSE_UP, mouseUpHandler);

             

             

                                          // Images slide to the RIGHT

                                          if (this.mouseX > mousedownX && slideAnchorTargetX + imageWidth <= 0)

                                          {

                                                    slideAnchorTargetX +=  imageWidth;

                                                    imageCurrentIndex--;

                                          }

                                          // Images slide to the LEFT

                                          else if (this.mouseX < mousedownX && slideAnchorTargetX - imageWidth > -imageWidth * imageArray.length)

                                          {

                                                    slideAnchorTargetX -=  imageWidth;

                                                    imageCurrentIndex++;

                                          }

                                          TweenLite.to(slideAnchor, 0.5, {x:slideAnchorTargetX, onUpdate:blitMask.update, onComplete:blitMask.disableBitmapMode});

             

                                }

             

            ////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////

             

                      }// public class Gallery

             

            }// package

             

            I'm only loading 3x jpg 1024x768 images at the same time for this test but my Ipad1 is still very slow to run this and all motions are not smooth at all.

            did I miss something with the blitMask ?

            • 3. Re: Ipad slowdown
              sinious Community Member

              I'd make 2 recommendations. First, let me say I've never used greensock's blitmask. I do my own blitting just copyPixels()ing from images in memory onto my bitmapdata. It's a pretty straigth forward technique.

               

              For one, I find MOUSE_MOVE is a very sporadic and loud event. It fires off TONS of times and the firing is very erratic. What I do is start the MOUSE_DOWN. Once that handler fires I remember where my mouse is (stage position) and I just keep track of a single integer. I subtract from it if the user moves their finger left or add to it if they go right. I then use the integer to determine what pixels I need to copy and from what images (which are loaded in memory in a vector). To keep the app feeling a bit more responsive I use Event.ENTER_FRAME and sample the position rather than MOUSE_MOVE. I find it's a lot smoother.

               

              Second, often a persons finger can go off the object it started on. You should consider listening for MOUSE_UP on the stage itself so you guarantee your success at capturing that event. Otherwise you might get some odd behavior if the MOUSE_MOVE event is allowed to continuously fire like crazy.

               

              You'll have to experiment with disableBitmapMode(), I'm not sure what will run better.

               

              Just remember to do as little as humanly possible in whatever event handler handles moving your tween. If you have to crunch a lot of math you'll kill your frameRate.

              • 4. Re: Ipad slowdown
                fljot Community Member

                Two key things could help you in this situation:

                 

                1. For image Loaders set LoaderContext#imageDecodingPolicy to ImageDecodingPolicy.ON_LOAD

                2. Reduce potention GC calls by keeping and reusing objects when possible

                • 5. Re: Ipad slowdown
                  AnthonyAdb Community Member

                  @sinious

                   

                  I've totally taken out all events for testing and made the movieclip ping pong tween from side to side, the result is still the same, very very choppy animation.

                  I've tested it with and without BitmapMode, same result.

                   

                  I've taken a look at some blitting tutorials, this seems to be used mainly for displaying a small part of a larger image.

                  In my case I've well over 50+ jpg that need to be placed side by side and have their own buttons so I'm not really sure how to apply this method.

                  Would you have any specific tutorial or doc I could look at ?

                   

                  @fljot

                   

                  I'm not using any loaders, my images are in my library, I've placed each of them in a separate MovieClip saved in the library and setup to "Export as ActionScript" + "Export on frame 1"

                  For this test I'm only adding 3x images placed in movieclip, I did that to have buttons placed over the image.

                  I import them in the stage by calling their class:

                       var mc:MovieClip = new imageArray[i];

                       slideAnchor.addChild(mc);

                   

                  Should I be loading those images with a Loader instead, will that improve the performance ?

                  • 6. Re: Ipad slowdown
                    fljot Community Member

                    Should I be loading those images with a Loader instead, will that improve the performance ?

                    No, I thought you load them in runtime. Strange though in general. I wrote an app several monthes ago with the functionality quite similar to MinimalFolio (scrolling is done via scrollRect) — was running smoothly with AIR 3 on the first iPad (it was more then 3 images). So you're doing something wrong =) Check your app descriptor (gpu/cpu) and packaging target mode.

                    • 7. Re: Ipad slowdown
                      AnthonyAdb Community Member

                      I'm using CS5 (not CS5.5), my document is setup to 1024x768 with 60fps, and here are the publishing settings

                      PublishingSettings_01.jpg

                      • 8. Re: Ipad slowdown
                        fljot Community Member

                        Of course that deployment type is the quickest to publish but the slowest to run.

                        http://help.adobe.com/en_US/air/build/WS901d38e593cd1bac1e63e3d128cdca935b-8000.html

                        • 9. Re: Ipad slowdown
                          sinious Community Member

                          Oh geez, you're using CS5? You don't know what you're missing in CS5.5..

                           

                          I would honestly say Flash Builder is the best path forward if you REALLY want performance but being you're probably unwilling to learn a whole new paradigm then download the trial version of CS5.5 and output your project using AIR for iOS. The output proceedure is just about the same as CS5 so there won't be any learning curve. However. The performance will be MUCH better.

                           

                          Also if you take Flash CS5.5 and overlay AIR3.2 (latest version) you will also see a noticable performance bump on that.

                           

                          Here is AIR 3.2 SDK:

                          http://www.adobe.com/devnet/air/air-sdk-download.html

                           

                          Here are instructions to overlay it on Flash CS5.5:

                          http://helpx.adobe.com/x-productkb/multi/overlay-air-sdk-flash-professional.html

                           

                          I know it's a lot of work just to test something but I never made anything in Flash CS5 that didn't immediately make me upgrade. You'll be amazed at the performance difference using the same code.

                           

                          Note: I'm only suggesting using the trials. Be warned that the CS6 suite is probably pretty close to being released. It'd be worth waiting for CS5 rather than buying CS5.5 right now. It's pegged for Juneish.

                          • 10. Re: Ipad slowdown
                            AnthonyAdb Community Member

                            I just found this : http://store.adobe.com/store/en_us/popup/offer/cs55_cs6.html

                            I'll check with my local reseller

                             

                            so CS5.5 + ADT package command should give me the smooth scroll I'm looking for ?

                            I'll have a look at those command lines today and see how it goes

                            thx

                            • 11. Re: Ipad slowdown
                              sinious Community Member

                              Perfect! Grab the CS5.5 trial and test your product but be sure to overlay AIR3.2 before you do it. Follow the instructions I linked you to. CS5 is only capable of producing iOS apps and it does not embed the AIR runtime. Now you'll be running the latest version of AIR runtime which itself should give you a noticable boost. It also opens up the latest AIR framework and AIR for Android and Blackberry as well which CS5 didn't have when I used it.

                               

                              Downloading a trial costs you nothing. If it works, buy it. At least you know CS6 will be free for you. Good link on that offer, I wondered where that cutoff was.

                               

                              Note: If you have Master Suite you obviously get Flash Pro, Flash Catalyst and Flash Builder all together. If you REALLY want the best performance with the best debugger (with profiling) with serious ease of use (eventually) in Spark/Flex, Flash Builder is what you want.

                              • 12. Re: Ipad slowdown
                                AnthonyAdb Community Member

                                I finally got my CS5.5 last week and tested the same AS3 code using AIR3.2 and adt, the result is pretty decent on IPad 1 and 3, MUCH better than with CS5 which was very laggy, but not ultra smooth :-P

                                Would it achievable to get the same scrolling smoothness as the original Ipad photo app or is that impossible ?

                                 

                                here is the adt command I used :

                                adt.bat -package -target ipa-ad-hoc -storetype pkcs12 -keystore C:\OpenSSL-Win32\bin\ios_development.p12 -provisioning-profile C:\OpenSSL-Win32\bin\development.mobileprovision Catalogue.ipa CatalogueIpad-app.xml CatalogueIpad.swf

                                 

                                I should be receiving CS6 soon since it's already out (?) so I will be running the same test code once I get the package.

                                • 13. Re: Ipad slowdown
                                  AnthonyAdb Community Member

                                  I finally got it to work ...

                                  I got rid of the blitMask and TweenLite and simply used an event listener with "enterFrame". I'm really not sure what was going on before but it's now scrolling very smoothly at 60fps

                                  Thanks for your help and patience guys

                                  • 14. Re: Ipad slowdown
                                    sinious Community Member

                                    Glad you got it to work! CS5 was simply the issue. You can use adt and AIR3.2 with CS5 but it's such a pain in the neck it's worth the money over wasted time to simply upgrade. And at the same time if you upgraded you get CS6 free. Even though CS6 is acting extremely poorly (as you can see people complaining all over) so I myself would avoid using it, even if you have it, until they fix some rampant issues.

                                     

                                    Aside that, manual blitting is how I'd handle your situation with a Vector continuously being loaded/unloaded with the next/prev photo and simply slide them in using ENTER_FRAME blitting. It seems like you're doing that now. And this is the easy way of doing things so glad you got that working! On iPad1 I find it to be 'tolerable' but on iPad2 and up it's very smooth.

                                     

                                    If you really want it silky smooth, you should consult using Stage3D. Blitting uses the CPU whereas Stage3D is all GPU. Use the Starling2D framework which you should find extremely simple and you can achieve near iOS native smoothness pretty easily.

                                     

                                    Download (has a github link there as well):

                                    http://gamua.com/starling/

                                     

                                    Basics tutorials on the wiki:

                                    http://wiki.starling-framework.org/tutorials/start

                                    • 15. Re: Ipad slowdown
                                      AnthonyAdb Community Member

                                      Do you mean adt is only useful with CS5 ? no need to use it with CS5.5 + ? I have to say I didn't see much of a difference using it with CS5.5, not sure whats the difference with the built in flash publishing to AIR 3.2

                                       

                                      I'm actually not using any blitting atm, my previous blitmask test didnt go so well , so I'll see how it goes with my 50+ images with dynamic loading/unloading and plan from there.

                                       

                                      I was about to install CS6 to have a try but now I'll just wait for some fix I guess ... I hope they can patch things soon

                                       

                                      This small catalogue I'm working on is very very simple so I'm hopping I can complete it using my limited knowledge of AS3

                                      I'm very tempted to try Stage3d / Starling2d I'll probably check out the video tutorial a bit later ... back to my dynamic loader test 1st !

                                      thx

                                      • 16. Re: Ipad slowdown
                                        sinious Community Member

                                        CS5.5 uses ADT to export for you so no, you don't need to use adt. Just use the publish menu. I 'read' that CS5 users can use adt to compile for them so I mentioned that. Only if you use native extensions will you need to use adt to compile with CS5.5. In CS6 I read they support native extensions but with all the issues I see all over the forums I'm avoid that like a pothole.

                                         

                                        Starling2D is a great framework and for your simple needs should be ideal. It will give your performance a considerable bump. Just note that they try to make it similar to using the display list, but Stage3D and GPU programming is a whole different world. You will need to learn how to use it. Only limited flash knowledge transfers.

                                         

                                        Do note Stage3D is below the display list in flash. Any content you add to flash's normal non-3d display list will appear over it. So if you have a background of any type you will need to put that background in Stage3D instead or you will cover it up completely and see nothing.

                                         

                                        The tutorials are good. Take a look