Skip to content

Instantly share code, notes, and snippets.

@lucien144
Last active November 23, 2016 22:59
Show Gist options
  • Save lucien144/01c9104b48519fe9cd201eb72aeb2b75 to your computer and use it in GitHub Desktop.
Save lucien144/01c9104b48519fe9cd201eb72aeb2b75 to your computer and use it in GitHub Desktop.
Parallax effect for Starling's display objects
package com.thebutton.utils {
import flash.events.AccelerometerEvent;
import flash.sensors.Accelerometer;
/**
* Accelerometer is now a singleton - saves a lot of events being created and fired - for better performance.
* @author Jakub Wagner, thebuttongame.io
*/
public class AccelerometerSingleton {
private static var _instance:AccelerometerSingleton = new AccelerometerSingleton();
private var accelerometer:Accelerometer;
private var _accelerationX:Number = 0;
private var _accelerationY:Number = 0;
private var _accelerationZ:Number = 0;
public function AccelerometerSingleton() {
if (_instance) {
throw new Error("Cannot create an instance of AccelerometerManager. Use AccelerometerManager.instance instead.");
return;
}
accelerometer = new Accelerometer();
accelerometer.addEventListener(AccelerometerEvent.UPDATE, onAccelerometerUpdate);
}
static public function get instance():AccelerometerSingleton {
return _instance;
}
public function get accelerationX():Number {
return _accelerationX;
}
public function get accelerationY():Number {
return _accelerationY;
}
public function get accelerationZ():Number {
return _accelerationZ;
}
/* DELEGATE flash.sensors.Accelerometer */
public function get isSupported():Boolean {
return Accelerometer.isSupported;
}
public function setRequestedUpdateInterval(interval:Number):void {
accelerometer.setRequestedUpdateInterval(interval);
}
public function get muted():Boolean {
return accelerometer.muted;
}
//*************************************************************//
//******************** Event Listeners **********************//
//*************************************************************//
private function onAccelerometerUpdate(e:AccelerometerEvent):void {
_accelerationX = e.accelerationX;
_accelerationY = e.accelerationY;
_accelerationZ = e.accelerationZ;
}
}
}
package com.thebutton.game.effects {
import com.thebutton.utils.AccelerometerSingleton;
import flash.sensors.Accelerometer;
import flash.utils.getTimer;
import starling.display.DisplayObject;
import starling.display.Sprite;
import starling.events.EnterFrameEvent;
import starling.events.Event;
/**
* Easy paralax controller.
* Don't forget to add in into the DisplayList.
* If added to DisplayList it automatically handles adding/removing from DisplayList and disposing.
* @author Jakub Wagner, thebuttongame.io
*/
public class Parallax extends Sprite {
private var displayObjects:Vector.<DisplayObject> = new Vector.<DisplayObject>();
private var zIndexes:Vector.<Number> = new Vector.<Number>();
private var origins:Vector.<Object> = new Vector.<Object>();
public var cameraX:Number = 0;
public var cameraY:Number = 0;
private var accelerometer:AccelerometerSingleton;
public function Parallax() {
addEventListener(Event.ADDED_TO_STAGE, onAddedToStage);
addEventListener(Event.REMOVED_FROM_STAGE, onRemovedFromStage);
accelerometer = AccelerometerSingleton.instance;
}
override public function dispose():void {
super.dispose();
removeListeners();
accelerometer = null;
}
/**
* Push object to parallax so it's being automatically animated.
* @param displayObject Display object to add.
* @param zIndex zIndex, the lower value (ie. 50) the closer to the camera
* the higher value (ie. 600) for objects far from camera
*/
public function push(displayObject:DisplayObject, zIndex:Number):void {
displayObjects.push(displayObject);
zIndexes.push(zIndex);
origins.push({x: displayObject.pivotX, y: displayObject.pivotY});
}
private function update():void {
var origin:Object;
var zIndex:Number;
var object:DisplayObject;
for (var i:int = 0, l:int = displayObjects.length; i < l; i++) {
object = displayObjects[i];
zIndex = zIndexes[i];
origin = origins[i];
object.pivotX = object.pivotX - (object.pivotX - (origin.x + cameraX / zIndex)) / 10;
object.pivotY = object.pivotY - (object.pivotY - (origin.y + cameraY / zIndex)) / 10;
}
}
private function addListeners():void {
addEventListener(EnterFrameEvent.ENTER_FRAME, onStageEnterFrame);
}
private function removeListeners():void {
removeEventListener(EnterFrameEvent.ENTER_FRAME, onStageEnterFrame);
}
//*************************************************************//
//******************** Event Listeners **********************//
//*************************************************************//
private function onAddedToStage(e:Event):void {
addListeners();
}
private function onRemovedFromStage(e:Event):void {
removeListeners();
}
private function onStageEnterFrame(e:EnterFrameEvent):void {
cameraX = accelerometer.accelerationX * stage.stageWidth * 4;
cameraY = -accelerometer.accelerationY * stage.stageHeight * 4;
CONFIG::debug {
if (!Accelerometer.isSupported) {
// if there is not accelerometer, fake camera data just in time
cameraX = Math.sin(2 * Math.PI * (getTimer() % 1000) / 1000) * 600;
cameraY = Math.cos(2 * Math.PI * (getTimer() % 1000) / 1000) * 600;
}
}
update();
}
}
}
var paralax:Parallax = new Parallax();
paralax.push(bush, 100);
paralax.push(silo, 350);
paralax.push(siloNeon, 350);
paralax.push(rocket, 450);
paralax.push(satellite, 550);
paralax.push(observatory, 700);
paralax.push(landscapeContainer, 600);
addChild(paralax);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment