2

in order to increase performance of a scrollRect i must cache the vector as a bitmap, otherwise the scrollRect will be simply a less performant mask (info source).

however, i can't seem to move an object/scrollRect once i've applied cacheAsBitmap. why?

package
{
    //Imports
    import flash.display.Screen;
    import flash.display.Sprite;
    import flash.display.StageAlign;
    import flash.display.StageScaleMode;
    import flash.events.Event;
    import flash.events.MouseEvent;
    import flash.geom.Rectangle;

    //Class
    [SWF(width = "800", height = "500", backgroundColor = "0x444444")]
    public class ScrollRectTest extends Sprite
    {
        //Variables
        private var background:Sprite;
        private var ball:Sprite;
        private var newScrollRect:Rectangle;

        //Constructor
        public function ScrollRectTest()
        {
            stage.scaleMode = StageScaleMode.NO_SCALE;
            stage.align = StageAlign.TOP_LEFT;
            stage.frameRate = 60;

            init();
        }

        //Initialize
        private function init():void
        {
            background = new Sprite();
            background.graphics.beginFill(0x000000, 1.0);
            background.graphics.drawRect(0, 0, 200, 400);
            background.graphics.endFill();

            ball = new Sprite();
            ball.graphics.beginFill(0xFF0000, 1.0);
            ball.graphics.drawCircle(0, 0, 100);
            ball.graphics.endFill();
            //ball.cacheAsBitmap = true; //<-- uncomment this
            ball.scrollRect = new Rectangle(background.x, background.y, background.width, background.height);

            stage.addEventListener(MouseEvent.MOUSE_DOWN, mouseDownEventHandler);
            stage.addEventListener(MouseEvent.MOUSE_UP, mouseUpEventHandler);

            addChild(background);
            addChild(ball);
        }

        //Mouse Down Event Handler
        private function mouseDownEventHandler(evt:MouseEvent):void
        {   
            addEventListener(Event.ENTER_FRAME, enterFrameEventHandler);
        }

        //Mouse Up Event Handler
        private function mouseUpEventHandler(evt:MouseEvent):void
        {
            removeEventListener(Event.ENTER_FRAME, enterFrameEventHandler);
        }

        //Enter Frame Event Handler
        private function enterFrameEventHandler(evt:Event):void
        {
            newScrollRect = ball.scrollRect;
            newScrollRect.y -= 10;
            newScrollRect.x -= 5;
            ball.scrollRect = newScrollRect;
        }
    }
}
Chunky Chunk
  • 16,553
  • 15
  • 84
  • 162
  • 1
    I'm in stupor. This code really don't work as expected. I wonder how is it possible that all my scrolling stuff actually works... Somehow ball.scaleX = 1 + Math.random() * 0.1; will make your ball re-render. But I still can't get why the hell it's not working. – average dev Aug 30 '11 at 10:24
  • I'm not sure why you're applying the scrollRect to the ball. scrollRect is used to display only a portion of a display object. For example, if you had an object called "Page" and it was 2000px by 2000px and you wanted to view only a small 100px rectangular square portion of the page, you'd set the page's scrollRect to something like new Rectangle( 900, 900, 100, 100 ). That would cause the Page object to be reduced to a 100px by 100px square, displaying the 100 pixel region at point 900, 900 within the page. In other words, it brings point 900,900 to the origin at 0,0 and clips it. – Triynko Jan 08 '14 at 16:44
  • scrollRect essentially shifts the coordinate system of a display object to the origin of the scrollRect and then clips the display object to the size of the scrollRect. The display object is always rendered at its own x,y coordinates. When you combine it with using cacheAsBitmap, the drawing and clipping is more efficient, so it will "scroll" faster as you update scrollRect's x and y coordinates, assuming you don't modify its width or height. – Triynko Jan 08 '14 at 16:46

1 Answers1

2

Even more funny:

package
{
    import flash.display.Graphics;
    import flash.display.Sprite;
    import flash.display.StageAlign;
    import flash.display.StageScaleMode;
    import flash.events.Event;
    import flash.events.MouseEvent;
    import flash.geom.Rectangle;


    [SWF(width = "800", height = "500", backgroundColor = "0x444444")]
    public class ScrollRectTest extends Sprite
    {
        //Variables
        private var background:Sprite;
        private var ball:Sprite;
        private var newScrollRect:Rectangle;

        //Constructor
        public function ScrollRectTest()
        {
            stage.scaleMode = StageScaleMode.NO_SCALE;
            stage.align = StageAlign.TOP_LEFT;
            stage.frameRate = 60;

            init();
        }

        //Initialize
        private function init():void
        {
            background = new Sprite();
            background.graphics.beginFill(0x000000, 1.0);
            background.graphics.drawRect(0, 0, 200, 400);
            background.graphics.endFill();

            ball = new Sprite();
            ball.graphics.beginFill(0xFFFF00, 1.0);
            ball.graphics.drawCircle(0, 0, 100);
            ball.graphics.endFill();

            var foo:Sprite = new Sprite();
            var g:Graphics = foo.graphics;
            g.beginFill(0xFF0000, 0.2);
            g.drawRect(0, 0, 100, 100);
            g.endFill();
            ball.addChild(foo);


            ball.cacheAsBitmap = true; //<-- uncomment this
            ball.scrollRect = new Rectangle(background.x, background.y, background.width, background.height);

            stage.addEventListener(MouseEvent.MOUSE_DOWN, mouseDownEventHandler);
            stage.addEventListener(MouseEvent.MOUSE_UP, mouseUpEventHandler);

            addChild(background);
            addChild(ball);
        }

        //Mouse Down Event Handler
        private function mouseDownEventHandler(evt:MouseEvent):void
        {   
            addEventListener(Event.ENTER_FRAME, enterFrameEventHandler);
        }

        //Mouse Up Event Handler
        private function mouseUpEventHandler(evt:MouseEvent):void
        {
            removeEventListener(Event.ENTER_FRAME, enterFrameEventHandler);
        }

        //Enter Frame Event Handler
        private function enterFrameEventHandler(evt:Event):void
        {
            newScrollRect = ball.scrollRect;
            newScrollRect.y -= 1;
            newScrollRect.x -= 1;
            ball.scrollRect = newScrollRect;
//          ball.scaleX = 1 + Math.random() * 0.01;// uncomment this to force redraw
        }
    }
}

So I assume it's some kind of bug.

average dev
  • 1,128
  • 7
  • 22
  • humm. i've never used scrollRect before until now, so you assume it's a bug that was introduced in a recent flash player? i'm using Flash 10.3 / AIR 2.7 with Flash Builder 4.5 on Mac OS X 10.6.7. – Chunky Chunk Aug 30 '11 at 10:49
  • I guess I've never tried to use scrollRect & cacheAsBitmap on Sprite that has a graphics made via Drawing API, so I don't know if it's a new one. Also haven't seen any mentions about it. – average dev Aug 30 '11 at 10:59
  • perhaps it's more of a confusing dead end rather than an bug. i mean, even the name `scrollRect` implies scrolling, or movement, instead of a better performing mask. additionally, when it's cached as a bitmap and not moving, the scrollrect is still changing, as you can see if you simply `trace(ball.scrollRect)` in the entre frame event handler. – Chunky Chunk Aug 30 '11 at 11:18
  • 1
    i think perhaps that scrollRect is a bit underdeveloped or at least underdocumented. it works if i'm moving a bitmap asset, not a sprite that is cached as a bitmap. additionally, it's quite counter intuitive that when using a bitmap asset it's still required to assign `cacheAsBitmap = true` or else it will only perform as well as a mask. – Chunky Chunk Aug 31 '11 at 12:07
  • Someone also says that you can't use scrollRect for TextField.. keep in mind. – average dev Sep 01 '11 at 09:16
  • There are problems with scrollRect unless you set cacheAsBitmap to true. With cacheAsBitmap set to true, it (supposedly) uses an optimized code path that only draws the visible region of the clip. With cacheAsBitmap = false and a scrollRect applied, I've noticed that it completely fails to draw any child object which has cacheAsBitmap set to true, presumably because it's not properly updating the cached objects. It's really noticeable when animating the size of the scrollRect, because you'll see that newly exposed areas (or the entire area) of cached-as-bitmap objects will fail to draw. – Triynko May 27 '14 at 21:12