Last active
May 3, 2016 22:43
-
-
Save gmattie/7347573 to your computer and use it in GitHub Desktop.
MultidirectionalTileScroller is a Starling framework extension that easily facilitates multidirectional scrolling of a tiled texture.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package starling.extensions | |
{ | |
//Imports | |
import flash.geom.Point; | |
import starling.display.DisplayObjectContainer; | |
import starling.display.Image; | |
import starling.display.MeshBatch; | |
import starling.events.EnterFrameEvent; | |
import starling.textures.Texture; | |
//Class | |
public class MultidirectionalTileScroller extends DisplayObjectContainer | |
{ | |
//Properties | |
private var m_Canvas:MeshBatch; | |
private var m_Width:uint; | |
private var m_Height:uint; | |
private var m_Texture:Texture; | |
private var m_Image:Image; | |
private var m_TextureNativeWidth:Number; | |
private var m_TextureNativeHeight:Number; | |
private var m_TextureScaleX:Number; | |
private var m_TextureScaleY:Number; | |
private var m_TextureWidth:Number; | |
private var m_TextureHeight:Number; | |
private var m_PivotPoint:Point; | |
private var m_IsAnimating:Boolean; | |
private var m_Speed:Number; | |
private var m_Angle:Number; | |
//Constructor | |
public function MultidirectionalTileScroller(width:uint, height:uint, texture:Texture, textureScaleX:Number = 1.0, textureScaleY:Number = 1.0) | |
{ | |
m_Width = width; | |
m_Height = height; | |
m_Texture = texture; | |
m_TextureScaleX = textureScaleX; | |
m_TextureScaleY = textureScaleY; | |
init(); | |
} | |
//Init | |
private function init():void | |
{ | |
touchable = false; | |
drawTexture(); | |
} | |
//Draw Texture | |
private function drawTexture():void | |
{ | |
m_TextureNativeWidth = m_Texture.nativeWidth; | |
m_TextureNativeHeight = m_Texture.nativeHeight; | |
m_Image = new Image(m_Texture); | |
m_Image.scaleX = m_TextureScaleX; | |
m_Image.scaleY = m_TextureScaleY; | |
drawCanvas(); | |
} | |
//Draw Canvas | |
private function drawCanvas():void | |
{ | |
if (numChildren) removeChildren(); | |
m_Canvas = new MeshBatch(); | |
for (var columns:uint = 0; columns <= Math.ceil(m_Width / (m_TextureNativeWidth * m_TextureScaleX)) + 1; columns++) | |
{ | |
for (var rows:uint = 0; rows <= Math.ceil(m_Height / (m_TextureNativeHeight * m_TextureScaleY)) + 1; rows++) | |
{ | |
m_Image.x = m_TextureNativeWidth * m_TextureScaleX * columns; | |
m_Image.y = m_TextureNativeHeight * m_TextureScaleY * rows; | |
m_Canvas.addMesh(m_Image); | |
} | |
} | |
m_TextureWidth = m_TextureNativeWidth * m_TextureScaleX; | |
m_TextureHeight = m_TextureNativeHeight * m_TextureScaleY; | |
m_PivotPoint = new Point(m_Width / 2, m_Height / 2); | |
m_Canvas.alignPivot(); | |
m_Canvas.x = m_PivotPoint.x; | |
m_Canvas.y = m_PivotPoint.y; | |
addChild(m_Canvas); | |
} | |
//Play | |
public function play(speed:Number = NaN, angle:Number = NaN):void | |
{ | |
this.speed = (isNaN(speed)) ? this.speed : speed; | |
this.angle = (isNaN(speed)) ? this.angle : angle; | |
m_IsAnimating = true; | |
if (!m_Canvas.hasEventListener(EnterFrameEvent.ENTER_FRAME)) | |
{ | |
m_Canvas.addEventListener(EnterFrameEvent.ENTER_FRAME, enterFrameEventHandler); | |
} | |
} | |
//Stop | |
public function stop():void | |
{ | |
m_IsAnimating = false; | |
if (m_Canvas.hasEventListener(EnterFrameEvent.ENTER_FRAME)) | |
{ | |
m_Canvas.removeEventListener(EnterFrameEvent.ENTER_FRAME, enterFrameEventHandler); | |
} | |
} | |
//Enter Frame Event Handler | |
private function enterFrameEventHandler(event:EnterFrameEvent):void | |
{ | |
m_Canvas.x += Math.cos(m_Angle) * m_Speed; | |
m_Canvas.y += Math.sin(m_Angle) * m_Speed; | |
if (m_Canvas.x < m_PivotPoint.x - m_TextureWidth) | |
{ | |
m_Canvas.x += m_TextureWidth; | |
} | |
if (m_Canvas.x > m_PivotPoint.x + m_TextureWidth) | |
{ | |
m_Canvas.x -= m_TextureWidth; | |
} | |
if (m_Canvas.y < m_PivotPoint.y - m_TextureHeight) | |
{ | |
m_Canvas.y += m_TextureHeight; | |
} | |
if (m_Canvas.y > m_PivotPoint.y + m_TextureHeight) | |
{ | |
m_Canvas.y -= m_TextureHeight; | |
} | |
} | |
//Dispose | |
override public function dispose():void | |
{ | |
stop(); | |
m_Texture.dispose(); | |
super.dispose(); | |
} | |
//Set Texture | |
public function setTexture(texture:Texture, textureScaleX:Number = 1.0, textureScaleY:Number = 1.0):void | |
{ | |
if (isAnimating) | |
{ | |
stop(); | |
} | |
if (m_Texture) | |
{ | |
m_Texture.dispose(); | |
} | |
m_Texture = texture; | |
m_TextureScaleX = textureScaleX; | |
m_TextureScaleY = m_TextureScaleY; | |
drawTexture(); | |
} | |
//Set Size | |
public function setSize(width:uint, height:uint):void | |
{ | |
m_Width = width; | |
m_Height = height; | |
drawCanvas(); | |
} | |
//Set Speed | |
public function set speed(value:Number):void | |
{ | |
m_Speed = (isNaN(value) || value <= 0.0) ? 0.0 : Math.min(value, Math.min(m_TextureWidth, m_TextureHeight)); | |
} | |
//Get Speed | |
public function get speed():Number | |
{ | |
return m_Speed; | |
} | |
//Set Angle | |
public function set angle(value:Number):void | |
{ | |
m_Angle = (isNaN(value) ? 180 : 180 - value) * Math.PI / 180; | |
} | |
//Get Angle | |
public function get angle():Number | |
{ | |
return 180 - m_Angle * 180 / Math.PI; | |
} | |
//Get isAnimating | |
public function get isAnimating():Boolean | |
{ | |
return m_IsAnimating; | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Great extension! There is a small issue with using this with Retina devices and 2x textures though but the solution is pretty simple , Line 57&57 just need to change nativeWidth & nativeHeight to width & height.
m_TextureNativeWidth = m_Texture.width;
m_TextureNativeHeight = m_Texture.height;