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');
}
}