In case Flash no longer exists; a copy of this site is included in the Flashpoint archive's "ultimate" collection.

Dead Code Preservation :: Archived AS3 works from wonderfl.net

Flash Tip Collection - Tip 3 - Fast scrolling with scrollrect

@author YopSolo

In a non-gpu-accelerated context, moving a big texture cost a lot of ressources.
scrollRect is a really usefull feature that allow to clip a displayObject
and place a "camera" on it.
in a nutshell : you move the "Camera Rectangle" instead of the big object.
/**
 * Copyright YoupSolo ( http://wonderfl.net/user/YoupSolo )
 * MIT License ( http://www.opensource.org/licenses/mit-license.php )
 * Downloaded from: http://wonderfl.net/c/8Kyl
 */

package
{
    import flash.display.Bitmap;
    import flash.display.DisplayObjectContainer;
    import flash.display.Sprite;
    import flash.display.StageAlign;
    import flash.display.StageQuality;
    import flash.display.StageScaleMode;
    import flash.events.Event;
    import flash.events.MouseEvent;
    import flash.geom.Rectangle;
    import flash.text.TextField;
    import flash.text.TextFieldAutoSize;
    import flash.text.TextFormat;
    
    /**
     * @author YopSolo
     *
     * In a non-gpu-accelerated context, moving a big texture cost a lot of ressources.
     * scrollRect is a really usefull feature that allow to clip a displayObject
     * and place a "camera" on it.
     * in a nutshell : you move the "Camera Rectangle" instead of the big object.
     */
     
    public class Main extends Sprite
    {
        private const FRAMERATE:int = 60;
        
        private var _camera:Rectangle;
        private var _background:Bitmap;
        private var _targetX;
        private var _targetY;
        
        private var _stageW:int;
        private var _stageH:int;
        private var _halfStageW:int;
        private var _halfStageH:int;        
        
        public function Main():void
        {
            if (stage)
                init();
            else
                addEventListener(Event.ADDED_TO_STAGE, init);
        }
        
        private function init(e:Event = null):void
        {
            removeEventListener(Event.ADDED_TO_STAGE, init);
            
            // config stage
            stage.align = StageAlign.TOP_LEFT;
            stage.scaleMode = StageScaleMode.NO_SCALE;
            stage.quality = StageQuality.LOW;
            stage.stageFocusRect = false;
            stage.tabChildren = false;
            
            stage.frameRate = FRAMERATE;
            
            _stageW = stage.stageWidth;
            _stageH = stage.stageHeight;
            _halfStageW = int(_stageW / 2);
            _halfStageH = int(_stageH / 2);
            _targetX = 0;
            _targetY = 0;
            // add custom menu
            new CustomMenu(this);
            
            // run app            
            run();
        
        }
        
        // == APP ==
        private function run():void
        {
            // create my camera rectangle
            _camera = new Rectangle(0, 0, stage.stageWidth, stage.stageHeight);
            
            // create a big displayObject
            _background = new Bitmap(new XORTexture(2048, 2048));
            addChild(_background);
            
            stage.addEventListener(MouseEvent.CLICK, _onClickStage);
            addEventListener(Event.ENTER_FRAME, _oef);
            
            buildTextField(this, 'TIP 3 : Fast scrolling with scrollRect', 2, 2);
            buildTextField(this, 'displayObject.scrollRect = new Rectangle(orix, oriy, rectWidth, rectHeigth);', 2, 22);            
        }
        
        private function _oef(e:Event):void
        {
            if(_camera.x - _targetX == 0 && _camera.y - _targetY == 0){
                // the move is finished, 4 FPS to save CPU ^^
                stage.frameRate = 4;                
            }else{
                // update the camera position with the camera rectangle
                _camera.x = calcNextStep(_camera.x, _targetX, .15);
                _camera.y = calcNextStep(_camera.y, _targetY, .15);                
                _background.scrollRect = _camera;       
            }

        }
        
        // 
        private function calcNextStep(numA:int, numB:int, amount:Number):Number
        {
            return int( (numA + ((numB - numA) * amount)) );
        }
        
        private function _onClickStage(e:MouseEvent):void
        {
            stage.frameRate = FRAMERATE;
            _targetX = int((mouseX / _stageW) * 2048) - _halfStageW;
            _targetY = int((mouseY / _stageH) * 2048) - _halfStageH;
        }
        
        // == COMMON ==        
        private function buildTextField(doc:DisplayObjectContainer, txt:String, x:int = 0, y:int = 0):TextField
        {
            var fmt:TextFormat = new TextFormat;
            fmt.color = 0xFFFFFF;
            fmt.font = 'Arial'; //(new FONT_HARMONY() as Font).fontName;
            fmt.size = 11; // 8;
            
            var tf:TextField = new TextField;
            tf.autoSize = TextFieldAutoSize.LEFT;
            tf.opaqueBackground = 0x333333; // opaque background allow a perfect font rendering even in StageQuality.LOW mode
            tf.selectable = false;
            //tf.embedFonts = true;
            tf.defaultTextFormat = fmt;
            tf.text = txt;
            tf.x = x;
            tf.y = y;
            
            doc.addChild(tf);
            
            return tf;
        }
    
    }

}

import flash.display.BitmapData;

internal class XORTexture extends BitmapData
{
    
    public function XORTexture(width:int, height:int)
    {
        super(width, height, false, 0x0);
        
        var color:uint;
        var rbg_color:uint;
        for (var w:int = 0; w < width; w++)
        {
            for (var h:int = 0; h < height; h++)
            {
                color = w ^ h;
                rbg_color = color << 16 | color << 8 | color;
                this.setPixel(w, h, rbg_color);
            }
        }
    }
}

import flash.display.Sprite;
import flash.events.ContextMenuEvent;
import flash.net.navigateToURL;
import flash.net.URLRequest;
import flash.ui.ContextMenu;
import flash.ui.ContextMenuItem;

class CustomMenu
{
    
    private const NAME:String = "Flash Tips Collection : 'Fast scrolling with scrollRect'";
    
    public function CustomMenu(ref:Sprite):void
    {
        var appContextMenu:ContextMenu = new ContextMenu;
        appContextMenu.hideBuiltInItems();
        
        var cmi:ContextMenuItem = new ContextMenuItem(NAME);
        var credits:ContextMenuItem = new ContextMenuItem("by YopSolo");
        appContextMenu.customItems.push(cmi);
        appContextMenu.customItems.push(credits);
        
        cmi.addEventListener(ContextMenuEvent.MENU_ITEM_SELECT, _onClickCollection);
        credits.addEventListener(ContextMenuEvent.MENU_ITEM_SELECT, _onClickCredits);
        
        ref.contextMenu = appContextMenu;
    }
    
    private function _onClickCollection(e:ContextMenuEvent):void
    {
        navigateToURL(new URLRequest('http://www.yopsolo.fr/wp/2012/01/14/flash-tips-collection/'), '_blank');
    }
    
    private function _onClickCredits(e:ContextMenuEvent):void
    {
        navigateToURL(new URLRequest('http://www.yopsolo.fr'), '_blank');
    }
}