From 72d018ea047efbea81bbfd2918f909358b12ddef Mon Sep 17 00:00:00 2001
From: Terry Cavanagh
Date: Fri, 2 Dec 2022 18:19:58 +0100
Subject: [PATCH] Update mobile version to mobile v2.2.1
The android version just got a much needed update to fix some resolution issues on devices with cutouts.
It turns out the mobile source was actually pretty out of date, like 3 versions out of date! This commit brings it up to date.
All the changes have just been about keeping the game running on modern devices, though. The biggest change was adding the Starling library to the project, which made the game GPU powered and sped the whole thing up.
---
mobile_version/application.xml | 176 +-
mobile_version/src/EditorDataclass.as | 5 -
mobile_version/src/EmbeddedAssets.as | 12 +
mobile_version/src/LevelMetaData.as | 1 -
mobile_version/src/Load.as | 16 +
mobile_version/src/Main.as | 1238 ++++-----
mobile_version/src/Preloader.as | 310 ---
mobile_version/src/blockclass.as | 7 +-
.../src/com/adobe/utils/AGALMiniAssembler.as | 805 ++++++
mobile_version/src/device.as | 2 +
mobile_version/src/dwgraphicsclass.as | 2229 +++++++++--------
mobile_version/src/edentitiesclass.as | 5 -
mobile_version/src/editor.as | 148 +-
mobile_version/src/edlevelclass.as | 5 -
mobile_version/src/entclass.as | 7 +-
mobile_version/src/entityclass.as | 65 +-
mobile_version/src/gameclass.as | 18 +-
mobile_version/src/helpclass.as | 4 +-
mobile_version/src/includes/input.as | 18 +-
mobile_version/src/includes/logic.as | 2 +-
mobile_version/src/includes/render.as | 203 +-
mobile_version/src/includes/scripts.as | 4 +-
.../src/includes/terminalscripts.as | 10 +-
mobile_version/src/mapclass.as | 13 +-
mobile_version/src/musicclass.as | 5 +-
mobile_version/src/platformclass.as | 3 -
mobile_version/src/saveclass.as | 5 +-
mobile_version/src/scoreclass.as | 30 +-
mobile_version/src/scriptclass.as | 9 +-
.../src/starling/animation/DelayedCall.as | 140 ++
.../src/starling/animation/IAnimatable.as | 30 +
.../src/starling/animation/Juggler.as | 396 +++
.../src/starling/animation/Transitions.as | 233 ++
.../src/starling/animation/Tween.as | 451 ++++
.../src/starling/assets/AssetFactory.as | 122 +
.../src/starling/assets/AssetFactoryHelper.as | 124 +
.../src/starling/assets/AssetManager.as | 1034 ++++++++
.../src/starling/assets/AssetReference.as | 56 +
.../src/starling/assets/AssetType.as | 40 +
.../src/starling/assets/AtfTextureFactory.as | 73 +
.../starling/assets/BitmapTextureFactory.as | 167 ++
.../src/starling/assets/ByteArrayFactory.as | 30 +
.../src/starling/assets/DataLoader.as | 138 +
.../src/starling/assets/JsonFactory.as | 40 +
.../src/starling/assets/SoundFactory.as | 60 +
.../src/starling/assets/XmlFactory.as | 84 +
mobile_version/src/starling/core/Starling.as | 1051 ++++++++
.../src/starling/core/StatsDisplay.as | 160 ++
.../src/starling/core/starling_internal.as | 22 +
.../src/starling/display/BlendMode.as | 136 +
mobile_version/src/starling/display/Button.as | 455 ++++
.../src/starling/display/ButtonState.as | 33 +
mobile_version/src/starling/display/Canvas.as | 121 +
.../src/starling/display/DisplayObject.as | 1111 ++++++++
.../display/DisplayObjectContainer.as | 508 ++++
mobile_version/src/starling/display/Image.as | 493 ++++
mobile_version/src/starling/display/Mesh.as | 332 +++
.../src/starling/display/MeshBatch.as | 300 +++
.../src/starling/display/MovieClip.as | 479 ++++
mobile_version/src/starling/display/Quad.as | 209 ++
mobile_version/src/starling/display/Sprite.as | 27 +
.../src/starling/display/Sprite3D.as | 372 +++
mobile_version/src/starling/display/Stage.as | 350 +++
.../src/starling/errors/AbstractClassError.as | 23 +
.../starling/errors/AbstractMethodError.as | 22 +
.../starling/errors/MissingContextError.as | 23 +
.../src/starling/errors/NotSupportedError.as | 23 +
.../src/starling/events/EnterFrameEvent.as | 34 +
mobile_version/src/starling/events/Event.as | 190 ++
.../src/starling/events/EventDispatcher.as | 215 ++
.../src/starling/events/KeyboardEvent.as | 88 +
.../src/starling/events/ResizeEvent.as | 44 +
mobile_version/src/starling/events/Touch.as | 240 ++
.../src/starling/events/TouchEvent.as | 218 ++
.../src/starling/events/TouchMarker.as | 104 +
.../src/starling/events/TouchPhase.as | 53 +
.../src/starling/events/TouchProcessor.as | 481 ++++
.../src/starling/filters/BlurFilter.as | 305 +++
.../src/starling/filters/ColorMatrixFilter.as | 318 +++
.../src/starling/filters/CompositeFilter.as | 327 +++
.../starling/filters/DisplacementMapFilter.as | 355 +++
.../src/starling/filters/DropShadowFilter.as | 172 ++
.../src/starling/filters/FilterChain.as | 168 ++
.../src/starling/filters/FilterHelper.as | 215 ++
.../src/starling/filters/FragmentFilter.as | 634 +++++
.../src/starling/filters/GlowFilter.as | 125 +
.../src/starling/filters/IFilterHelper.as | 49 +
mobile_version/src/starling/geom/Polygon.as | 613 +++++
.../src/starling/rendering/BatchProcessor.as | 218 ++
.../src/starling/rendering/BatchToken.as | 77 +
.../src/starling/rendering/Effect.as | 381 +++
.../src/starling/rendering/FilterEffect.as | 147 ++
.../src/starling/rendering/IndexData.as | 552 ++++
.../src/starling/rendering/MeshEffect.as | 145 ++
.../src/starling/rendering/Painter.as | 909 +++++++
.../src/starling/rendering/Program.as | 104 +
.../src/starling/rendering/RenderState.as | 400 +++
.../src/starling/rendering/VertexData.as | 1129 +++++++++
.../starling/rendering/VertexDataAttribute.as | 47 +
.../starling/rendering/VertexDataFormat.as | 275 ++
.../src/starling/styles/DistanceFieldStyle.as | 684 +++++
.../src/starling/styles/MeshStyle.as | 436 ++++
.../src/starling/text/BitmapChar.as | 86 +
.../src/starling/text/BitmapFont.as | 548 ++++
.../src/starling/text/ITextCompositor.as | 29 +
.../src/starling/text/MiniBitmapFont.as | 314 +++
mobile_version/src/starling/text/TextField.as | 555 ++++
.../src/starling/text/TextFieldAutoSize.as | 36 +
.../src/starling/text/TextFormat.as | 236 ++
.../src/starling/text/TextOptions.as | 87 +
.../src/starling/text/TrueTypeCompositor.as | 187 ++
.../src/starling/textures/AtfData.as | 94 +
.../starling/textures/ConcretePotTexture.as | 140 ++
.../textures/ConcreteRectangleTexture.as | 54 +
.../src/starling/textures/ConcreteTexture.as | 269 ++
.../starling/textures/ConcreteVideoTexture.as | 98 +
.../src/starling/textures/RenderTexture.as | 336 +++
.../src/starling/textures/SubTexture.as | 183 ++
.../src/starling/textures/Texture.as | 753 ++++++
.../src/starling/textures/TextureAtlas.as | 221 ++
.../src/starling/textures/TextureOptions.as | 100 +
.../src/starling/textures/TextureSmoothing.as | 36 +
mobile_version/src/starling/utils/Align.as | 55 +
.../src/starling/utils/AssetManager.as | 1302 ++++++++++
mobile_version/src/starling/utils/Color.as | 117 +
mobile_version/src/starling/utils/MathUtil.as | 124 +
.../src/starling/utils/MatrixUtil.as | 382 +++
.../src/starling/utils/MeshSubset.as | 46 +
mobile_version/src/starling/utils/MeshUtil.as | 93 +
mobile_version/src/starling/utils/Padding.as | 105 +
mobile_version/src/starling/utils/Pool.as | 143 ++
.../src/starling/utils/RectangleUtil.as | 246 ++
.../src/starling/utils/RenderUtil.as | 275 ++
.../src/starling/utils/ScaleMode.as | 30 +
.../src/starling/utils/StringUtil.as | 95 +
.../src/starling/utils/SystemUtil.as | 197 ++
mobile_version/src/starling/utils/deg2rad.as | 18 +
mobile_version/src/starling/utils/execute.as | 42 +
mobile_version/src/starling/utils/rad2deg.as | 18 +
mobile_version/src/textboxclass.as | 17 +-
140 files changed, 30533 insertions(+), 2409 deletions(-)
create mode 100644 mobile_version/src/EmbeddedAssets.as
create mode 100644 mobile_version/src/Load.as
delete mode 100644 mobile_version/src/Preloader.as
create mode 100644 mobile_version/src/com/adobe/utils/AGALMiniAssembler.as
create mode 100644 mobile_version/src/starling/animation/DelayedCall.as
create mode 100644 mobile_version/src/starling/animation/IAnimatable.as
create mode 100644 mobile_version/src/starling/animation/Juggler.as
create mode 100644 mobile_version/src/starling/animation/Transitions.as
create mode 100644 mobile_version/src/starling/animation/Tween.as
create mode 100644 mobile_version/src/starling/assets/AssetFactory.as
create mode 100644 mobile_version/src/starling/assets/AssetFactoryHelper.as
create mode 100644 mobile_version/src/starling/assets/AssetManager.as
create mode 100644 mobile_version/src/starling/assets/AssetReference.as
create mode 100644 mobile_version/src/starling/assets/AssetType.as
create mode 100644 mobile_version/src/starling/assets/AtfTextureFactory.as
create mode 100644 mobile_version/src/starling/assets/BitmapTextureFactory.as
create mode 100644 mobile_version/src/starling/assets/ByteArrayFactory.as
create mode 100644 mobile_version/src/starling/assets/DataLoader.as
create mode 100644 mobile_version/src/starling/assets/JsonFactory.as
create mode 100644 mobile_version/src/starling/assets/SoundFactory.as
create mode 100644 mobile_version/src/starling/assets/XmlFactory.as
create mode 100644 mobile_version/src/starling/core/Starling.as
create mode 100644 mobile_version/src/starling/core/StatsDisplay.as
create mode 100644 mobile_version/src/starling/core/starling_internal.as
create mode 100644 mobile_version/src/starling/display/BlendMode.as
create mode 100644 mobile_version/src/starling/display/Button.as
create mode 100644 mobile_version/src/starling/display/ButtonState.as
create mode 100644 mobile_version/src/starling/display/Canvas.as
create mode 100644 mobile_version/src/starling/display/DisplayObject.as
create mode 100644 mobile_version/src/starling/display/DisplayObjectContainer.as
create mode 100644 mobile_version/src/starling/display/Image.as
create mode 100644 mobile_version/src/starling/display/Mesh.as
create mode 100644 mobile_version/src/starling/display/MeshBatch.as
create mode 100644 mobile_version/src/starling/display/MovieClip.as
create mode 100644 mobile_version/src/starling/display/Quad.as
create mode 100644 mobile_version/src/starling/display/Sprite.as
create mode 100644 mobile_version/src/starling/display/Sprite3D.as
create mode 100644 mobile_version/src/starling/display/Stage.as
create mode 100644 mobile_version/src/starling/errors/AbstractClassError.as
create mode 100644 mobile_version/src/starling/errors/AbstractMethodError.as
create mode 100644 mobile_version/src/starling/errors/MissingContextError.as
create mode 100644 mobile_version/src/starling/errors/NotSupportedError.as
create mode 100644 mobile_version/src/starling/events/EnterFrameEvent.as
create mode 100644 mobile_version/src/starling/events/Event.as
create mode 100644 mobile_version/src/starling/events/EventDispatcher.as
create mode 100644 mobile_version/src/starling/events/KeyboardEvent.as
create mode 100644 mobile_version/src/starling/events/ResizeEvent.as
create mode 100644 mobile_version/src/starling/events/Touch.as
create mode 100644 mobile_version/src/starling/events/TouchEvent.as
create mode 100644 mobile_version/src/starling/events/TouchMarker.as
create mode 100644 mobile_version/src/starling/events/TouchPhase.as
create mode 100644 mobile_version/src/starling/events/TouchProcessor.as
create mode 100644 mobile_version/src/starling/filters/BlurFilter.as
create mode 100644 mobile_version/src/starling/filters/ColorMatrixFilter.as
create mode 100644 mobile_version/src/starling/filters/CompositeFilter.as
create mode 100644 mobile_version/src/starling/filters/DisplacementMapFilter.as
create mode 100644 mobile_version/src/starling/filters/DropShadowFilter.as
create mode 100644 mobile_version/src/starling/filters/FilterChain.as
create mode 100644 mobile_version/src/starling/filters/FilterHelper.as
create mode 100644 mobile_version/src/starling/filters/FragmentFilter.as
create mode 100644 mobile_version/src/starling/filters/GlowFilter.as
create mode 100644 mobile_version/src/starling/filters/IFilterHelper.as
create mode 100644 mobile_version/src/starling/geom/Polygon.as
create mode 100644 mobile_version/src/starling/rendering/BatchProcessor.as
create mode 100644 mobile_version/src/starling/rendering/BatchToken.as
create mode 100644 mobile_version/src/starling/rendering/Effect.as
create mode 100644 mobile_version/src/starling/rendering/FilterEffect.as
create mode 100644 mobile_version/src/starling/rendering/IndexData.as
create mode 100644 mobile_version/src/starling/rendering/MeshEffect.as
create mode 100644 mobile_version/src/starling/rendering/Painter.as
create mode 100644 mobile_version/src/starling/rendering/Program.as
create mode 100644 mobile_version/src/starling/rendering/RenderState.as
create mode 100644 mobile_version/src/starling/rendering/VertexData.as
create mode 100644 mobile_version/src/starling/rendering/VertexDataAttribute.as
create mode 100644 mobile_version/src/starling/rendering/VertexDataFormat.as
create mode 100644 mobile_version/src/starling/styles/DistanceFieldStyle.as
create mode 100644 mobile_version/src/starling/styles/MeshStyle.as
create mode 100644 mobile_version/src/starling/text/BitmapChar.as
create mode 100644 mobile_version/src/starling/text/BitmapFont.as
create mode 100644 mobile_version/src/starling/text/ITextCompositor.as
create mode 100644 mobile_version/src/starling/text/MiniBitmapFont.as
create mode 100644 mobile_version/src/starling/text/TextField.as
create mode 100644 mobile_version/src/starling/text/TextFieldAutoSize.as
create mode 100644 mobile_version/src/starling/text/TextFormat.as
create mode 100644 mobile_version/src/starling/text/TextOptions.as
create mode 100644 mobile_version/src/starling/text/TrueTypeCompositor.as
create mode 100644 mobile_version/src/starling/textures/AtfData.as
create mode 100644 mobile_version/src/starling/textures/ConcretePotTexture.as
create mode 100644 mobile_version/src/starling/textures/ConcreteRectangleTexture.as
create mode 100644 mobile_version/src/starling/textures/ConcreteTexture.as
create mode 100644 mobile_version/src/starling/textures/ConcreteVideoTexture.as
create mode 100644 mobile_version/src/starling/textures/RenderTexture.as
create mode 100644 mobile_version/src/starling/textures/SubTexture.as
create mode 100644 mobile_version/src/starling/textures/Texture.as
create mode 100644 mobile_version/src/starling/textures/TextureAtlas.as
create mode 100644 mobile_version/src/starling/textures/TextureOptions.as
create mode 100644 mobile_version/src/starling/textures/TextureSmoothing.as
create mode 100644 mobile_version/src/starling/utils/Align.as
create mode 100644 mobile_version/src/starling/utils/AssetManager.as
create mode 100644 mobile_version/src/starling/utils/Color.as
create mode 100644 mobile_version/src/starling/utils/MathUtil.as
create mode 100644 mobile_version/src/starling/utils/MatrixUtil.as
create mode 100644 mobile_version/src/starling/utils/MeshSubset.as
create mode 100644 mobile_version/src/starling/utils/MeshUtil.as
create mode 100644 mobile_version/src/starling/utils/Padding.as
create mode 100644 mobile_version/src/starling/utils/Pool.as
create mode 100644 mobile_version/src/starling/utils/RectangleUtil.as
create mode 100644 mobile_version/src/starling/utils/RenderUtil.as
create mode 100644 mobile_version/src/starling/utils/ScaleMode.as
create mode 100644 mobile_version/src/starling/utils/StringUtil.as
create mode 100644 mobile_version/src/starling/utils/SystemUtil.as
create mode 100644 mobile_version/src/starling/utils/deg2rad.as
create mode 100644 mobile_version/src/starling/utils/execute.as
create mode 100644 mobile_version/src/starling/utils/rad2deg.as
diff --git a/mobile_version/application.xml b/mobile_version/application.xml
index fcafcbbd..353e1ec7 100644
--- a/mobile_version/application.xml
+++ b/mobile_version/application.xml
@@ -1,73 +1,105 @@
-
-
- com.distractionware.vvvvvvmobile
- 1.02
- mobileDevice
- VVVVVV
- VVVVVV
-
-
-
-
-
-]]>
-
-
- UIStatusBarStyle
-UIStatusBarStyleBlackOpaque
-UIRequiresPersistentWiFi
-NO
-UIPrerenderedIcon
-
-UIApplicationExitsOnSuspend
-
-UIDeviceFamily
-
-
- 1
-
- 2
-]]>
- standard
-
-
- VVVVVV
- vvvvvv.swf
- true
- landscape
- gpu
- standard
- true
- true
-
-
- icons/icon_48.png
- icons/icon_57.png
- icons/icon_72.png
- icons/icon_76.png
- icons/icon_96.png
- icons/icon_114.png
- icons/icon_120.png
- icons/icon_144.png
- icons/icon_152.png
- icons/icon_512.png
- icons/icon_1024.png
-
-
-
- com.milkmangames.extensions.GameCenter
-
-
+
+
+ com.distractionware.vvvvvvmobile
+ 2.2.1
+ mobileDevice
+ VVVVVV
+ VVVVVV
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ ]]>
+ true
+
+
+ UIStatusBarStyle
+ UIStatusBarStyleBlackOpaque
+ UIRequiresPersistentWiFi
+ NO
+ UIPrerenderedIcon
+
+ UIApplicationExitsOnSuspend
+
+
+ UIDeviceFamily
+
+
+ 1
+
+
+
+
+
+ ]]>
+ high
+
+
+
+ VVVVVV
+ vvvvvv.swf
+ true
+ true
+ standard
+ true
+ landscape
+ direct
+
+
+
+
+ icons/icon_48.png
+ icons/icon_57.png
+ icons/icon_72.png
+ icons/icon_76.png
+ icons/icon_96.png
+ icons/icon_114.png
+ icons/icon_120.png
+ icons/icon_144.png
+ icons/icon_152.png
+ icons/icon_512.png
+ icons/icon_1024.png
+
+
+
+
+
+
\ No newline at end of file
diff --git a/mobile_version/src/EditorDataclass.as b/mobile_version/src/EditorDataclass.as
index ad88845e..b7766a5b 100644
--- a/mobile_version/src/EditorDataclass.as
+++ b/mobile_version/src/EditorDataclass.as
@@ -1,9 +1,4 @@
package {
- import flash.display.*;
- import flash.geom.*;
- import flash.events.*;
- import flash.net.*;
-
public class EditorDataclass{
public function EditorDataclass():void {
clear();
diff --git a/mobile_version/src/EmbeddedAssets.as b/mobile_version/src/EmbeddedAssets.as
new file mode 100644
index 00000000..350a2338
--- /dev/null
+++ b/mobile_version/src/EmbeddedAssets.as
@@ -0,0 +1,12 @@
+package {
+ public class EmbeddedAssets {
+ /* PNG texture */
+ [Embed(source = "../data/vvvvvv_graphics.png")]
+ public static const vvvvvv_graphics:Class;
+
+ /* XML file */
+ [Embed(source = "../data/vvvvvv_graphics.xml",
+ mimeType = "application/octet-stream")]
+ public static const vvvvvv_graphics_xml:Class;
+ }
+}
\ No newline at end of file
diff --git a/mobile_version/src/LevelMetaData.as b/mobile_version/src/LevelMetaData.as
index bea5ef71..ac8f3779 100644
--- a/mobile_version/src/LevelMetaData.as
+++ b/mobile_version/src/LevelMetaData.as
@@ -1,5 +1,4 @@
package {
- import flash.display.*;
import flash.geom.*;
import flash.events.*;
import flash.net.*;
diff --git a/mobile_version/src/Load.as b/mobile_version/src/Load.as
new file mode 100644
index 00000000..5e08380d
--- /dev/null
+++ b/mobile_version/src/Load.as
@@ -0,0 +1,16 @@
+package{
+ import flash.display.Sprite;
+ import starling.core.Starling;
+
+ [SWF(backgroundColor="#000000", frameRate="30")]
+ public class Load extends Sprite{
+ private var _starling:Starling;
+
+ public function Load() {
+ Starling.multitouchEnabled = true;
+
+ _starling = new Starling(Main, stage);
+ _starling.start();
+ }
+ }
+}
\ No newline at end of file
diff --git a/mobile_version/src/Main.as b/mobile_version/src/Main.as
index a010f250..2e1e3ba2 100644
--- a/mobile_version/src/Main.as
+++ b/mobile_version/src/Main.as
@@ -1,36 +1,35 @@
-package{
- import flash.display.*;
+package {
import flash.geom.*;
- import flash.events.*;
- import flash.net.*;
- import flash.media.*;
- import flash.text.*;
- import flash.ui.ContextMenu;
- import flash.ui.ContextMenuItem;
- import flash.events.ContextMenuEvent;
+ import flash.net.*;
+ import flash.display.Screen;
+ import flash.display.StageAlign;
+ import flash.display.StageQuality;
+ import flash.display.StageScaleMode;
+ import flash.system.Capabilities;
+ import starling.core.Starling;
+ import starling.display.Image;
+ import starling.text.BitmapFont;
+ import starling.text.TextField;
+ import starling.core.StatsDisplay;
+ import starling.events.Event;
+ import starling.utils.Color;
+ import starling.textures.*;
+ import starling.display.*;
+ import flash.filesystem.File;
+ import starling.events.KeyboardEvent;
import flash.ui.Keyboard;
- import flash.ui.Mouse;
+ import starling.utils.AssetManager;
import bigroom.input.KeyPoll;
- import flash.system.fscommand;
- import flash.system.Capabilities;
+ //import com.mesmotronic.ane.AndroidFullScreen; //This doesn't seem to be needed anymore
+ import flash.display.StageDisplayState;
+ import flash.media.*;
+
+
import flash.utils.getTimer;
import flash.utils.Timer;
- //import com.mesmotronic.ane.AndroidFullScreen;
+ import flash.events.TimerEvent;
- //import com.sociodox.theminer.TheMiner; //Profiler
-
- //Real value
- //[SWF(width = "1136", height = "768", frameRate = "30", backgroundColor = "#000000")] //Set the size and color of the Flash file
- //Big frame for big androids!
- //[SWF(width = "3000", height = "2000", frameRate = "30", backgroundColor = "#000000")] //Set the size and color of the Flash file
- [SWF(frameRate = "30", backgroundColor = "#000000")] //Set the size and color of the Flash file
- //iPad test
- //[SWF(width = "1024", height = "768", frameRate="60", backgroundColor = "#000000")] //Set the size and color of the Flash file
- //iPhone test
- //[SWF(width = "480", height = "320", frameRate="30", backgroundColor = "#000000")] //Set the size and color of the Flash file
- //[SWF(width = "960", height = "640", frameRate="30", backgroundColor = "#000000")] //Set the size and color of the Flash file
-
- public class Main extends Sprite {
+ public class Main extends Sprite{
static public var BLOCK:Number = 0;
static public var TRIGGER:Number = 1;
static public var DAMAGE:Number = 2;
@@ -49,7 +48,11 @@
public var EDITORMODE:int = 8;
public var CONTROLTUTORIALMODE:int = 9;
- public function Main():void {
+ public var addedtwice:Boolean = false;
+
+ public function Main() {
+ super();
+
if (stage) gameinit();
else addEventListener(Event.ADDED_TO_STAGE, gameinit);
}
@@ -57,565 +60,395 @@
private function gameinit(e:Event = null):void {
removeEventListener(Event.ADDED_TO_STAGE, gameinit);
// entry point
- var tempbmp:Bitmap;
-
- this.mouseEnabled = false;
- this.mouseChildren = false;
+ if (addedtwice) return; //I don't think I actually need this, but... I have a hunch
+ addedtwice = true;
//Ok: quick security check to make sure it doesn't get posted about
- if (sitelock()) {
- key = new KeyPoll(stage);
+ key = new KeyPoll(Starling.current.nativeStage);
+
+ //immersivemode = AndroidFullScreen.isSupported;
+ stage.addEventListener(Event.RESIZE, function(e:Event):void{
+ androidresize();
+ });
+
+ device.deviceresolution = device.ANDROID;
+
+ editor.init(); //Load in all the levels
+
+ //General game variables
+ obj.init();
+ help.init();
+
+ /*obj.createblock(BLOCK,20,200,128,16);
+ obj.createblock(BLOCK,130,170,128,16);
+ obj.createblock(BLOCK,240,150,128,16);
+ obj.createblock(BLOCK,240,20,128,16);
+ obj.createblock(BLOCK,130,40,128,16);
+ obj.createblock(BLOCK,20,60,128,16);*/
+
+ //Input
+ key.definestickrange(device.xres / 2, 0, 6);
+
+ SoundMixer.soundTransform = new SoundTransform(1);
+
+ music.currentsong = -1; music.musicfade = 0;//no music, no amb
+ music.initefchannels(); music.currentefchan = 0;
+ music.nicechange = -1;
+
+ music.numplays = 0;
+ music.musicchan.push(new music_1()); // 0: Level Complete
+ music.musicchan.push(new vmaintheme_hq()); // 1: VVVVVV Main Theme (Pushing Forward)
+ music.musicchan.push(new vtempo_hq()); // 2: VVVVVV Tempo Theme (Positive Force)
+ music.musicchan.push(new vpfa_hq()); // 3: Potential for Anything
+ music.musicchan.push(new passionforexploring()); // 4: UU Brothers Instrumental
+ music.musicchan.push(new souleye_intermission()); // 5: Jingle: Intermission
+ music.musicchan.push(new presentingvvvvvv()); // 6: Jingle: Menu Loop
+ music.musicchan.push(new music_2()); // 7: Jingle: Game Complete
+ music.musicchan.push(new configmegamix_hq()); // 8: Config Megamix
+ music.musicchan.push(new posreverse()); // 9: Tempo Theme, Reversed
+ music.musicchan.push(new poppot()); // 10: Extra
+ music.musicchan.push(new pipedream_hq()); // 11: Highscore
+ music.musicchan.push(new pressurecooker_hq()); // 12: Pressure Cooker
+ music.musicchan.push(new pacedenergy()); // NEW 13: Paced Energy
+ music.musicchan.push(new piercingthesky()); // NEW 14: Piercing the Sky
+ music.musicchan.push(new predestinedfateremix()); // NEW 15: Predestined Fate Remix
+
+ music.efchan.push(new ef_0());
+ music.efchan.push(new ef_1());
+ music.efchan.push(new ef_2());
+ music.efchan.push(new ef_3());
+ music.efchan.push(new ef_4());
+ music.efchan.push(new ef_5());
+ music.efchan.push(new ef_6());
+ music.efchan.push(new ef_7());
+ music.efchan.push(new ef_8());
+ music.efchan.push(new ef_9());
+ music.efchan.push(new ef_10());
+ music.efchan.push(new ef_11());
+ music.efchan.push(new ef_12());
+ music.efchan.push(new ef_13());
+ music.efchan.push(new ef_14());
+ music.efchan.push(new ef_15());
+ music.efchan.push(new ef_16());
+ music.efchan.push(new ef_17());
+ music.efchan.push(new ef_18());
+ music.efchan.push(new ef_19());
+ music.efchan.push(new ef_20());
+ music.efchan.push(new ef_21());
+ music.efchan.push(new ef_22());
+ music.efchan.push(new ef_23());
+ music.efchan.push(new ef_24());
+ music.efchan.push(new ef_25());
+ music.efchan.push(new ef_26());
+ music.efchan.push(new ef_27());
- //ANDROID SPECIFIC CODE HERE
- /*
- if (AndroidFullScreen.isSupported) {
- if (!AndroidFullScreen.immersiveMode()){
- stage.displayState = StageDisplayState.FULL_SCREEN_INTERACTIVE;
- device.xres = flash.system.Capabilities.screenResolutionX;
- device.yres = flash.system.Capabilities.screenResolutionY;
- immersivemode = false;
- }else {
- device.xres = stage.stageWidth;
- device.yres = stage.stageHeight;
- immersivemode = true;
- }
- }else {
- */
- stage.displayState = StageDisplayState.FULL_SCREEN_INTERACTIVE;
- device.xres = flash.system.Capabilities.screenResolutionX;
- device.yres = flash.system.Capabilities.screenResolutionY;
- immersivemode = false;
- //}
+ /*
+ Graphics Init
+ */
+ dwgfx.init(stage);
+ //Load assets
+ dwgfx.starlingassets = new AssetManager();
+ dwgfx.starlingassets.enqueue(EmbeddedAssets);
+
+ Starling.current.nativeStage.scaleMode = StageScaleMode.NO_SCALE;
+ Starling.current.nativeStage.align = StageAlign.TOP_LEFT;
+ Starling.current.nativeStage.quality = StageQuality.LOW;
+
+ //TO DO: orientation code
+ game = new gameclass(dwgfx, map, obj, help, music);
- /*
- if (immersivemode) {
- stage.addEventListener(Event.RESIZE, androidresize);
- }
- */
- /*
- trace("NOTE: REMEMBER TO FIX RESOLUTION SUPPORT BEFORE BUILDING");
- device.xres = 1024;
- device.yres = 768;
- device.deviceresolution = device.IPAD;
- */
- //Testing:Let's be an ipad
- /*
- device.xres = 1024;
- device.yres = 768;
- device.deviceresolution = device.IPAD;
- */
- /*
- device.xres = 480;
- device.yres = 320;
- device.deviceresolution = device.IPHONE;
- */
- /*
- device.xres = 960;
- device.yres = 640;
- device.deviceresolution = device.IPHONE;
- */
-
- editor.init(); //Load in all the levels
-
- if (device.xres < device.yres) {
- //Switch them!
- t = device.yres;
- device.yres = device.xres;
- device.xres = t;
- }
-
- if (device.yres < 768) {
- device.deviceresolution = device.IPHONE;
- }else {
- device.deviceresolution = device.IPAD;
- }
-
- //Manually enable androids here! Mostly just changed buttons sizes
- // device.deviceresolution = device.ANDROID;
-
- //General game variables
- obj.init();
- help.init();
-
- /*obj.createblock(BLOCK,20,200,128,16);
- obj.createblock(BLOCK,130,170,128,16);
- obj.createblock(BLOCK,240,150,128,16);
- obj.createblock(BLOCK,240,20,128,16);
- obj.createblock(BLOCK,130,40,128,16);
- obj.createblock(BLOCK,20,60,128,16);*/
-
- //Input
- key.definestickrange(device.xres / 2, 0, 6);
-
- SoundMixer.soundTransform = new SoundTransform(1);
-
- music.currentsong = -1; music.musicfade = 0;//no music, no amb
- music.initefchannels(); music.currentefchan = 0;
- music.nicechange = -1;
-
- music.numplays = 0;
- music.musicchan.push(new music_1()); // 0: Level Complete
- music.musicchan.push(new vmaintheme_hq()); // 1: VVVVVV Main Theme (Pushing Forward)
- music.musicchan.push(new vtempo_hq()); // 2: VVVVVV Tempo Theme (Positive Force)
- music.musicchan.push(new vpfa_hq()); // 3: Potential for Anything
- music.musicchan.push(new passionforexploring()); // 4: UU Brothers Instrumental
- music.musicchan.push(new souleye_intermission()); // 5: Jingle: Intermission
- music.musicchan.push(new presentingvvvvvv()); // 6: Jingle: Menu Loop
- music.musicchan.push(new music_2()); // 7: Jingle: Game Complete
- music.musicchan.push(new configmegamix_hq()); // 8: Config Megamix
- music.musicchan.push(new posreverse()); // 9: Tempo Theme, Reversed
- music.musicchan.push(new poppot()); // 10: Extra
- music.musicchan.push(new pipedream_hq()); // 11: Highscore
- music.musicchan.push(new pressurecooker_hq()); // 12: Pressure Cooker
- music.musicchan.push(new pacedenergy()); // NEW 13: Paced Energy
- music.musicchan.push(new piercingthesky()); // NEW 14: Piercing the Sky
- music.musicchan.push(new predestinedfateremix()); // NEW 15: Predestined Fate Remix
-
- music.efchan.push(new ef_0());
- music.efchan.push(new ef_1());
- music.efchan.push(new ef_2());
- music.efchan.push(new ef_3());
- music.efchan.push(new ef_4());
- music.efchan.push(new ef_5());
- music.efchan.push(new ef_6());
- music.efchan.push(new ef_7());
- music.efchan.push(new ef_8());
- music.efchan.push(new ef_9());
- music.efchan.push(new ef_10());
- music.efchan.push(new ef_11());
- music.efchan.push(new ef_12());
- music.efchan.push(new ef_13());
- music.efchan.push(new ef_14());
- music.efchan.push(new ef_15());
- music.efchan.push(new ef_16());
- music.efchan.push(new ef_17());
- music.efchan.push(new ef_18());
- music.efchan.push(new ef_19());
- music.efchan.push(new ef_20());
- music.efchan.push(new ef_21());
- music.efchan.push(new ef_22());
- music.efchan.push(new ef_23());
- music.efchan.push(new ef_24());
- music.efchan.push(new ef_25());
- music.efchan.push(new ef_26());
- music.efchan.push(new ef_27());
-
- /*
- Graphics Init
- */
- //First we init the class and add its display list to the main display list
-
- dwgfx.buttonimg.push(new BitmapData(92, 30, true, 0x00000000));
- dwgfx.buttonimg.push(new BitmapData(92, 30, true, 0x00000000));
- dwgfx.buttonimg.push(new BitmapData(40, 40, true, 0x00000000));
- dwgfx.buttonimg.push(new BitmapData(40, 40, true, 0x00000000));
- tempbmp = new im_button_0(); dwgfx.buffer = tempbmp.bitmapData; dwgfx.addbutton();
- tempbmp = new im_button_1(); dwgfx.buffer = tempbmp.bitmapData; dwgfx.addbutton();
- tempbmp = new im_button_2(); dwgfx.buffer = tempbmp.bitmapData; dwgfx.addbutton();
- tempbmp = new im_button_3(); dwgfx.buffer = tempbmp.bitmapData; dwgfx.addbutton();
- tempbmp = new im_button_4(); dwgfx.buffer = tempbmp.bitmapData; dwgfx.addbutton();
- tempbmp = new im_button_5(); dwgfx.buffer = tempbmp.bitmapData; dwgfx.addbutton();
- tempbmp = new im_button_6(); dwgfx.buffer = tempbmp.bitmapData; dwgfx.addbutton();
- tempbmp = new im_button_7(); dwgfx.buffer = tempbmp.bitmapData; dwgfx.addbutton();
- tempbmp = new im_button_8(); dwgfx.buffer = tempbmp.bitmapData; dwgfx.addbutton();
- tempbmp = new im_button_9(); dwgfx.buffer = tempbmp.bitmapData; dwgfx.addbutton();
- tempbmp = new im_button_10(); dwgfx.buffer = tempbmp.bitmapData; dwgfx.addbutton();
- tempbmp = new im_button_11(); dwgfx.buffer = tempbmp.bitmapData; dwgfx.addbutton();
- tempbmp = new im_button_12(); dwgfx.buffer = tempbmp.bitmapData; dwgfx.addbutton();
-
- dwgfx.init();
-
- //We load all our graphics in:
- tempbmp = new im_tiles(); dwgfx.buffer = tempbmp.bitmapData; dwgfx.maketilearray();
- tempbmp = new im_tiles2(); dwgfx.buffer = tempbmp.bitmapData; dwgfx.maketile2array();
- tempbmp = new im_tiles3(); dwgfx.buffer = tempbmp.bitmapData; dwgfx.maketile3array();
- tempbmp = new im_sprites(); dwgfx.buffer = tempbmp.bitmapData; dwgfx.makespritearray();
- tempbmp = new im_flipsprites(); dwgfx.buffer = tempbmp.bitmapData; dwgfx.makeflipspritearray();
- tempbmp = new im_bfont(); dwgfx.buffer = tempbmp.bitmapData; dwgfx.makebfont();
- tempbmp = new im_bfontmask(); dwgfx.buffer = tempbmp.bitmapData; dwgfx.makebfontmask();
- tempbmp = new im_teleporter(); dwgfx.buffer = tempbmp.bitmapData; dwgfx.maketelearray();
- tempbmp = new im_entcolours(); dwgfx.buffer = tempbmp.bitmapData; dwgfx.makeentcolourarray();
- //Load in the images
- tempbmp = new im_image0(); dwgfx.buffer = tempbmp.bitmapData; dwgfx.addimage(); // 0
- tempbmp = new im_image1(); dwgfx.buffer = tempbmp.bitmapData; dwgfx.addimage(); // 1 (this is the minimap!)
- tempbmp = new im_image2(); dwgfx.buffer = tempbmp.bitmapData; dwgfx.addimage(); // 2
- tempbmp = new im_image3(); dwgfx.buffer = tempbmp.bitmapData; dwgfx.addimage(); // 3
- tempbmp = new im_image4(); dwgfx.buffer = tempbmp.bitmapData; dwgfx.addimage(); // 4
- tempbmp = new im_image5(); dwgfx.buffer = tempbmp.bitmapData; dwgfx.addimage(); // 5
- tempbmp = new im_image6(); dwgfx.buffer = tempbmp.bitmapData; dwgfx.addimage(); // 6
- tempbmp = new im_image7(); dwgfx.buffer = tempbmp.bitmapData; dwgfx.addimage(); // 7
- tempbmp = new im_image8(); dwgfx.buffer = tempbmp.bitmapData; dwgfx.addimage(); // 8
- tempbmp = new im_image9(); dwgfx.buffer = tempbmp.bitmapData; dwgfx.addimage(); // 9
- tempbmp = new im_image10(); dwgfx.buffer = tempbmp.bitmapData; dwgfx.addimage(); // 10
-
- tempbmp = new im_image1(); dwgfx.buffer = tempbmp.bitmapData; dwgfx.addimage(); // Minimap
- tempbmp = new im_image1(); dwgfx.buffer = tempbmp.bitmapData; dwgfx.addimage(); // Minimap
-
- tempbmp = new im_mobileimage1(); dwgfx.buffer = tempbmp.bitmapData; dwgfx.addmobileimage();
- tempbmp = new im_mobileimage2(); dwgfx.buffer = tempbmp.bitmapData; dwgfx.addmobileimage();
- tempbmp = new im_mobileimage3(); dwgfx.buffer = tempbmp.bitmapData; dwgfx.addmobileimage();
- tempbmp = new im_mobileimage4(); dwgfx.buffer = tempbmp.bitmapData; dwgfx.addmobileimage();
- tempbmp = new im_mobileimage5(); dwgfx.buffer = tempbmp.bitmapData; dwgfx.addmobileimage();
- tempbmp = new im_mobileimage6(); dwgfx.buffer = tempbmp.bitmapData; dwgfx.addmobileimage();
- tempbmp = new im_mobileimage7(); dwgfx.buffer = tempbmp.bitmapData; dwgfx.addmobileimage();
- tempbmp = new im_mobileimage8(); dwgfx.buffer = tempbmp.bitmapData; dwgfx.addmobileimage();
- tempbmp = new im_mobileimage9(); dwgfx.buffer = tempbmp.bitmapData; dwgfx.addmobileimage();
-
- tempbmp = new im_imgplayerlevel0(); dwgfx.buffer = tempbmp.bitmapData; dwgfx.addplayerlevelimage();
- tempbmp = new im_imgplayerlevel1(); dwgfx.buffer = tempbmp.bitmapData; dwgfx.addplayerlevelimage();
- tempbmp = new im_imgplayerlevel2(); dwgfx.buffer = tempbmp.bitmapData; dwgfx.addplayerlevelimage();
- tempbmp = new im_imgplayerlevel3(); dwgfx.buffer = tempbmp.bitmapData; dwgfx.addplayerlevelimage();
- tempbmp = new im_imgplayerlevel4(); dwgfx.buffer = tempbmp.bitmapData; dwgfx.addplayerlevelimage();
- tempbmp = new im_imgplayerlevel5(); dwgfx.buffer = tempbmp.bitmapData; dwgfx.addplayerlevelimage();
- tempbmp = new im_imgplayerlevel6(); dwgfx.buffer = tempbmp.bitmapData; dwgfx.addplayerlevelimage();
- tempbmp = new im_imgplayerlevel7(); dwgfx.buffer = tempbmp.bitmapData; dwgfx.addplayerlevelimage();
- tempbmp = new im_imgplayerlevel8(); dwgfx.buffer = tempbmp.bitmapData; dwgfx.addplayerlevelimage();
- tempbmp = new im_imgplayerlevel9(); dwgfx.buffer = tempbmp.bitmapData; dwgfx.addplayerlevelimage();
- tempbmp = new im_imgplayerlevel10(); dwgfx.buffer = tempbmp.bitmapData; dwgfx.addplayerlevelimage();
- tempbmp = new im_imgplayerlevel11(); dwgfx.buffer = tempbmp.bitmapData; dwgfx.addplayerlevelimage();
- tempbmp = new im_imgplayerlevel12(); dwgfx.buffer = tempbmp.bitmapData; dwgfx.addplayerlevelimage();
- tempbmp = new im_imgplayerlevel13(); dwgfx.buffer = tempbmp.bitmapData; dwgfx.addplayerlevelimage();
- tempbmp = new im_imgplayerlevel14(); dwgfx.buffer = tempbmp.bitmapData; dwgfx.addplayerlevelimage();
- tempbmp = new im_imgplayerlevel15(); dwgfx.buffer = tempbmp.bitmapData; dwgfx.addplayerlevelimage();
- tempbmp = new im_imgplayerlevel16(); dwgfx.buffer = tempbmp.bitmapData; dwgfx.addplayerlevelimage();
-
- //Now that the graphics are loaded, init the background buffer
- dwgfx.buffer=new BitmapData(320,240,false,0x000000);
-
- stage.scaleMode = StageScaleMode.NO_SCALE;
- stage.align = StageAlign.TOP_LEFT;
- stage.quality = StageQuality.LOW;
-
- //EXACT FIT
- dwgfx.screensizemultiplier = device.yres / 240;
- dwgfx.screen.width = 320 * dwgfx.screensizemultiplier;
- dwgfx.screen.height = device.yres;
-
- dwgfx.screen.x = (device.xres / 2) - (320 * dwgfx.screensizemultiplier / 2);
- dwgfx.screen.y = 0;
-
- dwgfx.initbuttonpositions();
-
- //PIXEL PERFECT
- /*
- dwgfx.screensizemultiplier = int(device.yres / 240);
- dwgfx.screen.width = 320 * dwgfx.screensizemultiplier;
- dwgfx.screen.height = 240 * dwgfx.screensizemultiplier;
-
- dwgfx.screenoffx = (device.xres / 2) - (320 * dwgfx.screensizemultiplier / 2);
- dwgfx.screenoffy = (device.yres / 2) - (240 * dwgfx.screensizemultiplier / 2);
- dwgfx.screen.x = dwgfx.screenoffx;
- dwgfx.screen.y = dwgfx.screenoffy;
- */
-
- addChild(dwgfx);
- //stage.addChild(new TheMiner()); //Profiler
-
-
- //Iphone orientation fix
- var startOrientation:String = stage.orientation;
- if (startOrientation == StageOrientation.DEFAULT || startOrientation == StageOrientation.UPSIDE_DOWN){
- //stage.setOrientation(StageOrientation.ROTATED_RIGHT);
- stage.setAspectRatio(StageAspectRatio.LANDSCAPE);
- }else{
- stage.setOrientation(startOrientation);
- }
- stage.addEventListener(StageOrientationEvent.ORIENTATION_CHANGING, orientationChangeListener);
-
- game = new gameclass(dwgfx, map, obj, help, music);
-
-
- map.ypos = (700-29) * 8;
- map.bypos = map.ypos / 2;
- map.cameramode = 0;
-
-
- ///Test Start:
- //-- Comment this for real start
- /*
- gamestate = GAMEMODE;
- /*map.finalmode = true; //Enable final level mode
- //map.finalx = 41; map.finaly = 52; //Midpoint
- //map.finalx = 48; map.finaly = 52; //Just before the tower
+ map.ypos = (700-29) * 8;
+ map.bypos = map.ypos / 2;
+ map.cameramode = 0;
+
+
+ ///Test Start:
+ //-- Comment this for real start
+ /*
+ gamestate = GAMEMODE;
+ /*map.finalmode = true; //Enable final level mode
+ //map.finalx = 41; map.finaly = 52; //Midpoint
+ //map.finalx = 48; map.finaly = 52; //Just before the tower
+ map.finalx = 46; map.finaly = 54; //Current
+ //map.finalstretch = true;
+ map.final_colormode = true;
+ map.final_mapcol = 0;
+ map.final_colorframe = 0;
+ */
+ /*
+ game.starttest(obj, music);
+ obj.createentity(game, game.savex, game.savey, 0); //In this game, constant, never destroyed
+ map.gotoroom(game.saverx, game.savery, dwgfx, game, obj, music);
+ music.play(1);
+ */
+ //game.crewstats[1] = true;
+ //game.crewstats[2] = true;
+ //game.crewstats[3] = true;
+ //game.crewstats[4] = true;
+ //game.crewstats[5] = true;
+ //script.load("intro");
+
+ //crew member test
+ //obj.createentity(game, game.savex - 10, game.savey - 10, 14);
+ //game.companion = 6; //different rules for different members
+
+
+
+ //--
+ //Uncomment this if testing the final level
+ /*
+ map.finalmode = true; //Enable final level mode
map.finalx = 46; map.finaly = 54; //Current
- //map.finalstretch = true;
+ //map.finalx = 41; map.finaly = 52; //Midpoint
+ map.final_colormode = false; map.final_mapcol = 0; map.final_colorframe = 0;
+ */
+ //And this if after the midpoint:
+ /*
+ map.finalx = 52; map.finaly = 53; //Current
+ map.finalstretch = true;
map.final_colormode = true;
map.final_mapcol = 0;
map.final_colorframe = 0;
- */
- /*
- game.starttest(obj, music);
- obj.createentity(game, game.savex, game.savey, 0); //In this game, constant, never destroyed
- map.gotoroom(game.saverx, game.savery, dwgfx, game, obj, music);
- music.play(1);
- */
- //game.crewstats[1] = true;
- //game.crewstats[2] = true;
- //game.crewstats[3] = true;
- //game.crewstats[4] = true;
- //game.crewstats[5] = true;
- //script.load("intro");
-
- //crew member test
- //obj.createentity(game, game.savex - 10, game.savey - 10, 14);
- //game.companion = 6; //different rules for different members
-
-
-
- //--
- //Uncomment this if testing the final level
- /*
- map.finalmode = true; //Enable final level mode
- map.finalx = 46; map.finaly = 54; //Current
- //map.finalx = 41; map.finaly = 52; //Midpoint
- map.final_colormode = false; map.final_mapcol = 0; map.final_colorframe = 0;
- */
- //And this if after the midpoint:
- /*
- map.finalx = 52; map.finaly = 53; //Current
- map.finalstretch = true;
- map.final_colormode = true;
- map.final_mapcol = 0;
- map.final_colorframe = 0;
- //map.background = 6;
- */
- //-- Jumping right in
- /*
- game.gamestate = GAMEMODE;
- game.starttest(obj, music);
- //game.loadquick(map, obj, music);
- obj.createentity(game, game.savex, game.savey, 0); //In this game, constant, never destroyed
- map.gotoroom(game.saverx, game.savery, dwgfx, game, obj, music);
- music.play(4);
- //fscommand("quit");
-
- game.crewstats[1] = true;
- //game.crewstats[2] = true;
- game.crewstats[3] = true;
- game.crewstats[4] = true;
- //game.crewstats[5] = true;
-
- map.showtargets = true;
- map.showteleporters = true;
- //map.showtrinkets = true;
-
- //obj.flags[34] = 1;
- //obj.flags[20] = 1;
- //obj.flags[67] = 1; //Game complete
+ //map.background = 6;
+ */
+ //-- Jumping right in
+ /*
+ game.gamestate = GAMEMODE;
+ game.starttest(obj, music);
+ //game.loadquick(map, obj, music);
+ obj.createentity(game, game.savex, game.savey, 0); //In this game, constant, never destroyed
+ map.gotoroom(game.saverx, game.savery, dwgfx, game, obj, music);
+ music.play(4);
+ //fscommand("quit");
+
+ game.crewstats[1] = true;
+ //game.crewstats[2] = true;
+ game.crewstats[3] = true;
+ game.crewstats[4] = true;
+ //game.crewstats[5] = true;
+
+ map.showtargets = true;
+ map.showteleporters = true;
+ //map.showtrinkets = true;
+
+ //obj.flags[34] = 1;
+ //obj.flags[20] = 1;
+ //obj.flags[67] = 1; //Game complete
+ for (i = 0; i < 20; i++) {
+ obj.collect[i] = true;
+ }
+ game.trinkets = 19; obj.collect[18] = false;
+ game.stat_trinkets = 20;
+ //obj.altstates = 1;
+
+ //initilise map info
+ for (j = 0; j < 20; j++) {
for (i = 0; i < 20; i++) {
- obj.collect[i] = true;
+ map.explored[i + (j * 20)] = 1;
}
- game.trinkets = 19; obj.collect[18] = false;
- game.stat_trinkets = 20;
- //obj.altstates = 1;
-
- //initilise map info
- for (j = 0; j < 20; j++) {
- for (i = 0; i < 20; i++) {
- map.explored[i + (j * 20)] = 1;
- }
- }
- */
- //obj.entities[obj.getplayer()].size = 13;
-
- //game.gamestate = 6;
-
- //game.intimetrail = true; game.timetrialcountdown = 0;
- //game.nodeathmode = true;
- //dwgfx.flipmode = true;
- //game.nocutscenes = true;
- //map.invincibility = true;
- //stage.frameRate = 24;
- //game.colourblindmode = true;
- //game.noflashingmode = true;
- //for intermission 2 test
- //game.lastsaved = 3;
- /*
- game.swnmode = true;
- game.swngame = 2;
- game.swndelay = 120;
- game.swntimer = 60 * 30;
- */
- //script.load("intermission_2");
-
-
- //for intermission 1 test
- /*
- game.companion = 11;
- game.supercrewmate = true;
- game.scmprogress = 0;
- game.scmprogress = 10;
- game.lastsaved = 4;
- music.play(8);
- */
- //game.sfpsmode = true; //Run at 60 FPS
- //stage.frameRate = 60; // doesn't work, it's a bit more complex than this - will have to do a double sized window instead...
-
- //dwgfx.flipmode = true;
-
- //Testing some unlock stuff
- /*
- game.unlock[9] = true; //Space Station Intro Time Trial
- game.unlock[10] = true; //Lab Time Trial
- game.unlock[11] = true; //Tower Time Trial
- game.unlock[12] = true; //Space Station 2 Time Trial
- game.unlock[13] = true; //Warp Zone Time Trial
- game.unlock[14] = true; //Final Level Time Trial
-
- game.unlock[17] = true; //No death mode
- game.unlock[18] = true; //Flip Mode
-
- */
- //-- Normal start, with no fancy stuff!
-
- /*
- game.gamestate = CLICKTOSTART;
- dwgfx.createtextbox(" Click to Start ", 96, 107, 164, 164, 255);
- dwgfx.textboxcenter();
- */
- //No click to start any more! Instead go right to the menu
-
- //INIT GRAPHIC MODE HERE
- game.loadstats(map, dwgfx);
-
- //updategraphicsmode(game, dwgfx);
-
- game.gamestate = TITLEMODE;
-
- game.menustart = false;
- game.mainmenu = 0;
-
- /*if (game.quicksummary != "") {
- game.mainmenu = 2;
- }
- if (game.telesummary != "") {
- game.mainmenu = 1;
- }*/ //what the hell is that for
-
-
- /*
- game.gamestate = 6;
- game.menustart = true;
- map.ypos = (700-29) * 8;
- map.bypos = map.ypos / 2;
- map.cameramode = 0;
- */
- //--Everything after this is screen recording
-
- //ok, screenrecording here
- //don't record anything (comment both next parts)
-
- game.recording = 0;
-
- if(game.recording==1){
- trace("warning! recording input!");
- }else if(game.recording==2){
- trace("playing back input!");
- game.recordstring = "blahblahblah";
- help.toclipboard(game.recordstring);
-
- game.initplayback();
- game.playbackpos = 5;
- game.savex = game.playback[0]; game.savey = game.playback[1];
- game.saverx = game.playback[2]; game.savery = game.playback[3];
- game.savegc = game.playback[4]; game.savedir = 1;
- }
-
- //addEventListener(Event.ENTER_FRAME, mainloop);
-
- // start the tick-timer, which updates roughly every 4 milliseconds
- _timer.addEventListener(TimerEvent.TIMER, mainloop);
- _timer.start();
- }else {
- dwgfx.init();
- addChild(dwgfx);
- //We load the font in:
- tempbmp = new im_bfont(); dwgfx.buffer = tempbmp.bitmapData; dwgfx.makebfont();
- tempbmp = new im_bfontmask(); dwgfx.buffer = tempbmp.bitmapData; dwgfx.makebfontmask();
- //Now that the graphics are loaded, init the background buffer
- dwgfx.buffer = new BitmapData(320, 240, false, 0x000000);
-
- addEventListener(Event.ENTER_FRAME, lockedloop);
}
- }
-
- public function visit_distractionware(e:Event):void{
- var distractionware_link:URLRequest = new URLRequest( "http://www.distractionware.com" );
- navigateToURL( distractionware_link, "_blank" );
- }
-
- public function visit_sponsor(e:Event):void{
- var sponsor_link:URLRequest = new URLRequest( "http://www.kongregate.com/?gamereferral=dontlookback" );
- navigateToURL( sponsor_link, "_blank" );
- }
-
- public function visit_sponsor_logo():void{
- var sponsor_link:URLRequest = new URLRequest( "http://www.kongregate.com/?gamereferral=dontlookback" );
- navigateToURL( sponsor_link, "_blank" );
- }
-
- /*
- public function androidresize(e:Event):void {
- if (immersivemode) {
- device.xres = stage.stageWidth;
- device.yres = stage.stageHeight;
- }else{
- device.xres = flash.system.Capabilities.screenResolutionX;
- device.yres = flash.system.Capabilities.screenResolutionY;
+ */
+ //obj.entities[obj.getplayer()].size = 13;
+
+ //game.gamestate = 6;
+
+ //game.intimetrail = true; game.timetrialcountdown = 0;
+ //game.nodeathmode = true;
+ //dwgfx.flipmode = true;
+ //game.nocutscenes = true;
+ //map.invincibility = true;
+ //stage.frameRate = 24;
+ //game.colourblindmode = true;
+ //game.noflashingmode = true;
+ //for intermission 2 test
+ //game.lastsaved = 3;
+ /*
+ game.swnmode = true;
+ game.swngame = 2;
+ game.swndelay = 120;
+ game.swntimer = 60 * 30;
+ */
+ //script.load("intermission_2");
+
+
+ //for intermission 1 test
+ /*
+ game.companion = 11;
+ game.supercrewmate = true;
+ game.scmprogress = 0;
+ game.scmprogress = 10;
+ game.lastsaved = 4;
+ music.play(8);
+ */
+ //game.sfpsmode = true; //Run at 60 FPS
+ //stage.frameRate = 60; // doesn't work, it's a bit more complex than this - will have to do a double sized window instead...
+
+ //dwgfx.flipmode = true;
+
+ //Testing some unlock stuff
+ /*
+ game.unlock[9] = true; //Space Station Intro Time Trial
+ game.unlock[10] = true; //Lab Time Trial
+ game.unlock[11] = true; //Tower Time Trial
+ game.unlock[12] = true; //Space Station 2 Time Trial
+ game.unlock[13] = true; //Warp Zone Time Trial
+ game.unlock[14] = true; //Final Level Time Trial
+
+ game.unlock[17] = true; //No death mode
+ game.unlock[18] = true; //Flip Mode
+
+ */
+ //-- Normal start, with no fancy stuff!
+
+ /*
+ game.gamestate = CLICKTOSTART;
+ dwgfx.createtextbox(" Click to Start ", 96, 107, 164, 164, 255);
+ dwgfx.textboxcenter();
+ */
+ //No click to start any more! Instead go right to the menu
+
+ //INIT GRAPHIC MODE HERE
+ game.loadstats(map, dwgfx);
+ //updategraphicsmode(game, dwgfx);
+
+ game.gamestate = TITLEMODE;
+
+ game.menustart = false;
+ game.mainmenu = 0;
+
+ /*if (game.quicksummary != "") {
+ game.mainmenu = 2;
}
- if (device.xres < device.yres) {
- //Switch them!
- t = device.yres;
- device.yres = device.xres;
- device.xres = t;
+ if (game.telesummary != "") {
+ game.mainmenu = 1;
+ }*/ //what the hell is that for
+
+
+ /*
+ game.gamestate = 6;
+ game.menustart = true;
+ map.ypos = (700-29) * 8;
+ map.bypos = map.ypos / 2;
+ map.cameramode = 0;
+ */
+ //--Everything after this is screen recording
+
+ //ok, screenrecording here
+ //don't record anything (comment both next parts)
+
+ game.recording = 0;
+
+ if(game.recording==1){
+ trace("warning! recording input!");
+ }else if(game.recording==2){
+ trace("playing back input!");
+ game.recordstring = "blahblahblah";
+ help.toclipboard(game.recordstring);
+
+ game.initplayback();
+ game.playbackpos = 5;
+ game.savex = game.playback[0]; game.savey = game.playback[1];
+ game.saverx = game.playback[2]; game.savery = game.playback[3];
+ game.savegc = game.playback[4]; game.savedir = 1;
}
- key.definestickrange(device.xres / 2, 0, 6);
+ //addEventListener(Event.ENTER_FRAME, mainloop);
- dwgfx.screensizemultiplier = device.yres / 240;
- dwgfx.screen.width = 320 * dwgfx.screensizemultiplier;
- dwgfx.screen.height = device.yres;
-
- dwgfx.screen.x = (device.xres / 2) - (320 * dwgfx.screensizemultiplier / 2);
- dwgfx.screen.y = 0;
-
- dwgfx.initbuttonpositions();
- }
- */
-
- public function orientationChangeListener(e:StageOrientationEvent):void{
- if (e.afterOrientation == StageOrientation.DEFAULT || e.afterOrientation == StageOrientation.UPSIDE_DOWN) {
- e.preventDefault();
- }
- }
-
- public function lockedloop(e:Event):void {
- dwgfx.backbuffer.lock();
-
- dwgfx.bprint(5, 110, "Sorry! This game can only be", 196-help.glow, 196-help.glow, 255-help.glow, true);
- dwgfx.bprint(5, 120, "played on thelettervsixtim.es", 196-help.glow, 196-help.glow, 255-help.glow, true);
- dwgfx.render();
- dwgfx.backbuffer.unlock();
-
- help.updateglow();
+ dwgfx.starlingassets.loadQueue(function(ratio:Number):void {
+ trace(ratio);
+ if (ratio == 1){
+ waitforassetstoload();
+ }
+ });
}
- public function setstage(w:int, h:int):void {
- //stage.stageWidth = w;
- //stage.stageHeight = h;
+ public function waitforassetstoload():void {
+ //Wait till this has loaded the texture before processing
+ dwgfx.button_texture.push(new RenderTexture(92, 30));
+ dwgfx.button_texture.push(new RenderTexture(92, 30));
+ dwgfx.button_texture.push(new RenderTexture(40, 40));
+ dwgfx.button_texture.push(new RenderTexture(40, 40));
+ dwgfx.addbutton("mobilebuttons/map");
+ dwgfx.addbutton("mobilebuttons/back");
+ dwgfx.addbutton("mobilebuttons/talk_1");
+ dwgfx.addbutton("mobilebuttons/talk_2");
+ dwgfx.addbutton("mobilebuttons/use_1");
+ dwgfx.addbutton("mobilebuttons/use_2");
+ dwgfx.addbutton("mobilebuttons/teleport_1");
+ dwgfx.addbutton("mobilebuttons/teleport_2");
+ dwgfx.addbutton("mobilebuttons/controls_1");
+ dwgfx.addbutton("mobilebuttons/controls_2");
+ dwgfx.addbutton("mobilebuttons/gamecenter");
+ dwgfx.addbutton("mobilebuttons/button_left");
+ dwgfx.addbutton("mobilebuttons/button_right");
+ dwgfx.initbuttonstuff();
+
+ //We load all our graphics in:
+ dwgfx.maketilearray();
+ dwgfx.maketile2array();
+ dwgfx.maketile3array();
+ dwgfx.makespritearray();
+ dwgfx.makeflipspritearray();
+ dwgfx.maketelearray();
+ dwgfx.makeentcolourarray();
+
+ //Load in the images
+ dwgfx.addimage("levelcomplete"); // 0
+ dwgfx.addimage("minimap"); // 1 (this is the minimap!)
+ dwgfx.addimage("covered"); // 2
+ dwgfx.addimage("elephant"); // 3
+ dwgfx.addimage("gamecomplete"); // 4
+ dwgfx.addimage("fliplevelcomplete"); // 5
+ dwgfx.addimage("flipgamecomplete"); // 6
+ dwgfx.addimage("site"); // 7
+ dwgfx.addimage("site2"); // 8
+ dwgfx.addimage("site3"); // 9
+ dwgfx.addimage("ending"); // 10
+
+ dwgfx.addimage("minimap"); // Minimap
+ dwgfx.addimage_rendertexture("minimap"); // Minimap
+
+ dwgfx.addmobileimage("controls/touchscreen");
+ dwgfx.addmobileimage("controls/lefthand_off");
+ dwgfx.addmobileimage("controls/lefthand_near");
+ dwgfx.addmobileimage("controls/lefthand_far");
+ dwgfx.addmobileimage("controls/righthand_off");
+ dwgfx.addmobileimage("controls/righthand_near");
+ dwgfx.addmobileimage("controls/righthand_far");
+ dwgfx.addmobileimage("controls/arrowleft");
+ dwgfx.addmobileimage("controls/arrowright");
+
+ dwgfx.addplayerlevelimage("playerlevels/playerlevel_0");
+ dwgfx.addplayerlevelimage("playerlevels/playerlevel_1");
+ dwgfx.addplayerlevelimage("playerlevels/playerlevel_2");
+ dwgfx.addplayerlevelimage("playerlevels/playerlevel_3");
+ dwgfx.addplayerlevelimage("playerlevels/playerlevel_4");
+ dwgfx.addplayerlevelimage("playerlevels/playerlevel_5");
+ dwgfx.addplayerlevelimage("playerlevels/playerlevel_6");
+ dwgfx.addplayerlevelimage("playerlevels/playerlevel_7");
+ dwgfx.addplayerlevelimage("playerlevels/playerlevel_8");
+ dwgfx.addplayerlevelimage("playerlevels/playerlevel_9");
+ dwgfx.addplayerlevelimage("playerlevels/playerlevel_10");
+ dwgfx.addplayerlevelimage("playerlevels/playerlevel_11");
+ dwgfx.addplayerlevelimage("playerlevels/playerlevel_12");
+ dwgfx.addplayerlevelimage("playerlevels/playerlevel_13");
+ dwgfx.addplayerlevelimage("playerlevels/playerlevel_14");
+ dwgfx.addplayerlevelimage("playerlevels/playerlevel_15");
+ dwgfx.addplayerlevelimage("playerlevels/playerlevel_16");
+
+ var c64fontbm:BitmapFont = new BitmapFont(dwgfx.starlingassets.getTexture("c64/c64_0"),
+ XML(new c64font_xml));
+ TextField.registerCompositor(c64fontbm, "c64");
+
+ _timer.addEventListener(TimerEvent.TIMER, mainloop);
+ _timer.start();
+
+ androidresize();
}
public function sitelock():Boolean {
- //No preloader for Kong version
- var currUrl:String = stage.loaderInfo.url.toLowerCase();
- //chat.kongregate.com
- if ((currUrl.indexOf("ile:///") <= 0) || (currUrl.indexOf("http") == 0)){
- //if ((currUrl.indexOf("distractionware.com/games") <= 0) && (currUrl.indexOf("thelettervsixtim.es/secretarea") <= 0)){
- return true;
- //return false;
- }else{
- return true;
- }
+ //we don't care about this on mobile
+ return true;
}
public function input():void {
@@ -741,9 +574,9 @@
if (game.platform.wakeupcall > 0) {
game.platform.wakeupcall--;
if (game.platform.wakeupcall == 0) {
- if(immersivemode){
- //AndroidFullScreen.immersiveMode();
- }
+ //if(immersivemode){
+ // AndroidFullScreen.immersiveMode();
+ //}
}
}
@@ -768,52 +601,54 @@
}
}
- public function render():void {
- if (!game.infocus) {
- dwgfx.backbuffer.lock();
- /*
- dwgfx.bprint(5, 110, "Game paused", 196 - help.glow, 255 - help.glow, 196 - help.glow, true);
- dwgfx.bprint(5, 120, "[click to resume]", 196 - help.glow, 255 - help.glow, 196 - help.glow, true);
- dwgfx.bprint(5, 230, "Press M to mute in game", 164 - help.glow, 196 - help.glow, 164 - help.glow, true);
- */
- dwgfx.render();
- dwgfx.backbuffer.unlock();
- }else {
- switch(game.gamestate){
- case TITLEMODE:
- titlerender(key, dwgfx, map, game, obj, help);
- break;
- case GAMEMODE:
- if (map.towermode) {
- towerrender(key, dwgfx, game, map, obj, help);
- }else{
- gamerender(key, dwgfx, game, map, obj, help);
- }
- break;
- case CONTROLTUTORIALMODE:
- controltutorialrender(key, dwgfx, game, map, obj, help);
- break;
- case MAPMODE:
- maprender(key, dwgfx, game, map, obj, help);
- break;
- case TELEPORTERMODE:
- teleporterrender(key, dwgfx, game, map, obj, help);
- break;
- case GAMECOMPLETE:
- gamecompleterender(key, dwgfx, game, obj, help);
- break;
- case GAMECOMPLETE2:
- gamecompleterender2(key, dwgfx, game, obj, help);
- break;
- case CLICKTOSTART:
- dwgfx.backbuffer.lock();
- //dwgfx.bprint(5, 115, "[Click to start]", 196 - help.glow, 196 - help.glow, 255 - help.glow, true);
- dwgfx.drawgui(help);
- dwgfx.render();
- dwgfx.backbuffer.unlock();
- break;
+ public function dorender():void {
+ dwgfx.backbuffer.drawBundled(function():void {
+ if (!game.infocus) {
+ //dwgfx.backbuffer.lock();
+ /*
+ dwgfx.bprint(5, 110, "Game paused", 196 - help.glow, 255 - help.glow, 196 - help.glow, true);
+ dwgfx.bprint(5, 120, "[click to resume]", 196 - help.glow, 255 - help.glow, 196 - help.glow, true);
+ dwgfx.bprint(5, 230, "Press M to mute in game", 164 - help.glow, 196 - help.glow, 164 - help.glow, true);
+ */
+ dwgfx.render();
+ //dwgfx.backbuffer.unlock();
+ }else {
+ switch(game.gamestate){
+ case TITLEMODE:
+ titlerender(key, dwgfx, map, game, obj, help);
+ break;
+ case GAMEMODE:
+ if (map.towermode) {
+ towerrender(key, dwgfx, game, map, obj, help);
+ }else{
+ gamerender(key, dwgfx, game, map, obj, help);
+ }
+ break;
+ case CONTROLTUTORIALMODE:
+ controltutorialrender(key, dwgfx, game, map, obj, help);
+ break;
+ case MAPMODE:
+ maprender(key, dwgfx, game, map, obj, help);
+ break;
+ case TELEPORTERMODE:
+ teleporterrender(key, dwgfx, game, map, obj, help);
+ break;
+ case GAMECOMPLETE:
+ gamecompleterender(key, dwgfx, game, map, obj, help);
+ break;
+ case GAMECOMPLETE2:
+ gamecompleterender2(key, dwgfx, game, obj, help);
+ break;
+ case CLICKTOSTART:
+ //dwgfx.backbuffer.lock();
+ //dwgfx.bprint(5, 115, "[Click to start]", 196 - help.glow, 196 - help.glow, 255 - help.glow, true);
+ dwgfx.drawgui(help);
+ dwgfx.render();
+ //dwgfx.backbuffer.unlock();
+ break;
+ }
}
- }
+ });
}
public function mainloop(e:TimerEvent):void {
@@ -829,82 +664,45 @@
logic();
if (key.hasclicked) key.click = false;
}
- render();
+ dorender();
e.updateAfterEvent();
}
}
- public function setzoom(t:int, dwgfx:dwgraphicsclass):void {
- /*
- switch(t) {
- case 1:
- dwgfx.screen.width = 320;
- dwgfx.screen.height = 240;
- dwgfx.screen.x = (640 - 320) / 2;
- dwgfx.screen.y = (480 - 240) / 2;
- break;
- case 2:
- dwgfx.screen.width = 640;
- dwgfx.screen.height = 480;
- dwgfx.screen.x = 0;
- dwgfx.screen.y = 0;
- break;
- case 3:
- dwgfx.screen.width = 960;
- dwgfx.screen.height = 720;
- dwgfx.screen.x = (640 - 960) / 2;
- dwgfx.screen.y = (480 - 720) / 2;
- break;
- case 4:
- dwgfx.screen.width = 1280;
- dwgfx.screen.height = 960;
- dwgfx.screen.x = (640 - 1280) / 2;
- dwgfx.screen.y = (480 - 960) / 2;
- break;
- }
- */
+ public function androidresize():void {
+ /*if(immersivemode){
+ AndroidFullScreen.stage = Starling.current.nativeStage; // Set this to your app's stage
+ AndroidFullScreen.fullScreen();
+
+ device.xres = AndroidFullScreen.immersiveWidth;
+ device.yres = AndroidFullScreen.immersiveHeight;
+ }else {*/
+ Starling.current.nativeStage.displayState = StageDisplayState.FULL_SCREEN_INTERACTIVE;
+ if(!device.localtesting){
+ //device.xres = flash.system.Capabilities.screenResolutionX;
+ //device.yres = flash.system.Capabilities.screenResolutionY;
+ device.xres = Screen.mainScreen.safeArea.width;
+ device.yres = Screen.mainScreen.safeArea.height;
+ }else{
+ device.xres = 1280;
+ device.yres = 800;
+ }
+ //}
+
+ if (device.xres < device.yres) {
+ //Switch them!
+ var t:int = device.yres;
+ device.yres = device.xres;
+ device.xres = t;
+ }
+ key.definestickrange(device.xres / 2, 0, 6);
+
+ dwgfx.updatescreen(device.xres, device.yres);
+ if(dwgfx.buttonsready) dwgfx.initbuttonpositions();
}
public function updategraphicsmode(game:gameclass, dwgfx:dwgraphicsclass):void {
- /*
- swfStage = stage;
-
- if (game.advanced_mode) { //advanced graphics mode
- //Screen Smooting
- dwgfx.screen.smoothing = game.advanced_smoothing;
-
- //Scaling
- if(game.advanced_scaling==0){
- swfStage.scaleMode = StageScaleMode.SHOW_ALL;
- setzoom(2, dwgfx);
- }else{
- swfStage.scaleMode = StageScaleMode.NO_SCALE; //Turn Scaling off
- setzoom(game.advanced_scaling, dwgfx);
- }
-
- stage.fullScreenSourceRect = null;
- //Fullscreen
- if (game.fullscreen) {
- stage.displayState = StageDisplayState.FULL_SCREEN;
- Mouse.hide();
- }else {
- stage.displayState = StageDisplayState.NORMAL;
- Mouse.show();
- }
- }else{
- swfStage.scaleMode = StageScaleMode.SHOW_ALL;
- if (game.fullscreen) {
- dwgfx.screen.smoothing = true;
- stage.fullScreenSourceRect = new Rectangle(0, 0, 640, 480);
- stage.displayState = StageDisplayState.FULL_SCREEN;
- Mouse.hide();
- }else {
- dwgfx.screen.smoothing = false;
- stage.displayState = StageDisplayState.NORMAL;
- Mouse.show();
- }
- }
- */
+ //ghost of a function that once was
}
// Timer information (a shout out to ChevyRay for the implementation)
@@ -916,6 +714,7 @@
private var _delta:Number = 0;
private var _timer:Timer = new Timer(4);
+
public var dwgfx:dwgraphicsclass = new dwgraphicsclass();
public var music:musicclass = new musicclass();
public var help:helpclass = new helpclass();
@@ -932,75 +731,12 @@
public var i:int, j:int, k:int, temp:int, tempx:int, tempy:int, tempstring:String;
public var tr:int, tg:int, tb:int, t:int;
public var tvel:Number;
- public var swfStage:Stage;
public var immersivemode:Boolean;
- //Embedded resources:
- //Graphics
- [Embed(source = '../data/graphics/tiles.png')] private var im_tiles:Class;
- [Embed(source = '../data/graphics/tiles2.png')] private var im_tiles2:Class;
- [Embed(source = '../data/graphics/tiles3.png')] private var im_tiles3:Class;
- [Embed(source = '../data/graphics/sprites.png')] private var im_sprites:Class;
- [Embed(source = '../data/graphics/flipsprites.png')] private var im_flipsprites:Class;
- [Embed(source = '../data/graphics/font.png')] private var im_bfont:Class;
- [Embed(source = '../data/graphics/fontmask.png')] private var im_bfontmask:Class;
- [Embed(source = '../data/graphics/teleporter.png')] private var im_teleporter:Class;
- [Embed(source = '../data/graphics/entcolours.png')] private var im_entcolours:Class;
- [Embed(source = '../data/graphics/levelcomplete.png')] private var im_image0:Class;
- [Embed(source = '../data/graphics/minimap.png')] private var im_image1:Class;
- [Embed(source = '../data/graphics/covered.png')] private var im_image2:Class;
- [Embed(source = '../data/graphics/elephant.png')] private var im_image3:Class;
- [Embed(source = '../data/graphics/gamecomplete.png')] private var im_image4:Class;
- [Embed(source = '../data/graphics/fliplevelcomplete.png')] private var im_image5:Class;
- [Embed(source = '../data/graphics/flipgamecomplete.png')] private var im_image6:Class;
- [Embed(source = '../data/graphics/site.png')] private var im_image7:Class;
- [Embed(source = '../data/graphics/site2.png')] private var im_image8:Class;
- [Embed(source = '../data/graphics/site3.png')] private var im_image9:Class;
- [Embed(source = '../data/graphics/ending.png')] private var im_image10:Class;
+ [Embed(source="../data/c64.fnt", mimeType="application/octet-stream")]
+ public static const c64font_xml:Class;
- [Embed(source = '../data/graphics/controls/touchscreen.png')] private var im_mobileimage1:Class;
- [Embed(source = '../data/graphics/controls/lefthand_off.png')] private var im_mobileimage2:Class;
- [Embed(source = '../data/graphics/controls/lefthand_near.png')] private var im_mobileimage3:Class;
- [Embed(source = '../data/graphics/controls/lefthand_far.png')] private var im_mobileimage4:Class;
- [Embed(source = '../data/graphics/controls/righthand_off.png')] private var im_mobileimage5:Class;
- [Embed(source = '../data/graphics/controls/righthand_near.png')] private var im_mobileimage6:Class;
- [Embed(source = '../data/graphics/controls/righthand_far.png')] private var im_mobileimage7:Class;
- [Embed(source = '../data/graphics/controls/arrowleft.png')] private var im_mobileimage8:Class;
- [Embed(source = '../data/graphics/controls/arrowright.png')] private var im_mobileimage9:Class;
- //Playerlevel images
- [Embed(source = '../data/graphics/playerlevels/playerlevel_0.png')] private var im_imgplayerlevel0:Class;
- [Embed(source = '../data/graphics/playerlevels/playerlevel_1.png')] private var im_imgplayerlevel1:Class;
- [Embed(source = '../data/graphics/playerlevels/playerlevel_2.png')] private var im_imgplayerlevel2:Class;
- [Embed(source = '../data/graphics/playerlevels/playerlevel_3.png')] private var im_imgplayerlevel3:Class;
- [Embed(source = '../data/graphics/playerlevels/playerlevel_4.png')] private var im_imgplayerlevel4:Class;
- [Embed(source = '../data/graphics/playerlevels/playerlevel_5.png')] private var im_imgplayerlevel5:Class;
- [Embed(source = '../data/graphics/playerlevels/playerlevel_6.png')] private var im_imgplayerlevel6:Class;
- [Embed(source = '../data/graphics/playerlevels/playerlevel_7.png')] private var im_imgplayerlevel7:Class;
- [Embed(source = '../data/graphics/playerlevels/playerlevel_8.png')] private var im_imgplayerlevel8:Class;
- [Embed(source = '../data/graphics/playerlevels/playerlevel_9.png')] private var im_imgplayerlevel9:Class;
- [Embed(source = '../data/graphics/playerlevels/playerlevel_10.png')] private var im_imgplayerlevel10:Class;
- [Embed(source = '../data/graphics/playerlevels/playerlevel_11.png')] private var im_imgplayerlevel11:Class;
- [Embed(source = '../data/graphics/playerlevels/playerlevel_12.png')] private var im_imgplayerlevel12:Class;
- [Embed(source = '../data/graphics/playerlevels/playerlevel_13.png')] private var im_imgplayerlevel13:Class;
- [Embed(source = '../data/graphics/playerlevels/playerlevel_14.png')] private var im_imgplayerlevel14:Class;
- [Embed(source = '../data/graphics/playerlevels/playerlevel_15.png')] private var im_imgplayerlevel15:Class;
- [Embed(source = '../data/graphics/playerlevels/playerlevel_16.png')] private var im_imgplayerlevel16:Class;
- //iOS Buttons
- [Embed(source = '../data/graphics/mobilebuttons/map.png')] private var im_button_0:Class;
- [Embed(source = '../data/graphics/mobilebuttons/back.png')] private var im_button_1:Class;
- [Embed(source = '../data/graphics/mobilebuttons/talk_1.png')] private var im_button_2:Class;
- [Embed(source = '../data/graphics/mobilebuttons/talk_2.png')] private var im_button_3:Class;
- [Embed(source = '../data/graphics/mobilebuttons/use_1.png')] private var im_button_4:Class;
- [Embed(source = '../data/graphics/mobilebuttons/use_2.png')] private var im_button_5:Class;
- [Embed(source = '../data/graphics/mobilebuttons/teleport_1.png')] private var im_button_6:Class;
- [Embed(source = '../data/graphics/mobilebuttons/teleport_2.png')] private var im_button_7:Class;
- [Embed(source = '../data/graphics/mobilebuttons/controls_1.png')] private var im_button_8:Class;
- [Embed(source = '../data/graphics/mobilebuttons/controls_2.png')] private var im_button_9:Class;
- [Embed(source = '../data/graphics/mobilebuttons/gamecenter.png')] private var im_button_10:Class;
- [Embed(source = '../data/graphics/mobilebuttons/button_left.png')] private var im_button_11:Class;
- [Embed(source = '../data/graphics/mobilebuttons/button_right.png')] private var im_button_12:Class;
-
- //Music
+ //Music
[Embed(source = '../data/music/levelcomplete.mp3')] private var music_1:Class;
[Embed(source = '../data/music/endgame.mp3')] private var music_2:Class;
//Sound effects
@@ -1033,4 +769,4 @@
[Embed(source = '../data/sounds/trophy.mp3')] private var ef_26:Class;
[Embed(source = '../data/sounds/rescue.mp3')] private var ef_27:Class;
}
-}
\ No newline at end of file
+}
\ No newline at end of file
diff --git a/mobile_version/src/Preloader.as b/mobile_version/src/Preloader.as
deleted file mode 100644
index 286678d1..00000000
--- a/mobile_version/src/Preloader.as
+++ /dev/null
@@ -1,310 +0,0 @@
-//Big thanks to Muku for his help with working out how to do a preloader in FlashDevelop!
-
-package {
- import flash.display.*;
- import flash.geom.*;
- import flash.events.*;
- import flash.net.*;
- import flash.utils.getDefinitionByName;
- import flash.system.fscommand;
- import flash.ui.ContextMenu;
- import flash.ui.ContextMenuItem;
- //import com.kongregate.as3.client.KongregateAPI;
-
- //Mochi and Kongregate stuff is more or less ready here
-
- public dynamic class Preloader extends MovieClip {
- public function Preloader() {
- fscommand("trapallkeys", "true");
- if (stage.root.loaderInfo.url.search(/.swf$/) >= 0) {
- //fscommand("showmenu", "false");
- }
- stage.showDefaultContextMenu = (stage.root.loaderInfo.url.search(/.swf$/) >= 0);
-
- //For the offline version, manually change this
- if (checksite()) {
- adson = false;
- }else{
- adson = true;
- }
- adson = false;
-
- //Let's assume the kong API is clever enough to do its own checking
- //var kongregate:KongregateAPI = new KongregateAPI();
- //this.addChild ( kongregate );
-
- //stage.showDefaultContextMenu = false;
-
-
- //show c64 intro (30, 0), set to (-10, 100) to not show
- //transition = -10; fakepercent = 100;
- transition = 30; fakepercent = 0;
-
-
- var rc_menu:ContextMenu = new ContextMenu();
- rc_menu.hideBuiltInItems();
- this.contextMenu = rc_menu;
- ct = new ColorTransform(0, 0, 0, 1, 255, 255, 255, 1); //Set to white
-
- darkcol = 0x000000; lightcol = 0x000000; curcol = 0;
- offset = 0; coltimer = 0;
-
- frontrect = new Rectangle(30, 20, 260, 200);
- temprect = new Rectangle(0, 0, 320, 24);
-
- tl = new Point(0, 0);
- tpoint = new Point(0, 0);
- bfont_rect=new Rectangle(0,0,8,8);
- var tempbmp:Bitmap;
- tempbmp = new im_bfont(); buffer = tempbmp.bitmapData;
- makebfont();
-
- backbuffer=new BitmapData(320, 240,false,0x000000);
- screenbuffer = new BitmapData(320, 240, false, 0x000000);
- screen = new Bitmap(screenbuffer);
- screen.width = 640;//320;//;640;
- screen.height = 480;// 240;//480;
-
- addChild(screen);
-
- addEventListener(Event.ENTER_FRAME, checkFrame);
-
- if (!adson) {
- /*
- loading = new im_loading();
- loading.x = 320 - (loading.width / 2);
- loading.y = 316;
- addChild(loading);
- */
- }
-
- showctp = false;
- startgame = false;
- }
-
- public function visit_distractionware(e:Event):void{
- var distractionware_link:URLRequest = new URLRequest( "http://www.distractionware.com" );
- navigateToURL( distractionware_link, "_blank" );
- }
-
- public function visit_sponsor(e:Event):void{
- var sponsor_link:URLRequest = new URLRequest( "http://www.kongregate.com/?gamereferral=dontlookback" );
- navigateToURL( sponsor_link, "_blank" );
- }
-
- public function print(x:int, y:int, t:String, r:int, g:int, b:int, cen:Boolean = false):void {
- if (r < 0) r = 0; if (g < 0) g = 0; if (b < 0) b = 0;
- if (r > 255) r = 255; if (g > 255) g = 255; if (b > 255) b = 255;
- ct.color = RGB(r, g, b);
- if (cen) x = x - (len(t));
- bfontpos = 0;
- for (var i:int = 0; i < t.length; i++) {
- cur = t.charCodeAt(i);
- tpoint.x = x + bfontpos; tpoint.y = y;
- bfont[cur].colorTransform(bfont_rect, ct);
- backbuffer.copyPixels(bfont[cur], bfont_rect, tpoint);
- bfontpos+=bfontlen[cur];
- }
- }
-
- public function checkFrame(e:Event):void {
- var p:Number = this.loaderInfo.bytesLoaded / this.loaderInfo.bytesTotal;
-
- //if (stage.root.loaderInfo.url.search(/.swf$/) >= 0) p = 0; //Not for the demo!
- transition = -10; fakepercent = 100;
-
- if (transition < 30) transition--;
- if(transition>=30){
- if (int(p * 100) >= fakepercent) fakepercent++;
- if (fakepercent >= 100) {
- fakepercent = 100;
- startgame = true;
- }
-
- offset = (offset + 4 + int(Math.random()*5))%32;
- coltimer--;
- if (coltimer <= 0) {
- curcol = (curcol + int(Math.random() * 5)) % 6;
- coltimer = 8;
- }
- switch(curcol) {
- case 0:
- lightcol = 0xBF596F;
- darkcol = 0x883E53;
- break;
- case 1:
- lightcol = 0x6CBC5C;
- darkcol = 0x508640;
- break;
- case 2:
- lightcol = 0x5D57AA;
- darkcol = 0x2F2F6C;
- break;
- case 3:
- lightcol = 0xB7BA5E;
- darkcol = 0x848342;
- break;
- case 4:
- lightcol = 0x5790AA;
- darkcol = 0x2F5B6C;
- break;
- case 5:
- lightcol = 0x9061B1;
- darkcol = 0x583D71;
- break;
- }
-
- for (var i:int = 0; i < 18; i++) {
- temprect.y = (i * 16) -offset;
- if (i % 2 == 0) {
- backbuffer.fillRect(temprect, lightcol);
- }else{
- backbuffer.fillRect(temprect, darkcol);
- }
- }
-
- backbuffer.fillRect(frontrect, 0x3E31A2);
-
-
- tempstring = "LOADING... " + String(int(fakepercent))+"%";
- print(282, 204, tempstring, 124, 112, 218, true);
-
- //Render
- screenbuffer.lock();
- screenbuffer.copyPixels(backbuffer, backbuffer.rect, tl, null, null, false);
- screenbuffer.unlock();
-
- backbuffer.lock();
- backbuffer.fillRect(backbuffer.rect, 0x000000);
- backbuffer.unlock();
- if (currentFrame >= totalFrames){
- if (startgame) {
- transition = 29;
- }
- }
- }else if (transition <= -10) {
- if (currentFrame >= totalFrames){
- startup();
- }
- }else if (transition < 5) {
- backbuffer.fillRect(backbuffer.rect, 0x000000);
- //Render
- screenbuffer.lock();
- screenbuffer.copyPixels(backbuffer, backbuffer.rect, tl, null, null, false);
- screenbuffer.unlock();
-
- backbuffer.lock();
- backbuffer.fillRect(backbuffer.rect, 0x000000);
- backbuffer.unlock();
- }else if (transition < 20) {
- temprect.y = 0;
- temprect.height = 240;
- backbuffer.fillRect(temprect, 0x000000);
- backbuffer.fillRect(frontrect, 0x3E31A2);
-
- tempstring = "LOADING... 100%";
- print(282, 204, tempstring, 124, 112, 218, true);
- //Render
- screenbuffer.lock();
- screenbuffer.copyPixels(backbuffer, backbuffer.rect, tl, null, null, false);
- screenbuffer.unlock();
-
- backbuffer.lock();
- backbuffer.fillRect(backbuffer.rect, 0x000000);
- backbuffer.unlock();
- }
- }
-
- private function startup():void {
- // hide loader
- //stop();
- removeChild(screen);
- removeEventListener(Event.ENTER_FRAME, checkFrame);
- //loaderInfo.removeEventListener(ProgressEvent.PROGRESS, progress);
- var mainClass:Class = getDefinitionByName("Main") as Class;
- addChild(new mainClass() as DisplayObject);
- //stage.removeChild(this);
- }
-
- public function checksite():Boolean {
- //Returns true if on a site that doesn't use mochiads
- var currUrl:String = stage.loaderInfo.url.toLowerCase();
- //chat.kongregate.com
- if ((currUrl.indexOf("distractionware.com") <= 0) &&
- (currUrl.indexOf("flashgamelicense.com") <= 0) &&
- (currUrl.indexOf("kongregate.com") <= 0) &&
- (currUrl.indexOf("chat.kongregate.com") <= 0)){
- //return true;
- return false;
- }else{
- return true;
- }
- }
-
- public function len(t:String):int {
- bfontpos = 0;
- for (var i:int = 0; i < t.length; i++) {
- cur = t.charCodeAt(i);
- bfontpos+=bfontlen[cur];
- }
- return bfontpos;
- }
-
- public function RGB(red:Number,green:Number,blue:Number):Number{
- return (blue | (green << 8) | (red << 16))
- }
-
- public function makebfont():void {
- for (var j:Number = 0; j < 16; j++) {
- for (var i:Number = 0; i < 16; i++) {
- var t:BitmapData = new BitmapData(8, 8, true, 0x000000);
- var t2emprect:Rectangle = new Rectangle(i * 8, j * 8, 8, 8);
- t.copyPixels(buffer, t2emprect, tl);
- bfont.push(t);
- }
- }
-
- //Ok, now we work out the lengths (this data string cortesy of a program I wrote!)
- for (i = 0; i < 256; i++) bfontlen.push(6);
- var maprow:Array;
- var tstring:String="4,3,5,7,6,7,6,3,4,4,7,7,3,5,2,5,6,5,6,6,6,6,6,6,6,6,2,3,5,5,5,6,7,6,6,6,6,5,5,6,6,3,6,6,5,7,7,6,6,6,6,6,5,6,7,7,7,7,5,4,5,4,5,6,4,6,6,6,6,5,5,6,6,3,6,6,5,7,7,6,6,6,6,6,5,6,7,7,7,7,5,5,3,5,6,4";
-
- maprow = new Array();
- maprow = tstring.split(",");
- for(var k:int = 0; k < 96; k++) {
- bfontlen[k + 32] = 8;// int(maprow[k]);
- }
- }
-
- public var darkcol:int, lightcol:int, curcol:int, coltimer:int;
- public var offset:int;
-
- public var buffer:BitmapData;
- public var backbuffer:BitmapData;
- public var screenbuffer:BitmapData;
- public var screen:Bitmap;
-
- public var frontrect:Rectangle;
- public var temprect:Rectangle;
-
- public var showctp:Boolean;
- public var startgame:Boolean;
- public var adson:Boolean;
-
- [Embed(source = '../data/graphics/font.png')] private var im_bfont:Class;
- public var bfontlen:Array = new Array();
- public var bfont:Array = new Array();
- public var bfont_rect:Rectangle;
- public var tl:Point, tpoint:Point;
- public var bfontpos:int;
- public var cur:int;
- public var ct:ColorTransform;
-
- public var tempstring:String;
- public var fakepercent:int;
-
- public var transition:int;
-
- public var statcookie:SharedObject;
- }
-}
\ No newline at end of file
diff --git a/mobile_version/src/blockclass.as b/mobile_version/src/blockclass.as
index 23801faf..864ca8d9 100644
--- a/mobile_version/src/blockclass.as
+++ b/mobile_version/src/blockclass.as
@@ -1,10 +1,7 @@
-package {
- import flash.display.*;
+package {
import flash.geom.*;
- import flash.events.*;
- import flash.net.*;
- public class blockclass extends Sprite {
+ public class blockclass {
public function blockclass():void {
rect = new Rectangle();
clear();
diff --git a/mobile_version/src/com/adobe/utils/AGALMiniAssembler.as b/mobile_version/src/com/adobe/utils/AGALMiniAssembler.as
new file mode 100644
index 00000000..ca511f44
--- /dev/null
+++ b/mobile_version/src/com/adobe/utils/AGALMiniAssembler.as
@@ -0,0 +1,805 @@
+/*
+Copyright (c) 2015, Adobe Systems Incorporated
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+* Redistributions of source code must retain the above copyright notice,
+this list of conditions and the following disclaimer.
+
+* Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in the
+documentation and/or other materials provided with the distribution.
+
+* Neither the name of Adobe Systems Incorporated nor the names of its
+contributors may be used to endorse or promote products derived from
+this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
+IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+package com.adobe.utils
+{
+ // ===========================================================================
+ // Imports
+ // ---------------------------------------------------------------------------
+ import flash.display3D.*;
+ import flash.utils.*;
+
+ // ===========================================================================
+ // Class
+ // ---------------------------------------------------------------------------
+ public class AGALMiniAssembler
+ { // ======================================================================
+ // Constants
+ // ----------------------------------------------------------------------
+ protected static const REGEXP_OUTER_SPACES:RegExp = /^\s+|\s+$/g;
+
+ // ======================================================================
+ // Properties
+ // ----------------------------------------------------------------------
+ // AGAL bytes and error buffer
+ private var _agalcode:ByteArray = null;
+ private var _error:String = "";
+
+ private var debugEnabled:Boolean = false;
+
+ private static var initialized:Boolean = false;
+ public var verbose:Boolean = false;
+
+ // ======================================================================
+ // Getters
+ // ----------------------------------------------------------------------
+ public function get error():String { return _error; }
+ public function get agalcode():ByteArray { return _agalcode; }
+
+ // ======================================================================
+ // Constructor
+ // ----------------------------------------------------------------------
+ public function AGALMiniAssembler( debugging:Boolean = false ):void
+ {
+ debugEnabled = debugging;
+ if ( !initialized )
+ init();
+ }
+ // ======================================================================
+ // Methods
+ // ----------------------------------------------------------------------
+
+ public function assemble2( ctx3d : Context3D, version:uint, vertexsrc:String, fragmentsrc:String ) : Program3D
+ {
+ var agalvertex : ByteArray = assemble ( VERTEX, vertexsrc, version );
+ var agalfragment : ByteArray = assemble ( FRAGMENT, fragmentsrc, version );
+ var prog : Program3D = ctx3d.createProgram();
+ prog.upload(agalvertex,agalfragment);
+ return prog;
+ }
+
+ public function assemble( mode:String, source:String, version:uint=1, ignorelimits:Boolean=false ):ByteArray
+ {
+ var start:uint = getTimer();
+
+ _agalcode = new ByteArray();
+ _error = "";
+
+ var isFrag:Boolean = false;
+
+ if ( mode == FRAGMENT )
+ isFrag = true;
+ else if ( mode != VERTEX )
+ _error = 'ERROR: mode needs to be "' + FRAGMENT + '" or "' + VERTEX + '" but is "' + mode + '".';
+
+ agalcode.endian = Endian.LITTLE_ENDIAN;
+ agalcode.writeByte( 0xa0 ); // tag version
+ agalcode.writeUnsignedInt( version ); // AGAL version, big endian, bit pattern will be 0x01000000
+ agalcode.writeByte( 0xa1 ); // tag program id
+ agalcode.writeByte( isFrag ? 1 : 0 ); // vertex or fragment
+
+ initregmap(version, ignorelimits);
+
+ var lines:Array = source.replace( /[\f\n\r\v]+/g, "\n" ).split( "\n" );
+ var nest:int = 0;
+ var nops:int = 0;
+ var i:int;
+ var lng:int = lines.length;
+
+ for ( i = 0; i < lng && _error == ""; i++ )
+ {
+ var line:String = new String( lines[i] );
+ line = line.replace( REGEXP_OUTER_SPACES, "" );
+
+ // remove comments
+ var startcomment:int = line.search( "//" );
+ if ( startcomment != -1 )
+ line = line.slice( 0, startcomment );
+
+ // grab options
+ var optsi:int = line.search( /<.*>/g );
+ var opts:Array;
+ if ( optsi != -1 )
+ {
+ opts = line.slice( optsi ).match( /([\w\.\-\+]+)/gi );
+ line = line.slice( 0, optsi );
+ }
+
+ // find opcode
+ var opCode:Array = line.match( /^\w{3}/ig );
+ if ( !opCode )
+ {
+ if ( line.length >= 3 )
+ trace( "warning: bad line "+i+": "+lines[i] );
+ continue;
+ }
+ var opFound:OpCode = OPMAP[ opCode[0] ];
+
+ // if debug is enabled, output the opcodes
+ if ( debugEnabled )
+ trace( opFound );
+
+ if ( opFound == null )
+ {
+ if ( line.length >= 3 )
+ trace( "warning: bad line "+i+": "+lines[i] );
+ continue;
+ }
+
+ line = line.slice( line.search( opFound.name ) + opFound.name.length );
+
+ if ( ( opFound.flags & OP_VERSION2 ) && version<2 )
+ {
+ _error = "error: opcode requires version 2.";
+ break;
+ }
+
+ if ( ( opFound.flags & OP_VERT_ONLY ) && isFrag )
+ {
+ _error = "error: opcode is only allowed in vertex programs.";
+ break;
+ }
+
+ if ( ( opFound.flags & OP_FRAG_ONLY ) && !isFrag )
+ {
+ _error = "error: opcode is only allowed in fragment programs.";
+ break;
+ }
+ if ( verbose )
+ trace( "emit opcode=" + opFound );
+
+ agalcode.writeUnsignedInt( opFound.emitCode );
+ nops++;
+
+ if ( nops > MAX_OPCODES )
+ {
+ _error = "error: too many opcodes. maximum is "+MAX_OPCODES+".";
+ break;
+ }
+
+ // get operands, use regexp
+ var regs:Array;
+
+ // will match both syntax
+ regs = line.match( /vc\[([vof][acostdip]?)(\d*)?(\.[xyzw](\+\d{1,3})?)?\](\.[xyzw]{1,4})?|([vof][acostdip]?)(\d*)?(\.[xyzw]{1,4})?/gi );
+
+ if ( !regs || regs.length != opFound.numRegister )
+ {
+ _error = "error: wrong number of operands. found "+regs.length+" but expected "+opFound.numRegister+".";
+ break;
+ }
+
+ var badreg:Boolean = false;
+ var pad:uint = 64 + 64 + 32;
+ var regLength:uint = regs.length;
+
+ for ( var j:int = 0; j < regLength; j++ )
+ {
+ var isRelative:Boolean = false;
+ var relreg:Array = regs[ j ].match( /\[.*\]/ig );
+ if ( relreg && relreg.length > 0 )
+ {
+ regs[ j ] = regs[ j ].replace( relreg[ 0 ], "0" );
+
+ if ( verbose )
+ trace( "IS REL" );
+ isRelative = true;
+ }
+
+ var res:Array = regs[j].match( /^\b[A-Za-z]{1,2}/ig );
+ if ( !res )
+ {
+ _error = "error: could not parse operand "+j+" ("+regs[j]+").";
+ badreg = true;
+ break;
+ }
+ var regFound:Register = REGMAP[ res[ 0 ] ];
+
+ // if debug is enabled, output the registers
+ if ( debugEnabled )
+ trace( regFound );
+
+ if ( regFound == null )
+ {
+ _error = "error: could not find register name for operand "+j+" ("+regs[j]+").";
+ badreg = true;
+ break;
+ }
+
+ if ( isFrag )
+ {
+ if ( !( regFound.flags & REG_FRAG ) )
+ {
+ _error = "error: register operand "+j+" ("+regs[j]+") only allowed in vertex programs.";
+ badreg = true;
+ break;
+ }
+ if ( isRelative )
+ {
+ _error = "error: register operand "+j+" ("+regs[j]+") relative adressing not allowed in fragment programs.";
+ badreg = true;
+ break;
+ }
+ }
+ else
+ {
+ if ( !( regFound.flags & REG_VERT ) )
+ {
+ _error = "error: register operand "+j+" ("+regs[j]+") only allowed in fragment programs.";
+ badreg = true;
+ break;
+ }
+ }
+
+ regs[j] = regs[j].slice( regs[j].search( regFound.name ) + regFound.name.length );
+ //trace( "REGNUM: " +regs[j] );
+ var idxmatch:Array = isRelative ? relreg[0].match( /\d+/ ) : regs[j].match( /\d+/ );
+ var regidx:uint = 0;
+
+ if ( idxmatch )
+ regidx = uint( idxmatch[0] );
+
+ if ( regFound.range < regidx )
+ {
+ _error = "error: register operand "+j+" ("+regs[j]+") index exceeds limit of "+(regFound.range+1)+".";
+ badreg = true;
+ break;
+ }
+
+ var regmask:uint = 0;
+ var maskmatch:Array = regs[j].match( /(\.[xyzw]{1,4})/ );
+ var isDest:Boolean = ( j == 0 && !( opFound.flags & OP_NO_DEST ) );
+ var isSampler:Boolean = ( j == 2 && ( opFound.flags & OP_SPECIAL_TEX ) );
+ var reltype:uint = 0;
+ var relsel:uint = 0;
+ var reloffset:int = 0;
+
+ if ( isDest && isRelative )
+ {
+ _error = "error: relative can not be destination";
+ badreg = true;
+ break;
+ }
+
+ if ( maskmatch )
+ {
+ regmask = 0;
+ var cv:uint;
+ var maskLength:uint = maskmatch[0].length;
+ for ( var k:int = 1; k < maskLength; k++ )
+ {
+ cv = maskmatch[0].charCodeAt(k) - "x".charCodeAt(0);
+ if ( cv > 2 )
+ cv = 3;
+ if ( isDest )
+ regmask |= 1 << cv;
+ else
+ regmask |= cv << ( ( k - 1 ) << 1 );
+ }
+ if ( !isDest )
+ for ( ; k <= 4; k++ )
+ regmask |= cv << ( ( k - 1 ) << 1 ); // repeat last
+ }
+ else
+ {
+ regmask = isDest ? 0xf : 0xe4; // id swizzle or mask
+ }
+
+ if ( isRelative )
+ {
+ var relname:Array = relreg[0].match( /[A-Za-z]{1,2}/ig );
+ var regFoundRel:Register = REGMAP[ relname[0]];
+ if ( regFoundRel == null )
+ {
+ _error = "error: bad index register";
+ badreg = true;
+ break;
+ }
+ reltype = regFoundRel.emitCode;
+ var selmatch:Array = relreg[0].match( /(\.[xyzw]{1,1})/ );
+ if ( selmatch.length==0 )
+ {
+ _error = "error: bad index register select";
+ badreg = true;
+ break;
+ }
+ relsel = selmatch[0].charCodeAt(1) - "x".charCodeAt(0);
+ if ( relsel > 2 )
+ relsel = 3;
+ var relofs:Array = relreg[0].match( /\+\d{1,3}/ig );
+ if ( relofs.length > 0 )
+ reloffset = relofs[0];
+ if ( reloffset < 0 || reloffset > 255 )
+ {
+ _error = "error: index offset "+reloffset+" out of bounds. [0..255]";
+ badreg = true;
+ break;
+ }
+ if ( verbose )
+ trace( "RELATIVE: type="+reltype+"=="+relname[0]+" sel="+relsel+"=="+selmatch[0]+" idx="+regidx+" offset="+reloffset );
+ }
+
+ if ( verbose )
+ trace( " emit argcode="+regFound+"["+regidx+"]["+regmask+"]" );
+ if ( isDest )
+ {
+ agalcode.writeShort( regidx );
+ agalcode.writeByte( regmask );
+ agalcode.writeByte( regFound.emitCode );
+ pad -= 32;
+ } else
+ {
+ if ( isSampler )
+ {
+ if ( verbose )
+ trace( " emit sampler" );
+ var samplerbits:uint = 5; // type 5
+ var optsLength:uint = opts == null ? 0 : opts.length;
+ var bias:Number = 0;
+ for ( k = 0; k 50){
bvx = 9 - (Math.random() * 19); if (bvx > -6 && bvx < 6) bvx = 6;
- bvx = bvx * 1.5;
+ bvx = bvx * 1.5;
bb = new Rectangle(Math.random() * 320, Math.random() * 240, 32, 12);
}else {
bvy = 9 - (Math.random() * 19); if (bvy > -6 && bvy < 6) bvy = 6;
- bvy = bvy * 1.5;
+ bvy = bvy * 1.5;
bb = new Rectangle(Math.random() * 320, Math.random() * 240, 12, 32);
}
var bint:Number = 0.5 + ((Math.random() * 100) / 200);
@@ -77,7 +144,7 @@
crewframe = 0; crewframedelay = 4;
menuoffset = 0; resumegamemode = false;
- //Textboxes!
+ //Textboxes!
for (i = 0; i < 30; i++) {
var t:textboxclass = new textboxclass;
textbox.push(t);
@@ -91,67 +158,27 @@
fadeamount = 0;
fademode = 0;
- bigbuffer = new BitmapData(320, 32, true, 0x000000);
- bigbufferscreen = new Bitmap(bigbuffer);
- bigbufferscreen.width = 640;
- bigbufferscreen.height = 20;
- towerbuffer = new BitmapData(320, 240, true, 0x000000);
- frontbuffer = new BitmapData(320, 240, true, 0x000000);
+ //var devicexres:int = int(Capabilities.screenResolutionX);
+ //var deviceyres:int = int(Capabilities.screenResolutionY);
+ //updatescreen(starstage.stageWidth, starstage.stageHeight);
- menubuffer = new BitmapData(320, 240, false, 0x000000); //yeah yeah I know this is lazy
-
- backbuffer=new BitmapData(320, 240,false,0x000000);
- screenbuffer = new BitmapData(320,240,false,0x000000);
-
- temptile = new BitmapData(8, 8, false, 0x000000);
- tempsprite = new BitmapData(32, 32, false, 0x000000);
- screen = new Bitmap(screenbuffer);
-
- //screen.width = 640;//320;//;640;
- //screen.height = 480;// 240;//480;
- screen.smoothing = true;
-
- addChild(screen);
-
- buttonscreen.push(new Bitmap(buttonimg[0]));
- buttonscreen.push(new Bitmap(buttonimg[1]));
- buttonscreen.push(new Bitmap(buttonimg[2]));
- buttonscreen.push(new Bitmap(buttonimg[3]));
-
- /*
- if (device.deviceresolution == device.IPAD) {
- buttonsize = 90;
- buttonyspacing = buttonsize / 3;
- buttonxspacing = 40;
- buttonscreen[0].width = 92*3; buttonscreen[0].height = buttonsize;
- buttonscreen[1].width = 92*3; buttonscreen[1].height = buttonsize;
- buttonscreen[2].width = 40*3; buttonscreen[2].height = 40*3;
- buttonscreen[3].width = 40 * 3; buttonscreen[3].height = 40 * 3;
- buttonydiff = buttonscreen[2].height / 2;
- }else if (device.deviceresolution == device.ANDROID) {
- */
-
- /*
- }else {
- buttonsize = 30;
- buttonyspacing = buttonsize / 3;
- buttonxspacing = 20;
- buttonscreen[0].width = 92; buttonscreen[0].height = buttonsize;
- buttonscreen[1].width = 92; buttonscreen[1].height = buttonsize;
- buttonscreen[2].width = 40; buttonscreen[2].height = 40;
- buttonscreen[3].width = 40; buttonscreen[3].height = 40;
- buttonydiff = buttonscreen[2].height / 2;
- }
- */
-
- /*buttonscreen.push(new Bitmap(buttonimg[1]));
- buttonscreen[1].width = buttonsize; buttonscreen[1].height = buttonsize;
- buttonscreen.push(new Bitmap(buttonimg[2]));
- buttonscreen[2].width = buttonsize; buttonscreen[2].height = buttonsize;
- buttonscreen.push(new Bitmap(buttonimg[3]));
- buttonscreen[3].width = buttonsize; buttonscreen[3].height = buttonsize;
- */
+ //Starling.current.showStats = true;
+ }
+
+ public function initbuttonstuff():void {
+ button_image_width.push(0); button_image_height.push(0);
+ button_image_width.push(0); button_image_height.push(0);
+ button_image_width.push(0); button_image_height.push(0);
+ button_image_width.push(0); button_image_height.push(0);
+ button_image.push(new Image(button_texture[0]));
+ button_image.push(new Image(button_texture[1]));
+ button_image.push(new Image(button_texture[2]));
+ button_image.push(new Image(button_texture[3]));
+ button_image[0].touchable = false; button_image[0].textureSmoothing = TextureSmoothing.NONE;
+ button_image[1].touchable = false; button_image[1].textureSmoothing = TextureSmoothing.NONE;
+ button_image[2].touchable = false; button_image[2].textureSmoothing = TextureSmoothing.NONE;
+ button_image[3].touchable = false; button_image[3].textureSmoothing = TextureSmoothing.NONE;
for (i = 0; i < 10; i++) {
buttonlerp.push(int(0));
@@ -172,72 +199,81 @@
initbuttonpositions();
- /*
- buttonscreen[0].x = buttonxspacing;
- buttonscreen[0].y = device.yres - buttonsize-buttonyspacing-buttonydiff;
- buttonpos.push(new Point(buttonscreen[0].x, buttonscreen[0].y));
-
- buttonscreen[1].x = buttonxspacing + buttonsize + buttonxspacing;
- buttonscreen[1].y = device.yres - buttonsize-buttonyspacing;
- buttonpos.push(new Point(buttonscreen[1].x, buttonscreen[1].y));
-
- buttonscreen[2].x = device.xres - buttonxspacing - buttonsize;
- buttonscreen[2].y = buttonsize / 4;
- buttonpos.push(new Point(buttonscreen[2].x, buttonscreen[2].y));
-
- buttonscreen[3].x = device.xres - buttonxspacing - buttonsize - buttonxspacing - buttonsize;
- buttonscreen[3].y = device.yres - buttonsize-buttonyspacing;
- buttonpos.push(new Point(buttonscreen[3].x, buttonscreen[3].y));
- */
drawonscreenbutton(0, -1);
drawonscreenbutton(1, -1);
drawonscreenbutton(2, -1);
drawonscreenbutton(3, -1);
- addChild(buttonscreen[0]);
- addChild(buttonscreen[1]);
- addChild(buttonscreen[2]);
- addChild(buttonscreen[3]);
- /*
- drawonscreenbutton(0, 0);
- drawonscreenbutton(1, 0);
- drawonscreenbutton(2, 0);
- drawonscreenbutton(3, 0);
- showarrows();
- */
- }
+ starstage.addChild(button_image[0]);
+ starstage.addChild(button_image[1]);
+ starstage.addChild(button_image[2]);
+ starstage.addChild(button_image[3]);
+
+ buttonsready = true;
+ }
+
+ public function updatescreen(w:int, h:int):void {
+ starstage.stageWidth = w;
+ starstage.stageHeight = h;
+
+ Starling.current.viewPort = new Rectangle(0, 0, w, h);
+
+ // set rectangle dimensions for viewPort:
+ var stretchscalex:Number = w / screenwidth;
+ var stretchscaley:Number = h / screenheight;
+ screensizemultiplier = Math.min(stretchscalex, stretchscaley);
+
+ //Never mess with starling's viewport for VVVVVV - instead, mess with the
+ //screen image
+ screen.width = screenwidth * screensizemultiplier;
+ screen.height = screenheight * screensizemultiplier;
+
+ screen.x = (w / 2) - (screenwidth * screensizemultiplier / 2);
+ }
public function initbuttonpositions():void {
- devicex = device.xres;
+ devicex = device.xres;
devicey = device.yres;
- buttonsize = device.yres / (32 / 3);
+ buttonsize = devicey / (32 / 3);
buttonyspacing = buttonsize / 3;
- buttonxspacing = (buttonsize * 3) / 3;
- buttonscreen[0].width = (buttonsize * 46) / 15; buttonscreen[0].height = buttonsize;
- buttonscreen[1].width = (buttonsize * 46) / 15; buttonscreen[1].height = buttonsize;
- buttonscreen[2].width = (buttonsize * 5) / 3; buttonscreen[2].height = (buttonsize * 5) / 3;
- buttonscreen[3].width = (buttonsize * 5) / 3; buttonscreen[3].height = (buttonsize * 5) / 3;
- buttonydiff = buttonscreen[2].height / 2;
+ buttonxspacing = (buttonsize * 3) / 3;
- buttonscreen[0].x = device.xres + 1;
- buttonscreen[0].y = 0;
- buttonpos[0].setTo(buttonscreen[0].x, buttonscreen[0].y);
+ button_image[0].width = (buttonsize * 46) / 15; button_image[0].height = buttonsize;
+ button_image[1].width = (buttonsize * 46) / 15; button_image[1].height = buttonsize;
+ button_image[2].width = (buttonsize * 5) / 3; button_image[2].height = (buttonsize * 5) / 3;
+ button_image[3].width = (buttonsize * 5) / 3; button_image[3].height = (buttonsize * 5) / 3;
- buttonscreen[1].x = 0;
- buttonscreen[1].y = 0;
- buttonpos[1].setTo(buttonscreen[1].x, buttonscreen[1].y);
+ button_image_width[0] = int(button_image[0].width);
+ button_image_width[1] = int(button_image[1].width);
+ button_image_width[2] = int(button_image[2].width);
+ button_image_width[3] = int(button_image[3].width);
+ button_image_height[0] = int(button_image[0].height);
+ button_image_height[1] = int(button_image[1].height);
+ button_image_height[2] = int(button_image[2].height);
+ button_image_height[3] = int(button_image[3].height);
- buttonscreen[2].x = (buttonxspacing / 2);
- buttonscreen[2].y = device.yres - buttonsize-buttonyspacing - buttonydiff;
- buttonpos[2].setTo(buttonscreen[2].x, buttonscreen[2].y);
- buttonscreen[3].x = (buttonxspacing/2) + buttonsize + buttonxspacing;
- buttonscreen[3].y = device.yres - buttonsize-buttonyspacing;
- buttonpos[3].setTo(buttonscreen[3].x, buttonscreen[3].y);
+ buttonydiff = button_image_height[2] / 2;
+
+ button_image[0].x = devicex + 1;
+ button_image[0].y = 0;
+ buttonpos[0].setTo(button_image[0].x, button_image[0].y);
+
+ button_image[1].x = 0;
+ button_image[1].y = 0;
+ buttonpos[1].setTo(button_image[1].x, button_image[1].y);
+
+ button_image[2].x = (buttonxspacing / 2);
+ button_image[2].y = devicey - buttonsize-buttonyspacing - buttonydiff;
+ buttonpos[2].setTo(button_image[2].x, button_image[2].y);
+
+ button_image[3].x = (buttonxspacing/2) + buttonsize + buttonxspacing ;
+ button_image[3].y = devicey - buttonsize-buttonyspacing;
+ buttonpos[3].setTo(button_image[3].x, button_image[3].y);
}
public function mobile_changebutton(t:int):void {
- if (newbuttontype[0] != t) {
+ if (newbuttontype[0] != t) {
if (currentbuttontype[0] != t) {
newbuttontype[0] = t;
buttonstate[0] = 1;
@@ -246,7 +282,7 @@
}
public function mobile_changeleftbutton(t:int):void {
- if (newbuttontype[1] != t) {
+ if (newbuttontype[1] != t) {
if (currentbuttontype[1] != t) {
newbuttontype[1] = t;
buttonstate[1] = 1;
@@ -275,7 +311,7 @@
}
public function drawbutton(game:gameclass, help:helpclass):void {
- //Called every frame, this function controls what buttons appear and when,
+ //Called every frame, this function controls what buttons appear and when,
//and lerps them in and out in a nice way.
//buttonstate[0]:
// 0 - Normal, slide in if not in
@@ -319,13 +355,13 @@
changebuttonframe(3, 12);
if (game.press_left) {
- changebuttonpos(2, buttonxspacing/2, devicey - buttonsize-buttonyspacing - buttonydiff+10);
+ changebuttonpos(2, (buttonxspacing/2), devicey - buttonsize-buttonyspacing - buttonydiff+10);
}else{
- changebuttonpos(2, buttonxspacing/2, devicey - buttonsize-buttonyspacing - buttonydiff);
+ changebuttonpos(2, (buttonxspacing/2), devicey - buttonsize-buttonyspacing - buttonydiff);
}
if (game.press_right) {
- changebuttonpos(3, (buttonxspacing/2)+ buttonsize + buttonxspacing, devicey - buttonsize-buttonyspacing - buttonydiff+10);
+ changebuttonpos(3, (buttonxspacing/2) + buttonsize + buttonxspacing, devicey - buttonsize-buttonyspacing - buttonydiff+10);
}else{
changebuttonpos(3, (buttonxspacing/2) + buttonsize + buttonxspacing, devicey - buttonsize-buttonyspacing - buttonydiff);
}
@@ -336,7 +372,7 @@
case BUTTON_BLANK:
//Blank
changebuttonframe(1, -1);
- changebuttonpos(1, 0 - ((buttonscreen[1].width * (buttonlerp[1])) / 100), 0);
+ changebuttonpos(1, 0 - ((button_image_width[1] * (buttonlerp[1])) / 100), 0);
break;
case BUTTON_CONTROLS:
//Controls button
@@ -346,15 +382,15 @@
changebuttonframe(1, 8);
}
if (flipmode) {
- changebuttonpos(1, 0 - ((buttonscreen[1].width * (buttonlerp[1])) / 100), devicey-buttonyspacing-buttonscreen[1].height);
+ changebuttonpos(1, 0 - ((button_image_width[1] * (buttonlerp[1])) / 100), devicey - buttonyspacing - button_image_height[1]);
}else {
- changebuttonpos(1, 0 - ((buttonscreen[1].width * (buttonlerp[1])) / 100), buttonyspacing);
+ changebuttonpos(1, 0 - ((button_image_width[1] * (buttonlerp[1])) / 100), buttonyspacing);
}
break;
case BUTTON_GAMECENTER:
changebuttonframe(1, 10);
- changebuttonpos(1, 0 - ((buttonscreen[1].width * (buttonlerp[1])) / 100), 5);
+ changebuttonpos(1, 0 - ((button_image_width[1] * (buttonlerp[1])) / 100), 5);
break;
}
@@ -362,20 +398,20 @@
case BUTTON_BLANK:
//Blank
changebuttonframe(0, -1);
- changebuttonpos(0, devicex - ((buttonscreen[0].width * (100-buttonlerp[0])) / 100), 0);
+ changebuttonpos(0, devicex - ((button_image_width[0] * (100-buttonlerp[0])) / 100), 0);
break;
case BUTTON_MENU:
//Menu button
changebuttonframe(0, 0);
- changebuttonpos(0, devicex - ((buttonscreen[0].width * (100-buttonlerp[0])) / 100), 0);
+ changebuttonpos(0, devicex - ((button_image_width[0] * (100-buttonlerp[0])) / 100), 0);
break;
case BUTTON_BACK:
//Back button
changebuttonframe(0, 1);
if (flipmode) {
- changebuttonpos(0, devicex - ((buttonscreen[0].width * (100 - buttonlerp[0])) / 100), devicey - buttonyspacing - buttonscreen[0].height);
+ changebuttonpos(0, devicex - ((button_image_width[0] * (100 - buttonlerp[0])) / 100), devicey - buttonyspacing - button_image_height[0]);
}else{
- changebuttonpos(0, devicex - ((buttonscreen[0].width * (100 - buttonlerp[0])) / 100), buttonyspacing);
+ changebuttonpos(0, devicex - ((button_image_width[0] * (100 - buttonlerp[0])) / 100), buttonyspacing);
}
break;
case BUTTON_USE:
@@ -385,7 +421,7 @@
}else {
changebuttonframe(0, 5);
}
- changebuttonpos(0, devicex - ((buttonscreen[0].width * (100-buttonlerp[0])) / 100), buttonyspacing);
+ changebuttonpos(0, devicex - ((button_image_width[0] * (100-buttonlerp[0])) / 100), buttonyspacing);
break;
case BUTTON_TALK:
//Talk button
@@ -394,7 +430,7 @@
}else {
changebuttonframe(0, 3);
}
- changebuttonpos(0, devicex - ((buttonscreen[0].width * (100-buttonlerp[0])) / 100), buttonyspacing);
+ changebuttonpos(0, devicex - ((button_image_width[0] * (100-buttonlerp[0])) / 100), buttonyspacing);
break;
case BUTTON_TELEPORT:
//Teleport button
@@ -403,48 +439,34 @@
}else {
changebuttonframe(0, 7);
}
- changebuttonpos(0, devicex - ((buttonscreen[0].width * (100-buttonlerp[0])) / 100), buttonyspacing);
+ changebuttonpos(0, devicex - ((button_image_width[0] * (100-buttonlerp[0])) / 100), buttonyspacing);
break;
}
-
- /*
- if (game.press_left) { drawonscreenbutton(0, 1);
- }else{ drawonscreenbutton(0, 0);}
-
- if (game.press_right) { drawonscreenbutton(1, 1);
- }else { drawonscreenbutton(1, 0); }
-
- if (game.press_map) { drawonscreenbutton(2, 1);
- }else { drawonscreenbutton(2, 0); }
- */
- //Draw circle pad!
- //if (key.controlstick != -1) {
- /*
- backbuffer.copyPixels(dwgfx.buttonimg[13], dwgfx.buttonimg[13].rect, new Point(key.controlstick_x - 18+18, key.controlstick_y - 18+18));
- for (i = 0; i < key.touchPoints; i++) {
- if (key.touchid[i] == key.controlstick) {
- dwgfx.backbuffer.copyPixels(dwgfx.buttonimg[14], dwgfx.buttonimg[14].rect, new Point(key.touchx[i] - 18, key.touchy[i] - 18));
- }
- }
- */
- //}
}
- public function addbutton():void {
- var t:BitmapData = new BitmapData(buffer.width, buffer.height, true, 0x00000000);
- t.copyPixels(buffer, new Rectangle(0,0,buffer.width, buffer.height), new Point(0,0));
- buttonimg.push(t);
+ public function addbutton(imgname:String):void {
+ var sourcetexture:Texture = starlingassets.getTexture(imgname);
+ var tmpimage:Image = new Image(sourcetexture);
+
+ var newtexture:RenderTexture = new RenderTexture(int(tmpimage.texture.width), int(tmpimage.texture.height));
+ newtexture.draw(tmpimage);
+
+ sourcetexture.dispose();
+ tmpimage.dispose();
+
+ button_texture.push(newtexture);
}
public function drawonscreenbutton(t:int, t2:int):void {
//Draw button t with frame t2
if (t2 == -1) {
- buttonimg[t].fillRect(buttonimg[t].rect, 0x00000000);
+ button_texture[t].clear();
}
if (buttonframe[t] != t2) {
buttonframe[t] = t2;
- buttonimg[t].fillRect(buttonimg[t].rect, 0x00000000);
- buttonimg[t].copyPixels(buttonimg[4 + t2], buttonimg[t].rect, tl);
+ button_texture[t].clear();
+ var tempimg:Image = new Image(button_texture[4 + t2]);
+ button_texture[t].draw(tempimg);
}
}
@@ -453,167 +475,169 @@
if (buttonframe[t] != t2) {
buttonframe[t] = t2;
if (t2 == -1) {
- buttonimg[t].fillRect(buttonimg[t].rect, 0x00000000);
+ button_texture[t].clear();
}else{
- buttonimg[t].fillRect(buttonimg[t].rect, 0x00000000);
- buttonimg[t].copyPixels(buttonimg[4 + t2], buttonimg[t].rect, tl);
+ button_texture[t].clear();
+ var tempimg:Image = new Image(button_texture[4 + t2]);
+ button_texture[t].draw(tempimg);
}
}
}
public function changebuttonpos(t:int, xp:int, yp:int):void {
- buttonscreen[t].x = xp;
- buttonscreen[t].y = yp;
+ button_image[t].x = xp;
+ button_image[t].y = yp;
}
public function changebuttonxpos(t:int, xp:int):void {
- buttonscreen[t].x = xp;
+ button_image[t].x = xp;
}
public function showarrows():void {
if (buttonactive[0] == false) {
buttonhighlight[0] = 120;
buttonactive[0] = true;
- addChild(buttonscreen[0]);
- addChild(buttonscreen[1]);
- addChild(buttonscreen[2]);
+ starstage.addChild(button_image[0]);
+ starstage.addChild(button_image[1]);
+ starstage.addChild(button_image[2]);
}
}
public function hidearrows():void {
if (buttonactive[0] == true) {
buttonactive[0] = false;
- removeChild(buttonscreen[0]);
- removeChild(buttonscreen[1]);
- removeChild(buttonscreen[2]);
+ starstage.removeChild(button_image[0]);
+ starstage.removeChild(button_image[1]);
+ starstage.removeChild(button_image[2]);
}
}
-
public function drawspritesetcol(x:int, y:int, t:int, c:int, help:helpclass):void {
- tpoint.x = x; tpoint.y = y;
- setcol(c, help);
- sprites[t].colorTransform(sprites_rect, ct);
- backbuffer.copyPixels(sprites[t], sprites_rect, tpoint);
- }
-
-
- public function makebfont():void {
- for (var j:Number = 0; j < 16; j++) {
- for (var i:Number = 0; i < 16; i++) {
- var t:BitmapData = new BitmapData(8, 8, true, 0x000000);
- var t2:BitmapData = new BitmapData(8, 8, true, 0x000000);
- var temprect:Rectangle = new Rectangle(i * 8, j * 8, 8, 8);
- t.copyPixels(buffer, temprect, tl);
- t2.draw(t, flipfontmatrix);
- bfont.push(t);
- flipbfont.push(t2);
- }
- }
-
- //Ok, now we work out the lengths (this data string cortesy of a program I wrote!)
- for (i = 0; i < 256; i++) bfontlen.push(6);
- var maprow:Array;
- var tstring:String="4,3,5,7,6,7,6,3,4,4,7,7,3,5,2,5,6,5,6,6,6,6,6,6,6,6,2,3,5,5,5,6,7,6,6,6,6,5,5,6,6,3,6,6,5,7,7,6,6,6,6,6,5,6,7,7,7,7,5,4,5,4,5,6,4,6,6,6,6,5,5,6,6,3,6,6,5,7,7,6,6,6,6,6,5,6,7,7,7,7,5,5,3,5,6,4";
-
- maprow = new Array();
- maprow = tstring.split(",");
- for(var k:int = 0; k < 96; k++) {
- bfontlen[k + 32] = 8;// int(maprow[k]);
- }
- }
-
- public function makebfontmask():void {
- for (var j:Number = 0; j < 16; j++) {
- for (var i:Number = 0; i < 16; i++) {
- var t:BitmapData = new BitmapData(9, 9, true, 0x000000);
- var t2:BitmapData = new BitmapData(9, 9, true, 0x000000);
- var temprect:Rectangle = new Rectangle(i * 9, j * 9, 9, 9);
- t.copyPixels(buffer, temprect, tl);
- t2.draw(t, flipfontmatrix2);
- bfontmask.push(t);
- flipbfontmask.push(t2);
- }
- }
+ setcol(c, help);
+ sprites[t].color = ct.color;
+ tposition.identity();
+ tposition.translate(x, y);
+ backbuffer.draw(sprites[t], tposition);
}
public function makeentcolourarray():void {
- for (var j:Number = 0; j < 60; j++) {
- for (var i:Number = 0; i < 12; i++) {
- var t:BitmapData = new BitmapData(8, 8, true, 0x000000);
- var temprect:Rectangle = new Rectangle(i * 8, j * 8, 8, 8);
- t.copyPixels(buffer, temprect, tl);
+ var sourcetexture:Texture = starlingassets.getTexture("entcolours");
+ for (var j:int = 0; j < 60; j++) {
+ for (var i:int = 0; i < 12; i++) {
+ var tiletex:Texture = Texture.fromTexture(sourcetexture, new Rectangle(i * 8, j * 8, 8, 8));
+ var t:Image = new Image(tiletex);
+ t.textureSmoothing = TextureSmoothing.NONE;
+ t.touchable = false;
entcolours.push(t);
}
}
}
public function maketilearray():void {
- for (var j:Number = 0; j < 30; j++) {
- for (var i:Number = 0; i < 40; i++) {
- var t:BitmapData = new BitmapData(8, 8, true, 0x000000);
- var temprect:Rectangle = new Rectangle(i * 8, j * 8, 8, 8);
- t.copyPixels(buffer, temprect, tl);
- tiles.push(t);
+ var sourcetexture:Texture = starlingassets.getTexture("tiles");
+ for (var j:int = 0; j < 30; j++) {
+ for (var i:int = 0; i < 40; i++) {
+ var tiletex:Texture = Texture.fromTexture(sourcetexture, new Rectangle(i * 8, j * 8, 8, 8));
+ var tile:Image = new Image(tiletex);
+ tile.textureSmoothing = TextureSmoothing.NONE;
+ tile.touchable = false;
+ tiles.push(tile);
}
}
}
public function maketile2array():void {
- for (var j:Number = 0; j < 30; j++) {
- for (var i:Number = 0; i < 40; i++) {
- var t:BitmapData = new BitmapData(8, 8, true, 0x000000);
- var temprect:Rectangle = new Rectangle(i * 8, j * 8, 8, 8);
- t.copyPixels(buffer, temprect, tl);
- tiles2.push(t);
+ var sourcetexture:Texture = starlingassets.getTexture("tiles2");
+ for (var j:int = 0; j < 30; j++) {
+ for (var i:int = 0; i < 40; i++) {
+ var tiletex:Texture = Texture.fromTexture(sourcetexture, new Rectangle(i * 8, j * 8, 8, 8));
+ var tile:Image = new Image(tiletex);
+ tile.textureSmoothing = TextureSmoothing.NONE;
+ tile.touchable = false;
+ tiles2.push(tile);
}
}
}
public function maketile3array():void {
- for (var j:Number = 0; j < 30; j++) {
- for (var i:Number = 0; i < 30; i++) {
- var t:BitmapData = new BitmapData(8, 8, true, 0x000000);
- var temprect:Rectangle = new Rectangle(i * 8, j * 8, 8, 8);
- t.copyPixels(buffer, temprect, tl);
- tiles3.push(t);
+ var sourcetexture:Texture = starlingassets.getTexture("tiles3");
+ for (var j:int = 0; j < 30; j++) {
+ for (var i:int = 0; i < 30; i++) {
+ var tiletex:Texture = Texture.fromTexture(sourcetexture, new Rectangle(i * 8, j * 8, 8, 8));
+ var tile:Image = new Image(tiletex);
+ tile.textureSmoothing = TextureSmoothing.NONE;
+ tile.touchable = false;
+ tiles3.push(tile);
}
}
}
public function makespritearray():void {
- for (var j:Number = 0; j < 16; j++) {
- for (var i:Number = 0; i < 12; i++) {
- var t:BitmapData = new BitmapData(32, 32, true, 0x000000);
- var temprect:Rectangle = new Rectangle(i * 32, j * 32, 32, 32);
- t.copyPixels(buffer, temprect, tl);
+ var sourcetexture:Texture = starlingassets.getTexture("sprites");
+ for (var j:int = 0; j < 16; j++) {
+ for (var i:int = 0; i < 12; i++) {
+ var tiletex:Texture = Texture.fromTexture(sourcetexture, new Rectangle(i * 32, j * 32, 32, 32));
+ var t:Image = new Image(tiletex);
+ t.textureSmoothing = TextureSmoothing.NONE;
+ t.touchable = false;
sprites.push(t);
}
}
+
+ //Sprites also need to load flash bitmapdatas, which are used for pixel perfect hittests
+ var b:Bitmap = new img_bitmapsprites();
+ var buffer:BitmapData = b.bitmapData;
+
+ for (j = 0; j < 16; j++) {
+ for (i = 0; i < 12; i++) {
+ var tb:BitmapData = new BitmapData(32, 32, true, 0x000000);
+ var temprect:Rectangle = new Rectangle(i * 32, j * 32, 32, 32);
+ tb.copyPixels(buffer, temprect, tl);
+ sprites_bitmap.push(tb);
+ }
+ }
}
public function makeflipspritearray():void {
- for (var j:Number = 0; j < 16; j++) {
- for (var i:Number = 0; i < 12; i++) {
- var t:BitmapData = new BitmapData(32, 32, true, 0x000000);
- var temprect:Rectangle = new Rectangle(i * 32, j * 32, 32, 32);
- t.copyPixels(buffer, temprect, tl);
+ var sourcetexture:Texture = starlingassets.getTexture("flipsprites");
+ for (var j:int = 0; j < 16; j++) {
+ for (var i:int = 0; i < 12; i++) {
+ var tiletex:Texture = Texture.fromTexture(sourcetexture, new Rectangle(i * 32, j * 32, 32, 32));
+ var t:Image = new Image(tiletex);
+ t.textureSmoothing = TextureSmoothing.NONE;
+ t.touchable = false;
flipsprites.push(t);
}
}
+
+
+ //Sprites also need to load flash bitmapdatas, which are used for pixel perfect hittests
+ var b:Bitmap = new img_bitmapflipsprites();
+ var buffer:BitmapData = b.bitmapData;
+
+ for (j = 0; j < 16; j++) {
+ for (i = 0; i < 12; i++) {
+ var tb:BitmapData = new BitmapData(32, 32, true, 0x000000);
+ var temprect:Rectangle = new Rectangle(i * 32, j * 32, 32, 32);
+ tb.copyPixels(buffer, temprect, tl);
+ flipsprites_bitmap.push(tb);
+ }
+ }
}
public function maketelearray():void {
- for (var i:Number = 0; i < 10; i++) {
- var t:BitmapData = new BitmapData(96, 96, true, 0x000000);
- var temprect:Rectangle = new Rectangle(i * 96, 0, 96, 96);
- t.copyPixels(buffer, temprect, tl);
+ var sourcetexture:Texture = starlingassets.getTexture("teleporter");
+ for (var i:int = 0; i < 10; i++) {
+ var tiletex:Texture = Texture.fromTexture(sourcetexture, new Rectangle(i * 96, j * 96, 96, 96));
+ var t:Image = new Image(tiletex);
+ t.textureSmoothing = TextureSmoothing.NONE;
+ t.touchable = false;
tele.push(t);
}
}
public function drawmobilebutton(game:gameclass, xp:int, yp:int, wp:int, hp:int, t:String, cr:int, cg:int, cb:int, xoff:int = -8, yoff:int = -10):void {
- xp = xp + xoff;
+ xp = xp + xoff;
yp = yp + yoff;
drawfillrect(xp + 4, yp + 4, wp, hp, cr * 0.25, cg * 0.25, cb * 0.25);
drawfillrect(xp, yp, wp, hp, cr, cg, cb);
@@ -827,51 +851,7 @@
}
public function drawlevelmenu(game:gameclass, cr:int, cg:int, cb:int, division:int = 30):void {
- for (var i:int = 0; i < game.nummenuoptions; i++){
- if (i == game.currentmenuoption){
- if(game.nummenuoptions-i<=2){
- //Draw it highlighted
- if (game.menuoptionsactive[i]) {
- tempstring = game.menuoptions[i]; tempstring = "[ " + tempstring.toUpperCase() + " ]";
- print(110 + (i * division) - 16 +game.menuxoff, 140 + 8 + (i * 12) +game.menuyoff, tempstring, cr, cg, cb);
- }else{
- tempstring = game.menuoptions[i];
- tempstring = "[ " + tempstring + " ]";
- //Draw it in gray
- print(110 + (i * division) - 16 +game.menuxoff, 140 + 8 + (i * 12) + game.menuyoff, tempstring, 128, 128, 128);
- }
- }else{
- //Draw it highlighted
- if (game.menuoptionsactive[i]){
- tempstring = game.menuoptions[i]; tempstring = "[ " + tempstring.toUpperCase() + " ]";
- print(110 + (i * division) - 16 +game.menuxoff, 140 + (i * 12) +game.menuyoff, tempstring, cr, cg, cb);
- }else{
- tempstring = game.menuoptions[i];
- tempstring = "[ " + tempstring + " ]";
- //Draw it in gray
- print(110 + (i * division) - 16 +game.menuxoff, 140 + (i * 12)+game.menuyoff, tempstring, 128, 128, 128);
- }
- }
- }else{
- if(game.nummenuoptions-i<=2){
- //Draw it normally
- if (game.menuoptionsactive[i]){
- print(110 + (i * division) +game.menuxoff, 140+8 + (i * 12)+game.menuyoff, game.menuoptions[i], cr, cg, cb);
- }else{
- //Draw it in gray
- print(110 + (i * division) +game.menuxoff, 140+8 + (i * 12)+game.menuyoff, game.menuoptions[i], 128, 128, 128);
- }
- }else{
- //Draw it normally
- if (game.menuoptionsactive[i]){
- print(110 + (i * division) +game.menuxoff, 140 + (i * 12)+game.menuyoff, game.menuoptions[i], cr, cg, cb);
- }else{
- //Draw it in gray
- print(110 + (i * division) +game.menuxoff, 140 + (i * 12)+game.menuyoff, game.menuoptions[i], 128, 128, 128);
- }
- }
- }
- }
+ trace("dwgfx.drawlevelmenu() is not implemented yet");
}
//Fade functions
@@ -907,16 +887,14 @@
public function drawfade():void {
if (fademode == 1) {
- backbuffer.fillRect(backbuffer.rect, 0x000000);
+ cls(0x000000);
}else if(fademode==3){
for (i = 0; i < 15; i++) {
- setmadrect(fadebars[i], i * 16, fadeamount, 16);
- backbuffer.fillRect(madrect, 0x000000);
+ drawfillrect(fadebars[i], i * 16, fadeamount, 16, 0, 0, 0);
}
}else if(fademode==5){
for (i = 0; i < 15; i++) {
- setmadrect(fadebars[i]-fadeamount, i * 16, 500, 16);
- backbuffer.fillRect(madrect, 0x000000);
+ drawfillrect(fadebars[i]-fadeamount, i * 16, 500, 16, 0, 0, 0);
}
}
}
@@ -941,7 +919,7 @@
m = ntextbox; ntextbox++;
}
- if(m<20){
+ if (m < 20) {
textbox[m].clear();
textbox[m].line[0] = t;
textbox[m].xp = xp;
@@ -1019,8 +997,7 @@
public function drawtextbox(x:int, y:int, w:int, h:int, r:int, g:int, b:int):void {
//given these parameters, draw a textbox
- madrect.x = x; madrect.y = y; madrect.width = w*8; madrect.height = h*8;
- backbuffer.fillRect(madrect, RGB(r / 6, g / 6, b / 6));
+ drawfillrect(x, y, w * 8, h * 8, r / 6, g / 6, b / 6);
drawcoloredtile(x, y, 40, r, g, b);
drawcoloredtile(x + (w*8) - 8, y, 42, r, g, b);
drawcoloredtile(x, y + (h*8) - 8, 45, r, g, b);
@@ -1037,10 +1014,9 @@
}
}
- public function drawpixeltextbox(x:int, y:int, w:int, h:int, w2:int, h2:int, r:int, g:int, b:int, xo:int=0, yo:int=0):void {
+ public function drawpixeltextbox(x:int, y:int, w:int, h:int, w2:int, h2:int, r:int, g:int, b:int, xo:int = 0, yo:int = 0):void {
//given these parameters, draw a textbox with a pixel width
- madrect.x = x; madrect.y = y; madrect.width = w; madrect.height = h;
- backbuffer.fillRect(madrect, RGB(r / 6, g / 6, b / 6));
+ drawfillrect(x, y, w, h, r / 6, g / 6, b / 6);
for (k = 0; k < w2-2; k++) {
drawcoloredtile(x + 8-xo + (k * 8), y, 41, r, g, b);
@@ -1058,13 +1034,9 @@
drawcoloredtile(x + (w) - 8, y + (h) - 8, 47, r, g, b);
}
- public function drawcustompixeltextbox(x:int, y:int, w:int, h:int, w2:int, h2:int, r:int, g:int, b:int, xo:int=0, yo:int=0):void {
+ public function drawcustompixeltextbox(x:int, y:int, w:int, h:int, w2:int, h2:int, r:int, g:int, b:int, xo:int = 0, yo:int = 0):void {
//given these parameters, draw a textbox with a pixel width
-
- //madrect.x = x; madrect.y = y; madrect.w = w; madrect.h = h;
- //backbuffer.fillRect(madrect, RGB(r / 6, g / 6, b / 6));
- madrect.x = x; madrect.y = y; madrect.width = w; madrect.height = h;
- backbuffer.fillRect(madrect, RGB(r / 6, g / 6, b / 6));
+ drawfillrect(x, y, w, h, r / 6, g / 6, b / 6);
for (k = 0; k < w2-2; k++){
drawcoloredtile(x + 8-xo + (k * 8), y, 41, r, g, b);
@@ -1092,34 +1064,67 @@
drawcoloredtile(x + (w) - 8, y + (h) - 8, 47, r, g, b);
}
- public function drawpartimage(t:int, xp:int, yp:int, wp:int, hp:int):void {
- tpoint.x = xp; tpoint.y = yp;
- madrect.x = 0; madrect.y = 0; madrect.width = wp; madrect.height = hp;
+ public var subtex:Texture;
+ public var subimage:Image;
+ public function drawpartimage(t:Texture, xp:int, yp:int, wp:int, hp:int):void {
+ // Acquire SubTexture and build an Image from it.
+ trect.x = 0;
+ trect.y = 0;
+ trect.width = wp;
+ trect.height = hp;
- backbuffer.copyPixels(images[t], madrect, tpoint);
+ if (subtex == null) {
+ subtex = Texture.fromTexture(t, trect);
+ subimage = new Image(subtex); // alloc. avoidable with pooling?
+ subimage.touchable = false;
+ subimage.textureSmoothing = TextureSmoothing.NONE;
+
+ tposition.identity();
+ tposition.translate(xp, yp);
+ backbuffer.draw(subimage, tposition);
+ return;
+ }else {
+ //dispose of the old one
+ //No memory leaks, but this is throwing away a texture every call, which might
+ //get expensive? Ideally you'd reuse an image here if it hasn't changed.
+ //Or, maybe easier, make a function that grabs the chunk we need and keeps it somewhere
+ //else, hardcoding around the problem. Let's see if this is a problem in practice, though.
+ subtex.dispose();
+ subimage.dispose();
+
+ subtex = Texture.fromTexture(t, trect);
+ subimage = new Image(subtex);
+ subimage.touchable = false;
+ subimage.textureSmoothing = TextureSmoothing.NONE;
+
+ tposition.identity();
+ tposition.translate(xp, yp);
+ backbuffer.draw(subimage, tposition);
+ return;
+ }
}
public function cutscenebars():void {
if (showcutscenebars) {
cutscenebarspos += 25;
if (cutscenebarspos >= 360) cutscenebarspos = 360;
- setmadrect(0, 0, cutscenebarspos, 16);
- backbuffer.fillRect(madrect, 0x000000);
- setmadrect(360-cutscenebarspos, 224, cutscenebarspos, 16);
- backbuffer.fillRect(madrect, 0x000000);
+ drawfillrect(0, 0, cutscenebarspos, 16, 0, 0, 0);
+ drawfillrect(360 - cutscenebarspos, 224, cutscenebarspos, 16, 0, 0, 0);
}else {
//disappearing
if (cutscenebarspos > 0) {
cutscenebarspos -= 25;
- //draw
- setmadrect(0, 0, cutscenebarspos, 16);
- backbuffer.fillRect(madrect, 0x000000);
- setmadrect(360-cutscenebarspos, 224, cutscenebarspos, 16);
- backbuffer.fillRect(madrect, 0x000000);
+ //draw
+ drawfillrect(0, 0, cutscenebarspos, 16, 0, 0, 0);
+ drawfillrect(360 - cutscenebarspos, 224, cutscenebarspos, 16, 0, 0, 0);
}
}
}
+ //For android: this function draws textboxes to a buffer first, where they're later copied to the screen
+ //buffer is a 320x500 image. X coordinates aren't changed, but y coordinates are
+ public var textbox_ybuffer:int;
+ public var textbox_ybufferheight:int = 0;
public function drawgui(help:helpclass):void {
textboxcleanup();
//Draw all the textboxes to the screen
@@ -1137,8 +1142,8 @@
print(textbox[i].xp + 8, textbox[i].yp + 8 + (j * 8), textbox[i].line[j], 196, 196, 255 - help.glow);
}
}
- }else{
- backbuffer.fillRect(textbox[i].textrect, RGB(textbox[i].r/6, textbox[i].g/6, textbox[i].b / 6));
+ }else {
+ drawfillrect(textbox[i].textrect.x, textbox[i].textrect.y, textbox[i].textrect.width, textbox[i].textrect.height, textbox[i].r/6, textbox[i].g/6, textbox[i].b / 6);
drawcoloredtile(textbox[i].xp, textbox[i].yp, 40, textbox[i].r, textbox[i].g, textbox[i].b);
drawcoloredtile(textbox[i].xp+textbox[i].w-8, textbox[i].yp, 42, textbox[i].r, textbox[i].g, textbox[i].b);
@@ -1223,111 +1228,258 @@
return (blue | (green << 8) | (red << 16))
}
- public function addmobileimage():void {
- var t:BitmapData = new BitmapData(buffer.width, buffer.height, true, 0x000000);
- setmadrect(0, 0, buffer.width, buffer.height);
- t.copyPixels(buffer, madrect, tl);
+ public function addmobileimage(imgname:String):void {
+ var sourcetexture:Texture = starlingassets.getTexture(imgname);
+ var t:Image = new Image(sourcetexture);
+ t.touchable = false;
+ t.textureSmoothing = TextureSmoothing.NONE;
mobileimages.push(t);
}
- public function addimage():void {
- var t:BitmapData = new BitmapData(buffer.width, buffer.height, true, 0x000000);
- setmadrect(0, 0, buffer.width, buffer.height);
- t.copyPixels(buffer, madrect, tl);
+ public function addimage(imgname:String):void {
+ var sourcetexture:Texture = starlingassets.getTexture(imgname);
+ var t:Image = new Image(sourcetexture);
+ t.touchable = false;
+ t.textureSmoothing = TextureSmoothing.NONE;
images.push(t);
}
- public function addplayerlevelimage():void {
- var t:BitmapData = new BitmapData(buffer.width, buffer.height, true, 0x000000);
- setmadrect(0, 0, buffer.width, buffer.height);
- t.copyPixels(buffer, madrect, tl);
+ public function addimage_rendertexture(imgname:String):void {
+ customminimap = starlingassets.getTexture(imgname) as RenderTexture;
+ var t:Image = new Image(customminimap);
+ t.touchable = false;
+ t.textureSmoothing = TextureSmoothing.NONE;
+ images.push(t);
+ }
+
+ public function addplayerlevelimage(imgname:String):void {
+ var sourcetexture:Texture = starlingassets.getTexture(imgname);
+ var t:Image = new Image(sourcetexture);
+ t.touchable = false;
+ t.textureSmoothing = TextureSmoothing.NONE;
playerlevelimages.push(t);
}
- public function addbackground():void {
- var t:BitmapData = new BitmapData(160, 144, true, 0x000000);
- t.copyPixels(buffer, bg_rect, tl);
+ public function addbackground(imgname:String):void {
+ //Don't think this is actually used in VVVVVV
+ var sourcetexture:Texture = starlingassets.getTexture(imgname);
+ var t:Image = new Image(sourcetexture);
+ t.touchable = false;
+ t.textureSmoothing = TextureSmoothing.NONE;
backgrounds.push(t);
}
+ public var towerx_pix:int;
+ public var towery_pix:int;
+ public var tower_bgcol:Vector. = new Vector.;
+ public var tower_bgdarkcol:Vector. = new Vector.;
+ public var lasttowercolstate:int = -1;
+ public var lasttowercolstate_front:int = -1;
+ public var maptdrawfront:Boolean = true;
+ public var forcetowerupdate:int = 10;
+ public var forcefronttowerupdate:int = 10;
+ public var towerfront_lastypos:int = 0;
+ public var tower_lastypos:int = 0;
+
+ public var forcewarpzonehorizontalupdate:int = 2;
+ public var forcewarpzoneverticalupdate:int = 1;
+ public var forcetowerstaticupdate:int = 1;
+
+ public function forcescreenupdates():void {
+ if (forcetowerupdate < 3) forcetowerupdate = 3;
+ if (forcefronttowerupdate < 3) forcefronttowerupdate = 3;
+ if (forcetowerstaticupdate < 3) forcetowerstaticupdate = 3;
+ if (forcewarpzoneverticalupdate < 1) forcewarpzoneverticalupdate = 1;
+ if (forcewarpzonehorizontalupdate < 1) forcewarpzonehorizontalupdate = 1;
+ }
+
public function drawtowerbackground(map:mapclass):void {
- if (map.bypos < 0) map.bypos += 120 * 8;
+ if (map.bypos < 0) {
+ map.bypos += 120 * 8;
+ forcetowerupdate += 5;
+ }
- if (map.scrolldir == 1) map.tdrawback = true;
-
- if (map.tdrawback) {
- //Draw the whole thing; needed for every colour cycle!
- for (j = 0; j < 30; j++) {
- for (i = 0; i < 40; i++) {
- temp = map.tower.backat(i, j, map.bypos);
- drawtowertile3(i * 8, (j * 8) - (map.bypos % 8), temp, map.colstate);
+ if (map.scrolldir == 1) {
+ if (map.tdrawback || lasttowercolstate != map.colstate || forcetowerupdate > 0) {
+ //Draw the whole thing; needed for every colour cycle!
+ towerbufferbackground_meshbatch.y = 0;
+ tower_lastypos = map.bypos;
+
+ towerbufferbackground_meshbatch.clear();
+ //Draw the whole thing; needed for every colour cycle!
+ for (j = 0; j < 40; j++) {
+ for (i = 0; i < 40; i++) {
+ temp = map.tower.backat(i, j, map.bypos);
+ drawtowertile3(i * 8, (j * 8) - (map.bypos % 8), temp, map.colstate);
+ }
+ }
+
+ backbuffer.draw(towerbufferbackground_meshbatch);
+
+ map.tdrawback = false;
+ lasttowercolstate = map.colstate;
+ if (forcetowerupdate > 0) forcetowerupdate--;
+ }else {
+ //just scroll down a bit
+ towerbufferbackground_meshbatch.y = -int(map.bypos - tower_lastypos);
+ backbuffer.draw(towerbufferbackground_meshbatch);
+
+ if (towerbufferbackground_meshbatch.y < -80) {
+ towerbufferbackground_meshbatch.y = 0;
+ map.tdrawback = true;
}
}
-
- backbuffer.copyPixels(towerbuffer, towerbuffer.rect, tl, null, null, false);
-
- map.tdrawback = false;
- }else {
- //just update the bottom
- towerbuffer.scroll(0, -map.bscroll);
- for (i = 0; i < 40; i++) {
- temp = map.tower.backat(i, 0, map.bypos);
- drawtowertile3(i * 8, -(map.bypos % 8), temp, map.colstate);
+ }else{
+ if (map.tdrawback || lasttowercolstate != map.colstate || forcetowerupdate > 0) {
+ //Draw the whole thing; needed for every colour cycle!
+ towerbufferbackground_meshbatch.y = 0;
+ tower_lastypos = map.bypos;
+
+ towerbufferbackground_meshbatch.clear();
+ //Draw the whole thing; needed for every colour cycle!
+ for (j = -10; j < 30; j++) {
+ for (i = 0; i < 40; i++) {
+ temp = map.tower.backat(i, j, map.bypos);
+ drawtowertile3(i * 8, (j * 8) - (map.bypos % 8), temp, map.colstate);
+ }
+ }
+
+ backbuffer.draw(towerbufferbackground_meshbatch);
+
+ map.tdrawback = false;
+ lasttowercolstate = map.colstate;
+ if (forcetowerupdate > 0) forcetowerupdate--;
+ }else {
+ //just scroll down a bit
+ towerbufferbackground_meshbatch.y = -int(map.bypos - tower_lastypos);
+ backbuffer.draw(towerbufferbackground_meshbatch);
+
+ if (towerbufferbackground_meshbatch.y > 80) {
+ towerbufferbackground_meshbatch.y = 0;
+ map.tdrawback = true;
+ }
}
-
- backbuffer.copyPixels(towerbuffer, towerbuffer.rect, tl, null, null, false);
}
}
public function drawtowerbackgroundsolo(map:mapclass):void {
- if (map.bypos < 0) map.bypos += 120 * 8;
+ if (map.bypos < 0) {
+ map.bypos += 120 * 8;
+ forcetowerupdate += 5;
+ }
- if (map.tdrawback) {
+ if (map.scrolldir == 1) map.tdrawback = true;
+
+ if (map.tdrawback || lasttowercolstate != map.colstate || forcetowerupdate > 0) {
//Draw the whole thing; needed for every colour cycle!
- for (j = 0; j < 31; j++) {
+ towerbufferbackground_meshbatch.y = 0;
+ tower_lastypos = map.bypos;
+
+ towerbufferbackground_meshbatch.clear();
+ //Draw the whole thing; needed for every colour cycle!
+ for (j = -10; j < 31; j++) {
for (i = 0; i < 40; i++) {
temp = map.tower.backat(i, j, map.bypos);
drawtowertile3(i * 8, (j * 8) - (map.bypos % 8), temp, map.colstate);
}
}
- backbuffer.copyPixels(towerbuffer, towerbuffer.rect, tl, null, null, false);
+ backbuffer.draw(towerbufferbackground_meshbatch);
map.tdrawback = false;
+ lasttowercolstate = map.colstate;
+ if (forcetowerupdate > 0) forcetowerupdate--;
}else {
- //just update the bottom
- towerbuffer.scroll(0, -map.bscroll);
- for (i = 0; i < 40; i++) {
- temp = map.tower.backat(i, 0, map.bypos);
- drawtowertile3(i * 8, -(map.bypos % 8), temp, map.colstate);
- }
+ //just scroll down a bit
+ towerbufferbackground_meshbatch.y = -int(map.bypos - tower_lastypos);
+ backbuffer.draw(towerbufferbackground_meshbatch);
- backbuffer.copyPixels(towerbuffer, towerbuffer.rect, tl, null, null, false);
+ if (towerbufferbackground_meshbatch.y > 80) {
+ towerbufferbackground_meshbatch.y = 0;
+ map.tdrawback = true;
+ }
}
}
- public function drawtowermap(map:mapclass):void {
- for (j = 0; j < 30; j++) {
- for (i = 0; i < 40; i++) {
- temp = map.tower.at(i, j, map.ypos);
- if (temp > 0) drawtile3(i * 8, (j * 8) - (map.ypos % 8), temp, map.colstate);
+ public function drawtowermap(game:gameclass, map:mapclass):void {
+ if (game.deathseq > 0) { forcefronttowerupdate = 20; }
+
+ if (map.scrolldir == 1) {
+ if (maptdrawfront || lasttowercolstate_front != map.colstate || forcefronttowerupdate > 0) {
+ towerbufferforeground_meshbatch.y = 0;
+ towerfront_lastypos = map.ypos;
+ towerbufferforeground_meshbatch.clear();
+
+ for (j = 0; j < 40; j++) {
+ for (i = 0; i < 40; i++) {
+ temp = map.tower.at(i, j, map.ypos);
+ if (temp > 0) drawtile3_batch(i * 8, (j * 8) - (map.ypos % 8), temp, map.colstate);
+ }
+ }
+
+ backbuffer.draw(towerbufferforeground_meshbatch);
+
+ maptdrawfront = false;
+ lasttowercolstate_front = map.colstate;
+ if (forcefronttowerupdate > 0) forcefronttowerupdate--;
+ }else {
+ //just scroll down a bit
+ towerbufferforeground_meshbatch.y = -int(map.ypos - towerfront_lastypos);
+ backbuffer.draw(towerbufferforeground_meshbatch);
+
+ if (towerbufferforeground_meshbatch.y < -80) {
+ towerbufferforeground_meshbatch.y = 0;
+ maptdrawfront = true;
+ }
+ }
+ }else{
+ if (maptdrawfront || lasttowercolstate_front != map.colstate || forcefronttowerupdate > 0) {
+ towerbufferforeground_meshbatch.y = 0;
+ towerfront_lastypos = map.ypos;
+ towerbufferforeground_meshbatch.clear();
+
+ for (j = -10; j < 30; j++) {
+ for (i = 0; i < 40; i++) {
+ temp = map.tower.at(i, j, map.ypos);
+ if (temp > 0) drawtile3_batch(i * 8, (j * 8) - (map.ypos % 8), temp, map.colstate);
+ }
+ }
+
+ backbuffer.draw(towerbufferforeground_meshbatch);
+
+ maptdrawfront = false;
+ lasttowercolstate_front = map.colstate;
+ if (forcefronttowerupdate > 0) forcefronttowerupdate--;
+ }else {
+ //just scroll down a bit
+ towerbufferforeground_meshbatch.y = -int(map.ypos - towerfront_lastypos);
+ backbuffer.draw(towerbufferforeground_meshbatch);
+
+ if (towerbufferforeground_meshbatch.y > 80) {
+ towerbufferforeground_meshbatch.y = 0;
+ maptdrawfront = true;
+ }
}
}
}
public function drawtowermap_nobackground(map:mapclass):void {
+ towerbufferforeground_meshbatch.clear();
+
for (j = 0; j < 30; j++) {
for (i = 0; i < 40; i++) {
temp = map.tower.at(i, j, map.ypos);
- if (temp > 0 && temp<28) drawtile3(i * 8, (j * 8) - (map.ypos % 8), temp, map.colstate);
+ if (temp > 0 && temp<28) drawtile3_batch(i * 8, (j * 8) - (map.ypos % 8), temp, map.colstate);
}
}
+
+ backbuffer.draw(towerbufferforeground_meshbatch);
}
public function drawtowerspikes(map:mapclass):void {
for (i = 0; i < 40; i++) {
- drawtile3(i * 8, -8+map.spikeleveltop, 9, map.colstate);
- drawtile3(i * 8, 230-map.spikelevelbottom, 8, map.colstate);
+ drawtile3(i * 8, -8 + map.spikeleveltop, 9, map.colstate);
+ drawtile3(i * 8, 230 - map.spikelevelbottom, 8, map.colstate);
}
}
@@ -1345,39 +1497,53 @@
for (var i:int = 0; i < obj.nentity; i++) {
if (!obj.entities[i].invis && obj.entities[i].active) {
if (obj.entities[i].size == 0) { // Sprites
- tpoint.x = obj.entities[i].xp; tpoint.y = obj.entities[i].yp-map.ypos;
+ tposition.identity();
+ tposition.translate(obj.entities[i].xp, obj.entities[i].yp - map.ypos);
+
setcol(obj.entities[i].colour, help);
- sprites[obj.entities[i].drawframe].colorTransform(sprites_rect, ct);
- backbuffer.copyPixels(sprites[obj.entities[i].drawframe], sprites_rect, tpoint);
+ sprites[obj.entities[i].drawframe].color = ct.color;
+ backbuffer.draw(sprites[obj.entities[i].drawframe], tposition);
//screenwrapping!
if (!map.minitowermode) {
if ( map.ypos >= 500 && map.ypos <= 5000) { //The "wrapping" area of the tower
if (tpoint.x < 0) {
- tpoint.x += 320;
- backbuffer.copyPixels(sprites[obj.entities[i].drawframe], sprites_rect, tpoint);
+ tposition.identity();
+ tposition.translate(obj.entities[i].xp + 320, obj.entities[i].yp - map.ypos);
+ backbuffer.draw(sprites[obj.entities[i].drawframe], tposition);
}
if (tpoint.x > 300) {
- tpoint.x -= 320;
- backbuffer.copyPixels(sprites[obj.entities[i].drawframe], sprites_rect, tpoint);
+ tposition.identity();
+ tposition.translate(obj.entities[i].xp - 320, obj.entities[i].yp - map.ypos);
+ backbuffer.draw(sprites[obj.entities[i].drawframe], tposition);
}
}
}
- }else if (obj.entities[i].size == 1) { // Tiles
- tpoint.x = obj.entities[i].xp; tpoint.y = obj.entities[i].yp-map.ypos;
- backbuffer.copyPixels(tiles[obj.entities[i].drawframe], tiles_rect, tpoint);
+ }else if (obj.entities[i].size == 1) { // Tiles
+ tposition.identity();
+ tposition.translate(obj.entities[i].xp, obj.entities[i].yp - map.ypos);
+ backbuffer.draw(tiles[obj.entities[i].drawframe], tposition);
}else if (obj.entities[i].size == 2) { // Special: Moving platform, 4 tiles
- tpoint.x = obj.entities[i].xp; tpoint.y = obj.entities[i].yp-map.ypos;
- backbuffer.copyPixels(tiles[obj.entities[i].drawframe], tiles_rect, tpoint);
- tpoint.x += 8; backbuffer.copyPixels(tiles[obj.entities[i].drawframe], tiles_rect, tpoint);
- tpoint.x += 8; backbuffer.copyPixels(tiles[obj.entities[i].drawframe], tiles_rect, tpoint);
- tpoint.x += 8; backbuffer.copyPixels(tiles[obj.entities[i].drawframe], tiles_rect, tpoint);
+ tposition.identity();
+ tposition.translate(obj.entities[i].xp, obj.entities[i].yp - map.ypos);
+ backbuffer.draw(tiles[obj.entities[i].drawframe], tposition);
+
+ tposition.identity();
+ tposition.translate(obj.entities[i].xp + 8, obj.entities[i].yp - map.ypos);
+ backbuffer.draw(tiles[obj.entities[i].drawframe], tposition);
+
+ tposition.identity();
+ tposition.translate(obj.entities[i].xp + 16, obj.entities[i].yp - map.ypos);
+ backbuffer.draw(tiles[obj.entities[i].drawframe], tposition);
+
+ tposition.identity();
+ tposition.translate(obj.entities[i].xp + 24, obj.entities[i].yp - map.ypos);
}else if (obj.entities[i].size == 3) { // Big chunky pixels!
prect.x = obj.entities[i].xp; prect.y = obj.entities[i].yp-map.ypos;
//A seperate index of colours, for simplicity
- if(obj.entities[i].colour==1){
- backbuffer.fillRect(prect, RGB(196 - (Math.random() * 64), 10, 10));
+ if (obj.entities[i].colour == 1) {
+ drawfillrect(prect.x, prect.y, prect.width, prect.height, 196 - (Math.random() * 64), 10, 10);
}else if (obj.entities[i].colour == 2) {
- backbuffer.fillRect(prect, RGB(160- help.glow/2 - (Math.random()*20), 200- help.glow/2, 220 - help.glow));
+ drawfillrect(prect.x, prect.y, prect.width, prect.height, 160- help.glow/2 - (Math.random()*20), 200- help.glow/2, 220 - help.glow);
}
}else if (obj.entities[i].size == 4) { // Small pickups
drawhuetile(obj.entities[i].xp, obj.entities[i].yp-map.ypos, obj.entities[i].tile, obj.entities[i].colour);
@@ -1397,24 +1563,25 @@
public function drawbackground(t:int, map:mapclass):void {
switch(t) {
case 1:
- //Starfield
- backbuffer.fillRect(backbuffer.rect, 0x000000);
+ //Starfield
+ drawfillrect(0, 0, 320, 240, 0, 0, 0);
for (i = 0; i < 50; i++) {
if (starsspeed[i] <= 6) {
- backbuffer.fillRect(stars[i], 0x222222);
+ drawfillrect(stars[i].x, stars[i].y, stars[i].width, stars[i].height, 34, 34, 34);
}else {
- backbuffer.fillRect(stars[i], 0x555555);
+ drawfillrect(stars[i].x, stars[i].y, stars[i].width, stars[i].height, 85, 85, 85);
}
stars[i].x -= starsspeed[i];
if (stars[i].x < -10) {
stars[i].x += 340;
stars[i].y = Math.random() * 240;
- starsspeed[i] = 4+(Math.random()*4);
+ starsspeed[i] = 4 + (Math.random()*4);
}
}
break;
case 2:
- //Lab
+ //Lab
+ i = 0;
switch(rcol) {
//Akward ordering to match tileset
case 0: bcol2 = RGB(0, 16*backboxint[i], 16*backboxint[i]); break; //Cyan
@@ -1432,7 +1599,7 @@
if (spcol >= 12) spcol = 0;
}
switch(spcol) {
- case 0: bcol2 = RGB(0, 16*backboxint[i], 16*backboxint[i]); break; //Cyan
+ case 0: bcol2 = RGB(0, 16 * backboxint[i], 16 * backboxint[i]); break; //Cyan
case 1: bcol2 = RGB(0, (spcoldel+1)*backboxint[i], 16*backboxint[i]); break; //Cyan
case 2: bcol2 = RGB(0, 0, 16*backboxint[i]); break; //Blue
case 3: bcol2 = RGB((16-spcoldel)*backboxint[i], 0, 16*backboxint[i]); break; //Blue
@@ -1447,7 +1614,7 @@
}
break;
}
- backbuffer.fillRect(backbuffer.rect, bcol2);
+ cls(bcol2);
for (i = 0; i < 18; i++) {
switch(rcol) {
//Akward ordering to match tileset
@@ -1475,11 +1642,11 @@
}
break;
}
- backbuffer.fillRect(backboxes[i], bcol);
+ drawfillrect(backboxes[i].x, backboxes[i].y, backboxes[i].width, backboxes[i].height, bcol);
backboxrect.x = backboxes[i].x + 1; backboxrect.y = backboxes[i].y + 1;
backboxrect.width = backboxes[i].width - 2; backboxrect.height = backboxes[i].height - 2;
- backbuffer.fillRect(backboxrect, bcol2);
+ drawfillrect(backboxrect.x, backboxrect.y, backboxrect.width, backboxrect.height, bcol2);
backboxes[i].x += backboxvx[i];
backboxes[i].y += backboxvy[i];
@@ -1490,67 +1657,65 @@
}
break;
case 3: //Warp zone (horizontal)
- backoffset+=3; if (backoffset >= 16) backoffset -= 16;
+ backoffset += 3; if (backoffset >= 16) backoffset -= 16;
- if (backgrounddrawn) {
- towerbuffer.scroll( -3, 0);
+ if (forcewarpzonehorizontalupdate > 0) {
+ warpzonehorizontal_meshbatch.x = 0;
+ warpzonehorizontal_meshbatch.clear();
for (j = 0; j < 15; j++) {
- temp = 680 + (rcol * 3);
- drawtowertile(317 - backoffset, (j * 16), temp+40); //20*16 = 320
- drawtowertile(317 - backoffset + 8, (j * 16), temp + 41);
- drawtowertile(317 - backoffset, (j * 16) + 8, temp + 80);
- drawtowertile(317 - backoffset + 8, (j * 16) + 8, temp + 81);
- }
- }else {
- //draw the whole thing for the first time!
- backoffset = 0;
- towerbuffer.fillRect(towerbuffer.rect, 0x000000);
- for (j = 0; j < 15; j++) {
- for (i = 0; i < 21; i++) {
+ for (i = -1; i < 21; i++) {
temp = 680 + (rcol * 3);
- drawtowertile((i * 16) - backoffset, (j * 16), temp+40);
- drawtowertile((i * 16) - backoffset + 8, (j * 16), temp + 41);
- drawtowertile((i * 16) - backoffset, (j * 16) + 8, temp + 80);
- drawtowertile((i * 16) - backoffset + 8, (j * 16) + 8, temp + 81);
+ tposition.identity(); tposition.translate(int((i * 16) - backoffset), int(j * 16));
+ warpzonehorizontal_meshbatch.addMesh(tiles2[temp+40], tposition);
+ tposition.identity(); tposition.translate(int((i * 16) - backoffset + 8), int((j * 16)));
+ warpzonehorizontal_meshbatch.addMesh(tiles2[temp + 41], tposition);
+ tposition.identity(); tposition.translate(int((i * 16) - backoffset), int((j * 16) + 8));
+ warpzonehorizontal_meshbatch.addMesh(tiles2[temp + 80], tposition);
+ tposition.identity(); tposition.translate(int((i * 16) - backoffset + 8), int((j * 16) + 8));
+ warpzonehorizontal_meshbatch.addMesh(tiles2[temp + 81], tposition);
}
}
- backgrounddrawn = true;
+
+ backbuffer.draw(warpzonehorizontal_meshbatch);
+ forcewarpzonehorizontalupdate--;
+ }else {
+ warpzonehorizontal_meshbatch.x = backoffset;
+ backbuffer.draw(warpzonehorizontal_meshbatch);
}
- backbuffer.copyPixels(towerbuffer, towerbuffer.rect, tl);
break;
case 4: //Warp zone (vertical)
- backoffset+=3; if (backoffset >= 16) backoffset -= 16;
+ backoffset += 3;
+ if (backoffset >= 16) backoffset -= 16;
- if (backgrounddrawn) {
- towerbuffer.scroll(0, -3);
- for (i = 0; i < 21; i++) {
- temp = 760 + (rcol * 3);
- drawtowertile((i * 16), 237 - backoffset, temp + 40); //14*17=240 - 3
- drawtowertile((i * 16) + 8, 237 - backoffset, temp + 41);
- drawtowertile((i * 16), 237 - backoffset + 8, temp + 80);
- drawtowertile((i * 16) + 8, 237 - backoffset + 8, temp + 81);
- }
- }else {
- //draw the whole thing for the first time!
- backoffset = 0;
- towerbuffer.fillRect(towerbuffer.rect, 0x000000);
- for (j = 0; j < 15; j++) {
+ if (forcewarpzoneverticalupdate > 0) {
+ warpzonevertical_meshbatch.y = 0;
+ warpzonevertical_meshbatch.clear();
+ for (j = -1; j < 16; j++) {
for (i = 0; i < 21; i++) {
temp = 760 + (rcol * 3);
- drawtowertile((i * 16), (j * 16)- backoffset, temp+40);
- drawtowertile((i * 16)+ 8, (j * 16)- backoffset, temp + 41);
- drawtowertile((i * 16), (j * 16)- backoffset + 8, temp + 80);
- drawtowertile((i * 16)+ 8, (j * 16)- backoffset + 8, temp + 81);
+ tposition.identity(); tposition.translate(int((i * 16)), int((j * 16) - backoffset));
+ warpzonevertical_meshbatch.addMesh(tiles2[temp+40], tposition);
+ tposition.identity(); tposition.translate(int((i * 16) + 8), int((j * 16) - backoffset));
+ warpzonevertical_meshbatch.addMesh(tiles2[temp + 41], tposition);
+ tposition.identity(); tposition.translate(int((i * 16)), int((j * 16) - backoffset + 8));
+ warpzonevertical_meshbatch.addMesh(tiles2[temp + 80], tposition);
+ tposition.identity(); tposition.translate(int((i * 16) + 8), int((j * 16) - backoffset + 8));
+ warpzonevertical_meshbatch.addMesh(tiles2[temp + 81], tposition);
}
}
- backgrounddrawn = true;
+
+ backbuffer.draw(warpzonevertical_meshbatch);
+ forcewarpzoneverticalupdate--;
+ }else {
+ warpzonevertical_meshbatch.y = backoffset;
+ backbuffer.draw(warpzonevertical_meshbatch);
}
- backbuffer.copyPixels(towerbuffer, towerbuffer.rect, tl);
+ //backbuffer.copyPixels(towerbuffer, towerbuffer.rect, tl);
break;
case 5:
- //Warp zone, central
+ //Warp zone, central
switch(rcol) {
//Akward ordering to match tileset
case 0: warpbcol = 0x0A100E; warpfcol = 0x102221; break; //Cyan
@@ -1568,24 +1733,24 @@
warpskip = (warpskip + 1) % 2;
}
- for (i = 10 ; i >= 0; i--) {
+ for (i = 10; i >= 0; i--) {
temp = (i << 4) + backoffset;
setwarprect(160 - temp, 120 - temp, temp * 2, temp * 2);
if (i % 2 == warpskip) {
- backbuffer.fillRect(warprect, warpbcol);
+ drawfillrect(warprect.x, warprect.y, warprect.width, warprect.height, warpbcol);
}else {
- backbuffer.fillRect(warprect, warpfcol);
+ drawfillrect(warprect.x, warprect.y, warprect.width, warprect.height, warpfcol);
}
}
break;
case 6:
//Final Starfield
- backbuffer.fillRect(backbuffer.rect, 0x000000);
+ cls(0x000000);
for (i = 0; i < 50; i++) {
if (starsspeed[i] <= 8) {
- backbuffer.fillRect(stars[i], 0x222222);
+ drawfillrect(stars[i].x, stars[i].y, stars[i].width, stars[i].height, 0x222222);
}else {
- backbuffer.fillRect(stars[i], 0x555555);
+ drawfillrect(stars[i].x, stars[i].y, stars[i].width, stars[i].height, 0x555555);
}
stars[i].y -= starsspeed[i];
if (stars[i].y < -10) {
@@ -1597,71 +1762,118 @@
break;
case 7:
//Static, unscrolling section of the tower
- for (j = 0; j < 30; j++) { for (i = 0; i < 40; i++) { drawtile3(i * 8, j * 8, map.tower.backat(i, j, 200), 15); } }
+ if (forcetowerstaticupdate > 0) {
+ towerbufferstatic_meshbatch.clear();
+
+ for (j = 0; j < 30; j++) {
+ for (i = 0; i < 40; i++) {
+ tposition.identity();
+ tposition.translate(int(i * 8), int(j * 8));
+ towerbufferstatic_meshbatch.addMesh(tiles3[map.tower.backat(i, j, 200) + (15 * 30)], tposition);
+ }
+ }
+
+ backbuffer.draw(towerbufferstatic_meshbatch);
+ forcetowerstaticupdate--;
+ }else {
+ backbuffer.draw(towerbufferstatic_meshbatch);
+ }
break;
case 8:
//Static, unscrolling section of the tower
- for (j = 0; j < 30; j++) { for (i = 0; i < 40; i++) { drawtile3(i * 8, j * 8, map.tower.backat(i, j, 200), 10); } }
+ if (forcetowerstaticupdate > 0) {
+ towerbufferstatic_meshbatch.clear();
+
+ for (j = 0; j < 30; j++) {
+ for (i = 0; i < 40; i++) {
+ tposition.identity();
+ tposition.translate(int(i * 8), int(j * 8));
+ towerbufferstatic_meshbatch.addMesh(tiles3[map.tower.backat(i, j, 200) + (15 * 10)], tposition);
+ }
+ }
+
+ backbuffer.draw(towerbufferstatic_meshbatch);
+ forcetowerstaticupdate--;
+ }else {
+ backbuffer.draw(towerbufferstatic_meshbatch);
+ }
break;
case 9:
//Static, unscrolling section of the tower
- for (j = 0; j < 30; j++) { for (i = 0; i < 40; i++) { drawtile3(i * 8, j * 8, map.tower.backat(i, j, 600), 0); } }
+ if (forcetowerstaticupdate > 0) {
+ towerbufferstatic_meshbatch.clear();
+
+ for (j = 0; j < 30; j++) {
+ for (i = 0; i < 40; i++) {
+ tposition.identity();
+ tposition.translate(int(i * 8), int(j * 8));
+ towerbufferstatic_meshbatch.addMesh(tiles3[map.tower.backat(i, j, 600)], tposition);
+ }
+ }
+
+ backbuffer.draw(towerbufferstatic_meshbatch);
+ forcetowerstaticupdate--;
+ }else {
+ backbuffer.draw(towerbufferstatic_meshbatch);
+ }
break;
default:
- backbuffer.fillRect(backbuffer.rect, 0x000000);
- //backbuffer.copyPixels(backgrounds[t], bg_rect, tl);
+ drawfillrect(0, 0, 320, 240, 0, 0, 0);
break;
}
}
+ public function textbox_drawimage(t:int, xp:int, yp:int, cent:Boolean=false):void {
+ trace("dwgfx.textbox_drawimage() is not implemented yet");
+ }
+
public function drawimage(t:int, xp:int, yp:int, cent:Boolean=false):void {
if (cent) {
- tpoint.x = 160 - int(images[t].width / 2); tpoint.y = yp;
- trect.x = 0; trect.y = 0; trect.width = images[t].width; trect.height = images[t].height;
- backbuffer.copyPixels(images[t], trect, tpoint);
+ tposition.identity();
+ tposition.translate(160 - int(images[t].width / 2), yp);
+ backbuffer.draw(images[t], tposition);
}else {
- tpoint.x = xp; tpoint.y = yp;
- trect.x = 0; trect.y = 0; trect.width = images[t].width; trect.height = images[t].height;
- backbuffer.copyPixels(images[t], trect, tpoint);
+ tposition.identity();
+ tposition.translate(xp, yp);
+ backbuffer.draw(images[t], tposition);
}
}
public function drawmobileimage(t:int, xp:int, yp:int, cent:Boolean=false):void {
if (cent) {
- tpoint.x = 160 - int(mobileimages[t].width / 2); tpoint.y = yp;
- trect.x = 0; trect.y = 0; trect.width = mobileimages[t].width; trect.height = mobileimages[t].height;
- backbuffer.copyPixels(mobileimages[t], trect, tpoint);
+ tposition.identity();
+ tposition.translate(160 - int(mobileimages[t].width / 2), yp);
+ backbuffer.draw(mobileimages[t], tposition);
}else {
- tpoint.x = xp; tpoint.y = yp;
- trect.x = 0; trect.y = 0; trect.width = mobileimages[t].width; trect.height = mobileimages[t].height;
- backbuffer.copyPixels(mobileimages[t], trect, tpoint);
+ tposition.identity();
+ tposition.translate(xp, yp);
+ backbuffer.draw(mobileimages[t], tposition);
}
}
public function drawmobilehands(t:int, xp:int, yp:int):void {
- tpoint.x = xp; tpoint.y = yp;
- trect.x = 0; trect.y = 0; trect.width = mobileimages[t].width; trect.height = 70;
- backbuffer.copyPixels(mobileimages[t], trect, tpoint);
+ tposition.identity();
+ tposition.translate(xp, yp);
+ backbuffer.draw(mobileimages[t], tposition);
}
public function drawplayerlevelimage(t:int, xp:int, yp:int):void {
- tpoint.x = xp; tpoint.y = yp;
- trect.x = 0; trect.y = 0; trect.width = playerlevelimages[t].width; trect.height = playerlevelimages[t].height;
- backbuffer.copyPixels(playerlevelimages[t], trect, tpoint);
+ tposition.identity();
+ tposition.translate(xp, yp);
+ backbuffer.draw(playerlevelimages[t], tposition);
}
public function drawimagecol(t:int, xp:int, yp:int, r:int, g:int, b:int, cent:Boolean = false):void {
- setcolreal(RGB(r,g,b));
if (cent) {
- tpoint.x = 160 - int(images[t].width / 2); tpoint.y = yp;
- trect.x = 0; trect.y = 0; trect.width = images[t].width; trect.height = images[t].height;
- images[t].colorTransform(trect, ct);
- backbuffer.copyPixels(images[t], trect, tpoint);
+ tposition.identity();
+ tposition.translate(160 - int(images[t].width / 2), yp);
+ images[t].color = RGB(r, g, b);
+ backbuffer.draw(images[t], tposition);
}else {
- tpoint.x = xp; tpoint.y = yp;
- trect.x = 0; trect.y = 0; trect.width = images[t].width; trect.height = images[t].height;
- images[t].colorTransform(trect, ct);
- backbuffer.copyPixels(images[t], trect, tpoint);
+ tposition.identity();
+ tposition.translate(xp, yp);
+ images[t].color = RGB(r, g, b);
+ backbuffer.draw(images[t], tposition);
}
}
@@ -1677,7 +1889,7 @@
}
public function setcol(t:int, help:helpclass):void {
- //Setup predefinied colours as per our zany palette
+ //Setup predefinied colours as per our zany palette
switch(t) {
//Player Normal
case 0: ct.color = RGB(160- help.glow/2 - (Math.random()*20), 200- help.glow/2, 220 - help.glow); break;
@@ -1824,25 +2036,30 @@
public function setcolreal(t:int):void {
ct.color = t;
}
-
+
+ public function textbox_drawcoloredtile(x:int, y:int, t:int, r:int, g:int, b:int):void {
+ trace("dwgfx.textbox_drawcoloredtile() is not implemented yet");
+ }
+
public function drawcoloredtile(x:int, y:int, t:int, r:int, g:int, b:int):void {
- tpoint.x = x; tpoint.y = y;
- setcolreal(RGB(r,g,b));
- tiles[t].colorTransform(tiles_rect, ct);
- backbuffer.copyPixels(tiles[t], tiles_rect, tpoint);
+ tposition.identity();
+ tposition.translate(x, y);
+
+ tiles[t].color = RGB(r, g, b);
+ backbuffer.draw(tiles[t], tposition);
}
public function drawhuetile(x:int, y:int, t:int, c:int):void {
- tpoint.x = x; tpoint.y = y;
+ tposition.identity();
+ tposition.translate(x, y);
switch(c) {
- case 0:setcolreal(RGB(250-(Math.random()*32), 250-(Math.random()*32), 10)); break;
- case 1:setcolreal(RGB(250-(Math.random()*32), 250-(Math.random()*32), 10)); break;
+ case 0: tiles[t].color = RGB(250-(Math.random()*32), 250-(Math.random()*32), 10); break;
+ case 1: tiles[t].color = RGB(250-(Math.random()*32), 250-(Math.random()*32), 10); break;
- default:setcolreal(RGB(250-(Math.random()*32), 250-(Math.random()*32), 10)); break;
+ default: tiles[t].color = RGB(250-(Math.random()*32), 250-(Math.random()*32), 10); break;
}
- tiles[t].colorTransform(tiles_rect, ct);
- backbuffer.copyPixels(tiles[t], tiles_rect, tpoint);
+ backbuffer.draw(tiles[t], tposition);
}
public function drawcrewman(x:int, y:int, t:int, act:Boolean, help:helpclass, noshift:Boolean=false):void {
@@ -1945,42 +2162,32 @@
}
public function drawsprite(x:int, y:int, t:int, r:int, g:int, b:int):void {
- tpoint.x = x; tpoint.y = y;
- setcolreal(RGB(r,g,b));
- sprites[t].colorTransform(sprites_rect, ct);
- backbuffer.copyPixels(sprites[t], sprites_rect, tpoint);
+ sprites[t].color = RGB(r, g, b);
+ tposition.identity();
+ tposition.translate(x, y);
+ backbuffer.draw(sprites[t], tposition);
+ }
+
+ public function textbox_drawsprite(x:int, y:int, t:int, r:int, g:int, b:int):void {
+ trace("dwgfx.textbox_drawsprite() is not implemented yet");
}
public function drawgravityline(t:int, obj:entityclass):void {
if (obj.entities[t].life == 0) {
- /*
switch(linestate) {
- case 0: backbuffer.fillRect(line_rect, RGB(0, 200, 0)); break;
- case 1: backbuffer.fillRect(line_rect, RGB(16, 245, 0)); break;
- case 2: backbuffer.fillRect(line_rect, RGB(0, 245, 16)); break;
- case 3: backbuffer.fillRect(line_rect, RGB(16, 200, 0)); break;
- case 4: backbuffer.fillRect(line_rect, RGB(24, 255, 16)); break;
- case 5: backbuffer.fillRect(line_rect, RGB(16, 235, 0)); break;
- case 6: backbuffer.fillRect(line_rect, RGB(0, 164, 16)); break;
- case 7: backbuffer.fillRect(line_rect, RGB(16, 245, 24)); break;
- case 8: backbuffer.fillRect(line_rect, RGB(0, 255, 16)); break;
- case 9: backbuffer.fillRect(line_rect, RGB(96, 245, 96)); break;
- }
- */
- switch(linestate) {
- case 0: backbuffer.fillRect(line_rect, RGB(200 - 20, 200 - 20, 200 - 20)); break;
- case 1: backbuffer.fillRect(line_rect, RGB(225 - 30, 245 - 30, 245 - 30)); break;
- case 2: backbuffer.fillRect(line_rect, RGB(245 - 30, 245 - 30, 225 - 30)); break;
- case 3: backbuffer.fillRect(line_rect, RGB(164 - 10, 200 - 20, 200 - 20)); break;
- case 4: backbuffer.fillRect(line_rect, RGB(224 - 20, 255 - 30, 196 - 20)); break;
- case 5: backbuffer.fillRect(line_rect, RGB(205 - 20, 235 - 30, 196 - 20)); break;
- case 6: backbuffer.fillRect(line_rect, RGB(164 - 10, 164 - 10, 164 - 10)); break;
- case 7: backbuffer.fillRect(line_rect, RGB(225 - 30, 245 - 30, 205 - 20)); break;
- case 8: backbuffer.fillRect(line_rect, RGB(205 - 20, 255 - 30, 225 - 30)); break;
- case 9: backbuffer.fillRect(line_rect, RGB(245 - 30, 245 - 30, 245 - 30)); break;
+ case 0: drawfillrect(line_rect.x, line_rect.y, line_rect.width, line_rect.height, 200 - 20, 200 - 20, 200 - 20); break;
+ case 1: drawfillrect(line_rect.x, line_rect.y, line_rect.width, line_rect.height, 225 - 30, 245 - 30, 245 - 30); break;
+ case 2: drawfillrect(line_rect.x, line_rect.y, line_rect.width, line_rect.height, 245 - 30, 245 - 30, 225 - 30); break;
+ case 3: drawfillrect(line_rect.x, line_rect.y, line_rect.width, line_rect.height, 164 - 10, 200 - 20, 200 - 20); break;
+ case 4: drawfillrect(line_rect.x, line_rect.y, line_rect.width, line_rect.height, 224 - 20, 255 - 30, 196 - 20); break;
+ case 5: drawfillrect(line_rect.x, line_rect.y, line_rect.width, line_rect.height, 205 - 20, 235 - 30, 196 - 20); break;
+ case 6: drawfillrect(line_rect.x, line_rect.y, line_rect.width, line_rect.height, 164 - 10, 164 - 10, 164 - 10); break;
+ case 7: drawfillrect(line_rect.x, line_rect.y, line_rect.width, line_rect.height, 225 - 30, 245 - 30, 205 - 20); break;
+ case 8: drawfillrect(line_rect.x, line_rect.y, line_rect.width, line_rect.height, 205 - 20, 255 - 30, 225 - 30); break;
+ case 9: drawfillrect(line_rect.x, line_rect.y, line_rect.width, line_rect.height, 245 - 30, 245 - 30, 245 - 30); break;
}
}else{
- backbuffer.fillRect(line_rect, RGB(96, 96, 96));
+ drawfillrect(line_rect.x, line_rect.y, line_rect.width, line_rect.height, 96, 96, 96);
}
}
@@ -1999,184 +2206,229 @@
if (!obj.entities[i].invis && obj.entities[i].active) {
if (obj.entities[i].size == 0) { // Sprites
if (flipmode) {
- tpoint.x = obj.entities[i].xp; tpoint.y = obj.entities[i].yp;
+ tposition.identity();
+ tposition.translate(int(obj.entities[i].xp), int(obj.entities[i].yp));
setcol(obj.entities[i].colour, help);
- flipsprites[obj.entities[i].drawframe].colorTransform(sprites_rect, ct);
- backbuffer.copyPixels(flipsprites[obj.entities[i].drawframe], sprites_rect, tpoint);
+ flipsprites[obj.entities[i].drawframe].color = ct.color;
+ backbuffer.draw(flipsprites[obj.entities[i].drawframe], tposition);
if (map.warpx) {
//screenwrapping!
if (tpoint.x < 0) {
- tpoint.x += 320;
- backbuffer.copyPixels(flipsprites[obj.entities[i].drawframe], sprites_rect, tpoint);
+ tposition.identity();
+ tposition.translate(int(obj.entities[i].xp) + 320, int(obj.entities[i].yp));
+ backbuffer.draw(flipsprites[obj.entities[i].drawframe], tposition);
}
if (tpoint.x > 300) {
- tpoint.x -= 320;
- backbuffer.copyPixels(flipsprites[obj.entities[i].drawframe], sprites_rect, tpoint);
+ tposition.identity();
+ tposition.translate(int(obj.entities[i].xp) - 320, int(obj.entities[i].yp));
+ backbuffer.draw(flipsprites[obj.entities[i].drawframe], tposition);
}
}else if (map.warpy) {
if (tpoint.y < 0) {
- tpoint.y += 230;
- backbuffer.copyPixels(flipsprites[obj.entities[i].drawframe], sprites_rect, tpoint);
+ tposition.identity();
+ tposition.translate(int(obj.entities[i].xp), int(obj.entities[i].yp) + 230);
+ backbuffer.draw(flipsprites[obj.entities[i].drawframe], tposition);
}
if (tpoint.y > 210) {
- tpoint.y -= 230;
- backbuffer.copyPixels(flipsprites[obj.entities[i].drawframe], sprites_rect, tpoint);
+ tposition.identity();
+ tposition.translate(int(obj.entities[i].xp), int(obj.entities[i].yp) - 230);
+ backbuffer.draw(flipsprites[obj.entities[i].drawframe], tposition);
}
}
- }else{
- tpoint.x = obj.entities[i].xp; tpoint.y = obj.entities[i].yp;
+ }else {
+ tposition.identity();
+ tposition.translate(int(obj.entities[i].xp), int(obj.entities[i].yp));
setcol(obj.entities[i].colour, help);
- sprites[obj.entities[i].drawframe].colorTransform(sprites_rect, ct);
- backbuffer.copyPixels(sprites[obj.entities[i].drawframe], sprites_rect, tpoint);
+ sprites[obj.entities[i].drawframe].color = ct.color;
+ backbuffer.draw(sprites[obj.entities[i].drawframe], tposition);
if (map.warpx) {
//screenwrapping!
if (tpoint.x < 0) {
- tpoint.x += 320;
- backbuffer.copyPixels(sprites[obj.entities[i].drawframe], sprites_rect, tpoint);
+ tposition.identity();
+ tposition.translate(int(obj.entities[i].xp) + 320, int(obj.entities[i].yp));
+ backbuffer.draw(sprites[obj.entities[i].drawframe], tposition);
}
if (tpoint.x > 300) {
- tpoint.x -= 320;
- backbuffer.copyPixels(sprites[obj.entities[i].drawframe], sprites_rect, tpoint);
+ tposition.identity();
+ tposition.translate(int(obj.entities[i].xp) - 320, int(obj.entities[i].yp));
+ backbuffer.draw(sprites[obj.entities[i].drawframe], tposition);
}
}else if (map.warpy) {
if (tpoint.y < 0) {
- tpoint.y += 230;
- backbuffer.copyPixels(sprites[obj.entities[i].drawframe], sprites_rect, tpoint);
+ tposition.identity();
+ tposition.translate(int(obj.entities[i].xp), int(obj.entities[i].yp) + 230);
+ backbuffer.draw(sprites[obj.entities[i].drawframe], tposition);
}
if (tpoint.y > 210) {
- tpoint.y -= 230;
- backbuffer.copyPixels(sprites[obj.entities[i].drawframe], sprites_rect, tpoint);
+ tposition.identity();
+ tposition.translate(int(obj.entities[i].xp), int(obj.entities[i].yp) - 230);
+ backbuffer.draw(sprites[obj.entities[i].drawframe], tposition);
}
}
}
}else if (obj.entities[i].size == 1) { // Tiles
- tpoint.x = obj.entities[i].xp; tpoint.y = obj.entities[i].yp;
- backbuffer.copyPixels(tiles[obj.entities[i].drawframe], tiles_rect, tpoint);
+ tposition.identity();
+ tposition.translate(int(obj.entities[i].xp), int(obj.entities[i].yp));
+ backbuffer.draw(tiles[obj.entities[i].drawframe], tposition);
}else if (obj.entities[i].size == 2) { // Special: Moving platform, 4 tiles
- tpoint.x = obj.entities[i].xp; tpoint.y = obj.entities[i].yp;
- if(map.custommode){
- backbuffer.copyPixels(entcolours[obj.entities[i].drawframe], tiles_rect, tpoint);
- tpoint.x += 8; backbuffer.copyPixels(entcolours[obj.entities[i].drawframe], tiles_rect, tpoint);
- tpoint.x += 8; backbuffer.copyPixels(entcolours[obj.entities[i].drawframe], tiles_rect, tpoint);
- tpoint.x += 8; backbuffer.copyPixels(entcolours[obj.entities[i].drawframe], tiles_rect, tpoint);
- }else{
- backbuffer.copyPixels(tiles[obj.entities[i].drawframe], tiles_rect, tpoint);
- tpoint.x += 8; backbuffer.copyPixels(tiles[obj.entities[i].drawframe], tiles_rect, tpoint);
- tpoint.x += 8; backbuffer.copyPixels(tiles[obj.entities[i].drawframe], tiles_rect, tpoint);
- tpoint.x += 8; backbuffer.copyPixels(tiles[obj.entities[i].drawframe], tiles_rect, tpoint);
+ tposition.identity(); tposition.translate(int(obj.entities[i].xp), int(obj.entities[i].yp));
+ if (map.custommode) {
+ backbuffer.draw(entcolours[obj.entities[i].drawframe], tposition);
+ tposition.identity(); tposition.translate(int(obj.entities[i].xp) + 8, int(obj.entities[i].yp));
+ backbuffer.draw(entcolours[obj.entities[i].drawframe], tposition);
+ tposition.identity(); tposition.translate(int(obj.entities[i].xp) + 16, int(obj.entities[i].yp));
+ backbuffer.draw(entcolours[obj.entities[i].drawframe], tposition)
+ tposition.identity(); tposition.translate(int(obj.entities[i].xp) + 24, int(obj.entities[i].yp));
+ backbuffer.draw(entcolours[obj.entities[i].drawframe], tposition)
+ }else {
+ backbuffer.draw(tiles[obj.entities[i].drawframe], tposition);
+ tposition.identity(); tposition.translate(int(obj.entities[i].xp) + 8, int(obj.entities[i].yp));
+ backbuffer.draw(tiles[obj.entities[i].drawframe], tposition);
+ tposition.identity(); tposition.translate(int(obj.entities[i].xp) + 16, int(obj.entities[i].yp));
+ backbuffer.draw(tiles[obj.entities[i].drawframe], tposition)
+ tposition.identity(); tposition.translate(int(obj.entities[i].xp) + 24, int(obj.entities[i].yp));
+ backbuffer.draw(tiles[obj.entities[i].drawframe], tposition)
}
}else if (obj.entities[i].size == 3) { // Big chunky pixels!
- prect.x = obj.entities[i].xp; prect.y = obj.entities[i].yp;
+ prect.x = int(obj.entities[i].xp); prect.y = int(obj.entities[i].yp);
//A seperate index of colours, for simplicity
- if(obj.entities[i].colour==1){
- backbuffer.fillRect(prect, RGB(196 - (Math.random() * 64), 10, 10));
+ if (obj.entities[i].colour == 1) {
+ drawfillrect(prect.x, prect.y, prect.width, prect.height, 196 - (Math.random() * 64), 10, 10);
}else if (obj.entities[i].colour == 2) {
- backbuffer.fillRect(prect, RGB(160- help.glow/2 - (Math.random()*20), 200- help.glow/2, 220 - help.glow));
+ drawfillrect(prect.x, prect.y, prect.width, prect.height, 160 - help.glow / 2 - (Math.random() * 20), 200 - help.glow / 2, 220 - help.glow);
}
}else if (obj.entities[i].size == 4) { // Small pickups
- drawhuetile(obj.entities[i].xp, obj.entities[i].yp, obj.entities[i].tile, obj.entities[i].colour);
+ drawhuetile(int(obj.entities[i].xp), int(obj.entities[i].yp), obj.entities[i].tile, obj.entities[i].colour);
}else if (obj.entities[i].size == 5) { //Horizontal Line
- line_rect.x = obj.entities[i].xp; line_rect.y = obj.entities[i].yp;
+ line_rect.x = int(obj.entities[i].xp); line_rect.y = int(obj.entities[i].yp);
line_rect.width = obj.entities[i].w; line_rect.height = 1;
drawgravityline(i, obj);
}else if (obj.entities[i].size == 6) { //Vertical Line
- line_rect.x = obj.entities[i].xp; line_rect.y = obj.entities[i].yp;
+ line_rect.x = int(obj.entities[i].xp); line_rect.y = int(obj.entities[i].yp);
line_rect.width = 1; line_rect.height = obj.entities[i].h;
drawgravityline(i, obj);
}else if (obj.entities[i].size == 7) { //Teleporter
- drawtele(obj.entities[i].xp, obj.entities[i].yp, obj.entities[i].drawframe, obj.entities[i].colour, help);
+ drawtele(int(obj.entities[i].xp), int(obj.entities[i].yp), obj.entities[i].drawframe, obj.entities[i].colour, help);
}else if (obj.entities[i].size == 8) { // Special: Moving platform, 8 tiles
- tpoint.x = obj.entities[i].xp; tpoint.y = obj.entities[i].yp;
+ tposition.identity(); tposition.translate(int(obj.entities[i].xp), int(obj.entities[i].yp));
if (map.custommode) {
- backbuffer.copyPixels(entcolours[obj.entities[i].drawframe], tiles_rect, tpoint);
- tpoint.x += 8; backbuffer.copyPixels(entcolours[obj.entities[i].drawframe], tiles_rect, tpoint);
- tpoint.x += 8; backbuffer.copyPixels(entcolours[obj.entities[i].drawframe], tiles_rect, tpoint);
- tpoint.x += 8; backbuffer.copyPixels(entcolours[obj.entities[i].drawframe], tiles_rect, tpoint);
- tpoint.x += 8; backbuffer.copyPixels(entcolours[obj.entities[i].drawframe], tiles_rect, tpoint);
- tpoint.x += 8; backbuffer.copyPixels(entcolours[obj.entities[i].drawframe], tiles_rect, tpoint);
- tpoint.x += 8; backbuffer.copyPixels(entcolours[obj.entities[i].drawframe], tiles_rect, tpoint);
- tpoint.x += 8; backbuffer.copyPixels(entcolours[obj.entities[i].drawframe], tiles_rect, tpoint);
+ backbuffer.draw(entcolours[obj.entities[i].drawframe], tposition);
+ tposition.identity(); tposition.translate(int(obj.entities[i].xp + 8), int(obj.entities[i].yp));
+ backbuffer.draw(entcolours[obj.entities[i].drawframe], tposition);
+ tposition.identity(); tposition.translate(int(obj.entities[i].xp + 16), int(obj.entities[i].yp));
+ backbuffer.draw(entcolours[obj.entities[i].drawframe], tposition);
+ tposition.identity(); tposition.translate(int(obj.entities[i].xp + 24), int(obj.entities[i].yp));
+ backbuffer.draw(entcolours[obj.entities[i].drawframe], tposition);
+ tposition.identity(); tposition.translate(int(obj.entities[i].xp + 32), int(obj.entities[i].yp));
+ backbuffer.draw(entcolours[obj.entities[i].drawframe], tposition);
+ tposition.identity(); tposition.translate(int(obj.entities[i].xp + 40), int(obj.entities[i].yp));
+ backbuffer.draw(entcolours[obj.entities[i].drawframe], tposition);
+ tposition.identity(); tposition.translate(int(obj.entities[i].xp + 48), int(obj.entities[i].yp));
+ backbuffer.draw(entcolours[obj.entities[i].drawframe], tposition);
+ tposition.identity(); tposition.translate(int(obj.entities[i].xp + 56), int(obj.entities[i].yp));
+ backbuffer.draw(entcolours[obj.entities[i].drawframe], tposition);
}else{
- backbuffer.copyPixels(tiles[obj.entities[i].drawframe], tiles_rect, tpoint);
- tpoint.x += 8; backbuffer.copyPixels(tiles[obj.entities[i].drawframe], tiles_rect, tpoint);
- tpoint.x += 8; backbuffer.copyPixels(tiles[obj.entities[i].drawframe], tiles_rect, tpoint);
- tpoint.x += 8; backbuffer.copyPixels(tiles[obj.entities[i].drawframe], tiles_rect, tpoint);
- tpoint.x += 8; backbuffer.copyPixels(tiles[obj.entities[i].drawframe], tiles_rect, tpoint);
- tpoint.x += 8; backbuffer.copyPixels(tiles[obj.entities[i].drawframe], tiles_rect, tpoint);
- tpoint.x += 8; backbuffer.copyPixels(tiles[obj.entities[i].drawframe], tiles_rect, tpoint);
- tpoint.x += 8; backbuffer.copyPixels(tiles[obj.entities[i].drawframe], tiles_rect, tpoint);
+ backbuffer.draw(tiles[obj.entities[i].drawframe], tposition);
+ tposition.identity(); tposition.translate(int(obj.entities[i].xp + 8), int(obj.entities[i].yp));
+ backbuffer.draw(tiles[obj.entities[i].drawframe], tposition);
+ tposition.identity(); tposition.translate(int(obj.entities[i].xp + 16), int(obj.entities[i].yp));
+ backbuffer.draw(tiles[obj.entities[i].drawframe], tposition);
+ tposition.identity(); tposition.translate(int(obj.entities[i].xp + 24), int(obj.entities[i].yp));
+ backbuffer.draw(tiles[obj.entities[i].drawframe], tposition);
+ tposition.identity(); tposition.translate(int(obj.entities[i].xp + 32), int(obj.entities[i].yp));
+ backbuffer.draw(tiles[obj.entities[i].drawframe], tposition);
+ tposition.identity(); tposition.translate(int(obj.entities[i].xp + 40), int(obj.entities[i].yp));
+ backbuffer.draw(tiles[obj.entities[i].drawframe], tposition);
+ tposition.identity(); tposition.translate(int(obj.entities[i].xp + 48), int(obj.entities[i].yp));
+ backbuffer.draw(tiles[obj.entities[i].drawframe], tposition);
+ tposition.identity(); tposition.translate(int(obj.entities[i].xp + 56), int(obj.entities[i].yp));
+ backbuffer.draw(tiles[obj.entities[i].drawframe], tposition);
}
}else if (obj.entities[i].size == 9) { // Really Big Sprite! (2x2)
if (flipmode) {
- setcol(obj.entities[i].colour, help);
+ setcol(obj.entities[i].colour, help);
- tpoint.x = obj.entities[i].xp; tpoint.y = obj.entities[i].yp;
- flipsprites[obj.entities[i].drawframe].colorTransform(sprites_rect, ct);
- backbuffer.copyPixels(flipsprites[obj.entities[i].drawframe], sprites_rect, tpoint);
+ tposition.identity();
+ tposition.translate(int(obj.entities[i].xp), int(obj.entities[i].yp));
+ flipsprites[obj.entities[i].drawframe].color = ct.color;
+ backbuffer.draw(flipsprites[obj.entities[i].drawframe], tposition);
- tpoint.x = obj.entities[i].xp+32; tpoint.y = obj.entities[i].yp;
- flipsprites[obj.entities[i].drawframe+1].colorTransform(sprites_rect, ct);
- backbuffer.copyPixels(flipsprites[obj.entities[i].drawframe+1], sprites_rect, tpoint);
+ tposition.identity();
+ tposition.translate(int(obj.entities[i].xp) + 32, int(obj.entities[i].yp));
+ flipsprites[obj.entities[i].drawframe + 1].color = ct.color;
+ backbuffer.draw(flipsprites[obj.entities[i].drawframe + 1], tposition);
- tpoint.x = obj.entities[i].xp; tpoint.y = obj.entities[i].yp+32;
- flipsprites[obj.entities[i].drawframe+12].colorTransform(sprites_rect, ct);
- backbuffer.copyPixels(flipsprites[obj.entities[i].drawframe+12], sprites_rect, tpoint);
+ tposition.identity();
+ tposition.translate(int(obj.entities[i].xp), int(obj.entities[i].yp) + 32);
+ flipsprites[obj.entities[i].drawframe + 12].color = ct.color;
+ backbuffer.draw(flipsprites[obj.entities[i].drawframe + 12], tposition);
- tpoint.x = obj.entities[i].xp+32; tpoint.y = obj.entities[i].yp+32;
- flipsprites[obj.entities[i].drawframe+13].colorTransform(sprites_rect, ct);
- backbuffer.copyPixels(flipsprites[obj.entities[i].drawframe + 13], sprites_rect, tpoint);
+ tposition.identity();
+ tposition.translate(int(obj.entities[i].xp) + 32, int(obj.entities[i].yp) + 32);
+ flipsprites[obj.entities[i].drawframe + 13].color = ct.color;
+ backbuffer.draw(flipsprites[obj.entities[i].drawframe + 13], tposition);
}else{
- setcol(obj.entities[i].colour, help);
+ setcol(obj.entities[i].colour, help);
- tpoint.x = obj.entities[i].xp; tpoint.y = obj.entities[i].yp;
- sprites[obj.entities[i].drawframe].colorTransform(sprites_rect, ct);
- backbuffer.copyPixels(sprites[obj.entities[i].drawframe], sprites_rect, tpoint);
+ tposition.identity();
+ tposition.translate(int(obj.entities[i].xp), int(obj.entities[i].yp));
+ sprites[obj.entities[i].drawframe].color = ct.color;
+ backbuffer.draw(sprites[obj.entities[i].drawframe], tposition);
- tpoint.x = obj.entities[i].xp+32; tpoint.y = obj.entities[i].yp;
- sprites[obj.entities[i].drawframe+1].colorTransform(sprites_rect, ct);
- backbuffer.copyPixels(sprites[obj.entities[i].drawframe+1], sprites_rect, tpoint);
+ tposition.identity();
+ tposition.translate(int(obj.entities[i].xp) + 32, int(obj.entities[i].yp));
+ sprites[obj.entities[i].drawframe + 1].color = ct.color;
+ backbuffer.draw(sprites[obj.entities[i].drawframe + 1], tposition);
- tpoint.x = obj.entities[i].xp; tpoint.y = obj.entities[i].yp+32;
- sprites[obj.entities[i].drawframe+12].colorTransform(sprites_rect, ct);
- backbuffer.copyPixels(sprites[obj.entities[i].drawframe+12], sprites_rect, tpoint);
+ tposition.identity();
+ tposition.translate(int(obj.entities[i].xp), int(obj.entities[i].yp) + 32);
+ sprites[obj.entities[i].drawframe + 12].color = ct.color;
+ backbuffer.draw(sprites[obj.entities[i].drawframe + 12], tposition);
- tpoint.x = obj.entities[i].xp+32; tpoint.y = obj.entities[i].yp+32;
- sprites[obj.entities[i].drawframe+13].colorTransform(sprites_rect, ct);
- backbuffer.copyPixels(sprites[obj.entities[i].drawframe + 13], sprites_rect, tpoint);
+ tposition.identity();
+ tposition.translate(int(obj.entities[i].xp) + 32, int(obj.entities[i].yp) + 32);
+ sprites[obj.entities[i].drawframe + 13].color = ct.color;
+ backbuffer.draw(sprites[obj.entities[i].drawframe + 13], tposition);
}
}else if (obj.entities[i].size == 10) { // 2x1 Sprite
if (flipmode) {
- setcol(obj.entities[i].colour, help);
+ setcol(obj.entities[i].colour, help);
- tpoint.x = obj.entities[i].xp; tpoint.y = obj.entities[i].yp;
- flipsprites[obj.entities[i].drawframe].colorTransform(sprites_rect, ct);
- backbuffer.copyPixels(flipsprites[obj.entities[i].drawframe], sprites_rect, tpoint);
+ tposition.identity();
+ tposition.translate(int(obj.entities[i].xp), int(obj.entities[i].yp));
+ flipsprites[obj.entities[i].drawframe].color = ct.color;
+ backbuffer.draw(flipsprites[obj.entities[i].drawframe], tposition);
- tpoint.x = obj.entities[i].xp+32; tpoint.y = obj.entities[i].yp;
- flipsprites[obj.entities[i].drawframe+1].colorTransform(sprites_rect, ct);
- backbuffer.copyPixels(flipsprites[obj.entities[i].drawframe + 1], sprites_rect, tpoint);
+ tposition.identity();
+ tposition.translate(int(obj.entities[i].xp) + 32, int(obj.entities[i].yp));
+ flipsprites[obj.entities[i].drawframe + 1].color = ct.color;
+ backbuffer.draw(flipsprites[obj.entities[i].drawframe + 1], tposition);
}else{
- setcol(obj.entities[i].colour, help);
+ setcol(obj.entities[i].colour, help);
- tpoint.x = obj.entities[i].xp; tpoint.y = obj.entities[i].yp;
- sprites[obj.entities[i].drawframe].colorTransform(sprites_rect, ct);
- backbuffer.copyPixels(sprites[obj.entities[i].drawframe], sprites_rect, tpoint);
+ tposition.identity();
+ tposition.translate(int(obj.entities[i].xp), int(obj.entities[i].yp));
+ sprites[obj.entities[i].drawframe].color = ct.color;
+ backbuffer.draw(sprites[obj.entities[i].drawframe], tposition);
- tpoint.x = obj.entities[i].xp+32; tpoint.y = obj.entities[i].yp;
- sprites[obj.entities[i].drawframe+1].colorTransform(sprites_rect, ct);
- backbuffer.copyPixels(sprites[obj.entities[i].drawframe + 1], sprites_rect, tpoint);
+ tposition.identity();
+ tposition.translate(int(obj.entities[i].xp) + 32, int(obj.entities[i].yp));
+ sprites[obj.entities[i].drawframe + 1].color = ct.color;
+ backbuffer.draw(sprites[obj.entities[i].drawframe + 1], tposition);
}
}else if (obj.entities[i].size == 11) { //The fucking elephant
- setcol(obj.entities[i].colour, help);
- images[3].colorTransform(images[3].rect, ct);
- drawimage(3, obj.entities[i].xp, obj.entities[i].yp);
+ setcol(obj.entities[i].colour, help);
+ images[3].color = ct.color;
+ drawimage(3, int(obj.entities[i].xp), int(obj.entities[i].yp));
}else if (obj.entities[i].size == 12) { // Regular sprites that don't wrap
if (flipmode) {
//forget this for a minute;
- tpoint.x = obj.entities[i].xp; tpoint.y = obj.entities[i].yp;
+ tpoint.x = int(obj.entities[i].xp); tpoint.y = int(obj.entities[i].yp);
setcol(obj.entities[i].colour, help);
- flipsprites[obj.entities[i].drawframe].colorTransform(sprites_rect, ct);
- backbuffer.copyPixels(flipsprites[obj.entities[i].drawframe], sprites_rect, tpoint);
+ flipsprites[obj.entities[i].drawframe].color = ct.color;
+ tposition.identity();
+ tposition.translate(tpoint.x, tpoint.y);
+ backbuffer.draw(flipsprites[obj.entities[i].drawframe], tposition);
//if we're outside the screen, we need to draw indicators
if (obj.entities[i].xp < -20 && obj.entities[i].vx > 0) {
@@ -2188,8 +2440,11 @@
tpoint.y = tpoint.y+4;
setcol(23, help);
- tiles[1167].colorTransform(tiles_rect, ct);
- backbuffer.copyPixels(tiles[1167], tiles_rect, tpoint);
+ tiles[1167].color = ct.color;
+ tposition.identity();
+ tposition.translate(tpoint.x, tpoint.y);
+
+ backbuffer.draw(tiles[1167], tposition);
}else if (obj.entities[i].xp > 340 && obj.entities[i].vx < 0) {
if (obj.entities[i].xp > 420) {
tpoint.x = 320 - (int(( obj.entities[i].xp-320) / 10));
@@ -2199,14 +2454,20 @@
tpoint.y = tpoint.y+4;
setcol(23, help);
- tiles[1166].colorTransform(tiles_rect, ct);
- backbuffer.copyPixels(tiles[1166], tiles_rect, tpoint);
+ tiles[1166].color = ct.color;
+
+ tposition.identity();
+ tposition.translate(tpoint.x, tpoint.y);
+
+ backbuffer.draw(tiles[1166], tposition);
}
}else{
- tpoint.x = obj.entities[i].xp; tpoint.y = obj.entities[i].yp;
+ tpoint.x = int(obj.entities[i].xp); tpoint.y = int(obj.entities[i].yp);
setcol(obj.entities[i].colour, help);
- sprites[obj.entities[i].drawframe].colorTransform(sprites_rect, ct);
- backbuffer.copyPixels(sprites[obj.entities[i].drawframe], sprites_rect, tpoint);
+ sprites[obj.entities[i].drawframe].color = ct.color;
+ tposition.identity();
+ tposition.translate(tpoint.x, tpoint.y);
+ backbuffer.draw(sprites[obj.entities[i].drawframe], tposition);
//if we're outside the screen, we need to draw indicators
@@ -2219,8 +2480,11 @@
tpoint.y = tpoint.y+4;
setcol(23, help);
- tiles[1167].colorTransform(tiles_rect, ct);
- backbuffer.copyPixels(tiles[1167], tiles_rect, tpoint);
+ tiles[1167].color = ct.color;
+ tposition.identity();
+ tposition.translate(tpoint.x, tpoint.y);
+
+ backbuffer.draw(tiles[1167], tposition);
}else if (obj.entities[i].xp > 340 && obj.entities[i].vx < 0) {
if (obj.entities[i].xp > 420) {
tpoint.x = 320 - (int(( obj.entities[i].xp-320) / 10));
@@ -2230,37 +2494,31 @@
tpoint.y = tpoint.y+4;
setcol(23, help);
- tiles[1166].colorTransform(tiles_rect, ct);
- backbuffer.copyPixels(tiles[1166], tiles_rect, tpoint);
+ tiles[1166].color = ct.color;
+
+ tposition.identity();
+ tposition.translate(tpoint.x, tpoint.y);
+
+ backbuffer.draw(tiles[1166], tposition);
}
}
}else if (obj.entities[i].size == 13) { // Special for epilogue: huge hero!
if (flipmode) {
- scaleMatrix = new Matrix();
- scaleMatrix.scale(6, 6);
- bigbuffer.fillRect(bigbuffer.rect, 0x000000);
+ tposition.identity();
+ tposition.scale(6, 6);
+ tposition.translate(int(obj.entities[i].xp), int(obj.entities[i].yp));
- tpoint.x = obj.entities[i].xp; tpoint.y = obj.entities[i].yp;
setcol(obj.entities[i].colour, help);
- flipsprites[obj.entities[i].drawframe].colorTransform(sprites_rect, ct);
- bigbuffer.copyPixels(flipsprites[obj.entities[i].drawframe], sprites_rect, new Point(0, 0));
-
- scaleMatrix.translate(obj.entities[i].xp, obj.entities[i].yp);
- backbuffer.draw(bigbufferscreen, scaleMatrix);
- scaleMatrix.translate(-obj.entities[i].xp, -obj.entities[i].yp);
+ flipsprites[obj.entities[i].drawframe].color = ct.color;
+ backbuffer.draw(flipsprites[obj.entities[i].drawframe], tposition);
}else {
- scaleMatrix = new Matrix();
- scaleMatrix.scale(6, 6);
- bigbuffer.fillRect(bigbuffer.rect, 0x000000);
+ tposition.identity();
+ tposition.scale(6, 6);
+ tposition.translate(int(obj.entities[i].xp), int(obj.entities[i].yp));
- tpoint.x = obj.entities[i].xp; tpoint.y = obj.entities[i].yp;
setcol(obj.entities[i].colour, help);
- sprites[obj.entities[i].drawframe].colorTransform(sprites_rect, ct);
- bigbuffer.copyPixels(sprites[obj.entities[i].drawframe], sprites_rect, new Point(0, 0));
-
- scaleMatrix.translate(obj.entities[i].xp, obj.entities[i].yp);
- backbuffer.draw(bigbufferscreen, scaleMatrix);
- scaleMatrix.translate(-obj.entities[i].xp, -obj.entities[i].yp);
+ sprites[obj.entities[i].drawframe].color = ct.color;
+ backbuffer.draw(sprites[obj.entities[i].drawframe], tposition);
}
}
}
@@ -2268,67 +2526,81 @@
}
public function drawbuffertile(x:int, y:int, t:int):void {
- tpoint.x = x; tpoint.y = y;
- buffer.copyPixels(tiles[t], tiles_rect, tpoint);
+ trace("dwgfx.drawbuffertile() is not implemented yet");
}
public function drawforetile(x:int, y:int, t:int):void {
- tpoint.x = x; tpoint.y = y;
- frontbuffer.copyPixels(tiles[t], tiles_rect, tpoint);
+ tposition.identity();
+ tposition.translate(x, y);
+ frontbuffer_meshbatch.addMesh(tiles[t], tposition);
}
public function drawforetile2(x:int, y:int, t:int):void {
- tpoint.x = x; tpoint.y = y;
- frontbuffer.copyPixels(tiles2[t], tiles_rect, tpoint);
+ tposition.identity();
+ tposition.translate(x, y);
+ frontbuffer_meshbatch.addMesh(tiles2[t], tposition);
}
public function drawforetile3(x:int, y:int, t:int, off:int):void {
- tpoint.x = x; tpoint.y = y;
- frontbuffer.copyPixels(tiles3[t+(off*30)], tiles_rect, tpoint);
+ tposition.identity();
+ tposition.translate(x, y);
+ frontbuffer_meshbatch.addMesh(tiles3[t+(off*30)], tposition);
}
-
public function drawtele(x:int, y:int, t:int, c:int, help:helpclass):void {
- tpoint.x = x; tpoint.y = y;
+ tele[0].color = RGB(16, 16, 16);
+ tposition.identity();
+ tposition.translate(x, y);
+ backbuffer.draw(tele[0], tposition);
- setcolreal(RGB(16,16,16));
- tele[0].colorTransform(tele_rect, ct);
- backbuffer.copyPixels(tele[0], tele_rect, tpoint);
-
- setcol(c, help);
+ setcol(c, help);
if (t > 9) t = 8; if (t < 0) t = 0;
- tele[t].colorTransform(tele_rect, ct);
- backbuffer.copyPixels(tele[t], tele_rect, tpoint);
+ tele[t].color = ct.color;
+
+ tposition.identity();
+ tposition.translate(x, y);
+ backbuffer.draw(tele[t], tposition);
}
public function drawtile(x:int, y:int, t:int):void {
- tpoint.x = x; tpoint.y = y;
- backbuffer.copyPixels(tiles[t], tiles_rect, tpoint);
+ tposition.identity();
+ tposition.translate(x, y);
+ backbuffer.draw(tiles[t], tposition);
}
public function drawtile2(x:int, y:int, t:int):void {
- tpoint.x = x; tpoint.y = y;
- backbuffer.copyPixels(tiles2[t], tiles_rect, tpoint);
+ tposition.identity();
+ tposition.translate(x, y);
+ backbuffer.draw(tiles2[t], tposition);
}
public function drawtile3(x:int, y:int, t:int, off:int):void {
- tpoint.x = x; tpoint.y = y;
- backbuffer.copyPixels(tiles3[t+(off*30)], tiles_rect, tpoint);
+ tposition.identity();
+ tposition.translate(x, y);
+ backbuffer.draw(tiles3[t + (off * 30)], tposition);
+ }
+
+ public function drawtile3_batch(x:int, y:int, t:int, off:int):void {
+ tposition.identity();
+ tposition.translate(x, y);
+ towerbufferforeground_meshbatch.addMesh(tiles3[t + (off * 30)], tposition);
}
public function drawtowertile3(x:int, y:int, t:int, off:int):void {
- tpoint.x = x; tpoint.y = y;
- towerbuffer.copyPixels(tiles3[t+(off*30)], tiles_rect, tpoint);
+ tposition.identity();
+ tposition.translate(x, y);
+ towerbufferbackground_meshbatch.addMesh(tiles3[t+(off*30)], tposition);
}
public function drawtowertile(x:int, y:int, t:int):void {
- tpoint.x = x; tpoint.y = y;
- towerbuffer.copyPixels(tiles2[t], tiles_rect, tpoint, null, null, true);
+ tposition.identity();
+ tposition.translate(x, y);
+ backbuffer.draw(tiles2[t], tposition);
}
public function drawmap(map:mapclass):void {
if (!foregrounddrawn) {
- frontbuffer.fillRect(frontbuffer.rect, 0x000000);
+ frontbuffer_meshbatch.clear();
if(map.tileset==0){
for (j = 0; j < 29+map.extrarow; j++) {
for (i = 0; i < 40; i++) {
@@ -2348,17 +2620,17 @@
}
}
}
- foregrounddrawn=true;
+ foregrounddrawn = true;
}
- backbuffer.copyPixels(frontbuffer, frontbuffer.rect, tl);
+ backbuffer.draw(frontbuffer_meshbatch);
}
public function drawfinalmap(map:mapclass):void {
//Update colour cycling for final level
if (map.final_colormode) {
map.final_aniframedelay--;
- if(map.final_aniframedelay==0) foregrounddrawn=false;
+ if (map.final_aniframedelay == 0) foregrounddrawn = false;
if (map.final_aniframedelay <= 0) {
map.final_aniframedelay = 2;
map.final_aniframe++;
@@ -2367,9 +2639,9 @@
}
if (!foregrounddrawn) {
- frontbuffer.fillRect(frontbuffer.rect, 0x000000);
+ frontbuffer_meshbatch.clear();
if(map.tileset==0){
- for (j = 0; j < 29+map.extrarow; j++) {
+ for (j = 0; j < 29 + map.extrarow; j++) {
for (i = 0; i < 40; i++) {
if(map.contents[i + map.vmult[j]]>0) drawforetile(i * 8, j * 8, map.finalat(i,j));
}
@@ -2384,54 +2656,69 @@
foregrounddrawn=true;
}
- backbuffer.copyPixels(frontbuffer, frontbuffer.rect, tl);
+ backbuffer.draw(frontbuffer_meshbatch);
}
public function drawmaptileat(xp:int, yp:int, mapx:int, mapy:int, map:mapclass):void {
- if (mapx < 100) mapx = 119; if (mapy < 100) mapy = 119;
- if (mapx > 119) mapx = 100; if (mapy > 119) mapy = 100;
- if (map.explored[(mapx - 100) + ((mapy - 100) * 20)] == 1) {
- madrect.x = (mapx - 100)*12; madrect.y = (mapy - 100)*9; madrect.width = 12; madrect.height = 9;
- madpoint.x = xp; madpoint.y = yp;
- backbuffer.copyPixels(images[1], madrect, madpoint);
- }else {
- drawimage(2, xp, yp);
- }
+ //Not used anymore, phew
+ trace("dwgfx.drawmaptileat() is not implemented yet");
}
public function drawminimap(game:gameclass, map:mapclass):void {
- drawfillrect(272, 8, 40, 31, 196, 196, 196);
- drawfillrect(273, 9, 38, 29, 164,164,164);
- for (j = 0; j < 3; j++){
- for (i = 0; i < 3; i++) {
- drawmaptileat(274 + (i * 12), 10 + (j * 9), game.roomx - 1 + i, game.roomy - 1 + j, map);
- }
- }
- }
-
- public function drawrect(x:int, y:int, w:int, h:int, r:int, g:int, b:int):void {
- //Draw the retangle indicated by that object
- madrect.x = x; madrect.y = y;
- madrect.width = w; madrect.height = 1;
- backbuffer.fillRect(madrect, RGB(r,g,b));
-
- madrect.width = 1; madrect.height = h;
- backbuffer.fillRect(madrect, RGB(r,g,b));
-
- madrect.x = x + w - 1;
- madrect.width = 1; madrect.height = h;
- backbuffer.fillRect(madrect, RGB(r,g,b));
-
- madrect.x = x; madrect.y = y + h - 1;
- madrect.width = w; madrect.height = 1;
- backbuffer.fillRect(madrect, RGB(r,g,b));
+ //Not used anymore, phew
+ trace("dwgfx.drawminimap() is not implemented yet");
}
- public function drawfillrect(x:int, y:int, w:int, h:int, r:int, g:int, b:int):void {
+ public function drawrect(x:int, y:int, w:int, h:int, r:int, g:int, b:int):void {
//Draw the retangle indicated by that object
- madrect.x = x; madrect.y = y;
- madrect.width = w; madrect.height = h;
- backbuffer.fillRect(madrect, RGB(r,g,b));
+ tquad.x = x; tquad.y = y;
+ tquad.width = w; tquad.height = 1;
+ tquad.color = RGB(r, g, b);
+ backbuffer.draw(tquad);
+
+ tquad.width = 1; tquad.height = h;
+ backbuffer.draw(tquad);
+
+ tquad.x = x + w - 1;
+ backbuffer.draw(tquad);
+
+ tquad.x = x; tquad.y = y + h - 1;
+ tquad.width = w; tquad.height = 1;
+ backbuffer.draw(tquad);
+ }
+
+ public function cls(c:int):void {
+ drawfillrect(0, 0, screenwidth, screenheight, c);
+ }
+
+ public function drawfillrect(x:int, y:int, w:int, h:int, r:int, g:int = -1, b:int = -1):void {
+ //Draw the retangle indicated by that object
+ tquad.x = x;
+ tquad.y = y;
+ tquad.width = w;
+ tquad.height = h;
+ if (b == -1) {
+ tquad.color = r;
+ }else{
+ tquad.color = RGB(r, g, b);
+ }
+
+ backbuffer.draw(tquad);
+ }
+
+ public function drawfillrect_onimage(img:RenderTexture, x:int, y:int, w:int, h:int, r:int, g:int = -1, b:int = -1):void {
+ //Draw the retangle indicated by that object
+ tquad.x = x;
+ tquad.y = y;
+ tquad.width = w;
+ tquad.height = h;
+ if (b == -1) {
+ tquad.color = r;
+ }else{
+ tquad.color = RGB(r, g, b);
+ }
+
+ img.draw(tquad);
}
public function printcrewname(x:int, y:int, t:int):void {
@@ -2470,82 +2757,85 @@
}
}
- public function printmask(x:int, y:int, t:String, cen:Boolean = false):void {
- if (cen) x = 160 - (len(t) / 2);
- bfontpos = 0;
- for (var i:int = 0; i < t.length; i++) {
- cur = t.charCodeAt(i);
- tpoint.x = x + bfontpos-1; tpoint.y = y;
- if (flipmode) {
- backbuffer.copyPixels(flipbfontmask[cur], bfont_rect, tpoint);
- }else{
- backbuffer.copyPixels(bfontmask[cur], bfont_rect, tpoint);
- }
- bfontpos+=bfontlen[cur];
- }
+ public function printmask(x:int, y:int, t:String, cen:Boolean = false):void {
+ trace("dwgfx.printmask() is not implemented yet");
+ }
+
+ public function textbox_print(x:int, y:int, t:String, r:int, g:int, b:int, cen:Boolean = false):void {
+ trace("dwgfx.textbox_print() is not implemented yet");
}
public function print(x:int, y:int, t:String, r:int, g:int, b:int, cen:Boolean = false):void {
if (r < 0) r = 0; if (g < 0) g = 0; if (b < 0) b = 0;
if (r > 255) r = 255; if (g > 255) g = 255; if (b > 255) b = 255;
- ct.color = RGB(r, g, b);
- if (cen) x = 160 - (len(t) / 2);
- bfontpos = 0;
- for (var i:int = 0; i < t.length; i++) {
- cur = t.charCodeAt(i);
- tpoint.x = x + bfontpos; tpoint.y = y;
- if (flipmode) {
- flipbfont[cur].colorTransform(bfont_rect, ct);
- backbuffer.copyPixels(flipbfont[cur], bfont_rect, tpoint);
- }else {
- bfont[cur].colorTransform(bfont_rect, ct);
- backbuffer.copyPixels(bfont[cur], bfont_rect, tpoint);
- }
- bfontpos+=bfontlen[cur];
+ if (cen) {
+ x = 0;
+ ttf.format.horizontalAlign = "center";
+ }else {
+ ttf.format.horizontalAlign = "left";
+ }
+
+ ttf.format.color = RGB(r, g, b);
+ ttf.text = t;
+
+ if (flipmode) {
+ tposition.identity();
+ tposition.scale(1, -1);
+ tposition.translate(x, y + 8);
+ backbuffer.draw(ttf, tposition);
+ }else{
+ tposition.identity();
+ tposition.translate(x, y);
+ backbuffer.draw(ttf, tposition);
}
}
public function rprint(x:int, y:int, t:String, r:int, g:int, b:int, cen:Boolean = false):void {
if (r < 0) r = 0; if (g < 0) g = 0; if (b < 0) b = 0;
if (r > 255) r = 255; if (g > 255) g = 255; if (b > 255) b = 255;
- ct.color = RGB(r, g, b);
- if (cen) x = 308 - (len(t));
- bfontpos = 0;
- for (var i:int = 0; i < t.length; i++) {
- cur = t.charCodeAt(i);
- tpoint.x = x + bfontpos; tpoint.y = y;
- if (flipmode) {
- flipbfont[cur].colorTransform(bfont_rect, ct);
- backbuffer.copyPixels(flipbfont[cur], bfont_rect, tpoint);
- }else{
- bfont[cur].colorTransform(bfont_rect, ct);
- backbuffer.copyPixels(bfont[cur], bfont_rect, tpoint);
- }
- bfontpos+=bfontlen[cur];
+ ttf.format.horizontalAlign = "right";
+ x = x - 320;
+
+ ttf.format.color = RGB(r, g, b);
+ ttf.text = t;
+
+ if (flipmode) {
+ tposition.identity();
+ tposition.scale(1, -1);
+ tposition.translate(x, y + 8);
+ backbuffer.draw(ttf, tposition);
+ }else {
+ tposition.identity();
+ tposition.translate(x, y);
+ backbuffer.draw(ttf, tposition);
}
}
public function printoff(x:int, y:int, t:String, r:int, g:int, b:int, cen:Boolean = false):void {
- if (r < 0) r = 0; if (g < 0) g = 0; if (b < 0) b = 0;
+ if (r < 0) r = 0; if (g < 0) g = 0; if (b < 0) b = 0;
if (r > 255) r = 255; if (g > 255) g = 255; if (b > 255) b = 255;
- ct.color = RGB(r, g, b);
- if (cen) x = (160 - (len(t) / 2))+x;
- bfontpos = 0;
- for (var i:int = 0; i < t.length; i++) {
- cur = t.charCodeAt(i);
- tpoint.x = x + bfontpos; tpoint.y = y;
- if (flipmode) {
- flipbfont[cur].colorTransform(bfont_rect, ct);
- backbuffer.copyPixels(flipbfont[cur], bfont_rect, tpoint);
- }else{
- bfont[cur].colorTransform(bfont_rect, ct);
- backbuffer.copyPixels(bfont[cur], bfont_rect, tpoint);
- }
- bfontpos+=bfontlen[cur];
+ if (cen) {
+ ttf.format.horizontalAlign = "center";
+ }else {
+ ttf.format.horizontalAlign = "left";
+ }
+
+ ttf.format.color = RGB(r, g, b);
+ ttf.text = t;
+
+ if (flipmode) {
+ tposition.identity();
+ tposition.scale(1, -1);
+ tposition.translate(x, y + 8);
+ backbuffer.draw(ttf, tposition);
+ }else {
+ tposition.identity();
+ tposition.translate(x, y);
+ backbuffer.draw(ttf, tposition);
}
}
- public function bprint(x:int, y:int, t:String, r:int, g:int, b:int, cen:Boolean=false):void {
+ public function bprint(x:int, y:int, t:String, r:int, g:int, b:int, cen:Boolean = false):void {
//printmask(x, y, t, cen);
print(x, y - 1, t, 0, 0, 0, cen);
if (cen) {
@@ -2561,38 +2851,11 @@
}
public function printmasktemptile(x:int, y:int, t:String, cen:Boolean = false):void {
- if (cen) x = 160- (len(t) / 2);
- bfontpos = 0;
- for (var i:int = 0; i < t.length; i++) {
- cur = t.charCodeAt(i);
- tpoint.x = x + bfontpos - 1; tpoint.y = y;
- if (flipmode) {
- temptile.copyPixels(flipbfontmask[cur], bfont_rect, tpoint);
- }else{
- temptile.copyPixels(bfontmask[cur], bfont_rect, tpoint);
- }
- bfontpos+=bfontlen[cur];
- }
+ trace("dwgfx.printmasktemptile() is not implemented yet");
}
public function printtemptile(x:int, y:int, t:String, r:int, g:int, b:int, cen:Boolean = false):void {
- if (r < 0) r = 0; if (g < 0) g = 0; if (b < 0) b = 0;
- if (r > 255) r = 255; if (g > 255) g = 255; if (b > 255) b = 255;
- ct.color = RGB(r, g, b);
- if (cen) x = 160 - (len(t) / 2);
- bfontpos = 0;
- for (var i:int = 0; i < t.length; i++) {
- cur = t.charCodeAt(i);
- tpoint.x = x + bfontpos; tpoint.y = y;
- if (flipmode) {
- flipbfont[cur].colorTransform(bfont_rect, ct);
- temptile.copyPixels(flipbfont[cur], bfont_rect, tpoint);
- }else{
- bfont[cur].colorTransform(bfont_rect, ct);
- temptile.copyPixels(bfont[cur], bfont_rect, tpoint);
- }
- bfontpos+=bfontlen[cur];
- }
+ trace("dwgfx.printtemptile() is not implemented yet");
}
public function onscreen(t:int):Boolean {
@@ -2603,175 +2866,154 @@
public function bigrprint(x:int, y:int, t:String, r:int, g:int, b:int, cen:Boolean = false, sc:Number = 2):void {
if (r < 0) r = 0; if (g < 0) g = 0; if (b < 0) b = 0;
if (r > 255) r = 255; if (g > 255) g = 255; if (b > 255) b = 255;
- ct.color = RGB(r, g, b);
+ ttf.format.horizontalAlign = "right";
+ x = x - 320;
- scaleMatrix = new Matrix();
- scaleMatrix.scale(sc, sc);
+ ttf.format.color = RGB(r, g, b);
+ ttf.format.size = BitmapFont.NATIVE_SIZE * sc;
+ ttf.text = t;
- bigbuffer.fillRect(bigbuffer.rect, 0x000000);
-
- x = x / sc;
-
- x -= (len(t));
-
- //if (r < -1) r = -1; if (g < 0) g = 0; if (b < 0) b = 0;?
- //if (r > 255) r = 255; if (g > 255) g = 255; if (b > 255) b = 255;
- ct.color = RGB(r, g, b);
- if(sc==2){
- if (cen) x = 80 - (len(t)/2);
- }else if (sc == 3) {
- if (cen) x = 160/3 - (len(t) / 2);
- }else if (sc == 4) {
- if (cen) x = 40 - (len(t) / 2);
+ if (flipmode) {
+ tposition.identity();
+ tposition.scale(1, -1);
+ tposition.translate(x, y + (8 * sc));
+ backbuffer.draw(ttf, tposition);
+ }else {
+ tposition.identity();
+ tposition.translate(x, y);
+ backbuffer.draw(ttf, tposition);
}
- bfontpos = 0;
- for (i = 0; i < t.length; i++) {
- cur = t.charCodeAt(i);
- if (flipmode) {
- flipbfont[cur].colorTransform(bfont_rect, ct);
- bigbuffer.copyPixels(flipbfont[cur], bfont_rect, new Point(x + bfontpos, 0));
- }else {
- bfont[cur].colorTransform(bfont_rect, ct);
- bigbuffer.copyPixels(bfont[cur], bfont_rect, new Point(x + bfontpos, 0));
- }
- bfontpos+=bfontlen[cur];
- }
-
- scaleMatrix.translate(0, y);
- backbuffer.draw(bigbufferscreen, scaleMatrix);
- scaleMatrix.translate(0, -y);
+ ttf.format.size = BitmapFont.NATIVE_SIZE;
}
public function bigprint(x:int, y:int, t:String, r:int, g:int, b:int, cen:Boolean = false, sc:Number = 2):void {
- if (r < 0) r = 0; if (g < 0) g = 0; if (b < 0) b = 0;
+ if (r < 0) r = 0; if (g < 0) g = 0; if (b < 0) b = 0;
if (r > 255) r = 255; if (g > 255) g = 255; if (b > 255) b = 255;
- ct.color = RGB(r, g, b);
-
- scaleMatrix = new Matrix();
- scaleMatrix.scale(sc, sc);
-
- bigbuffer.fillRect(bigbuffer.rect, 0x000000);
-
- x = x / sc;
-
- //if (r < -1) r = -1; if (g < 0) g = 0; if (b < 0) b = 0;?
- //if (r > 255) r = 255; if (g > 255) g = 255; if (b > 255) b = 255;
- ct.color = RGB(r, g, b);
- if(sc==2){
- if (cen) x = 80 - (len(t)/2);
- }else if (sc == 3) {
- if (cen) x = 160/3 - (len(t) / 2);
- }else if (sc == 4) {
- if (cen) x = 40 - (len(t) / 2);
- }
- bfontpos = 0;
- for (var ti:int = 0; ti < t.length; ti++) {
- cur = t.charCodeAt(ti);
- if (flipmode) {
- flipbfont[cur].colorTransform(bfont_rect, ct);
- bigbuffer.copyPixels(flipbfont[cur], bfont_rect, new Point(x + bfontpos, 0));
- }else {
- bfont[cur].colorTransform(bfont_rect, ct);
- bigbuffer.copyPixels(bfont[cur], bfont_rect, new Point(x + bfontpos, 0));
- }
- bfontpos+=bfontlen[cur];
+ if (cen) {
+ x = 0;
+ ttf.format.horizontalAlign = "center";
+ }else {
+ ttf.format.horizontalAlign = "left";
}
- scaleMatrix.translate(0, y);
- backbuffer.draw(bigbufferscreen, scaleMatrix);
- scaleMatrix.translate(0, -y);
+ ttf.format.color = RGB(r, g, b);
+ ttf.format.size = BitmapFont.NATIVE_SIZE * sc;
+ ttf.text = t;
+
+ if (flipmode) {
+ tposition.identity();
+ tposition.scale(1, -1);
+ tposition.translate(x, y + (8 * sc));
+ backbuffer.draw(ttf, tposition);
+ }else {
+ tposition.identity();
+ tposition.translate(x, y);
+ backbuffer.draw(ttf, tposition);
+ }
+
+ ttf.format.size = BitmapFont.NATIVE_SIZE;
}
- public function bprinttemptile(x:int, y:int, t:String, r:int, g:int, b:int, cen:Boolean=false):void {
- printmasktemptile(x, y, t, cen);
- printtemptile(x, y, t, r, g, b, cen);
- }
public function len(t:String):int {
- bfontpos = 0;
- for (var i:int = 0; i < t.length; i++) {
- cur = t.charCodeAt(i);
- bfontpos+=bfontlen[cur];
- }
- return bfontpos;
+ //For VVVVVV, we're using a fixed width font, so...
+ return t.length * 8;
}
public function flashlight():void {
- backbuffer.fillRect(backbuffer.rect, 0xBBBBBB);
+ drawfillrect(0, 0, 320, 240, 187, 187, 187);
}
public function screenshake():void {
- screenbuffer.lock();
- if(flipmode){
- tpoint.x = int((Math.random() * 7) - 4); tpoint.y = int((Math.random() * 7) - 4);
- flipmatrix.translate(tpoint.x, tpoint.y);
- screenbuffer.draw(backbuffer, flipmatrix);
- flipmatrix.translate(-tpoint.x, -tpoint.y);
- }else{
- screenbuffer.copyPixels(backbuffer, backbuffer.rect, tl, null, null, false);
- tpoint.x = (Math.random() * 7) - 4; tpoint.y = (Math.random() * 7) - 4;
- screenbuffer.copyPixels(backbuffer, backbuffer.rect, tpoint, null, null, false);
- }
- screenbuffer.unlock();
+ screenmenubuffer.draw(smallscreen);
- backbuffer.lock();
- backbuffer.fillRect(backbuffer.rect, 0x000000);
- backbuffer.unlock();
+ if (flipmode) {
+ tposition.identity();
+ tposition.scale(1, -1);
+ tposition.translate(int((Math.random() * 7) - 4), screenheight + int((Math.random() * 7) - 4));
+ drawfillrect(0, 0, screenwidth, screenheight, 0, 0, 0);
+ backbuffer.draw(screenmenubuffer_image, tposition);
+ }else{
+ tposition.identity();
+ tposition.translate(int((Math.random() * 7) - 4), int((Math.random() * 7) - 4));
+
+ backbuffer.draw(screenmenubuffer_image, tposition);
+ }
}
public function render():void {
- screenbuffer.lock();
- if(flipmode){
- screenbuffer.draw(backbuffer, flipmatrix);
- }else{
- screenbuffer.copyPixels(backbuffer, backbuffer.rect, tl, null, null, false);
+ if (flipmode) {
+ tposition.identity();
+ tposition.scale(1, -1);
+ tposition.translate(0, screenheight);
+
+ screenmenubuffer.drawBundled(function():void {
+ screenmenubuffer.draw(smallscreen);
+ });
+
+ backbuffer.draw(screenmenubuffer_image, tposition);
}
- screenbuffer.unlock();
+ }
+
+ public function clear_menubuffer():void {
+ tquad.x = 0; tquad.y = 0;
+ tquad.width = screenwidth;
+ tquad.height = screenheight;
+ tquad.color = RGB(0, 0, 0);
- backbuffer.lock();
- backbuffer.fillRect(backbuffer.rect, 0x000000);
- backbuffer.unlock();
+ menubuffer.drawBundled(function():void {
+ menubuffer.draw(tquad);
+ });
+ screenmenubuffer.drawBundled(function():void {
+ screenmenubuffer.draw(tquad);
+ });
+ }
+
+ public function setup_menubuffer():void {
+ menubuffer.draw(smallscreen);
}
public function menuoffrender():void {
- screenbuffer.lock();
- screenbuffer.copyPixels(menubuffer, menubuffer.rect, tl, null, null, false);
+ //The backbuffer currently contains the menu, so we save this...
+ screenmenubuffer.draw(smallscreen);
- if(flipmode){
- flipmatrix.translate(0, menuoffset);
- screenbuffer.draw(backbuffer, flipmatrix);
- flipmatrix.translate(0, -menuoffset);
+ //Then we draw the old in-game screen instead
+ backbuffer.draw(menubuffer_image);
+
+ //Finally, we draw the menu back on top of this, offset.
+ if (flipmode) {
+ tposition.identity();
+ tposition.scale(1, -1);
+ tposition.translate(0, screenheight + menuoffset);
+ backbuffer.draw(screenmenubuffer_image, tposition);
}else {
- tpoint.x = 0;
- tpoint.y = menuoffset;
- screenbuffer.copyPixels(backbuffer, backbuffer.rect, tpoint, null, null, false);
+ tposition.identity();
+ tposition.translate(0, menuoffset);
+ backbuffer.draw(screenmenubuffer_image, tposition);
}
-
- screenbuffer.unlock();
-
- backbuffer.lock();
- backbuffer.fillRect(backbuffer.rect, 0x000000);
- backbuffer.unlock();
}
- public var backgrounds:Vector. = new Vector.;
- public var images:Vector. = new Vector.;
- public var playerlevelimages:Vector. = new Vector.;
- public var mobileimages:Vector. = new Vector.;
- public var tele:Vector. = new Vector.;
- public var tele_rect:Rectangle;
- public var tiles:Vector. = new Vector.;
- public var tiles2:Vector. = new Vector.;
- public var tiles3:Vector. = new Vector.;
- public var sprites:Vector. = new Vector.;
- public var flipsprites:Vector. = new Vector.;
- public var entcolours:Vector. = new Vector.;
- public var bfont:Vector. = new Vector.;
- public var bfontmask:Vector. = new Vector.;
- public var flipbfont:Vector. = new Vector.;
- public var flipbfontmask:Vector. = new Vector.;
- public var bfontlen:Vector. = new Vector.;
- public var bfontpos:int;
+ public var tquad:Quad;
+ public var ttf:TextField;
+ public var tposition:Matrix;
+ public var starlingassets:AssetManager;
+ public var starstage:Stage
+
+ public var backgrounds:Vector. = new Vector.;
+ public var images:Vector. = new Vector.;
+ public var playerlevelimages:Vector. = new Vector.;
+ public var mobileimages:Vector. = new Vector.;
+ public var tele:Vector. = new Vector.;
+ public var tiles:Vector. = new Vector.;
+ public var tiles2:Vector. = new Vector.;
+ public var tiles3:Vector. = new Vector.;
+ public var sprites:Vector. = new Vector.;
+ public var flipsprites:Vector. = new Vector.;
+ public var sprites_bitmap:Vector. = new Vector.;
+ public var flipsprites_bitmap:Vector. = new Vector.;
+ public var entcolours:Vector. = new Vector.;
+ public var customminimap:RenderTexture;
+
public var cur:int;
public var ct:ColorTransform;
public var tiles_rect:Rectangle;
@@ -2789,22 +3031,30 @@
public var tempstring:String;
public var alphamult:uint;
public var stemp:String;
- public var buffer:BitmapData;
public var i:int, j:int, k:int, m:int;
public var tpoint:Point, trect:Rectangle;
public var madrect:Rectangle, madpoint:Point;
- public var temptile:BitmapData;
- public var tempsprite:BitmapData;
+ public var temptile:RenderTexture;
+ public var tempsprite:RenderTexture;
public var footerrect:Rectangle;
+
//Actual backgrounds
- public var backbuffer:BitmapData;
- public var frontbuffer:BitmapData;
- public var towerbuffer:BitmapData;
- public var screenbuffer:BitmapData;
- public var menubuffer:BitmapData;
- public var screen:Bitmap;
+ public var backbuffer:RenderTexture;
+ public var frontbuffer_meshbatch:MeshBatch;
+ public var menubuffer:RenderTexture;
+ public var menubuffer_image:Image;
+ public var screenmenubuffer:RenderTexture;
+ public var screenmenubuffer_image:Image;
+ public var towerbufferforeground_meshbatch:MeshBatch;
+ public var towerbufferbackground_meshbatch:MeshBatch;
+ public var towerbufferstatic_meshbatch:MeshBatch;
+ public var warpzonehorizontal_meshbatch:MeshBatch;
+ public var warpzonevertical_meshbatch:MeshBatch;
+ public var screen:Image;
+ public var smallscreen:Image;
public var updatebackground:Boolean;
+
//Textbox Stuff
public var ntextbox:int;
public var textbox:Vector. = new Vector.;
@@ -2846,17 +3096,16 @@
public var flipfontmatrix:Matrix = new Matrix();
public var flipfontmatrix2:Matrix = new Matrix();
- public var scaleMatrix:Matrix = new Matrix();
- public var bigbuffer:BitmapData;
- public var bigbufferscreen:Bitmap;
-
//Mobile stuff
public var screensizemultiplier:Number;
public var screenoffx:int, screenoffy:int;
- public var buttonimg:Vector. = new Vector.;
- public var buttonscreen:Vector. = new Vector.;
+ public var buttonsready:Boolean = false;
+ public var button_texture:Vector. = new Vector.;
+ public var button_image:Vector. = new Vector.;
+ public var button_image_width:Vector. = new Vector.;
+ public var button_image_height:Vector. = new Vector.;
public var buttonactive:Vector. = new Vector.;
public var buttonhighlight:Vector. = new Vector.;
@@ -2870,5 +3119,11 @@
public var b_gap:int = 40, b_size:int = 26;
public var devicex:int, devicey:int;
+
+ [Embed(source = "../data/bitmapsprites.png")]
+ public static const img_bitmapsprites:Class;
+
+ [Embed(source = "../data/bitmapflipsprites.png")]
+ public static const img_bitmapflipsprites:Class;
}
}
\ No newline at end of file
diff --git a/mobile_version/src/edentitiesclass.as b/mobile_version/src/edentitiesclass.as
index 493eaf33..78d4ddd0 100644
--- a/mobile_version/src/edentitiesclass.as
+++ b/mobile_version/src/edentitiesclass.as
@@ -1,9 +1,4 @@
package {
- import flash.display.*;
- import flash.geom.*;
- import flash.events.*;
- import flash.net.*;
-
public class edentitiesclass {
public function edentitiesclass():void {
clear();
diff --git a/mobile_version/src/editor.as b/mobile_version/src/editor.as
index 6dbe5828..8edb57ea 100644
--- a/mobile_version/src/editor.as
+++ b/mobile_version/src/editor.as
@@ -1,9 +1,9 @@
package {
- import flash.display.*;
- import flash.display3D.textures.RectangleTexture;
import flash.geom.*;
import flash.events.*;
import flash.net.*;
+ import starling.display.Image;
+ import starling.textures.RenderTexture;
public class editor {
public static function init():void {
@@ -1249,17 +1249,17 @@ package {
}
public static function fillbox(dwgfx:dwgraphicsclass, x:int, y:int, x2:int, y2:int, c:int):void {
- dwgfx.backbuffer.fillRect(new Rectangle(x, y, x2 - x, 1), c);
- dwgfx.backbuffer.fillRect(new Rectangle(x, y2 - 1, x2 - x, 1), c);
- dwgfx.backbuffer.fillRect(new Rectangle(x, y, 1, y2 - y), c);
- dwgfx.backbuffer.fillRect(new Rectangle(x2 - 1, y, 1, y2 - y), c);
+ dwgfx.drawfillrect(x, y, x2 - x, 1, c);
+ dwgfx.drawfillrect(x, y2 - 1, x2 - x, 1, c);
+ dwgfx.drawfillrect(x, y, 1, y2 - y, c);
+ dwgfx.drawfillrect(x2 - 1, y, 1, y2 - y, c);
}
public static function fillboxabs(dwgfx:dwgraphicsclass, x:int, y:int, x2:int, y2:int, c:int):void {
- dwgfx.backbuffer.fillRect(new Rectangle(x, y, x2, 1), c);
- dwgfx.backbuffer.fillRect(new Rectangle(x, y + y2 - 1, x2, 1), c);
- dwgfx.backbuffer.fillRect(new Rectangle(x, y, 1, y2), c);
- dwgfx.backbuffer.fillRect(new Rectangle(x + x2 - 1, y, 1, y2), c);
+ dwgfx.drawfillrect(x, y, x2, 1, c);
+ dwgfx.drawfillrect(x, y + y2 - 1, x2, 1, c);
+ dwgfx.drawfillrect(x, y, 1, y2, c);
+ dwgfx.drawfillrect(x + x2 - 1, y, 1, y2, c);
}
public static function generatecustomminimap(dwgfx:dwgraphicsclass, map:mapclass):void {
@@ -1291,68 +1291,74 @@ package {
map.custommmysize = 180 - (map.custommmyoff * 2);
}
- dwgfx.images[12].fillRect(dwgfx.images[12].rect, dwgfx.RGBA(0, 0, 0));
-
- var tm:int = 0;
- var temp:int = 0;
- //Scan over the map size
- if(mapheight<=5 && mapwidth<=5){
- //4x map
- for (var j2:int = 0; j2 < mapheight; j2++){
- for (var i2:int = 0; i2 < mapwidth; i2++) {
- //Ok, now scan over each square
- tm = 196;
- if (level[i2 + (j2 * maxwidth)].tileset == 1) tm = 96;
-
- for (var j:int = 0; j < 36; j++) {
- for (var i:int = 0; i < 48; i++) {
- temp = absfree(int(i * 0.83) + (i2 * 40), int(j * 0.83) + (j2 * 30));
- if(temp>=1){
- //Fill in this pixel
- dwgfx.images[12].fillRect(new Rectangle((i2 * 48) + i, (j2 * 36) + j, 1, 1), dwgfx.RGBA(tm, tm, tm));
- }
- }
- }
- }
- }
- }else if (mapheight <= 10 && mapwidth <= 10) {
- //2x map
- for (j2 = 0; j2 < mapheight; j2++) {
- for (i2 = 0; i2 < mapwidth; i2++) {
- //Ok, now scan over each square
- tm = 196;
- if (level[i2 + (j2 * maxwidth)].tileset == 1) tm = 96;
-
- for (j = 0; j < 18; j++) {
- for (i = 0; i < 24; i++) {
- temp = absfree(int(i * 1.6) + (i2 * 40), int(j * 1.6) + (j2 * 30));
- if (temp >= 1) {
- //Fill in this pixel
- dwgfx.images[12].fillRect(new Rectangle((i2 * 24) + i, (j2 * 18) + j, 1, 1), dwgfx.RGBA(tm, tm, tm));
- }
- }
- }
- }
- }
- }else {
- for (j2 = 0; j2 < mapheight; j2++) {
- for (i2 = 0; i2 < mapwidth; i2++) {
- //Ok, now scan over each square
- tm=196;
- if (level[i2 + (j2 * maxwidth)].tileset == 1) tm = 96;
-
- for (j = 0; j < 9; j++) {
- for (i = 0; i < 12; i++) {
- temp = absfree(3 + (i * 3) + (i2 * 40), (j * 3) + (j2 * 30));
- if(temp>=1){
- //Fill in this pixel
- dwgfx.images[12].fillRect(new Rectangle((i2 * 12) + i, (j2 * 9) + j, 1, 1), dwgfx.RGBA(tm, tm, tm));
- }
- }
- }
- }
- }
+ if (dwgfx.customminimap == null) {
+ dwgfx.customminimap = new RenderTexture(240, 180);
+ dwgfx.images[12] = new Image(dwgfx.customminimap);
}
+ dwgfx.customminimap.clear(dwgfx.RGB(0, 0, 0), 1.0);
+
+ dwgfx.customminimap.drawBundled(function():void {
+ var tm:int = 0;
+ var temp:int = 0;
+ //Scan over the map size
+ if(mapheight<=5 && mapwidth<=5){
+ //4x map
+ for (var j2:int = 0; j2 < mapheight; j2++){
+ for (var i2:int = 0; i2 < mapwidth; i2++) {
+ //Ok, now scan over each square
+ tm = 196;
+ if (level[i2 + (j2 * maxwidth)].tileset == 1) tm = 96;
+
+ for (var j:int = 0; j < 36; j++) {
+ for (var i:int = 0; i < 48; i++) {
+ temp = absfree(int(i * 0.83) + (i2 * 40), int(j * 0.83) + (j2 * 30));
+ if(temp>=1){
+ //Fill in this pixel
+ dwgfx.drawfillrect_onimage(dwgfx.customminimap, (i2 * 48) + i, (j2 * 36) + j, 1, 1, tm, tm, tm);
+ }
+ }
+ }
+ }
+ }
+ }else if (mapheight <= 10 && mapwidth <= 10) {
+ //2x map
+ for (j2 = 0; j2 < mapheight; j2++) {
+ for (i2 = 0; i2 < mapwidth; i2++) {
+ //Ok, now scan over each square
+ tm = 196;
+ if (level[i2 + (j2 * maxwidth)].tileset == 1) tm = 96;
+
+ for (j = 0; j < 18; j++) {
+ for (i = 0; i < 24; i++) {
+ temp = absfree(int(i * 1.6) + (i2 * 40), int(j * 1.6) + (j2 * 30));
+ if (temp >= 1) {
+ //Fill in this pixel
+ dwgfx.drawfillrect_onimage(dwgfx.customminimap, (i2 * 24) + i, (j2 * 18) + j, 1, 1, tm, tm, tm);
+ }
+ }
+ }
+ }
+ }
+ }else {
+ for (j2 = 0; j2 < mapheight; j2++) {
+ for (i2 = 0; i2 < mapwidth; i2++) {
+ //Ok, now scan over each square
+ tm=196;
+ if (level[i2 + (j2 * maxwidth)].tileset == 1) tm = 96;
+
+ for (j = 0; j < 9; j++) {
+ for (i = 0; i < 12; i++) {
+ temp = absfree(3 + (i * 3) + (i2 * 40), (j * 3) + (j2 * 30));
+ if(temp>=1){
+ //Fill in this pixel
+ dwgfx.drawfillrect_onimage(dwgfx.customminimap, (i2 * 12) + i, (j2 * 9) + j, 1, 1, tm, tm, tm);
+ }
+ }
+ }
+ }
+ }
+ }
+ });
}
public static function editorrender(dwgfx:dwgraphicsclass, game:gameclass, map:mapclass, obj:entityclass, help:helpclass):void {
diff --git a/mobile_version/src/edlevelclass.as b/mobile_version/src/edlevelclass.as
index 19f18a8f..56f96300 100644
--- a/mobile_version/src/edlevelclass.as
+++ b/mobile_version/src/edlevelclass.as
@@ -1,9 +1,4 @@
package {
- import flash.display.*;
- import flash.geom.*;
- import flash.events.*;
- import flash.net.*;
-
public class edlevelclass{
public function edlevelclass():void {
clear();
diff --git a/mobile_version/src/entclass.as b/mobile_version/src/entclass.as
index c95c3e6e..d8e65ddf 100644
--- a/mobile_version/src/entclass.as
+++ b/mobile_version/src/entclass.as
@@ -1,10 +1,7 @@
-package {
- import flash.display.*;
+package {
import flash.geom.*;
- import flash.events.*;
- import flash.net.*;
- public class entclass extends Sprite {
+ public class entclass{
public function entclass():void {
clear();
}
diff --git a/mobile_version/src/entityclass.as b/mobile_version/src/entityclass.as
index d1deaed8..813f7154 100644
--- a/mobile_version/src/entityclass.as
+++ b/mobile_version/src/entityclass.as
@@ -1,11 +1,8 @@
-package {
+package {
import bigroom.input.KeyPoll;
- import flash.display.*;
import flash.geom.*;
- import flash.events.*;
- import flash.net.*;
-
- public class entityclass extends Sprite {
+
+ public class entityclass {
static public var BLOCK:Number = 0;
static public var TRIGGER:Number = 1;
static public var DAMAGE:Number = 2;
@@ -587,8 +584,8 @@
break;
case TRIGGER: //Trigger
blocks[k].type = TRIGGER;
- blocks[k].x = xp;
- blocks[k].y = yp;
+ blocks[k].xp = xp;
+ blocks[k].yp = yp;
blocks[k].wp = w;
blocks[k].hp = h;
blocks[k].rectset(xp, yp, w, h);
@@ -598,8 +595,8 @@
break;
case DAMAGE: //Damage
blocks[k].type = DAMAGE;
- blocks[k].x = xp;
- blocks[k].y = yp;
+ blocks[k].xp = xp;
+ blocks[k].yp = yp;
blocks[k].wp = w;
blocks[k].hp = h;
blocks[k].rectset(xp, yp, w, h);
@@ -608,8 +605,8 @@
break;
case DIRECTIONAL: //Directional
blocks[k].type = DIRECTIONAL;
- blocks[k].x = xp;
- blocks[k].y = yp;
+ blocks[k].xp = xp;
+ blocks[k].yp = yp;
blocks[k].wp = w;
blocks[k].hp = h;
blocks[k].rectset(xp, yp, w, h);
@@ -629,8 +626,8 @@
break;
case ACTIVITY: //Activity Zone
blocks[k].type = ACTIVITY;
- blocks[k].x = xp;
- blocks[k].y = yp;
+ blocks[k].xp = xp;
+ blocks[k].yp = yp;
blocks[k].wp = w;
blocks[k].hp = h;
blocks[k].rectset(xp, yp, w, h);
@@ -816,19 +813,19 @@
trig=0;
break;
case 25:
- blocks[k].prompt = "Passion for Exploring";
+ blocks[k].prompt = "Passion for exploring";
blocks[k].script = "terminal_juke1";
setblockcolour(k, "orange");
trig=0;
break;
case 26:
- blocks[k].prompt = "Pushing Onwards";
+ blocks[k].prompt = "Pushing onwards";
blocks[k].script = "terminal_juke2";
setblockcolour(k, "orange");
trig=0;
break;
case 27:
- blocks[k].prompt = "Positive Force";
+ blocks[k].prompt = "Positive force";
blocks[k].script = "terminal_juke3";
setblockcolour(k, "orange");
trig=0;
@@ -840,13 +837,13 @@
trig=0;
break;
case 29:
- blocks[k].prompt = "Potential for Anything";
+ blocks[k].prompt = "Potential for anything";
blocks[k].script = "terminal_juke5";
setblockcolour(k, "orange");
trig=0;
break;
case 30:
- blocks[k].prompt = "Predestined Fate";
+ blocks[k].prompt = "Predestined fate";
blocks[k].script = "terminal_juke6";
setblockcolour(k, "orange");
trig=0;
@@ -870,7 +867,7 @@
trig=0;
break;
case 34:
- blocks[k].prompt = "ecroF evitisoP";
+ blocks[k].prompt = "ecrof evitisoP";
blocks[k].script = "terminal_juke10";
setblockcolour(k, "orange");
trig=0;
@@ -1276,7 +1273,7 @@
entities[k].gravity = true;
break;
- case 1: //Simple enemy, bouncing off the walls
+ case 1:
entities[k].rule = 1;
entities[k].xp = xp; entities[k].yp = yp;
entities[k].behave = vx; entities[k].para = vy;
@@ -3790,14 +3787,14 @@
colpoint1.x = entities[i].xp; colpoint1.y = entities[i].yp;
colpoint2.x = entities[j].xp; colpoint2.y = entities[j].yp;
if (dwgfx.flipmode) {
- if (dwgfx.flipsprites[entities[i].drawframe].hitTest(
- colpoint1, 1, dwgfx.flipsprites[entities[j].drawframe], colpoint2, 1)) {
+ if (dwgfx.flipsprites_bitmap[entities[i].drawframe].hitTest(
+ colpoint1, 1, dwgfx.flipsprites_bitmap[entities[j].drawframe], colpoint2, 1)) {
//Do the collision stuff
game.deathseq = 30;
}
- }else{
- if (dwgfx.sprites[entities[i].drawframe].hitTest(
- colpoint1, 1, dwgfx.sprites[entities[j].drawframe], colpoint2, 1)) {
+ }else {
+ if (dwgfx.sprites_bitmap[entities[i].drawframe].hitTest(
+ colpoint1, 1, dwgfx.sprites_bitmap[entities[j].drawframe], colpoint2, 1)) {
//Do the collision stuff
game.deathseq = 30;
}
@@ -3851,9 +3848,9 @@
if (entities[j].onentity > 0) {
//ok; only check the actual collision if they're in a close proximity
temp = entities[i].yp - entities[j].yp;
- if (temp > -30 && temp < 30) {
+ if (temp < 30 || temp > -30) {
temp = entities[i].xp - entities[j].xp;
- if (temp > -30 && temp < 30) {
+ if (temp < 30 || temp > -30) {
if (entitycollide(i, j)) entities[j].state = entities[j].onentity;
}
}
@@ -3890,14 +3887,14 @@
colpoint1.x = entities[i].xp; colpoint1.y = entities[i].yp;
colpoint2.x = entities[j].xp; colpoint2.y = entities[j].yp;
if (dwgfx.flipmode) {
- if (dwgfx.flipsprites[entities[i].drawframe].hitTest(
- colpoint1, 1, dwgfx.flipsprites[entities[j].drawframe], colpoint2, 1)) {
+ if (dwgfx.flipsprites_bitmap[entities[i].drawframe].hitTest(
+ colpoint1, 1, dwgfx.flipsprites_bitmap[entities[j].drawframe], colpoint2, 1)) {
//Do the collision stuff
game.deathseq = 30; game.scmhurt = true;
}
- }else{
- if (dwgfx.sprites[entities[i].drawframe].hitTest(
- colpoint1, 1, dwgfx.sprites[entities[j].drawframe], colpoint2, 1)) {
+ }else {
+ if (dwgfx.sprites_bitmap[entities[i].drawframe].hitTest(
+ colpoint1, 1, dwgfx.sprites_bitmap[entities[j].drawframe], colpoint2, 1)) {
//Do the collision stuff
game.deathseq = 30; game.scmhurt = true;
}
@@ -4019,4 +4016,4 @@
public var mobilemenus:Boolean = true;
}
-}
+}
\ No newline at end of file
diff --git a/mobile_version/src/gameclass.as b/mobile_version/src/gameclass.as
index 2f487b8f..e2e69729 100644
--- a/mobile_version/src/gameclass.as
+++ b/mobile_version/src/gameclass.as
@@ -325,7 +325,7 @@
//These coordinates now need to be translated to actual screen coordinates
//Gamecenter
if(menustart && !showloadingnotice) {
- if (inbox(m_touchx, m_touchy, 0, 0, dwgfx.buttonscreen[0].width + (dwgfx.buttonxspacing * 2), dwgfx.buttonscreen[0].height + (dwgfx.buttonyspacing * 2))) {
+ if (inbox(m_touchx, m_touchy, 0, 0, dwgfx.button_image_width[0] + (dwgfx.buttonxspacing * 2), dwgfx.button_image_height[0] + (dwgfx.buttonyspacing * 2))) {
//Bring up game center achievements
scores.showAchievements();
}
@@ -465,11 +465,11 @@
m_touchy = key.touchy[key.touchPoints - 1];
if (dwgfx.flipmode) m_touchy = dwgfx.devicey - m_touchy;
- if (inbox(m_touchx, m_touchy, dwgfx.devicex - dwgfx.buttonscreen[0].width - dwgfx.buttonxspacing, 0, dwgfx.buttonscreen[0].width + (dwgfx.buttonxspacing*2), dwgfx.buttonscreen[0].height + (dwgfx.buttonyspacing*2) )) {
+ if (inbox(m_touchx, m_touchy, dwgfx.devicex - dwgfx.button_image_width[0] - dwgfx.buttonxspacing, 0, dwgfx.button_image_width[0] + (dwgfx.buttonxspacing*2), dwgfx.button_image_height[0] + (dwgfx.buttonyspacing*2) )) {
press_map = true;
}
if(menupage == 0){
- if (inbox(m_touchx, m_touchy, 0, 0, dwgfx.buttonscreen[1].width + (dwgfx.buttonxspacing*2), dwgfx.buttonscreen[1].height + (dwgfx.buttonyspacing*2) )) {
+ if (inbox(m_touchx, m_touchy, 0, 0, dwgfx.button_image_width[1] + (dwgfx.buttonxspacing*2), dwgfx.button_image_height[1] + (dwgfx.buttonyspacing*2) )) {
menupage = 30;
music.playef(11, 10);
}
@@ -646,12 +646,12 @@
}else
*/
if (insecretlab) {
- if (inbox(key.touchx[i], key.touchy[i], 0, 0, dwgfx.buttonscreen[0].width + (dwgfx.buttonxspacing * 2), dwgfx.buttonscreen[0].height + (dwgfx.buttonyspacing * 2) )) {
+ if (inbox(key.touchx[i], key.touchy[i], 0, 0, dwgfx.button_image_width[0] + (dwgfx.buttonxspacing * 2), dwgfx.button_image_height[0] + (dwgfx.buttonyspacing * 2) )) {
scores.opengamecenter();
press_map = true;
}
}
- if (inbox(key.touchx[i], key.touchy[i], dwgfx.devicex - dwgfx.buttonscreen[0].width - dwgfx.buttonxspacing, 0, dwgfx.buttonscreen[0].width + (dwgfx.buttonxspacing*2), dwgfx.buttonscreen[0].height + (dwgfx.buttonyspacing*2) )) {
+ if (inbox(key.touchx[i], key.touchy[i], dwgfx.devicex - dwgfx.button_image_width[0] - dwgfx.buttonxspacing, 0, dwgfx.button_image_width[0] + (dwgfx.buttonxspacing*2), dwgfx.button_image_height[0] + (dwgfx.buttonyspacing*2) )) {
press_map = true;
}else {
if (key.touchid[i] != key.controlstick) {
@@ -670,12 +670,12 @@
// press_action = true;
//}else
if (insecretlab) {
- if (inbox(key.touchx[i], key.touchy[i], 0, 0, dwgfx.buttonscreen[0].width + (dwgfx.buttonxspacing * 2), dwgfx.buttonscreen[0].height + (dwgfx.buttonyspacing * 2) )) {
+ if (inbox(key.touchx[i], key.touchy[i], 0, 0, dwgfx.button_image_width[0] + (dwgfx.buttonxspacing * 2), dwgfx.button_image_height[0] + (dwgfx.buttonyspacing * 2) )) {
scores.opengamecenter();
press_map = true;
}
}
- if (inbox(key.touchx[i], key.touchy[i], dwgfx.devicex - dwgfx.buttonscreen[0].width - dwgfx.buttonxspacing, 0, dwgfx.buttonscreen[0].width + (dwgfx.buttonxspacing*2), dwgfx.buttonscreen[0].height + (dwgfx.buttonyspacing*2) )) {
+ if (inbox(key.touchx[i], key.touchy[i], dwgfx.devicex - dwgfx.button_image_width[0] - dwgfx.buttonxspacing, 0, dwgfx.button_image_width[0] + (dwgfx.buttonxspacing*2), dwgfx.button_image_height[0] + (dwgfx.buttonyspacing*2) )) {
press_map = true;
}else{
if (inbox(key.touchx[i], key.touchy[i], 0, 0, dwgfx.devicex / 2, dwgfx.devicey)) {
@@ -729,12 +729,12 @@
//D-Pad controls
for (i = 0; i < key.touchPoints; i++) {
if (insecretlab) {
- if (inbox(key.touchx[i], key.touchy[i], 0, 0, dwgfx.buttonscreen[0].width + (dwgfx.buttonxspacing * 2), dwgfx.buttonscreen[0].height + (dwgfx.buttonyspacing * 2) )) {
+ if (inbox(key.touchx[i], key.touchy[i], 0, 0, dwgfx.button_image_width[0] + (dwgfx.buttonxspacing * 2), dwgfx.button_image_height[0] + (dwgfx.buttonyspacing * 2) )) {
scores.opengamecenter();
press_map = true;
}
}
- if (inbox(key.touchx[i], key.touchy[i], dwgfx.devicex - dwgfx.buttonscreen[0].width - dwgfx.buttonxspacing, 0, dwgfx.buttonscreen[0].width + (dwgfx.buttonxspacing*2), dwgfx.buttonscreen[0].height + (dwgfx.buttonyspacing*2) )) {
+ if (inbox(key.touchx[i], key.touchy[i], dwgfx.devicex - dwgfx.button_image_width[0] - dwgfx.buttonxspacing, 0, dwgfx.button_image_width[0] + (dwgfx.buttonxspacing*2), dwgfx.button_image_height[0] + (dwgfx.buttonyspacing*2) )) {
press_map = true;
}else if (inbox(key.touchx[i], key.touchy[i], 0, dwgfx.buttonpos[2].y - (dwgfx.devicey*2/3), dwgfx.buttonsize + dwgfx.buttonxspacing+ (dwgfx.buttonxspacing/2), dwgfx.devicey)) {
press_left = true;
diff --git a/mobile_version/src/helpclass.as b/mobile_version/src/helpclass.as
index 59f0b59b..5c2c723b 100644
--- a/mobile_version/src/helpclass.as
+++ b/mobile_version/src/helpclass.as
@@ -1,11 +1,11 @@
-package {
+package {
import flash.display.*;
import flash.geom.*;
import flash.events.*;
import flash.net.*;
import flash.system.System;
- public class helpclass extends Sprite {
+ public class helpclass{
public function init():void {
sine = new Array();
cosine = new Array();
diff --git a/mobile_version/src/includes/input.as b/mobile_version/src/includes/input.as
index 5c792a83..91f170e2 100644
--- a/mobile_version/src/includes/input.as
+++ b/mobile_version/src/includes/input.as
@@ -239,8 +239,8 @@ public function titleinput(key:KeyPoll, dwgfx:dwgraphicsclass, map:mapclass, gam
}else if (game.currentmenuoption == 4) {
//More games (external link)
music.playef(11, 10);
- var distractionware_link:URLRequest = new URLRequest( "http://distractionware.com/games/ios/" );
- //var distractionware_link:URLRequest = new URLRequest( "http://distractionware.com/games/android/" );
+ //var distractionware_link:URLRequest = new URLRequest( "http://distractionware.com/games/ios/" );
+ var distractionware_link:URLRequest = new URLRequest( "http://distractionware.com/games/android/" );
navigateToURL( distractionware_link, "_blank" );
}
}else{
@@ -649,7 +649,7 @@ public function titleinput(key:KeyPoll, dwgfx:dwgraphicsclass, map:mapclass, gam
}
}else if (game.currentmenuname == "unlockmenu") {
if (game.currentmenuoption == 0) {
- //unlock time trials separately...
+ //unlock time trials seperately...
music.playef(11, 10);
game.createmenu("unlockmenutrials");
map.nexttowercolour();
@@ -1337,7 +1337,7 @@ public function gameinput(key:KeyPoll, dwgfx:dwgraphicsclass, game:gameclass, ma
game.gamestate = 5;
dwgfx.menuoffset = 240; //actually this should count the roomname
if (map.extrarow) dwgfx.menuoffset -= 10;
- dwgfx.menubuffer.copyPixels(dwgfx.screenbuffer, dwgfx.screenbuffer.rect, dwgfx.tl, null, null, false);
+ dwgfx.setup_menubuffer();
dwgfx.resumegamemode = false;
game.useteleporter = true;
@@ -1371,7 +1371,7 @@ public function gameinput(key:KeyPoll, dwgfx:dwgraphicsclass, game:gameclass, ma
game.gamestate = MAPMODE;
game.gamesaved = false; dwgfx.resumegamemode = false;
game.menupage = 20; // The Map Page
- dwgfx.menubuffer.copyPixels(dwgfx.screenbuffer, dwgfx.screenbuffer.rect, dwgfx.tl, null, null, false);
+ dwgfx.setup_menubuffer();
dwgfx.menuoffset = 240; //actually this should count the roomname
if (map.extrarow) dwgfx.menuoffset -= 10;
}else if (game.intimetrial && dwgfx.fademode == 0) {
@@ -1382,7 +1382,7 @@ public function gameinput(key:KeyPoll, dwgfx:dwgraphicsclass, game:gameclass, ma
game.gamestate = MAPMODE;
game.gamesaved = false; dwgfx.resumegamemode = false;
game.menupage = 10; // The Map Page
- dwgfx.menubuffer.copyPixels(dwgfx.screenbuffer, dwgfx.screenbuffer.rect, dwgfx.tl, null, null, false);
+ dwgfx.setup_menubuffer();
dwgfx.menuoffset = 240; //actually this should count the roomname
if (map.extrarow) dwgfx.menuoffset -= 10;
}else{
@@ -1399,7 +1399,7 @@ public function gameinput(key:KeyPoll, dwgfx:dwgraphicsclass, game:gameclass, ma
map.cursordelay = 0; map.cursorstate = 0;
game.gamesaved = false; dwgfx.resumegamemode = false;
game.menupage = 0; // The Map Page
- dwgfx.menubuffer.copyPixels(dwgfx.screenbuffer, dwgfx.screenbuffer.rect, dwgfx.tl, null, null, false);
+ dwgfx.setup_menubuffer();
dwgfx.menuoffset = 240; //actually this should count the roomname
if (map.extrarow) dwgfx.menuoffset -= 10;
}
@@ -1411,7 +1411,7 @@ public function gameinput(key:KeyPoll, dwgfx:dwgraphicsclass, game:gameclass, ma
game.gamestate = MAPMODE;
game.gamesaved = false; dwgfx.resumegamemode = false;
game.menupage = 10; // The Map Page
- dwgfx.menubuffer.copyPixels(dwgfx.screenbuffer, dwgfx.screenbuffer.rect, dwgfx.tl, null, null, false);
+ dwgfx.setup_menubuffer();
dwgfx.menuoffset = 240; //actually this should count the roomname
if (map.extrarow) dwgfx.menuoffset -= 10;
}
@@ -1553,7 +1553,7 @@ public function mapinput(key:KeyPoll, dwgfx:dwgraphicsclass, game:gameclass, map
}
if (dwgfx.fademode == 1) {
- dwgfx.menubuffer.fillRect(dwgfx.menubuffer.rect, 0x000000);
+ dwgfx.clear_menubuffer();
dwgfx.resumegamemode = true;
obj.removeallblocks();
game.menukludge = false;
diff --git a/mobile_version/src/includes/logic.as b/mobile_version/src/includes/logic.as
index 4993a378..46fd3af2 100644
--- a/mobile_version/src/includes/logic.as
+++ b/mobile_version/src/includes/logic.as
@@ -465,7 +465,7 @@ public function gamelogic(key:KeyPoll, dwgfx:dwgraphicsclass, game:gameclass, ma
if (obj.entities[i].type == 2 && obj.entities[i].state == 3) {
//Ok! super magical exception for the room with the intention death for the shiny trinket
//fix this when the maps are finalised
- if (game.roomx != 111 || game.roomy != 107 || map.custommode) {
+ if (game.roomx != 111 && game.roomy != 107) {
obj.entities[i].state = 4;
}else {
obj.entities[i].state = 4;
diff --git a/mobile_version/src/includes/render.as b/mobile_version/src/includes/render.as
index 72dd7872..6d4d653f 100644
--- a/mobile_version/src/includes/render.as
+++ b/mobile_version/src/includes/render.as
@@ -1,11 +1,12 @@
import flash.geom.Point;
+import starling.textures.Texture;
public function titlerender(key:KeyPoll, dwgfx:dwgraphicsclass, map:mapclass, game:gameclass, obj:entityclass, help:helpclass):void {
dwgfx.drawbutton(game, help);
- dwgfx.backbuffer.lock();
- dwgfx.backbuffer.fillRect(dwgfx.backbuffer.rect, 0x000000);
+ //dwgfx.backbuffer.lock();
if (!game.menustart) {
+ dwgfx.cls(0x000000);
tr = 164 - (help.glow / 2) - Math.random() * 4;
tg = 164 - (help.glow / 2) - Math.random() * 4;
tb = 164 - (help.glow / 2) - Math.random() * 4;
@@ -26,9 +27,10 @@ public function titlerender(key:KeyPoll, dwgfx:dwgraphicsclass, map:mapclass, ga
/*dwgfx.print(5, 5, "IGF WIP Build, 29th Oct '09", tr, tg, tb, true);
dwgfx.print(5, 200, "Game by Terry Cavanagh", tr, tg, tb, true);
- dwgfx.print(5, 210, "Music by Magnus P~lsson", tr, tg, tb, true);
+ dwgfx.print(5, 210, "Music by Magnus Palsson", tr, tg, tb, true);
dwgfx.print(5, 220, "Roomnames by Bennett Foddy", tr, tg, tb, true);*/
}else {
+ dwgfx.cls(dwgfx.tower_bgdarkcol[map.colstate]);
if(!game.colourblindmode) dwgfx.drawtowerbackgroundsolo(map);
tr = map.r - (help.glow / 4) - Math.random() * 4;
@@ -39,8 +41,7 @@ public function titlerender(key:KeyPoll, dwgfx:dwgraphicsclass, map:mapclass, ga
if (tb < 0) tb = 0; if(tb>255) tb=255;
temp = 30+20;
-
- if(game.currentmenuname=="mainmenu"){
+ if (game.currentmenuname == "mainmenu") {
dwgfx.drawsprite((160 - 96) + 0 * 32, temp, 23, tr, tg, tb);
dwgfx.drawsprite((160 - 96) + 1 * 32, temp, 23, tr, tg, tb);
dwgfx.drawsprite((160 - 96) + 2 * 32, temp, 23, tr, tg, tb);
@@ -116,7 +117,7 @@ public function titlerender(key:KeyPoll, dwgfx:dwgraphicsclass, map:mapclass, ga
//dwgfx.print( 40, 85, "http://www.distractionware.com", tr, tg, tb, true);
dwgfx.print( -1, 120, "and features music by", tr, tg, tb, true);
- dwgfx.bigprint( 40, 135, "Magnus P~lsson", tr, tg, tb, true, 2);
+ dwgfx.bigprint( 40, 135, "Magnus Palsson", tr, tg, tb, true, 2);
dwgfx.drawimagecol(8, -1, 156, tr *0.75, tg *0.75, tb *0.75, true);
//dwgfx.print( 40, 155, "http://souleye.madtracker.net", tr, tg, tb, true);
}else if (game.currentmenuname == "credits2") {
@@ -199,7 +200,7 @@ public function titlerender(key:KeyPoll, dwgfx:dwgraphicsclass, map:mapclass, ga
dwgfx.print( 80, 80,"Joshua Buergel", tr, tg, tb);
dwgfx.print( 80, 90,"Joshua Hochner", tr, tg, tb);
dwgfx.print( 80, 100,"Kurt Ostfeld", tr, tg, tb);
- dwgfx.print( 80, 110,"Magnus P~lsson", tr, tg, tb);
+ dwgfx.print( 80, 110,"Magnus Palsson", tr, tg, tb);
dwgfx.print( 80, 120,"Mark Neschadimenko", tr, tg, tb);
dwgfx.print( 80, 130,"Matt Antonellis", tr, tg, tb);
dwgfx.print( 80, 140,"Matthew Reppert", tr, tg, tb);
@@ -483,7 +484,7 @@ public function titlerender(key:KeyPoll, dwgfx:dwgraphicsclass, map:mapclass, ga
/*
dwgfx.bigprint( -1, 30, "Unlock Time Trials", tr, tg, tb, true);
dwgfx.print( -1, 65, "You can unlock each time", tr, tg, tb, true);
- dwgfx.print( -1, 75, "trial separately.", tr, tg, tb, true);
+ dwgfx.print( -1, 75, "trial seperately.", tr, tg, tb, true);
*/
}else if (game.currentmenuname == "timetrials") {
/*
@@ -688,27 +689,27 @@ public function titlerender(key:KeyPoll, dwgfx:dwgraphicsclass, map:mapclass, ga
}else if (game.currentmenuname == "unlocktimetrial") {
dwgfx.bigprint( -1, 45, "Congratulations!", tr, tg, tb, true, 2);
- dwgfx.print( -1, 125, "You have unlocked", tr, tg, tb, true);
+ dwgfx.print( -1, 125, "Your have unlocked", tr, tg, tb, true);
dwgfx.print( -1, 135, "a new Time Trial.", tr, tg, tb, true);
}else if (game.currentmenuname == "unlocktimetrials") {
dwgfx.bigprint( -1, 45, "Congratulations!", tr, tg, tb, true, 2);
- dwgfx.print( -1, 125, "You have unlocked some", tr, tg, tb, true);
+ dwgfx.print( -1, 125, "Your have unlocked some", tr, tg, tb, true);
dwgfx.print( -1, 135, "new Time Trials.", tr, tg, tb, true);
}else if (game.currentmenuname == "unlocknodeathmode") {
dwgfx.bigprint( -1, 45, "Congratulations!", tr, tg, tb, true, 2);
- dwgfx.print( -1, 125, "You have unlocked", tr, tg, tb, true);
+ dwgfx.print( -1, 125, "Your have unlocked", tr, tg, tb, true);
dwgfx.print( -1, 135, "No Death Mode.", tr, tg, tb, true);
}else if (game.currentmenuname == "unlockflipmode") {
dwgfx.bigprint( -1, 45, "Congratulations!", tr, tg, tb, true, 2);
- dwgfx.print( -1, 125, "You have unlocked", tr, tg, tb, true);
+ dwgfx.print( -1, 125, "Your have unlocked", tr, tg, tb, true);
dwgfx.print( -1, 135, "Flip Mode.", tr, tg, tb, true);
}else if (game.currentmenuname == "unlockintermission") {
dwgfx.bigprint( -1, 45, "Congratulations!", tr, tg, tb, true, 2);
- dwgfx.print( -1, 125, "You have unlocked", tr, tg, tb, true);
+ dwgfx.print( -1, 125, "Your have unlocked", tr, tg, tb, true);
dwgfx.print( -1, 135, "the intermission levels.", tr, tg, tb, true);
}
@@ -784,14 +785,14 @@ public function titlerender(key:KeyPoll, dwgfx:dwgraphicsclass, map:mapclass, ga
}else{
dwgfx.render();
}
- dwgfx.backbuffer.unlock();
+ //dwgfx.backbuffer.unlock();
}
-public function gamecompleterender(key:KeyPoll, dwgfx:dwgraphicsclass, game:gameclass, obj:entityclass, help:helpclass):void {
+public function gamecompleterender(key:KeyPoll, dwgfx:dwgraphicsclass, game:gameclass, map:mapclass, obj:entityclass, help:helpclass):void {
dwgfx.drawbutton(game, help);
- dwgfx.backbuffer.lock();
- dwgfx.backbuffer.fillRect(dwgfx.backbuffer.rect, 0x000000);
+ //dwgfx.backbuffer.lock();
+ dwgfx.cls(dwgfx.tower_bgdarkcol[map.colstate]);
if(!game.colourblindmode) dwgfx.drawtowerbackgroundsolo(map);
//dwgfx.drawtowermap(map);
@@ -856,7 +857,7 @@ public function gamecompleterender(key:KeyPoll, dwgfx:dwgraphicsclass, game:game
if (dwgfx.onscreen(640 + game.creditposition)) {
dwgfx.print(40, 640 + game.creditposition, "With Music by", tr, tg, tb);
- dwgfx.bigprint(60, 650 + game.creditposition, "Magnus P~lsson", tr, tg, tb);
+ dwgfx.bigprint(60, 650 + game.creditposition, "Magnus Palsson", tr, tg, tb);
}
if (dwgfx.onscreen(680 + game.creditposition)) {
@@ -934,7 +935,7 @@ if (dwgfx.onscreen(1410 + game.creditposition)) dwgfx.print(-1, 1420 + game.cred
if (dwgfx.onscreen(1420 + game.creditposition)) dwgfx.print(-1, 1430 + game.creditposition,"Joshua Buergel", tr, tg, tb, true);
if (dwgfx.onscreen(1430 + game.creditposition)) dwgfx.print(-1, 1440 + game.creditposition,"Joshua Hochner", tr, tg, tb, true);
if (dwgfx.onscreen(1440 + game.creditposition)) dwgfx.print(-1, 1450 + game.creditposition,"Kurt Ostfeld", tr, tg, tb, true);
-if (dwgfx.onscreen(1450 + game.creditposition)) dwgfx.print(-1, 1460 + game.creditposition, "Magnus P~lsson", tr, tg, tb, true);
+if (dwgfx.onscreen(1450 + game.creditposition)) dwgfx.print(-1, 1460 + game.creditposition, "Magnus Palsson", tr, tg, tb, true);
if (dwgfx.onscreen(1460 + game.creditposition)) dwgfx.print(-1, 1470 + game.creditposition,"Mark Neschadimenko", tr, tg, tb, true);
if (dwgfx.onscreen(1470 + game.creditposition)) dwgfx.print(-1, 1480 + game.creditposition,"Matt Antonellis", tr, tg, tb, true);
if (dwgfx.onscreen(1480 + game.creditposition)) dwgfx.print(-1, 1490 + game.creditposition,"Matthew Reppert", tr, tg, tb, true);
@@ -971,14 +972,14 @@ if (dwgfx.onscreen(1760 + game.creditposition)) dwgfx.bigprint( -1, 1760 + game.
}else{
dwgfx.render();
}
- dwgfx.backbuffer.unlock();
+ //dwgfx.backbuffer.unlock();
}
public function gamecompleterender2(key:KeyPoll, dwgfx:dwgraphicsclass, game:gameclass, obj:entityclass, help:helpclass):void {
dwgfx.drawbutton(game, help);
- dwgfx.backbuffer.lock();
- dwgfx.backbuffer.fillRect(dwgfx.backbuffer.rect, 0x000000);
+ //dwgfx.backbuffer.lock();
+ dwgfx.cls(0x000000);
dwgfx.drawimage(10, 0, 0);
@@ -1013,7 +1014,7 @@ public function gamecompleterender2(key:KeyPoll, dwgfx:dwgraphicsclass, game:gam
}else{
dwgfx.render();
}
- dwgfx.backbuffer.unlock();
+ //dwgfx.backbuffer.unlock();
}
public function gamerender(key:KeyPoll, dwgfx:dwgraphicsclass, game:gameclass, map:mapclass,
@@ -1021,7 +1022,7 @@ public function gamerender(key:KeyPoll, dwgfx:dwgraphicsclass, game:gameclass, m
dwgfx.drawbutton(game, help);
- dwgfx.backbuffer.lock();
+ //dwgfx.backbuffer.lock();
if(!game.blackout){
if(!game.colourblindmode) dwgfx.drawbackground(map.background, map);
@@ -1050,6 +1051,8 @@ public function gamerender(key:KeyPoll, dwgfx:dwgraphicsclass, game:gameclass, m
}
dwgfx.drawentities(map, obj, help);
+ }else {
+ dwgfx.cls(0x000000);
}
/*for(i=0; i 100 && !game.advancetext && game.hascontrol && !script.running && !game.intimetrial) {
i = obj.getplayer();
if(dwgfx.flipmode){
- dwgfx.bprint(5, 20, "- Press ENTER to Teleport -", game.readytotele - 20 - (help.glow / 2), game.readytotele - 20 - (help.glow / 2), game.readytotele, true);
+ dwgfx.print(5, 20, "- Press ENTER to Teleport -", game.readytotele - 20 - (help.glow / 2), game.readytotele - 20 - (help.glow / 2), game.readytotele, true);
}else {
- dwgfx.bprint(5, 210, "- Press ENTER to Teleport -", game.readytotele - 20 - (help.glow / 2), game.readytotele - 20 - (help.glow / 2), game.readytotele, true);
+ dwgfx.print(5, 210, "- Press ENTER to Teleport -", game.readytotele - 20 - (help.glow / 2), game.readytotele - 20 - (help.glow / 2), game.readytotele, true);
}
}
}
@@ -1304,7 +1307,7 @@ public function gamerender(key:KeyPoll, dwgfx:dwgraphicsclass, game:gameclass, m
dwgfx.render();
}
- dwgfx.backbuffer.unlock();
+ //dwgfx.backbuffer.unlock();
}
public function maprender(key:KeyPoll, dwgfx:dwgraphicsclass, game:gameclass, map:mapclass,
@@ -1312,13 +1315,14 @@ public function maprender(key:KeyPoll, dwgfx:dwgraphicsclass, game:gameclass, ma
dwgfx.drawbutton(game, help);
- dwgfx.backbuffer.lock();
+ //dwgfx.backbuffer.lock();
//dwgfx.drawgui(help);
//draw screen alliteration
//Roomname:
+ dwgfx.drawfillrect(0, 0, 320, 12, 0, 0, 0);
temp = map.area(game.roomx, game.roomy);
if (temp < 2 && !map.custommode && dwgfx.fademode == 0) {
if (game.roomx >= 102 && game.roomx <= 104 && game.roomy >= 110 && game.roomy <= 111) {
@@ -1343,19 +1347,17 @@ public function maprender(key:KeyPoll, dwgfx:dwgraphicsclass, game:gameclass, ma
dwgfx.crewframedelay = 8;
dwgfx.crewframe = (dwgfx.crewframe + 1) % 2;
}
-
- //Menubar:
- dwgfx.drawtextbox( -10, 212, 42, 3, 65, 185, 207);
- switch(game.menupage) {
+ //Menubar:
+ //dwgfx.drawtextbox( -10, 212, 42, 3, 65, 185, 207);
+ dwgfx.drawfillrect(0, 212, 320, 24, 11, 31, 35);
+ dwgfx.drawfillrect(0, 212, 320, 2, 65, 185, 207);
+ dwgfx.drawfillrect(0, 215, 320, 1, 65, 185, 207);
+ dwgfx.drawfillrect(0, 230, 320, 1, 65, 185, 207);
+ dwgfx.drawfillrect(0, 232, 320, 2, 65, 185, 207);
+
+ switch(game.menupage) {
case 0:
- dwgfx.print(30 - 8, 220, "[MAP]", 196, 196, 255 - help.glow);
- if (game.insecretlab) { dwgfx.print(103, 220, "GRAV", 64, 64, 64);
- }else if (obj.flags[67] == 1 && !map.custommode) { dwgfx.print(103, 220, "SHIP", 64,64,64);
- }else{ dwgfx.print(103, 220, "CREW", 64,64,64);}
- dwgfx.print(185-4, 220, "STATS", 64,64,64);
- dwgfx.print(258, 220, "SAVE", 64, 64, 64);
-
if (game.mobilemenu) {
dwgfx.drawmobilebutton(game, 30 - 8, 220, 56, dwgfx.b_size, "MAP", 65, 185, 207);
if (game.insecretlab) { dwgfx.drawmobilebutton(game, 103, 220, 56, dwgfx.b_size, "GRAV", 32, 92, 104);
@@ -1363,6 +1365,13 @@ public function maprender(key:KeyPoll, dwgfx:dwgraphicsclass, game:gameclass, ma
}else{ dwgfx.drawmobilebutton(game, 103, 220, 56, dwgfx.b_size, "CREW", 32, 92, 104);}
dwgfx.drawmobilebutton(game, 185-4, 220, 56, dwgfx.b_size, "STATS", 32, 92, 104);
dwgfx.drawmobilebutton(game, 258, 220, 56, dwgfx.b_size, "QUIT", 32, 92, 104);
+ }else {
+ dwgfx.print(30 - 8, 220, "[MAP]", 196, 196, 255 - help.glow);
+ if (game.insecretlab) { dwgfx.print(103, 220, "GRAV", 64, 64, 64);
+ }else if (obj.flags[67] == 1 && !map.custommode) { dwgfx.print(103, 220, "SHIP", 64,64,64);
+ }else{ dwgfx.print(103, 220, "CREW", 64,64,64);}
+ dwgfx.print(185-4, 220, "STATS", 64,64,64);
+ dwgfx.print(258, 220, "SAVE", 64, 64, 64);
}
if (map.finalmode || (map.custommode && !map.customshowmm)) {
@@ -1379,7 +1388,7 @@ public function maprender(key:KeyPoll, dwgfx:dwgraphicsclass, game:gameclass, ma
}else if(map.custommode){
//draw the map image
dwgfx.drawcustompixeltextbox(35 + map.custommmxoff, 16 + map.custommmyoff, map.custommmxsize + 10, map.custommmysize + 10, (map.custommmxsize + 10) / 8, (map.custommmysize + 10) / 8, 65, 185, 207, 4, 0);
- dwgfx.drawpartimage(12, 40 + map.custommmxoff, 21 + map.custommmyoff, map.custommmxsize, map.custommmysize);
+ dwgfx.drawpartimage(dwgfx.customminimap as Texture, 40 + map.custommmxoff, 21 + map.custommmyoff, map.custommmxsize, map.custommmysize);
//Black out here
if(map.customzoom==4){
@@ -1564,16 +1573,16 @@ public function maprender(key:KeyPoll, dwgfx:dwgraphicsclass, game:gameclass, ma
break;
case 1:
if (game.insecretlab) {
- dwgfx.print(30, 220, "MAP", 64,64,64);
- dwgfx.print(103-8, 220, "[GRAV]", 196, 196, 255 - help.glow);
- dwgfx.print(185-4, 220, "STATS", 64,64,64);
- dwgfx.print(258, 220, "SAVE", 64, 64, 64);
-
if (game.mobilemenu) {
dwgfx.drawmobilebutton(game, 30 - 8, 220, 56, dwgfx.b_size, "MAP", 32, 92, 104);
dwgfx.drawmobilebutton(game, 103, 220, 56, dwgfx.b_size, "GRAV", 65, 185, 207);
dwgfx.drawmobilebutton(game, 185-4, 220, 56, dwgfx.b_size, "STATS", 32, 92, 104);
dwgfx.drawmobilebutton(game, 258, 220, 56, dwgfx.b_size, "QUIT", 32, 92, 104);
+ }else {
+ dwgfx.print(30, 220, "MAP", 64,64,64);
+ dwgfx.print(103-8, 220, "[GRAV]", 196, 196, 255 - help.glow);
+ dwgfx.print(185-4, 220, "STATS", 64,64,64);
+ dwgfx.print(258, 220, "SAVE", 64, 64, 64);
}
if (dwgfx.flipmode) {
@@ -1610,16 +1619,16 @@ public function maprender(key:KeyPoll, dwgfx:dwgraphicsclass, game:gameclass, ma
}
}
}else if (obj.flags[67] == 1 && !map.custommode) {
- dwgfx.print(30, 220, "MAP", 64,64,64);
- dwgfx.print(103-8, 220, "[SHIP]", 196, 196, 255 - help.glow);
- dwgfx.print(185-4, 220, "STATS", 64,64,64);
- dwgfx.print(258, 220, "SAVE", 64, 64, 64);
-
if (game.mobilemenu) {
dwgfx.drawmobilebutton(game, 30 - 8, 220, 56, dwgfx.b_size, "MAP", 32, 92, 104);
dwgfx.drawmobilebutton(game, 103, 220, 56, dwgfx.b_size, "SHIP", 65, 185, 207);
dwgfx.drawmobilebutton(game, 185-4, 220, 56, dwgfx.b_size, "STATS", 32, 92, 104);
dwgfx.drawmobilebutton(game, 258, 220, 56, dwgfx.b_size, "QUIT", 32, 92, 104);
+ }else {
+ dwgfx.print(30, 220, "MAP", 64,64,64);
+ dwgfx.print(103-8, 220, "[SHIP]", 196, 196, 255 - help.glow);
+ dwgfx.print(185-4, 220, "STATS", 64,64,64);
+ dwgfx.print(258, 220, "SAVE", 64, 64, 64);
}
if (game.mobilemenu) {
@@ -1635,16 +1644,16 @@ public function maprender(key:KeyPoll, dwgfx:dwgraphicsclass, game:gameclass, ma
dwgfx.print(0, 105, "Press ACTION to warp to the ship.", 196, 196, 255 - help.glow, true);
}
}else if(map.custommode){
- dwgfx.print(30, 220, "MAP", 64,64,64);
- dwgfx.print(103-8, 220, "[CREW]", 196, 196, 255 - help.glow);
- dwgfx.print(185-4, 220, "STATS", 64,64,64);
- dwgfx.print(258, 220, "SAVE", 64, 64, 64);
-
if (game.mobilemenu) {
dwgfx.drawmobilebutton(game, 30 - 8, 220, 56, dwgfx.b_size, "MAP", 32, 92, 104);
dwgfx.drawmobilebutton(game, 103, 220, 56, dwgfx.b_size, "CREW", 65, 185, 207);
dwgfx.drawmobilebutton(game, 185-4, 220, 56, dwgfx.b_size, "STATS", 32, 92, 104);
dwgfx.drawmobilebutton(game, 258, 220, 56, dwgfx.b_size, "QUIT", 32, 92, 104);
+ }else {
+ dwgfx.print(30, 220, "MAP", 64,64,64);
+ dwgfx.print(103-8, 220, "[CREW]", 196, 196, 255 - help.glow);
+ dwgfx.print(185-4, 220, "STATS", 64,64,64);
+ dwgfx.print(258, 220, "SAVE", 64, 64, 64);
}
if (dwgfx.flipmode){
@@ -1675,16 +1684,16 @@ public function maprender(key:KeyPoll, dwgfx:dwgraphicsclass, game:gameclass, ma
}
}
}else{
- dwgfx.print(30, 220, "MAP", 64,64,64);
- dwgfx.print(103-8, 220, "[CREW]", 196, 196, 255 - help.glow);
- dwgfx.print(185-4, 220, "STATS", 64,64,64);
- dwgfx.print(258, 220, "SAVE", 64, 64, 64);
-
if (game.mobilemenu) {
dwgfx.drawmobilebutton(game, 30 - 8, 220, 56, dwgfx.b_size, "MAP", 32, 92, 104);
dwgfx.drawmobilebutton(game, 103, 220, 56, dwgfx.b_size, "CREW", 65, 185, 207);
dwgfx.drawmobilebutton(game, 185-4, 220, 56, dwgfx.b_size, "STATS", 32, 92, 104);
dwgfx.drawmobilebutton(game, 258, 220, 56, dwgfx.b_size, "QUIT", 32, 92, 104);
+ }else {
+ dwgfx.print(30, 220, "MAP", 64,64,64);
+ dwgfx.print(103-8, 220, "[CREW]", 196, 196, 255 - help.glow);
+ dwgfx.print(185-4, 220, "STATS", 64,64,64);
+ dwgfx.print(258, 220, "SAVE", 64, 64, 64);
}
if (dwgfx.flipmode) {
@@ -1731,20 +1740,20 @@ public function maprender(key:KeyPoll, dwgfx:dwgraphicsclass, game:gameclass, ma
}
break;
case 2:
- dwgfx.print(30, 220, "MAP", 64,64,64);
- if (game.insecretlab) { dwgfx.print(103, 220, "GRAV", 64, 64, 64);
- }else if (obj.flags[67] == 1 && !map.custommode) { dwgfx.print(103, 220, "SHIP", 64,64,64);
- }else{ dwgfx.print(103, 220, "CREW", 64,64,64);}
- dwgfx.print(185-12, 220, "[STATS]", 196, 196, 255 - help.glow);
- dwgfx.print(258, 220, "SAVE", 64, 64, 64);
-
- if (game.mobilemenu) {
+ if (game.mobilemenu) {
dwgfx.drawmobilebutton(game, 30 - 8, 220, 56, dwgfx.b_size, "MAP", 32, 92, 104);
if (game.insecretlab) { dwgfx.drawmobilebutton(game, 103, 220, 56, dwgfx.b_size, "GRAV", 32, 92, 104);
}else if (obj.flags[67] == 1 && !map.custommode) { dwgfx.drawmobilebutton(game, 103, 220, 56, dwgfx.b_size, "SHIP", 32, 92, 104);
}else{ dwgfx.drawmobilebutton(game, 103, 220, 56, dwgfx.b_size, "CREW", 32, 92, 104);}
dwgfx.drawmobilebutton(game, 185-4, 220, 56, dwgfx.b_size, "STATS", 65, 185, 207);
dwgfx.drawmobilebutton(game, 258, 220, 56, dwgfx.b_size, "QUIT", 32, 92, 104);
+ }else {
+ dwgfx.print(30, 220, "MAP", 64,64,64);
+ if (game.insecretlab) { dwgfx.print(103, 220, "GRAV", 64, 64, 64);
+ }else if (obj.flags[67] == 1 && !map.custommode) { dwgfx.print(103, 220, "SHIP", 64,64,64);
+ }else{ dwgfx.print(103, 220, "CREW", 64,64,64);}
+ dwgfx.print(185-12, 220, "[STATS]", 196, 196, 255 - help.glow);
+ dwgfx.print(258, 220, "SAVE", 64, 64, 64);
}
if (map.custommode) {
@@ -1790,13 +1799,6 @@ public function maprender(key:KeyPoll, dwgfx:dwgraphicsclass, game:gameclass, ma
}
break;
case 3:
- dwgfx.print(30, 220, "MAP", 64,64,64);
- if (game.insecretlab) { dwgfx.print(103, 220, "GRAV", 64, 64, 64);
- }else if (obj.flags[67] == 1 && !map.custommode) { dwgfx.print(103, 220, "SHIP", 64,64,64);
- }else{ dwgfx.print(103, 220, "CREW", 64,64,64);}
- dwgfx.print(185-4, 220, "STATS", 64,64,64);
- dwgfx.print(258 - 8, 220, "[SAVE]", 196, 196, 255 - help.glow);
-
if (game.mobilemenu) {
dwgfx.drawmobilebutton(game, 30 - 8, 220, 56, dwgfx.b_size, "MAP", 32, 92, 104);
if (game.insecretlab) { dwgfx.drawmobilebutton(game, 103, 220, 56, dwgfx.b_size, "GRAV", 32, 92, 104);
@@ -1804,6 +1806,13 @@ public function maprender(key:KeyPoll, dwgfx:dwgraphicsclass, game:gameclass, ma
}else{ dwgfx.drawmobilebutton(game, 103, 220, 56, dwgfx.b_size, "CREW", 32, 92, 104);}
dwgfx.drawmobilebutton(game, 185-4, 220, 56, dwgfx.b_size, "STATS", 32, 92, 104);
dwgfx.drawmobilebutton(game, 258, 220, 56, dwgfx.b_size, "QUIT", 65, 185, 207);
+ }else {
+ dwgfx.print(30, 220, "MAP", 64,64,64);
+ if (game.insecretlab) { dwgfx.print(103, 220, "GRAV", 64, 64, 64);
+ }else if (obj.flags[67] == 1 && !map.custommode) { dwgfx.print(103, 220, "SHIP", 64,64,64);
+ }else{ dwgfx.print(103, 220, "CREW", 64,64,64);}
+ dwgfx.print(185-4, 220, "STATS", 64,64,64);
+ dwgfx.print(258 - 8, 220, "[SAVE]", 196, 196, 255 - help.glow);
}
dwgfx.print(0, 80, "Quit to main menu?", 255 - (help.glow * 2), 255 - (help.glow * 2), 255 - help.glow, true);
@@ -2140,21 +2149,20 @@ public function maprender(key:KeyPoll, dwgfx:dwgraphicsclass, game:gameclass, ma
}
}
- dwgfx.backbuffer.unlock();
+ //dwgfx.backbuffer.unlock();
}
public function towerrender(key:KeyPoll, dwgfx:dwgraphicsclass, game:gameclass, map:mapclass,
obj:entityclass, help:helpclass):void {
-
dwgfx.drawbutton(game, help);
//Couple of changes for the towermode
- dwgfx.backbuffer.lock();
- dwgfx.backbuffer.fillRect(dwgfx.backbuffer.rect, 0x000000);
+ //dwgfx.backbuffer.lock();
+ dwgfx.cls(dwgfx.tower_bgdarkcol[map.colstate]);
if (!game.colourblindmode) {
dwgfx.drawtowerbackground(map);
- dwgfx.drawtowermap(map);
+ dwgfx.drawtowermap(game, map);
}else {
dwgfx.drawtowermap_nobackground(map);
}
@@ -2191,12 +2199,12 @@ public function towerrender(key:KeyPoll, dwgfx:dwgraphicsclass, game:gameclass,
dwgfx.drawgui(help);
if (dwgfx.flipmode) {
- if (game.advancetext) dwgfx.bprint(5, 228, "- Tap screen to advance text -", 220 - (help.glow), 220 - (help.glow), 255 - (help.glow / 2), true);
+ if (game.advancetext) dwgfx.print(5, 228, "- Tap screen to advance text -", 220 - (help.glow), 220 - (help.glow), 255 - (help.glow / 2), true);
}else{
- if (game.advancetext) dwgfx.bprint(5, 5, "- Tap screen to advance text -", 220 - (help.glow), 220 - (help.glow), 255 - (help.glow / 2), true);
+ if (game.advancetext) dwgfx.print(5, 5, "- Tap screen to advance text -", 220 - (help.glow), 220 - (help.glow), 255 - (help.glow / 2), true);
}
- dwgfx.backbuffer.fillRect(dwgfx.footerrect, 0x000000);
+ dwgfx.drawfillrect(dwgfx.footerrect.x, dwgfx.footerrect.y, dwgfx.footerrect.width, dwgfx.footerrect.height, 0);
dwgfx.print(5, 231, map.roomname, 196, 196, 255 - help.glow, true);
//dwgfx.rprint(5, 231, String(game.coins), 255 - help.glow/2, 255 - help.glow/2, 196, true);
@@ -2259,17 +2267,18 @@ public function towerrender(key:KeyPoll, dwgfx:dwgraphicsclass, game:gameclass,
}
dwgfx.render();
- dwgfx.backbuffer.unlock();
+ //dwgfx.backbuffer.unlock();
}
public function teleporterrender(key:KeyPoll, dwgfx:dwgraphicsclass, game:gameclass, map:mapclass,
obj:entityclass, help:helpclass):void {
dwgfx.drawbutton(game, help);
- dwgfx.backbuffer.lock();
+ //dwgfx.backbuffer.lock();
//draw screen alliteration
//Roomname:
+ dwgfx.drawfillrect(0, 0, 320, 12, 0, 0, 0);
temp = map.area(game.roomx, game.roomy);
if (temp < 2 && !map.custommode && dwgfx.fademode==0) {
if (game.roomx >= 102 && game.roomx <= 104 && game.roomy >= 110 && game.roomy <= 111) {
@@ -2364,9 +2373,9 @@ public function teleporterrender(key:KeyPoll, dwgfx:dwgraphicsclass, game:gamecl
dwgfx.drawgui(help);
if (dwgfx.flipmode) {
- if (game.advancetext) dwgfx.bprint(5, 228, "- Tap screen to advance text -", 220 - (help.glow), 220 - (help.glow), 255 - (help.glow / 2), true);
+ if (game.advancetext) dwgfx.print(5, 228, "- Tap screen to advance text -", 220 - (help.glow), 220 - (help.glow), 255 - (help.glow / 2), true);
}else{
- if (game.advancetext) dwgfx.bprint(5, 5, "- Tap screen to advance text -", 220 - (help.glow), 220 - (help.glow), 255 - (help.glow / 2), true);
+ if (game.advancetext) dwgfx.print(5, 5, "- Tap screen to advance text -", 220 - (help.glow), 220 - (help.glow), 255 - (help.glow / 2), true);
}
@@ -2410,14 +2419,14 @@ public function teleporterrender(key:KeyPoll, dwgfx:dwgraphicsclass, game:gamecl
}
}
- dwgfx.backbuffer.unlock();
+ //dwgfx.backbuffer.unlock();
}
public function controltutorialrender(key:KeyPoll, dwgfx:dwgraphicsclass, game:gameclass, map:mapclass,
obj:entityclass, help:helpclass):void {
dwgfx.drawbutton(game, help);
- dwgfx.backbuffer.lock();
+ //dwgfx.backbuffer.lock();
//Background color
dwgfx.drawfillrect(0, 0, 320, 240, 10, 24, 26);
@@ -2444,12 +2453,12 @@ public function controltutorialrender(key:KeyPoll, dwgfx:dwgraphicsclass, game:g
dwgfx.print(5, 10, "-= TOUCHSCREEN CONTROLS =-", 220 - (help.glow), 220 - (help.glow), 255 - (help.glow / 2), true);
if(game.controltutorialstate>=3 &&game.controltutorialstate<=6){
- dwgfx.print(5, 195, "Swipe and hold on the left side", 220 - (help.glow), 220 - (help.glow), 255 - (help.glow / 2), true);
- dwgfx.print(5, 205, "of the screen to move", 220 - (help.glow), 220 - (help.glow), 255 - (help.glow / 2), true);
+ dwgfx.print(5, 195 + 8, "Swipe and hold on the left side", 220 - (help.glow), 220 - (help.glow), 255 - (help.glow / 2), true);
+ dwgfx.print(5, 205 + 8, "of the screen to move", 220 - (help.glow), 220 - (help.glow), 255 - (help.glow / 2), true);
}
if(game.controltutorialstate>=7 &&game.controltutorialstate<=11){
- dwgfx.print(5, 200, "Tap on the right to flip", 220 - (help.glow), 220 - (help.glow), 255 - (help.glow / 2), true);
+ dwgfx.print(5, 200 + 8, "Tap on the right to flip", 220 - (help.glow), 220 - (help.glow), 255 - (help.glow / 2), true);
}
if (game.controltutorialstate >= 13) {
@@ -2520,5 +2529,5 @@ public function controltutorialrender(key:KeyPoll, dwgfx:dwgraphicsclass, game:g
dwgfx.render();
}
- dwgfx.backbuffer.unlock();
-}
+ //dwgfx.backbuffer.unlock();
+}
\ No newline at end of file
diff --git a/mobile_version/src/includes/scripts.as b/mobile_version/src/includes/scripts.as
index 1488233f..7e3e555b 100644
--- a/mobile_version/src/includes/scripts.as
+++ b/mobile_version/src/includes/scripts.as
@@ -4710,7 +4710,7 @@
add("squeak(blue)");
add("text(blue,0,0,3)");
- add("This lab is amazing! The scientists");
+ add("This lab is amazing! The scentists");
add("who worked here know a lot more");
add("about warp technology than we do!");
add("position(blue,below)");
@@ -5819,4 +5819,4 @@
}
running = true;
-}
+}
\ No newline at end of file
diff --git a/mobile_version/src/includes/terminalscripts.as b/mobile_version/src/includes/terminalscripts.as
index bf13cefb..cd07a551 100644
--- a/mobile_version/src/includes/terminalscripts.as
+++ b/mobile_version/src/includes/terminalscripts.as
@@ -674,7 +674,7 @@
add(" NEXT UNLOCK: ");
add(" 5 Trinkets");
add("");
- add(" Pushing Onwards ");
+ add(" Pushing onwards ");
add("position(center)");
add("speak_active");
add("endtext");
@@ -687,7 +687,7 @@
add(" NEXT UNLOCK: ");
add(" 8 Trinkets");
add("");
- add(" Positive Force ");
+ add(" Positive force ");
add("position(center)");
add("speak_active");
add("endtext");
@@ -713,7 +713,7 @@
add(" NEXT UNLOCK: ");
add(" 12 Trinkets");
add("");
- add(" Potential for Anything ");
+ add(" Potential for anything ");
add("position(center)");
add("speak_active");
add("endtext");
@@ -739,7 +739,7 @@
add(" NEXT UNLOCK: ");
add(" 16 Trinkets");
add("");
- add(" Predestined Fate ");
+ add(" Predestined fate ");
add("position(center)");
add("speak_active");
add("endtext");
@@ -813,4 +813,4 @@
add("squeak(terminal)");
add("jukebox(10)");
}
-}
+}
\ No newline at end of file
diff --git a/mobile_version/src/mapclass.as b/mobile_version/src/mapclass.as
index 3ee1ddfd..692ce9ef 100644
--- a/mobile_version/src/mapclass.as
+++ b/mobile_version/src/mapclass.as
@@ -1,10 +1,9 @@
-package {
- import flash.display.*;
+package {
import flash.geom.*;
import flash.events.*;
import flash.net.*;
- public class mapclass extends Sprite {
+ public class mapclass {
public function mapclass():void {
//Start here!
r = 196; g = 196; b = 196;
@@ -612,6 +611,8 @@
game.activetele = false; game.readytotele = 0;
game.mobilequicksave_thisroom = false;
+ dwgfx.forcescreenupdates();
+
obj.opt_useblock = false;
obj.opt_usetrigger = false;
obj.opt_usedamage = false;
@@ -790,7 +791,7 @@
case 1: return "Dimension VVVVVV"; break;
case 2: return "Laboratory"; break;
case 3: return "The Tower"; break;
- case 4: return "Warp Zone"; break;
+ case 4: return "Warpzone"; break;
case 5: return "Space Station"; break;
case 6: return "Outside Dimension VVVVVV"; break;
case 7: return "Outside Dimension VVVVVV"; break;
@@ -892,7 +893,7 @@
}
}
- if (rx == 119 && ry == 108 && !custommode) {
+ if (rx == 119 && ry == 108) {
background = 5;
dwgfx.rcol = 3;
warpx = true;
@@ -1608,4 +1609,4 @@ obj.createentity(game, 72, 156, 11, 200); // (horizontal gravity line)
public var spikecount:int;
}
-}
+}
\ No newline at end of file
diff --git a/mobile_version/src/musicclass.as b/mobile_version/src/musicclass.as
index 254cd2c1..950e4aa8 100644
--- a/mobile_version/src/musicclass.as
+++ b/mobile_version/src/musicclass.as
@@ -1,9 +1,8 @@
-package {
- import flash.display.*;
+package {
import flash.media.*;
import flash.events.*;
- public class musicclass extends Sprite {
+ public class musicclass {
//For Music stuff
public function play(t:int):void {
if (currentsong !=t) {
diff --git a/mobile_version/src/platformclass.as b/mobile_version/src/platformclass.as
index fc5e0d69..06e2d7b5 100644
--- a/mobile_version/src/platformclass.as
+++ b/mobile_version/src/platformclass.as
@@ -2,13 +2,10 @@
package {
//import com.sticksports.nativeExtensions.SilentSwitch;
import flash.events.*;
- import flash.media.SoundMixer;
- import flash.media.AudioPlaybackMode;
public class platformclass {
public function init():void {
//SilentSwitch.apply();
- SoundMixer.audioPlaybackMode = AudioPlaybackMode.AMBIENT;
}
public function callonwake():void {
diff --git a/mobile_version/src/saveclass.as b/mobile_version/src/saveclass.as
index 7868839d..164fc397 100644
--- a/mobile_version/src/saveclass.as
+++ b/mobile_version/src/saveclass.as
@@ -1,10 +1,9 @@
-package {
- import flash.display.*;
+package {
import flash.geom.*;
import flash.events.*;
import flash.net.*;
- public class saveclass extends Sprite {
+ public class saveclass {
public function saveclass():void {
}
diff --git a/mobile_version/src/scoreclass.as b/mobile_version/src/scoreclass.as
index 076c5a75..bad5cc6c 100644
--- a/mobile_version/src/scoreclass.as
+++ b/mobile_version/src/scoreclass.as
@@ -1,10 +1,11 @@
package {
- import com.milkmangames.nativeextensions.ios.*;
- import com.milkmangames.nativeextensions.ios.events.*;
+ //import com.milkmangames.nativeextensions.ios.*;
+ //import com.milkmangames.nativeextensions.ios.events.*;
import flash.display.Stage;
public class scoreclass {
public function init(mystage:Stage):void {
+ /*
if (!GameCenter.isSupported()){
trace("GameCenter is not supported on this platform.");
}
@@ -32,41 +33,51 @@ package {
gameCenter.addEventListener(GameCenterErrorEvent.ACHIEVEMENT_REPORT_FAILED,onAchievementFailed);
gameCenter.addEventListener(GameCenterErrorEvent.ACHIEVEMENT_RESET_FAILED,onResetFailed);
GameCenter.gameCenter.authenticateLocalUser();
+ */
}
CONFIG::iphonemode {
/** Check Authentication */
- private function checkAuthentication():Boolean{
+ private function checkAuthentication():Boolean {
+ /*
if (!GameCenter.gameCenter.isUserAuthenticated()){
trace("not logged in!");
return false;
}
+ */
return true;
}
/** Reset Achievements */
- public function resetAchievements():void{
+ public function resetAchievements():void {
+ /*
if (!checkAuthentication()) return;
GameCenter.gameCenter.resetAchievements();
+ */
}
public function reportScore(t:int):void{
// we make sure you're logged in before bothering to report the score.
// later iOS versions may take care of waiting/resubmitting for you, but earlier ones won't.
+ /*
if (!checkAuthentication()) return;
t = t * 2; //Score is in 30 frame increments
GameCenter.gameCenter.reportScoreForCategory(t, "grp.supgravleaderboard");
+ */
}
public function opengamecenter():void {
+ /*
if (!checkAuthentication()) return;
GameCenter.gameCenter.showLeaderboardForCategory("grp.supgravleaderboard");
+ */
}
/** Show Achievements */
- public function showAchievements():void{
+ public function showAchievements():void {
+ /*
if (!checkAuthentication()) return;
//trace("showing achievements...");
@@ -75,6 +86,7 @@ package {
}catch (e:Error){
//trace("ERR showachievements:"+e.message+"/"+e.name+"/"+e.errorID);
}
+ */
}
public var vvvvvvgamecomplete:int = 0;
@@ -97,7 +109,8 @@ package {
public var vvvvvvsupgrav60:int = 17;
public var vvvvvvmaster:int = 18;
- public function reportAchievement(t:int):void{
+ public function reportAchievement(t:int):void {
+ /*
if (!checkAuthentication()) return;
// the '1.0' is a float (Number) value from 0.0-100.0 the percent completion of the achievement.
@@ -122,11 +135,13 @@ package {
case 17: GameCenter.gameCenter.reportAchievement("grp.vvvvvvsupgrav60", 100.0); break;
case 18: GameCenter.gameCenter.reportAchievement("grp.vvvvvvmaster", 100.0); break;
}
+ */
}
//
// Events
//
+ /*
private function onAuthSucceeded(e:GameCenterEvent):void
{
trace("Auth succeeded!");
@@ -176,10 +191,11 @@ package {
{
trace("failed to reset:"+e.message);
}
+ */
}
CONFIG::iphonemode {
- public var gameCenter:GameCenter;
+ //public var gameCenter:GameCenter;
public var gamecenteron:Boolean = true;
}
}
diff --git a/mobile_version/src/scriptclass.as b/mobile_version/src/scriptclass.as
index b1d12d8e..9d511365 100644
--- a/mobile_version/src/scriptclass.as
+++ b/mobile_version/src/scriptclass.as
@@ -1,13 +1,12 @@
-package {
+package {
import flash.ui.Keyboard;
- import flash.display.*;
import flash.geom.*;
import flash.events.*;
import flash.net.*;
import bigroom.input.KeyPoll;
import flash.system.fscommand;
- public class scriptclass extends Sprite {
+ public class scriptclass {
public var GAMEMODE:int = 0;
public var TITLEMODE:int = 1;
public var CLICKTOSTART:int = 2;
@@ -772,7 +771,7 @@
game.gamestate = 5;
dwgfx.menuoffset = 240; //actually this should count the roomname
if (map.extrarow) dwgfx.menuoffset -= 10;
- dwgfx.menubuffer.copyPixels(dwgfx.screenbuffer, dwgfx.screenbuffer.rect, dwgfx.tl, null, null, false);
+ dwgfx.setup_menubuffer();
dwgfx.resumegamemode = false;
game.useteleporter = false; //good heavens don't actually use it
@@ -1063,7 +1062,7 @@
}else if (words[0] == "foundlab2") {
dwgfx.textboxremovefast();
- dwgfx.createtextbox("The secret lab is separate from", 50, 85, 174, 174, 174);
+ dwgfx.createtextbox("The secret lab is seperate from", 50, 85, 174, 174, 174);
dwgfx.addline("the rest of the game. You can");
dwgfx.addline("now come back here at any time");
dwgfx.addline("by selecting the new SECRET LAB");
diff --git a/mobile_version/src/starling/animation/DelayedCall.as b/mobile_version/src/starling/animation/DelayedCall.as
new file mode 100644
index 00000000..46e6e673
--- /dev/null
+++ b/mobile_version/src/starling/animation/DelayedCall.as
@@ -0,0 +1,140 @@
+// =================================================================================================
+//
+// Starling Framework
+// Copyright Gamua GmbH. All Rights Reserved.
+//
+// This program is free software. You can redistribute and/or modify it
+// in accordance with the terms of the accompanying license agreement.
+//
+// =================================================================================================
+
+package starling.animation
+{
+ import starling.core.starling_internal;
+ import starling.events.Event;
+ import starling.events.EventDispatcher;
+
+ /** A DelayedCall allows you to execute a method after a certain time has passed. Since it
+ * implements the IAnimatable interface, it can be added to a juggler. In most cases, you
+ * do not have to use this class directly; the juggler class contains a method to delay
+ * calls directly.
+ *
+ *
DelayedCall dispatches an Event of type 'Event.REMOVE_FROM_JUGGLER' when it is finished,
+ * so that the juggler automatically removes it when its no longer needed.
+ *
+ * @see Juggler
+ */
+ public class DelayedCall extends EventDispatcher implements IAnimatable
+ {
+ private var _currentTime:Number;
+ private var _totalTime:Number;
+ private var _callback:Function;
+ private var _args:Array;
+ private var _repeatCount:int;
+
+ /** Creates a delayed call. */
+ public function DelayedCall(callback:Function, delay:Number, args:Array=null)
+ {
+ reset(callback, delay, args);
+ }
+
+ /** Resets the delayed call to its default values, which is useful for pooling. */
+ public function reset(callback:Function, delay:Number, args:Array=null):DelayedCall
+ {
+ _currentTime = 0;
+ _totalTime = Math.max(delay, 0.0001);
+ _callback = callback;
+ _args = args;
+ _repeatCount = 1;
+
+ return this;
+ }
+
+ /** @inheritDoc */
+ public function advanceTime(time:Number):void
+ {
+ var previousTime:Number = _currentTime;
+ _currentTime += time;
+
+ if (_currentTime > _totalTime)
+ _currentTime = _totalTime;
+
+ if (previousTime < _totalTime && _currentTime >= _totalTime)
+ {
+ if (_repeatCount == 0 || _repeatCount > 1)
+ {
+ _callback.apply(null, _args);
+
+ if (_repeatCount > 0) _repeatCount -= 1;
+ _currentTime = 0;
+ advanceTime((previousTime + time) - _totalTime);
+ }
+ else
+ {
+ // save call & args: they might be changed through an event listener
+ var call:Function = _callback;
+ var args:Array = _args;
+
+ // in the callback, people might want to call "reset" and re-add it to the
+ // juggler; so this event has to be dispatched *before* executing 'call'.
+ dispatchEventWith(Event.REMOVE_FROM_JUGGLER);
+ call.apply(null, args);
+ }
+ }
+ }
+
+ /** Advances the delayed call so that it is executed right away. If 'repeatCount' is
+ * anything else than '1', this method will complete only the current iteration. */
+ public function complete():void
+ {
+ var restTime:Number = _totalTime - _currentTime;
+ if (restTime > 0) advanceTime(restTime);
+ }
+
+ /** Indicates if enough time has passed, and the call has already been executed. */
+ public function get isComplete():Boolean
+ {
+ return _repeatCount == 1 && _currentTime >= _totalTime;
+ }
+
+ /** The time for which calls will be delayed (in seconds). */
+ public function get totalTime():Number { return _totalTime; }
+
+ /** The time that has already passed (in seconds). */
+ public function get currentTime():Number { return _currentTime; }
+
+ /** The number of times the call will be repeated.
+ * Set to '0' to repeat indefinitely. @default 1 */
+ public function get repeatCount():int { return _repeatCount; }
+ public function set repeatCount(value:int):void { _repeatCount = value; }
+
+ /** The callback that will be executed when the time is up. */
+ public function get callback():Function { return _callback; }
+
+ /** The arguments that the callback will be executed with.
+ * Beware: not a copy, but the actual object! */
+ public function get arguments():Array { return _args; }
+
+ // delayed call pooling
+
+ private static var sPool:Vector. = new [];
+
+ /** @private */
+ starling_internal static function fromPool(call:Function, delay:Number,
+ args:Array=null):DelayedCall
+ {
+ if (sPool.length) return sPool.pop().reset(call, delay, args);
+ else return new DelayedCall(call, delay, args);
+ }
+
+ /** @private */
+ starling_internal static function toPool(delayedCall:DelayedCall):void
+ {
+ // reset any object-references, to make sure we don't prevent any garbage collection
+ delayedCall._callback = null;
+ delayedCall._args = null;
+ delayedCall.removeEventListeners();
+ sPool.push(delayedCall);
+ }
+ }
+}
\ No newline at end of file
diff --git a/mobile_version/src/starling/animation/IAnimatable.as b/mobile_version/src/starling/animation/IAnimatable.as
new file mode 100644
index 00000000..d954426f
--- /dev/null
+++ b/mobile_version/src/starling/animation/IAnimatable.as
@@ -0,0 +1,30 @@
+// =================================================================================================
+//
+// Starling Framework
+// Copyright Gamua GmbH. All Rights Reserved.
+//
+// This program is free software. You can redistribute and/or modify it
+// in accordance with the terms of the accompanying license agreement.
+//
+// =================================================================================================
+
+package starling.animation
+{
+ /** The IAnimatable interface describes objects that are animated depending on the passed time.
+ * Any object that implements this interface can be added to a juggler.
+ *
+ *
When an object should no longer be animated, it has to be removed from the juggler.
+ * To do this, you can manually remove it via the method juggler.remove(object),
+ * or the object can request to be removed by dispatching a Starling event with the type
+ * Event.REMOVE_FROM_JUGGLER. The "Tween" class is an example of a class that
+ * dispatches such an event; you don't have to remove tweens manually from the juggler.
+ *
+ * @see Juggler
+ * @see Tween
+ */
+ public interface IAnimatable
+ {
+ /** Advance the time by a number of seconds. @param time in seconds. */
+ function advanceTime(time:Number):void;
+ }
+}
\ No newline at end of file
diff --git a/mobile_version/src/starling/animation/Juggler.as b/mobile_version/src/starling/animation/Juggler.as
new file mode 100644
index 00000000..810a7e82
--- /dev/null
+++ b/mobile_version/src/starling/animation/Juggler.as
@@ -0,0 +1,396 @@
+// =================================================================================================
+//
+// Starling Framework
+// Copyright Gamua GmbH. All Rights Reserved.
+//
+// This program is free software. You can redistribute and/or modify it
+// in accordance with the terms of the accompanying license agreement.
+//
+// =================================================================================================
+
+package starling.animation
+{
+ import flash.utils.Dictionary;
+
+ import starling.core.starling_internal;
+ import starling.events.Event;
+ import starling.events.EventDispatcher;
+
+ /** The Juggler takes objects that implement IAnimatable (like Tweens) and executes them.
+ *
+ *
A juggler is a simple object. It does no more than saving a list of objects implementing
+ * "IAnimatable" and advancing their time if it is told to do so (by calling its own
+ * "advanceTime"-method). When an animation is completed, it throws it away.
+ *
+ *
There is a default juggler available at the Starling class:
+ *
+ *
+ * var juggler:Juggler = Starling.juggler;
+ *
+ *
+ *
You can create juggler objects yourself, just as well. That way, you can group
+ * your game into logical components that handle their animations independently. All you have
+ * to do is call the "advanceTime" method on your custom juggler once per frame.
+ *
+ *
Another handy feature of the juggler is the "delayCall"-method. Use it to
+ * execute a function at a later time. Different to conventional approaches, the method
+ * will only be called when the juggler is advanced, giving you perfect control over the
+ * call.
+ *
+ * @see Tween
+ * @see DelayedCall
+ */
+ public class Juggler implements IAnimatable
+ {
+ private var _objects:Vector.;
+ private var _objectIDs:Dictionary;
+ private var _elapsedTime:Number;
+ private var _timeScale:Number;
+
+ private static var sCurrentObjectID:uint;
+
+ /** Create an empty juggler. */
+ public function Juggler()
+ {
+ _elapsedTime = 0;
+ _timeScale = 1.0;
+ _objects = new [];
+ _objectIDs = new Dictionary(true);
+ }
+
+ /** Adds an object to the juggler.
+ *
+ * @return Unique numeric identifier for the animation. This identifier may be used
+ * to remove the object via removeByID().
+ */
+ public function add(object:IAnimatable):uint
+ {
+ return addWithID(object, getNextID());
+ }
+
+ private function addWithID(object:IAnimatable, objectID:uint):uint
+ {
+ if (object && !(object in _objectIDs))
+ {
+ var dispatcher:EventDispatcher = object as EventDispatcher;
+ if (dispatcher) dispatcher.addEventListener(Event.REMOVE_FROM_JUGGLER, onRemove);
+
+ _objects[_objects.length] = object;
+ _objectIDs[object] = objectID;
+
+ return objectID;
+ }
+ else return 0;
+ }
+
+ /** Determines if an object has been added to the juggler. */
+ public function contains(object:IAnimatable):Boolean
+ {
+ return object in _objectIDs;
+ }
+
+ /** Removes an object from the juggler.
+ *
+ * @return The (now meaningless) unique numeric identifier for the animation, or zero
+ * if the object was not found.
+ */
+ public function remove(object:IAnimatable):uint
+ {
+ var objectID:uint = 0;
+
+ if (object && object in _objectIDs)
+ {
+ var dispatcher:EventDispatcher = object as EventDispatcher;
+ if (dispatcher) dispatcher.removeEventListener(Event.REMOVE_FROM_JUGGLER, onRemove);
+
+ var index:int = _objects.indexOf(object);
+ _objects[index] = null;
+
+ objectID = _objectIDs[object];
+ delete _objectIDs[object];
+ }
+
+ return objectID;
+ }
+
+ /** Removes an object from the juggler, identified by the unique numeric identifier you
+ * received when adding it.
+ *
+ *
It's not uncommon that an animatable object is added to a juggler repeatedly,
+ * e.g. when using an object-pool. Thus, when using the remove method,
+ * you might accidentally remove an object that has changed its context. By using
+ * removeByID instead, you can be sure to avoid that, since the objectID
+ * will always be unique.
+ *
+ * @return if successful, the passed objectID; if the object was not found, zero.
+ */
+ public function removeByID(objectID:uint):uint
+ {
+ for (var i:int=_objects.length-1; i>=0; --i)
+ {
+ var object:IAnimatable = _objects[i];
+
+ if (_objectIDs[object] == objectID)
+ {
+ remove(object);
+ return objectID;
+ }
+ }
+
+ return 0;
+ }
+
+ /** Removes all tweens with a certain target. */
+ public function removeTweens(target:Object):void
+ {
+ if (target == null) return;
+
+ for (var i:int=_objects.length-1; i>=0; --i)
+ {
+ var tween:Tween = _objects[i] as Tween;
+ if (tween && tween.target == target)
+ {
+ tween.removeEventListener(Event.REMOVE_FROM_JUGGLER, onRemove);
+ _objects[i] = null;
+ delete _objectIDs[tween];
+ }
+ }
+ }
+
+ /** Removes all delayed and repeated calls with a certain callback. */
+ public function removeDelayedCalls(callback:Function):void
+ {
+ if (callback == null) return;
+
+ for (var i:int=_objects.length-1; i>=0; --i)
+ {
+ var delayedCall:DelayedCall = _objects[i] as DelayedCall;
+ if (delayedCall && delayedCall.callback == callback)
+ {
+ delayedCall.removeEventListener(Event.REMOVE_FROM_JUGGLER, onRemove);
+ _objects[i] = null;
+ delete _objectIDs[tween];
+ }
+ }
+ }
+
+ /** Figures out if the juggler contains one or more tweens with a certain target. */
+ public function containsTweens(target:Object):Boolean
+ {
+ if (target)
+ {
+ for (var i:int=_objects.length-1; i>=0; --i)
+ {
+ var tween:Tween = _objects[i] as Tween;
+ if (tween && tween.target == target) return true;
+ }
+ }
+
+ return false;
+ }
+
+ /** Figures out if the juggler contains one or more delayed calls with a certain callback. */
+ public function containsDelayedCalls(callback:Function):Boolean
+ {
+ if (callback != null)
+ {
+ for (var i:int=_objects.length-1; i>=0; --i)
+ {
+ var delayedCall:DelayedCall = _objects[i] as DelayedCall;
+ if (delayedCall && delayedCall.callback == callback) return true;
+ }
+ }
+
+ return false;
+ }
+
+ /** Removes all objects at once. */
+ public function purge():void
+ {
+ // the object vector is not purged right away, because if this method is called
+ // from an 'advanceTime' call, this would make the loop crash. Instead, the
+ // vector is filled with 'null' values. They will be cleaned up on the next call
+ // to 'advanceTime'.
+
+ for (var i:int=_objects.length-1; i>=0; --i)
+ {
+ var object:IAnimatable = _objects[i];
+ var dispatcher:EventDispatcher = object as EventDispatcher;
+ if (dispatcher) dispatcher.removeEventListener(Event.REMOVE_FROM_JUGGLER, onRemove);
+ _objects[i] = null;
+ delete _objectIDs[object];
+ }
+ }
+
+ /** Delays the execution of a function until delay seconds have passed.
+ * This method provides a convenient alternative for creating and adding a DelayedCall
+ * manually.
+ *
+ * @return Unique numeric identifier for the delayed call. This identifier may be used
+ * to remove the object via removeByID().
+ */
+ public function delayCall(call:Function, delay:Number, ...args):uint
+ {
+ if (call == null) throw new ArgumentError("call must not be null");
+
+ var delayedCall:DelayedCall = DelayedCall.starling_internal::fromPool(call, delay, args);
+ delayedCall.addEventListener(Event.REMOVE_FROM_JUGGLER, onPooledDelayedCallComplete);
+ return add(delayedCall);
+ }
+
+ /** Runs a function at a specified interval (in seconds). A 'repeatCount' of zero
+ * means that it runs indefinitely.
+ *
+ * @return Unique numeric identifier for the delayed call. This identifier may be used
+ * to remove the object via removeByID().
+ */
+ public function repeatCall(call:Function, interval:Number, repeatCount:int=0, ...args):uint
+ {
+ if (call == null) throw new ArgumentError("call must not be null");
+
+ var delayedCall:DelayedCall = DelayedCall.starling_internal::fromPool(call, interval, args);
+ delayedCall.repeatCount = repeatCount;
+ delayedCall.addEventListener(Event.REMOVE_FROM_JUGGLER, onPooledDelayedCallComplete);
+ return add(delayedCall);
+ }
+
+ private function onPooledDelayedCallComplete(event:Event):void
+ {
+ DelayedCall.starling_internal::toPool(event.target as DelayedCall);
+ }
+
+ /** Utilizes a tween to animate the target object over time seconds. Internally,
+ * this method uses a tween instance (taken from an object pool) that is added to the
+ * juggler right away. This method provides a convenient alternative for creating
+ * and adding a tween manually.
+ *
+ *
Fill 'properties' with key-value pairs that describe both the
+ * tween and the animation target. Here is an example:
To cancel the tween, call 'Juggler.removeTweens' with the same target, or pass
+ * the returned 'IAnimatable' instance to 'Juggler.remove()'. Do not use the returned
+ * IAnimatable otherwise; it is taken from a pool and will be reused.
+ *
+ *
Note that some property types may be animated in a special way:
+ *
+ *
If the property contains the string color or Color,
+ * it will be treated as an unsigned integer with a color value
+ * (e.g. 0xff0000 for red). Each color channel will be animated
+ * individually.
+ *
The same happens if you append the string #rgb to the name.
+ *
If you append #rad, the property is treated as an angle in radians,
+ * making sure it always uses the shortest possible arc for the rotation.
+ *
The string #deg does the same for angles in degrees.
+ *
+ */
+ public function tween(target:Object, time:Number, properties:Object):uint
+ {
+ if (target == null) throw new ArgumentError("target must not be null");
+
+ var tween:Tween = Tween.starling_internal::fromPool(target, time);
+
+ for (var property:String in properties)
+ {
+ var value:Object = properties[property];
+
+ if (tween.hasOwnProperty(property))
+ tween[property] = value;
+ else if (target.hasOwnProperty(Tween.getPropertyName(property)))
+ tween.animate(property, value as Number);
+ else
+ throw new ArgumentError("Invalid property: " + property);
+ }
+
+ tween.addEventListener(Event.REMOVE_FROM_JUGGLER, onPooledTweenComplete);
+ return add(tween);
+ }
+
+ private function onPooledTweenComplete(event:Event):void
+ {
+ Tween.starling_internal::toPool(event.target as Tween);
+ }
+
+ /** Advances all objects by a certain time (in seconds). */
+ public function advanceTime(time:Number):void
+ {
+ var numObjects:int = _objects.length;
+ var currentIndex:int = 0;
+ var i:int;
+
+ time *= _timeScale;
+ if (numObjects == 0 || time == 0) return;
+ _elapsedTime += time;
+
+ // there is a high probability that the "advanceTime" function modifies the list
+ // of animatables. we must not process new objects right now (they will be processed
+ // in the next frame), and we need to clean up any empty slots in the list.
+
+ for (i=0; i { return _objects; }
+ }
+}
diff --git a/mobile_version/src/starling/animation/Transitions.as b/mobile_version/src/starling/animation/Transitions.as
new file mode 100644
index 00000000..de708b61
--- /dev/null
+++ b/mobile_version/src/starling/animation/Transitions.as
@@ -0,0 +1,233 @@
+// =================================================================================================
+//
+// Starling Framework
+// Copyright Gamua GmbH. All Rights Reserved.
+//
+// This program is free software. You can redistribute and/or modify it
+// in accordance with the terms of the accompanying license agreement.
+//
+// =================================================================================================
+//
+// easing functions thankfully taken from http://dojotoolkit.org
+// and http://www.robertpenner.com/easing
+//
+
+package starling.animation
+{
+ import flash.utils.Dictionary;
+
+ import starling.errors.AbstractClassError;
+
+ /** The Transitions class contains static methods that define easing functions.
+ * Those functions are used by the Tween class to execute animations.
+ *
+ *
Here is a visual representation of the available transitions:
+ *
+ *
+ *
You can define your own transitions through the "registerTransition" function. A
+ * transition function must have the following signature, where ratio is
+ * in the range 0-1:
+ *
+ *
function myTransition(ratio:Number):Number
+ */
+ public class Transitions
+ {
+ public static const LINEAR:String = "linear";
+ public static const EASE_IN:String = "easeIn";
+ public static const EASE_OUT:String = "easeOut";
+ public static const EASE_IN_OUT:String = "easeInOut";
+ public static const EASE_OUT_IN:String = "easeOutIn";
+ public static const EASE_IN_BACK:String = "easeInBack";
+ public static const EASE_OUT_BACK:String = "easeOutBack";
+ public static const EASE_IN_OUT_BACK:String = "easeInOutBack";
+ public static const EASE_OUT_IN_BACK:String = "easeOutInBack";
+ public static const EASE_IN_ELASTIC:String = "easeInElastic";
+ public static const EASE_OUT_ELASTIC:String = "easeOutElastic";
+ public static const EASE_IN_OUT_ELASTIC:String = "easeInOutElastic";
+ public static const EASE_OUT_IN_ELASTIC:String = "easeOutInElastic";
+ public static const EASE_IN_BOUNCE:String = "easeInBounce";
+ public static const EASE_OUT_BOUNCE:String = "easeOutBounce";
+ public static const EASE_IN_OUT_BOUNCE:String = "easeInOutBounce";
+ public static const EASE_OUT_IN_BOUNCE:String = "easeOutInBounce";
+
+ private static var sTransitions:Dictionary;
+
+ /** @private */
+ public function Transitions() { throw new AbstractClassError(); }
+
+ /** Returns the transition function that was registered under a certain name. */
+ public static function getTransition(name:String):Function
+ {
+ if (sTransitions == null) registerDefaults();
+ return sTransitions[name];
+ }
+
+ /** Registers a new transition function under a certain name. */
+ public static function register(name:String, func:Function):void
+ {
+ if (sTransitions == null) registerDefaults();
+ sTransitions[name] = func;
+ }
+
+ private static function registerDefaults():void
+ {
+ sTransitions = new Dictionary();
+
+ register(LINEAR, linear);
+ register(EASE_IN, easeIn);
+ register(EASE_OUT, easeOut);
+ register(EASE_IN_OUT, easeInOut);
+ register(EASE_OUT_IN, easeOutIn);
+ register(EASE_IN_BACK, easeInBack);
+ register(EASE_OUT_BACK, easeOutBack);
+ register(EASE_IN_OUT_BACK, easeInOutBack);
+ register(EASE_OUT_IN_BACK, easeOutInBack);
+ register(EASE_IN_ELASTIC, easeInElastic);
+ register(EASE_OUT_ELASTIC, easeOutElastic);
+ register(EASE_IN_OUT_ELASTIC, easeInOutElastic);
+ register(EASE_OUT_IN_ELASTIC, easeOutInElastic);
+ register(EASE_IN_BOUNCE, easeInBounce);
+ register(EASE_OUT_BOUNCE, easeOutBounce);
+ register(EASE_IN_OUT_BOUNCE, easeInOutBounce);
+ register(EASE_OUT_IN_BOUNCE, easeOutInBounce);
+ }
+
+ // transition functions
+
+ protected static function linear(ratio:Number):Number
+ {
+ return ratio;
+ }
+
+ protected static function easeIn(ratio:Number):Number
+ {
+ return ratio * ratio * ratio;
+ }
+
+ protected static function easeOut(ratio:Number):Number
+ {
+ var invRatio:Number = ratio - 1.0;
+ return invRatio * invRatio * invRatio + 1;
+ }
+
+ protected static function easeInOut(ratio:Number):Number
+ {
+ return easeCombined(easeIn, easeOut, ratio);
+ }
+
+ protected static function easeOutIn(ratio:Number):Number
+ {
+ return easeCombined(easeOut, easeIn, ratio);
+ }
+
+ protected static function easeInBack(ratio:Number):Number
+ {
+ var s:Number = 1.70158;
+ return Math.pow(ratio, 2) * ((s + 1.0)*ratio - s);
+ }
+
+ protected static function easeOutBack(ratio:Number):Number
+ {
+ var invRatio:Number = ratio - 1.0;
+ var s:Number = 1.70158;
+ return Math.pow(invRatio, 2) * ((s + 1.0)*invRatio + s) + 1.0;
+ }
+
+ protected static function easeInOutBack(ratio:Number):Number
+ {
+ return easeCombined(easeInBack, easeOutBack, ratio);
+ }
+
+ protected static function easeOutInBack(ratio:Number):Number
+ {
+ return easeCombined(easeOutBack, easeInBack, ratio);
+ }
+
+ protected static function easeInElastic(ratio:Number):Number
+ {
+ if (ratio == 0 || ratio == 1) return ratio;
+ else
+ {
+ var p:Number = 0.3;
+ var s:Number = p/4.0;
+ var invRatio:Number = ratio - 1;
+ return -1.0 * Math.pow(2.0, 10.0*invRatio) * Math.sin((invRatio-s)*(2.0*Math.PI)/p);
+ }
+ }
+
+ protected static function easeOutElastic(ratio:Number):Number
+ {
+ if (ratio == 0 || ratio == 1) return ratio;
+ else
+ {
+ var p:Number = 0.3;
+ var s:Number = p/4.0;
+ return Math.pow(2.0, -10.0*ratio) * Math.sin((ratio-s)*(2.0*Math.PI)/p) + 1;
+ }
+ }
+
+ protected static function easeInOutElastic(ratio:Number):Number
+ {
+ return easeCombined(easeInElastic, easeOutElastic, ratio);
+ }
+
+ protected static function easeOutInElastic(ratio:Number):Number
+ {
+ return easeCombined(easeOutElastic, easeInElastic, ratio);
+ }
+
+ protected static function easeInBounce(ratio:Number):Number
+ {
+ return 1.0 - easeOutBounce(1.0 - ratio);
+ }
+
+ protected static function easeOutBounce(ratio:Number):Number
+ {
+ var s:Number = 7.5625;
+ var p:Number = 2.75;
+ var l:Number;
+ if (ratio < (1.0/p))
+ {
+ l = s * Math.pow(ratio, 2);
+ }
+ else
+ {
+ if (ratio < (2.0/p))
+ {
+ ratio -= 1.5/p;
+ l = s * Math.pow(ratio, 2) + 0.75;
+ }
+ else
+ {
+ if (ratio < 2.5/p)
+ {
+ ratio -= 2.25/p;
+ l = s * Math.pow(ratio, 2) + 0.9375;
+ }
+ else
+ {
+ ratio -= 2.625/p;
+ l = s * Math.pow(ratio, 2) + 0.984375;
+ }
+ }
+ }
+ return l;
+ }
+
+ protected static function easeInOutBounce(ratio:Number):Number
+ {
+ return easeCombined(easeInBounce, easeOutBounce, ratio);
+ }
+
+ protected static function easeOutInBounce(ratio:Number):Number
+ {
+ return easeCombined(easeOutBounce, easeInBounce, ratio);
+ }
+
+ protected static function easeCombined(startFunc:Function, endFunc:Function, ratio:Number):Number
+ {
+ if (ratio < 0.5) return 0.5 * startFunc(ratio*2.0);
+ else return 0.5 * endFunc((ratio-0.5)*2.0) + 0.5;
+ }
+ }
+}
\ No newline at end of file
diff --git a/mobile_version/src/starling/animation/Tween.as b/mobile_version/src/starling/animation/Tween.as
new file mode 100644
index 00000000..561bd944
--- /dev/null
+++ b/mobile_version/src/starling/animation/Tween.as
@@ -0,0 +1,451 @@
+// =================================================================================================
+//
+// Starling Framework
+// Copyright Gamua GmbH. All Rights Reserved.
+//
+// This program is free software. You can redistribute and/or modify it
+// in accordance with the terms of the accompanying license agreement.
+//
+// =================================================================================================
+
+
+package starling.animation
+{
+ import starling.core.starling_internal;
+ import starling.events.Event;
+ import starling.events.EventDispatcher;
+ import starling.utils.Color;
+
+ /** A Tween animates numeric properties of objects. It uses different transition functions
+ * to give the animations various styles.
+ *
+ *
The primary use of this class is to do standard animations like movement, fading,
+ * rotation, etc. But there are no limits on what to animate; as long as the property you want
+ * to animate is numeric (int, uint, Number), the tween can handle it. For a list
+ * of available Transition types, look at the "Transitions" class.
+ *
+ *
Here is an example of a tween that moves an object to the right, rotates it, and
+ * fades it out:
Note that the object is added to a juggler at the end of this sample. That's because a
+ * tween will only be executed if its "advanceTime" method is executed regularly - the
+ * juggler will do that for you, and will remove the tween when it is finished.
+ *
+ * @see Juggler
+ * @see Transitions
+ */
+ public class Tween extends EventDispatcher implements IAnimatable
+ {
+ private static const HINT_MARKER:String = '#';
+
+ private var _target:Object;
+ private var _transitionFunc:Function;
+ private var _transitionName:String;
+
+ private var _properties:Vector.;
+ private var _startValues:Vector.;
+ private var _endValues:Vector.;
+ private var _updateFuncs:Vector.;
+
+ private var _onStart:Function;
+ private var _onUpdate:Function;
+ private var _onRepeat:Function;
+ private var _onComplete:Function;
+
+ private var _onStartArgs:Array;
+ private var _onUpdateArgs:Array;
+ private var _onRepeatArgs:Array;
+ private var _onCompleteArgs:Array;
+
+ private var _totalTime:Number;
+ private var _currentTime:Number;
+ private var _progress:Number;
+ private var _delay:Number;
+ private var _roundToInt:Boolean;
+ private var _nextTween:Tween;
+ private var _repeatCount:int;
+ private var _repeatDelay:Number;
+ private var _reverse:Boolean;
+ private var _currentCycle:int;
+
+ /** Creates a tween with a target, duration (in seconds) and a transition function.
+ * @param target the object that you want to animate
+ * @param time the duration of the Tween (in seconds)
+ * @param transition can be either a String (e.g. one of the constants defined in the
+ * Transitions class) or a function. Look up the 'Transitions' class for a
+ * documentation about the required function signature. */
+ public function Tween(target:Object, time:Number, transition:Object="linear")
+ {
+ reset(target, time, transition);
+ }
+
+ /** Resets the tween to its default values. Useful for pooling tweens. */
+ public function reset(target:Object, time:Number, transition:Object="linear"):Tween
+ {
+ _target = target;
+ _currentTime = 0.0;
+ _totalTime = Math.max(0.0001, time);
+ _progress = 0.0;
+ _delay = _repeatDelay = 0.0;
+ _onStart = _onUpdate = _onRepeat = _onComplete = null;
+ _onStartArgs = _onUpdateArgs = _onRepeatArgs = _onCompleteArgs = null;
+ _roundToInt = _reverse = false;
+ _repeatCount = 1;
+ _currentCycle = -1;
+ _nextTween = null;
+
+ if (transition is String)
+ this.transition = transition as String;
+ else if (transition is Function)
+ this.transitionFunc = transition as Function;
+ else
+ throw new ArgumentError("Transition must be either a string or a function");
+
+ if (_properties) _properties.length = 0; else _properties = new [];
+ if (_startValues) _startValues.length = 0; else _startValues = new [];
+ if (_endValues) _endValues.length = 0; else _endValues = new [];
+ if (_updateFuncs) _updateFuncs.length = 0; else _updateFuncs = new [];
+
+ return this;
+ }
+
+ /** Animates the property of the target to a certain value. You can call this method
+ * multiple times on one tween.
+ *
+ *
Some property types are handled in a special way:
+ *
+ *
If the property contains the string color or Color,
+ * it will be treated as an unsigned integer with a color value
+ * (e.g. 0xff0000 for red). Each color channel will be animated
+ * individually.
+ *
The same happens if you append the string #rgb to the name.
+ *
If you append #rad, the property is treated as an angle in radians,
+ * making sure it always uses the shortest possible arc for the rotation.
+ *
The string #deg does the same for angles in degrees.
+ *
+ */
+ public function animate(property:String, endValue:Number):void
+ {
+ if (_target == null) return; // tweening null just does nothing.
+
+ var pos:int = _properties.length;
+ var updateFunc:Function = getUpdateFuncFromProperty(property);
+
+ _properties[pos] = getPropertyName(property);
+ _startValues[pos] = Number.NaN;
+ _endValues[pos] = endValue;
+ _updateFuncs[pos] = updateFunc;
+ }
+
+ /** Animates the 'scaleX' and 'scaleY' properties of an object simultaneously. */
+ public function scaleTo(factor:Number):void
+ {
+ animate("scaleX", factor);
+ animate("scaleY", factor);
+ }
+
+ /** Animates the 'x' and 'y' properties of an object simultaneously. */
+ public function moveTo(x:Number, y:Number):void
+ {
+ animate("x", x);
+ animate("y", y);
+ }
+
+ /** Animates the 'alpha' property of an object to a certain target value. */
+ public function fadeTo(alpha:Number):void
+ {
+ animate("alpha", alpha);
+ }
+
+ /** Animates the 'rotation' property of an object to a certain target value, using the
+ * smallest possible arc. 'type' may be either 'rad' or 'deg', depending on the unit of
+ * measurement. */
+ public function rotateTo(angle:Number, type:String="rad"):void
+ {
+ animate("rotation#" + type, angle);
+ }
+
+ /** @inheritDoc */
+ public function advanceTime(time:Number):void
+ {
+ if (time == 0 || (_repeatCount == 1 && _currentTime == _totalTime)) return;
+
+ var i:int;
+ var previousTime:Number = _currentTime;
+ var restTime:Number = _totalTime - _currentTime;
+ var carryOverTime:Number = time > restTime ? time - restTime : 0.0;
+
+ _currentTime += time;
+
+ if (_currentTime <= 0)
+ return; // the delay is not over yet
+ else if (_currentTime > _totalTime)
+ _currentTime = _totalTime;
+
+ if (_currentCycle < 0 && previousTime <= 0 && _currentTime > 0)
+ {
+ _currentCycle++;
+ if (_onStart != null) _onStart.apply(this, _onStartArgs);
+ }
+
+ var ratio:Number = _currentTime / _totalTime;
+ var reversed:Boolean = _reverse && (_currentCycle % 2 == 1);
+ var numProperties:int = _startValues.length;
+ _progress = reversed ? _transitionFunc(1.0 - ratio) : _transitionFunc(ratio);
+
+ for (i=0; i= _totalTime)
+ {
+ if (_repeatCount == 0 || _repeatCount > 1)
+ {
+ _currentTime = -_repeatDelay;
+ _currentCycle++;
+ if (_repeatCount > 1) _repeatCount--;
+ if (_onRepeat != null) _onRepeat.apply(this, _onRepeatArgs);
+ }
+ else
+ {
+ // save callback & args: they might be changed through an event listener
+ var onComplete:Function = _onComplete;
+ var onCompleteArgs:Array = _onCompleteArgs;
+
+ // in the 'onComplete' callback, people might want to call "tween.reset" and
+ // add it to another juggler; so this event has to be dispatched *before*
+ // executing 'onComplete'.
+ dispatchEventWith(Event.REMOVE_FROM_JUGGLER);
+ if (onComplete != null) onComplete.apply(this, onCompleteArgs);
+ if (_currentTime == 0) carryOverTime = 0; // tween was reset
+ }
+ }
+
+ if (carryOverTime)
+ advanceTime(carryOverTime);
+ }
+
+ // animation hints
+
+ private function getUpdateFuncFromProperty(property:String):Function
+ {
+ var updateFunc:Function;
+ var hint:String = getPropertyHint(property);
+
+ switch (hint)
+ {
+ case null: updateFunc = updateStandard; break;
+ case "rgb": updateFunc = updateRgb; break;
+ case "rad": updateFunc = updateRad; break;
+ case "deg": updateFunc = updateDeg; break;
+ default:
+ trace("[Starling] Ignoring unknown property hint:", hint);
+ updateFunc = updateStandard;
+ }
+
+ return updateFunc;
+ }
+
+ /** @private */
+ internal static function getPropertyHint(property:String):String
+ {
+ // colorization is special; it does not require a hint marker, just the word 'color'.
+ if (property.indexOf("color") != -1 || property.indexOf("Color") != -1)
+ return "rgb";
+
+ var hintMarkerIndex:int = property.indexOf(HINT_MARKER);
+ if (hintMarkerIndex != -1) return property.substr(hintMarkerIndex+1);
+ else return null;
+ }
+
+ /** @private */
+ internal static function getPropertyName(property:String):String
+ {
+ var hintMarkerIndex:int = property.indexOf(HINT_MARKER);
+ if (hintMarkerIndex != -1) return property.substring(0, hintMarkerIndex);
+ else return property;
+ }
+
+ private function updateStandard(property:String, startValue:Number, endValue:Number):void
+ {
+ var newValue:Number = startValue + _progress * (endValue - startValue);
+ if (_roundToInt) newValue = Math.round(newValue);
+ _target[property] = newValue;
+ }
+
+ private function updateRgb(property:String, startValue:Number, endValue:Number):void
+ {
+ _target[property] = Color.interpolate(uint(startValue), uint(endValue), _progress);
+ }
+
+ private function updateRad(property:String, startValue:Number, endValue:Number):void
+ {
+ updateAngle(Math.PI, property, startValue, endValue);
+ }
+
+ private function updateDeg(property:String, startValue:Number, endValue:Number):void
+ {
+ updateAngle(180, property, startValue, endValue);
+ }
+
+ private function updateAngle(pi:Number, property:String, startValue:Number, endValue:Number):void
+ {
+ while (Math.abs(endValue - startValue) > pi)
+ {
+ if (startValue < endValue) endValue -= 2.0 * pi;
+ else endValue += 2.0 * pi;
+ }
+
+ updateStandard(property, startValue, endValue);
+ }
+
+ /** The end value a certain property is animated to. Throws an ArgumentError if the
+ * property is not being animated. */
+ public function getEndValue(property:String):Number
+ {
+ var index:int = _properties.indexOf(property);
+ if (index == -1) throw new ArgumentError("The property '" + property + "' is not animated");
+ else return _endValues[index] as Number;
+ }
+
+ /** Indicates if the tween is finished. */
+ public function get isComplete():Boolean
+ {
+ return _currentTime >= _totalTime && _repeatCount == 1;
+ }
+
+ /** The target object that is animated. */
+ public function get target():Object { return _target; }
+
+ /** The transition method used for the animation. @see Transitions */
+ public function get transition():String { return _transitionName; }
+ public function set transition(value:String):void
+ {
+ _transitionName = value;
+ _transitionFunc = Transitions.getTransition(value);
+
+ if (_transitionFunc == null)
+ throw new ArgumentError("Invalid transiton: " + value);
+ }
+
+ /** The actual transition function used for the animation. */
+ public function get transitionFunc():Function { return _transitionFunc; }
+ public function set transitionFunc(value:Function):void
+ {
+ _transitionName = "custom";
+ _transitionFunc = value;
+ }
+
+ /** The total time the tween will take per repetition (in seconds). */
+ public function get totalTime():Number { return _totalTime; }
+
+ /** The time that has passed since the tween was created (in seconds). */
+ public function get currentTime():Number { return _currentTime; }
+
+ /** The current progress between 0 and 1, as calculated by the transition function. */
+ public function get progress():Number { return _progress; }
+
+ /** The delay before the tween is started (in seconds). @default 0 */
+ public function get delay():Number { return _delay; }
+ public function set delay(value:Number):void
+ {
+ _currentTime = _currentTime + _delay - value;
+ _delay = value;
+ }
+
+ /** The number of times the tween will be executed.
+ * Set to '0' to tween indefinitely. @default 1 */
+ public function get repeatCount():int { return _repeatCount; }
+ public function set repeatCount(value:int):void { _repeatCount = value; }
+
+ /** The amount of time to wait between repeat cycles (in seconds). @default 0 */
+ public function get repeatDelay():Number { return _repeatDelay; }
+ public function set repeatDelay(value:Number):void { _repeatDelay = value; }
+
+ /** Indicates if the tween should be reversed when it is repeating. If enabled,
+ * every second repetition will be reversed. @default false */
+ public function get reverse():Boolean { return _reverse; }
+ public function set reverse(value:Boolean):void { _reverse = value; }
+
+ /** Indicates if the numeric values should be cast to Integers. @default false */
+ public function get roundToInt():Boolean { return _roundToInt; }
+ public function set roundToInt(value:Boolean):void { _roundToInt = value; }
+
+ /** A function that will be called when the tween starts (after a possible delay). */
+ public function get onStart():Function { return _onStart; }
+ public function set onStart(value:Function):void { _onStart = value; }
+
+ /** A function that will be called each time the tween is advanced. */
+ public function get onUpdate():Function { return _onUpdate; }
+ public function set onUpdate(value:Function):void { _onUpdate = value; }
+
+ /** A function that will be called each time the tween finishes one repetition
+ * (except the last, which will trigger 'onComplete'). */
+ public function get onRepeat():Function { return _onRepeat; }
+ public function set onRepeat(value:Function):void { _onRepeat = value; }
+
+ /** A function that will be called when the tween is complete. */
+ public function get onComplete():Function { return _onComplete; }
+ public function set onComplete(value:Function):void { _onComplete = value; }
+
+ /** The arguments that will be passed to the 'onStart' function. */
+ public function get onStartArgs():Array { return _onStartArgs; }
+ public function set onStartArgs(value:Array):void { _onStartArgs = value; }
+
+ /** The arguments that will be passed to the 'onUpdate' function. */
+ public function get onUpdateArgs():Array { return _onUpdateArgs; }
+ public function set onUpdateArgs(value:Array):void { _onUpdateArgs = value; }
+
+ /** The arguments that will be passed to the 'onRepeat' function. */
+ public function get onRepeatArgs():Array { return _onRepeatArgs; }
+ public function set onRepeatArgs(value:Array):void { _onRepeatArgs = value; }
+
+ /** The arguments that will be passed to the 'onComplete' function. */
+ public function get onCompleteArgs():Array { return _onCompleteArgs; }
+ public function set onCompleteArgs(value:Array):void { _onCompleteArgs = value; }
+
+ /** Another tween that will be started (i.e. added to the same juggler) as soon as
+ * this tween is completed. */
+ public function get nextTween():Tween { return _nextTween; }
+ public function set nextTween(value:Tween):void { _nextTween = value; }
+
+ // tween pooling
+
+ private static var sTweenPool:Vector. = new [];
+
+ /** @private */
+ starling_internal static function fromPool(target:Object, time:Number,
+ transition:Object="linear"):Tween
+ {
+ if (sTweenPool.length) return sTweenPool.pop().reset(target, time, transition);
+ else return new Tween(target, time, transition);
+ }
+
+ /** @private */
+ starling_internal static function toPool(tween:Tween):void
+ {
+ // reset any object-references, to make sure we don't prevent any garbage collection
+ tween._onStart = tween._onUpdate = tween._onRepeat = tween._onComplete = null;
+ tween._onStartArgs = tween._onUpdateArgs = tween._onRepeatArgs = tween._onCompleteArgs = null;
+ tween._target = null;
+ tween._transitionFunc = null;
+ tween.removeEventListeners();
+ sTweenPool.push(tween);
+ }
+ }
+}
diff --git a/mobile_version/src/starling/assets/AssetFactory.as b/mobile_version/src/starling/assets/AssetFactory.as
new file mode 100644
index 00000000..01cfeecc
--- /dev/null
+++ b/mobile_version/src/starling/assets/AssetFactory.as
@@ -0,0 +1,122 @@
+package starling.assets
+{
+ import flash.system.Capabilities;
+ import flash.utils.ByteArray;
+ import flash.utils.getQualifiedClassName;
+
+ import starling.errors.AbstractClassError;
+
+ /** An AssetFactory is responsible for creating a concrete instance of an asset.
+ *
+ *
The AssetManager contains a list of AssetFactories, registered via 'registerFactory'.
+ * When the asset queue is processed, each factory (sorted by priority) will be asked if it
+ * can handle a certain AssetReference (via the 'canHandle') method. If it can, the 'create'
+ * method will be called, which is responsible for creating at least one asset.
+ *
+ *
By extending 'AssetFactory' and registering your class at the AssetManager, you can
+ * customize how assets are being created and even add new types of assets.
+ */
+ public class AssetFactory
+ {
+ private var _priority:int;
+ private var _mimeTypes:Vector.;
+ private var _extensions:Vector.;
+
+ /** Creates a new instance. */
+ public function AssetFactory()
+ {
+ if (Capabilities.isDebugger &&
+ getQualifiedClassName(this) == "starling.assets::AssetFactory")
+ {
+ throw new AbstractClassError();
+ }
+
+ _mimeTypes = new [];
+ _extensions = new [];
+ }
+
+ /** Returns 'true' if this factory can handle the given reference. The default
+ * implementation checks if extension and/or mime type of the reference match those
+ * of the factory. */
+ public function canHandle(reference:AssetReference):Boolean
+ {
+ var mimeType:String = reference.mimeType;
+ var extension:String = reference.extension;
+
+ return reference.data is ByteArray && (
+ (mimeType && _mimeTypes.indexOf(reference.mimeType.toLowerCase()) != -1) ||
+ (extension && _extensions.indexOf(reference.extension.toLowerCase()) != -1));
+ }
+
+ /** This method will only be called if 'canHandle' returned 'true' for the given reference.
+ * It's responsible for creating at least one concrete asset and passing it to 'onComplete'.
+ *
+ * @param reference The asset to be created. If a local or remote URL is referenced,
+ * it will already have been loaded, and 'data' will contain a ByteArray.
+ * @param helper Contains useful utility methods to be used by the factory. Look
+ * at the class documentation for more information.
+ * @param onComplete To be called when loading is successful. 'type' parameter is optional.
+ *
+ * @param onError To be called when creation fails for some reason. Do not call
+ * 'onComplete' when that happens.
function(error:String):void
+ */
+ public function create(reference:AssetReference, helper:AssetFactoryHelper,
+ onComplete:Function, onError:Function):void
+ {
+ // to be implemented by subclasses
+ }
+
+ /** Add one or more mime types that identify the supported data types. Used by
+ * 'canHandle' to figure out if the factory is suitable for an asset reference. */
+ public function addMimeTypes(...args):void
+ {
+ for each (var mimeType:String in args)
+ {
+ mimeType = mimeType.toLowerCase();
+
+ if (_mimeTypes.indexOf(mimeType) == -1)
+ _mimeTypes[_mimeTypes.length] = mimeType;
+ }
+ }
+
+ /** Add one or more file extensions (without leading dot) that identify the supported data
+ * types. Used by 'canHandle' to figure out if the factory is suitable for an asset
+ * reference. */
+ public function addExtensions(...args):void
+ {
+ for each (var extension:String in args)
+ {
+ extension = extension.toLowerCase();
+
+ if (_extensions.indexOf(extension) == -1)
+ _extensions[_extensions.length] = extension;
+ }
+ }
+
+ /** Returns the mime types this factory supports. */
+ public function getMimeTypes(out:Vector.=null):Vector.
+ {
+ out ||= new Vector.();
+
+ for (var i:int=0; i<_mimeTypes.length; ++i)
+ out[i] = _mimeTypes[i];
+
+ return out;
+ }
+
+ /** Returns the file extensions this factory supports. */
+ public function getExtensions(out:Vector.=null):Vector.
+ {
+ out ||= new Vector.();
+
+ for (var i:int=0; i<_extensions.length; ++i)
+ out[i] = _extensions[i];
+
+ return out;
+ }
+
+ /** @private */
+ internal function get priority():int { return _priority; }
+ internal function set priority(value:int):void { _priority = value; }
+ }
+}
diff --git a/mobile_version/src/starling/assets/AssetFactoryHelper.as b/mobile_version/src/starling/assets/AssetFactoryHelper.as
new file mode 100644
index 00000000..6c8b57ea
--- /dev/null
+++ b/mobile_version/src/starling/assets/AssetFactoryHelper.as
@@ -0,0 +1,124 @@
+package starling.assets
+{
+ import starling.utils.SystemUtil;
+
+ /** A helper class that's passed to an AssetFactory's "create" method. */
+ public class AssetFactoryHelper
+ {
+ private var _dataLoader:DataLoader;
+ private var _getNameFromUrlFunc:Function;
+ private var _getExtensionFromUrlFunc:Function;
+ private var _addPostProcessorFunc:Function;
+ private var _addAssetFunc:Function;
+ private var _onRestoreFunc:Function;
+ private var _logFunc:Function;
+
+ /** @private */
+ public function AssetFactoryHelper()
+ { }
+
+ /** Forwarded to the AssetManager's method with the same name. */
+ public function getNameFromUrl(url:String):String
+ {
+ if (_getNameFromUrlFunc != null) return _getNameFromUrlFunc(url);
+ else return "";
+ }
+
+ /** Forwarded to the AssetManager's method with the same name. */
+ public function getExtensionFromUrl(url:String):String
+ {
+ if (_getExtensionFromUrlFunc != null) return _getExtensionFromUrlFunc(url);
+ else return "";
+ }
+
+ /** Accesses a URL (local or remote) and passes the loaded ByteArray to the
+ * 'onComplete' callback - or executes 'onError' when the data can't be loaded.
+ *
+ * @param url a string containing an URL.
+ * @param onComplete function(data:ByteArray, mimeType:String):void;
+ * @param onError function(error:String):void;
+ */
+ public function loadDataFromUrl(url:String, onComplete:Function, onError:Function):void
+ {
+ if (_dataLoader) _dataLoader.load(url, onComplete, onError);
+ }
+
+ /** Adds a method to be called by the AssetManager when the queue has finished processing.
+ * Useful e.g. if assets depend on other assets (like an atlas XML depending on the atlas
+ * texture).
+ *
+ * @param processor function(manager:AssetManager):void;
+ * @param priority Processors with a higher priority will be called first.
+ * The default processor for texture atlases is called with a
+ * priority of '100', others with '0'.
+ */
+ public function addPostProcessor(processor:Function, priority:int=0):void
+ {
+ if (_addPostProcessorFunc != null) _addPostProcessorFunc(processor, priority);
+ }
+
+ /** Textures are required to call this method when they begin their restoration process
+ * after a context loss. */
+ public function onBeginRestore():void
+ {
+ if (_onRestoreFunc != null) _onRestoreFunc(false);
+ }
+
+ /** Textures are required to call this method when they have finished their restoration
+ * process after a context loss. */
+ public function onEndRestore():void
+ {
+ if (_onRestoreFunc != null) _onRestoreFunc(true);
+ }
+
+ /** Forwarded to the AssetManager's method with the same name. */
+ public function log(message:String):void
+ {
+ if (_logFunc != null) _logFunc(message);
+ }
+
+ /** Adds additional assets to the AssetManager. To be called when the factory
+ * creates more than one asset. */
+ public function addComplementaryAsset(name:String, asset:Object, type:String=null):void
+ {
+ if (_addAssetFunc != null) _addAssetFunc(name, asset, type);
+ }
+
+ /** Delay the execution of 'call' until it's allowed. (On mobile, the context
+ * may not be accessed while the application is in the background.)
+ */
+ public function executeWhenContextReady(call:Function, ...args):void
+ {
+ // On mobile, it is not allowed / endorsed to make stage3D calls while the app
+ // is in the background. Thus, we pause execution if that's the case.
+
+ if (SystemUtil.isDesktop) call.apply(this, args);
+ else
+ {
+ args.unshift(call);
+ SystemUtil.executeWhenApplicationIsActive.apply(this, args);
+ }
+ }
+
+ /** @private */
+ internal function set getNameFromUrlFunc(value:Function):void { _getNameFromUrlFunc = value; }
+
+ /** @private */
+ internal function set getExtensionFromUrlFunc(value:Function):void { _getExtensionFromUrlFunc = value; }
+
+ /** @private */
+ internal function set dataLoader(value:DataLoader):void { _dataLoader = value; }
+
+ /** @private */
+ internal function set logFunc(value:Function):void { _logFunc = value; }
+
+ /** @private */
+ internal function set addAssetFunc(value:Function):void { _addAssetFunc = value; }
+
+ /** @private */
+ internal function set onRestoreFunc(value:Function):void { _onRestoreFunc = value; }
+
+ /** @private */
+ internal function set addPostProcessorFunc(value:Function):void { _addPostProcessorFunc = value; }
+ }
+}
diff --git a/mobile_version/src/starling/assets/AssetManager.as b/mobile_version/src/starling/assets/AssetManager.as
new file mode 100644
index 00000000..44541910
--- /dev/null
+++ b/mobile_version/src/starling/assets/AssetManager.as
@@ -0,0 +1,1034 @@
+package starling.assets
+{
+ import flash.media.Sound;
+ import flash.media.SoundChannel;
+ import flash.media.SoundTransform;
+ import flash.net.URLRequest;
+ import flash.system.System;
+ import flash.utils.ByteArray;
+ import flash.utils.Dictionary;
+ import flash.utils.describeType;
+ import flash.utils.getQualifiedClassName;
+ import flash.utils.setTimeout;
+
+ import starling.core.Starling;
+ import starling.events.Event;
+ import starling.events.EventDispatcher;
+ import starling.text.BitmapFont;
+ import starling.textures.Texture;
+ import starling.textures.TextureAtlas;
+ import starling.textures.TextureOptions;
+ import starling.utils.MathUtil;
+ import starling.utils.execute;
+
+ /** Dispatched when all textures have been restored after a context loss. */
+ [Event(name="texturesRestored", type="starling.events.Event")]
+
+ /** The AssetManager handles loading and accessing a variety of asset types. You can
+ * add assets directly (via the 'add...' methods) or asynchronously via a queue. This allows
+ * you to deal with assets in a unified way, no matter if they are loaded from a file,
+ * directory, URL, or from an embedded object.
+ *
+ *
The class can deal with the following media types:
+ *
+ *
Textures (either from Bitmaps or ATF data)
+ *
Texture atlases
+ *
Bitmap Fonts
+ *
Sounds
+ *
XML data
+ *
JSON data
+ *
ByteArrays
+ *
other AssetManagers
+ *
+ *
+ *
+ *
For more information on how to add assets from different sources, read the documentation
+ * of the "enqueue()" method.
+ *
+ * Context Loss
+ *
+ *
When the stage3D context is lost, the AssetManager will automatically restore all
+ * loaded textures. To save memory, it will get them from their original sources. Since
+ * this is done asynchronously, your images might not reappear all at once, but during
+ * a time frame of several seconds. If you want, you can pause your game during that time;
+ * the AssetManager dispatches an "Event.TEXTURES_RESTORED" event when all textures have
+ * been restored.
+ *
+ * Error Handling
+ *
+ *
Loading of some assets may fail while the queue is being processed. In that case, the
+ * AssetManager will call the 'onError' callback that you can optional provide to the
+ * 'loadQueue' method. Queue processing will continue after an error, so it's always
+ * guaranteed that the 'onComplete' callback is executed, too.
+ *
+ * Texture Properties
+ *
+ *
When you enqueue a texture, its properties for "format", "scale", "mipMapping", and
+ * "repeat" will reflect the settings of the AssetManager at the time they were enqueued.
+ * This means that you can enqueue a bunch of textures, then change the settings and enqueue
+ * some more. Like this:
When you enqueue one or more AssetManagers to another one, the "loadQueue" method will
+ * load the assets of the "child" AssetManager, as well. Later, when accessing assets,
+ * the "parent" AssetManager will return the "child" assets as well - just like it returns,
+ * say, the SubTextures from a contained TextureAtlas.
+ *
+ *
The main advantage of grouping your assets like this is something else, though: it
+ * allows to remove (and dispose) a complete group of assets in one step. The example
+ * below loads the assets from two directories. When the contents of one of them are no
+ * longer needed, all its assets are removed together.
+ *
+ *
+ * var manager:AssetManager = new AssetManager();
+ * var appDir:File = File.applicationDirectory;
+ *
+ * var redAssets:AssetManager = new AssetManager();
+ * redAssets.enqueueSingle(appDir.resolvePath("textures/red/"));
+ *
+ * var greenAssets:AssetManager = new AssetManager();
+ * greenAssets.enqueueSingle(appDir.resolvePath("textures/green/"));
+ *
+ * manager.enqueueSingle(redAssets, "redAssets");
+ * manager.enqueueSingle(greenAssets, "greenAssets");
+ * manager.loadQueue(...); // loads both "red" and "green" assets
+ *
+ * // ... later, remove all "red" assets together
+ * manager.removeAssetManager("redAssets");
+ *
+ * Customization
+ *
+ *
You can customize how assets are created by extending the 'AssetFactory' class and
+ * registering an instance of your new class at the AssetManager via 'registerFactory'.
+ * Factories are probed by priority; any factory with a priority > 0 will be executed
+ * before the built-in factories.
+ *
+ *
An asset type is identified by a unique String. You can add your own asset types
+ * by creating a custom 'AssetFactory' and having it add the asset with custom string
+ * identifier.
+ *
+ *
By overriding the methods 'getNameFromUrl', 'getExtensionFromUrl', 'disposeAsset',
+ * and 'log', you can customize how assets are named and disposed, and you can forward
+ * any logging to an external logger. To customize the way data is loaded from URLs or
+ * files, you can assign a custom 'DataLoader' instance to the AssetManager.
+ *
+ * @see starling.assets.AssetFactory
+ * @see starling.assets.AssetType
+ * @see starling.assets.DataLoader
+ */
+ public class AssetManager extends EventDispatcher
+ {
+ private var _starling:Starling;
+ private var _assets:Dictionary;
+ private var _verbose:Boolean;
+ private var _numConnections:int;
+ private var _dataLoader:DataLoader;
+ private var _textureOptions:TextureOptions;
+ private var _queue:Vector.;
+ private var _registerBitmapFontsWithFontFace:Boolean;
+ private var _assetFactories:Vector.;
+ private var _numRestoredTextures:int;
+ private var _numLostTextures:int;
+
+ // Regex for name / extension extraction from URLs.
+ private static const NAME_REGEX:RegExp = /(([^?\/\\]+?)(?:\.([\w\-]+))?)(?:\?.*)?$/;
+
+ // fallback for unnamed assets
+ private static const NO_NAME:String = "unnamed";
+ private static var sNoNameCount:int = 0;
+
+ // helper objects
+ private static var sNames:Vector. = new [];
+
+ /** Create a new instance with the given scale factor. */
+ public function AssetManager(scaleFactor:Number=1)
+ {
+ _assets = new Dictionary();
+ _verbose = true;
+ _textureOptions = new TextureOptions(scaleFactor);
+ _queue = new [];
+ _numConnections = 3;
+ _dataLoader = new DataLoader();
+ _assetFactories = new [];
+
+ registerFactory(new BitmapTextureFactory());
+ registerFactory(new AtfTextureFactory());
+ registerFactory(new SoundFactory());
+ registerFactory(new JsonFactory());
+ registerFactory(new XmlFactory());
+ registerFactory(new ByteArrayFactory(), -100);
+ }
+
+ /** Disposes all assets and purges the queue.
+ *
+ *
Beware that all references to the assets will remain intact, even though the assets
+ * are no longer valid. Call 'purge' if you want to remove all resources and reuse
+ * the AssetManager later.
+ */
+ public function dispose():void
+ {
+ purgeQueue();
+
+ for each (var store:Dictionary in _assets)
+ for each (var asset:Object in store)
+ disposeAsset(asset);
+ }
+
+ /** Removes assets of all types (disposing them along the way), empties the queue and
+ * aborts any pending load operations. */
+ public function purge():void
+ {
+ log("Purging all assets, emptying queue");
+
+ purgeQueue();
+ dispose();
+
+ _assets = new Dictionary();
+ }
+
+ // queue processing
+
+ /** Enqueues one or more raw assets; they will only be available after successfully
+ * executing the "loadQueue" method. This method accepts a variety of different objects:
+ *
+ *
+ *
Strings or URLRequests containing an URL to a local or remote resource. Supported
+ * types: png, jpg, gif, atf, mp3, xml, fnt, json, binary.
+ *
Instances of the File class (AIR only) pointing to a directory or a file.
+ * Directories will be scanned recursively for all supported types.
+ *
Classes that contain static embedded assets.
+ *
If the file extension is not recognized, the data is analyzed to see if
+ * contains XML or JSON data. If it's neither, it is stored as ByteArray.
+ *
+ *
+ *
Suitable object names are extracted automatically: A file named "image.png" will be
+ * accessible under the name "image". When enqueuing embedded assets via a class,
+ * the variable name of the embedded object will be used as its name. An exception
+ * are texture atlases: they will have the same name as the actual texture they are
+ * referencing.
+ *
+ *
XMLs are made available via "getXml()"; this includes XMLs containing texture
+ * atlases or bitmap fonts, which are processed along the way. Bitmap fonts are also
+ * registered at the TextField class.
+ *
+ *
If you pass in JSON data, it will be parsed into an object and will be available via
+ * "getObject()".
+ */
+ public function enqueue(...assets):void
+ {
+ for each (var asset:Object in assets)
+ {
+ if (asset is Array)
+ {
+ enqueue.apply(this, asset);
+ }
+ else if (asset is Class)
+ {
+ var typeXml:XML = describeType(asset);
+ var childNode:XML;
+
+ if (_verbose)
+ log("Looking for static embedded assets in '" +
+ (typeXml.@name).split("::").pop() + "'");
+
+ for each (childNode in typeXml.constant.(@type == "Class"))
+ enqueueSingle(asset[childNode.@name], childNode.@name);
+
+ for each (childNode in typeXml.variable.(@type == "Class"))
+ enqueueSingle(asset[childNode.@name], childNode.@name);
+ }
+ else if (getQualifiedClassName(asset) == "flash.filesystem::File")
+ {
+ if (!asset["exists"])
+ {
+ log("File or directory not found: '" + asset["url"] + "'");
+ }
+ else if (!asset["isHidden"])
+ {
+ if (asset["isDirectory"])
+ enqueue.apply(this, asset["getDirectoryListing"]());
+ else
+ enqueueSingle(asset);
+ }
+ }
+ else if (asset is String || asset is URLRequest || asset is AssetManager)
+ {
+ enqueueSingle(asset);
+ }
+ else
+ {
+ log("Ignoring unsupported asset type: " + getQualifiedClassName(asset));
+ }
+ }
+ }
+
+ /** Enqueues a single asset with a custom name that can be used to access it later.
+ * If the asset is a texture, you can also add custom texture options.
+ *
+ * @param asset The asset that will be enqueued; accepts the same objects as the
+ * 'enqueue' method.
+ * @param name The name under which the asset will be found later. If you pass null or
+ * omit the parameter, it's attempted to generate a name automatically.
+ * @param options Custom options that will be used if 'asset' points to texture data.
+ * @return the name with which the asset was registered.
+ */
+ public function enqueueSingle(asset:Object, name:String=null,
+ options:TextureOptions=null):String
+ {
+ if (asset is Class)
+ asset = new asset();
+
+ var assetReference:AssetReference = new AssetReference(asset);
+ assetReference.name = name || getNameFromUrl(assetReference.url) || getUniqueName();
+ assetReference.extension = getExtensionFromUrl(assetReference.url);
+ assetReference.textureOptions = options || _textureOptions;
+ var logName:String = getFilenameFromUrl(assetReference.url) || assetReference.name;
+
+ _queue.push(assetReference);
+ log("Enqueuing '" + logName + "'");
+ return assetReference.name;
+ }
+
+ /** Removes the asset(s) with the given name(s) from the queue. Note that this won't work
+ * after loading has started, even if these specific assets have not yet been processed. */
+ public function dequeue(...assetNames):void
+ {
+ _queue = _queue.filter(function(asset:AssetReference, i:int, v:*):Boolean
+ {
+ return assetNames.indexOf(asset.name) == -1;
+ });
+ }
+
+ /** Empties the queue and aborts any pending load operations. */
+ public function purgeQueue():void
+ {
+ _queue.length = 0;
+ _dataLoader.close();
+ dispatchEventWith(Event.CANCEL);
+ }
+
+ /** Loads all enqueued assets asynchronously. The 'onComplete' callback will be executed
+ * once all assets have been loaded - even when there have been errors, which are
+ * forwarded to the optional 'onError' callback. The 'onProgress' function will be called
+ * with a 'ratio' between '0.0' and '1.0' and is also optional. Furthermore, all
+ * parameters of all the callbacks are optional.
+ *
+ *
When you call this method, the manager will save a reference to "Starling.current";
+ * all textures that are loaded will be accessible only from within this instance. Thus,
+ * if you are working with more than one Starling instance, be sure to call
+ * "makeCurrent()" on the appropriate instance before processing the queue.
+ *
+ * @param onComplete function(manager:AssetManager):void;
+ * @param onError function(error:String, asset:AssetReference):void;
+ * @param onProgress function(ratio:Number):void;
+ */
+ public function loadQueue(onComplete:Function,
+ onError:Function=null, onProgress:Function=null):void
+ {
+ if (_queue.length == 0)
+ {
+ finish();
+ return;
+ }
+
+ // By using an event listener, we can make a call to "cancel" affect
+ // only the currently active loading process(es).
+ addEventListener(Event.CANCEL, onCanceled);
+
+ var factoryHelper:AssetFactoryHelper = new AssetFactoryHelper();
+ factoryHelper.getNameFromUrlFunc = getNameFromUrl;
+ factoryHelper.getExtensionFromUrlFunc = getExtensionFromUrl;
+ factoryHelper.addPostProcessorFunc = addPostProcessor;
+ factoryHelper.addAssetFunc = addAsset;
+ factoryHelper.onRestoreFunc = onAssetRestored;
+ factoryHelper.dataLoader = _dataLoader;
+ factoryHelper.logFunc = log;
+
+ var i:int;
+ var self:AssetManager = this;
+ var canceled:Boolean = false;
+ var queue:Vector. = _queue.concat();
+ var numAssets:int = queue.length;
+ var numComplete:int = 0;
+ var numConnections:int = MathUtil.min(_numConnections, numAssets);
+ var assetProgress:Vector. = new Vector.(numAssets, true);
+ var postProcessors:Vector. = new [];
+
+ _starling = Starling.current;
+ _queue.length = 0;
+
+ for (i=0; i, progressRatios:Vector., index:int,
+ helper:AssetFactoryHelper, onComplete:Function, onProgress:Function,
+ onError:Function, onIntermediateError:Function):void
+ {
+ var referenceCount:int = queue.length;
+ var reference:AssetReference = queue[index];
+ progressRatios[index] = 0;
+
+ if (reference.url)
+ _dataLoader.load(reference.url, onLoadComplete, onLoadError, onLoadProgress);
+ else if (reference.data is AssetManager)
+ (reference.data as AssetManager).loadQueue(onManagerComplete, onIntermediateError, onLoadProgress);
+ else
+ setTimeout(onLoadComplete, 1, reference.data);
+
+ function onLoadComplete(data:Object, mimeType:String=null,
+ name:String=null, extension:String=null):void
+ {
+ if (_starling) _starling.makeCurrent();
+
+ onLoadProgress(1.0);
+
+ if (data) reference.data = data;
+ if (name) reference.name = name;
+ if (extension) reference.extension = extension;
+ if (mimeType) reference.mimeType = mimeType;
+
+ var assetFactory:AssetFactory = getFactoryFor(reference);
+ if (assetFactory == null)
+ execute(onAnyError, "Warning: no suitable factory found for '" + reference.name + "'");
+ else
+ assetFactory.create(reference, helper, onComplete, onFactoryError);
+ }
+
+ function onLoadProgress(ratio:Number):void
+ {
+ progressRatios[index] = ratio;
+
+ var totalRatio:Number = 0;
+ var multiplier:Number = 1.0 / referenceCount;
+
+ for (var k:int=0; k 0) totalRatio += multiplier * r;
+ }
+
+ execute(onProgress, MathUtil.min(totalRatio, 1.0));
+ }
+
+ function onLoadError(error:String):void
+ {
+ onLoadProgress(1.0);
+ execute(onAnyError, "Error loading " + reference.name + ": " + error);
+ }
+
+ function onAnyError(error:String):void
+ {
+ log(error);
+ execute(onError, error, reference);
+ }
+
+ function onFactoryError(error:String):void
+ {
+ execute(onAnyError, "Error creating " + reference.name + ": " + error);
+ }
+
+ function onManagerComplete():void
+ {
+ onComplete(reference.name, reference.data);
+ }
+ }
+
+ private function getFactoryFor(asset:AssetReference):AssetFactory
+ {
+ var numFactories:int = _assetFactories.length;
+ for (var i:int=0; iBeware: if the slot (name + type) was already taken, the existing object will be
+ * disposed and replaced by the new one.
+ *
+ * @param name The name with which the asset can be retrieved later. Must be
+ * unique within this asset type.
+ * @param asset The actual asset to add (e.g. a texture, a sound, etc).
+ * @param type The type of the asset. If omitted, the type will be determined
+ * automatically (which works for all standard types defined within
+ * the 'AssetType' class).
+ */
+ public function addAsset(name:String, asset:Object, type:String=null):void
+ {
+ type ||= AssetType.fromAsset(asset);
+
+ var store:Dictionary = _assets[type];
+ if (store == null)
+ {
+ store = new Dictionary();
+ _assets[type] = store;
+ }
+
+ log("Adding " + type + " '" + name + "'");
+
+ var prevAsset:Object = store[name];
+ if (prevAsset && prevAsset != asset)
+ {
+ log("Warning: name was already in use; disposing the previous " + type);
+ disposeAsset(prevAsset);
+ }
+
+ store[name] = asset;
+ }
+
+ /** Retrieves an asset of the given type, with the given name. If 'recursive' is true,
+ * the method will traverse included texture atlases and asset managers.
+ *
+ *
Typically, you will use one of the type-safe convenience methods instead, like
+ * 'getTexture', 'getSound', etc.
+ */
+ public function getAsset(type:String, name:String, recursive:Boolean=true):Object
+ {
+ if (recursive)
+ {
+ var managerStore:Dictionary = _assets[AssetType.ASSET_MANAGER];
+ if (managerStore)
+ {
+ for each (var manager:AssetManager in managerStore)
+ {
+ var asset:Object = manager.getAsset(type, name, true);
+ if (asset) return asset;
+ }
+ }
+
+ if (type == AssetType.TEXTURE)
+ {
+ var atlasStore:Dictionary = _assets[AssetType.TEXTURE_ATLAS];
+ if (atlasStore)
+ {
+ for each (var atlas:TextureAtlas in atlasStore)
+ {
+ var texture:Texture = atlas.getTexture(name);
+ if (texture) return texture;
+ }
+ }
+ }
+ }
+
+ var store:Dictionary = _assets[type];
+ if (store) return store[name];
+ else return null;
+ }
+
+ /** Retrieves an alphabetically sorted list of all assets that have the given type and
+ * start with the given prefix. If 'recursive' is true, the method will traverse included
+ * texture atlases and asset managers. */
+ public function getAssetNames(assetType:String, prefix:String="", recursive:Boolean=true,
+ out:Vector.=null):Vector.
+ {
+ out ||= new Vector.();
+
+ if (recursive)
+ {
+ var managerStore:Dictionary = _assets[AssetType.ASSET_MANAGER];
+ if (managerStore)
+ {
+ for each (var manager:AssetManager in managerStore)
+ manager.getAssetNames(assetType, prefix, true, out);
+ }
+
+ if (assetType == AssetType.TEXTURE)
+ {
+ var atlasStore:Dictionary = _assets[AssetType.TEXTURE_ATLAS];
+ if (atlasStore)
+ {
+ for each (var atlas:TextureAtlas in atlasStore)
+ atlas.getNames(prefix, out);
+ }
+ }
+ }
+
+ getDictionaryKeys(_assets[assetType], prefix, out);
+ out.sort(Array.CASEINSENSITIVE);
+ return out;
+ }
+
+ /** Removes the asset with the given name and type, and will optionally dispose it. */
+ public function removeAsset(assetType:String, name:String, dispose:Boolean=true):void
+ {
+ var store:Dictionary = _assets[assetType];
+ if (store)
+ {
+ var asset:Object = store[name];
+ if (asset)
+ {
+ log("Removing " + assetType + " '" + name + "'");
+ if (dispose) disposeAsset(asset);
+ delete store[name];
+ }
+ }
+ }
+
+ // convenience access methods
+
+ /** Returns a texture with a certain name. Includes textures stored inside atlases. */
+ public function getTexture(name:String):Texture
+ {
+ return getAsset(AssetType.TEXTURE, name) as Texture;
+ }
+
+ /** Returns all textures that start with a certain string, sorted alphabetically
+ * (especially useful for "MovieClip"). Includes textures stored inside atlases. */
+ public function getTextures(prefix:String="", out:Vector.=null):Vector.
+ {
+ if (out == null) out = new [];
+
+ for each (var name:String in getTextureNames(prefix, sNames))
+ out[out.length] = getTexture(name); // avoid 'push'
+
+ sNames.length = 0;
+ return out;
+ }
+
+ /** Returns all texture names that start with a certain string, sorted alphabetically.
+ * Includes textures stored inside atlases. */
+ public function getTextureNames(prefix:String="", out:Vector.=null):Vector.
+ {
+ return getAssetNames(AssetType.TEXTURE, prefix, true, out);
+ }
+
+ /** Returns a texture atlas with a certain name, or null if it's not found. */
+ public function getTextureAtlas(name:String):TextureAtlas
+ {
+ return getAsset(AssetType.TEXTURE_ATLAS, name) as TextureAtlas;
+ }
+
+ /** Returns all texture atlas names that start with a certain string, sorted alphabetically.
+ * If you pass an out-vector, the names will be added to that vector. */
+ public function getTextureAtlasNames(prefix:String="", out:Vector.=null):Vector.
+ {
+ return getAssetNames(AssetType.TEXTURE_ATLAS, prefix, true, out);
+ }
+
+ /** Returns a sound with a certain name, or null if it's not found. */
+ public function getSound(name:String):Sound
+ {
+ return getAsset(AssetType.SOUND, name) as Sound;
+ }
+
+ /** Returns all sound names that start with a certain string, sorted alphabetically.
+ * If you pass an out-vector, the names will be added to that vector. */
+ public function getSoundNames(prefix:String="", out:Vector.=null):Vector.
+ {
+ return getAssetNames(AssetType.SOUND, prefix, true, out);
+ }
+
+ /** Generates a new SoundChannel object to play back the sound. This method returns a
+ * SoundChannel object, which you can access to stop the sound and to control volume. */
+ public function playSound(name:String, startTime:Number=0, loops:int=0,
+ transform:SoundTransform=null):SoundChannel
+ {
+ var sound:Sound = getSound(name);
+ if (sound) return sound.play(startTime, loops, transform);
+ else return null;
+ }
+
+ /** Returns an XML with a certain name, or null if it's not found. */
+ public function getXml(name:String):XML
+ {
+ return getAsset(AssetType.XML_DOCUMENT, name) as XML;
+ }
+
+ /** Returns all XML names that start with a certain string, sorted alphabetically.
+ * If you pass an out-vector, the names will be added to that vector. */
+ public function getXmlNames(prefix:String="", out:Vector.=null):Vector.
+ {
+ return getAssetNames(AssetType.XML_DOCUMENT, prefix, true, out);
+ }
+
+ /** Returns an object with a certain name, or null if it's not found. Enqueued JSON
+ * data is parsed and can be accessed with this method. */
+ public function getObject(name:String):Object
+ {
+ return getAsset(AssetType.OBJECT, name);
+ }
+
+ /** Returns all object names that start with a certain string, sorted alphabetically.
+ * If you pass an out-vector, the names will be added to that vector. */
+ public function getObjectNames(prefix:String="", out:Vector.=null):Vector.
+ {
+ return getAssetNames(AssetType.OBJECT, prefix, true, out);
+ }
+
+ /** Returns a byte array with a certain name, or null if it's not found. */
+ public function getByteArray(name:String):ByteArray
+ {
+ return getAsset(AssetType.BYTE_ARRAY, name) as ByteArray;
+ }
+
+ /** Returns all byte array names that start with a certain string, sorted alphabetically.
+ * If you pass an out-vector, the names will be added to that vector. */
+ public function getByteArrayNames(prefix:String="", out:Vector.=null):Vector.
+ {
+ return getAssetNames(AssetType.BYTE_ARRAY, prefix, true, out);
+ }
+
+ /** Returns a bitmap font with a certain name, or null if it's not found. */
+ public function getBitmapFont(name:String):BitmapFont
+ {
+ return getAsset(AssetType.BITMAP_FONT, name) as BitmapFont;
+ }
+
+ /** Returns all bitmap font names that start with a certain string, sorted alphabetically.
+ * If you pass an out-vector, the names will be added to that vector. */
+ public function getBitmapFontNames(prefix:String="", out:Vector.=null):Vector.
+ {
+ return getAssetNames(AssetType.BITMAP_FONT, prefix, true, out);
+ }
+
+ /** Returns an asset manager with a certain name, or null if it's not found. */
+ public function getAssetManager(name:String):AssetManager
+ {
+ return getAsset(AssetType.ASSET_MANAGER, name) as AssetManager;
+ }
+
+ /** Returns all asset manager names that start with a certain string, sorted alphabetically.
+ * If you pass an out-vector, the names will be added to that vector. */
+ public function getAssetManagerNames(prefix:String="", out:Vector.=null):Vector.
+ {
+ return getAssetNames(AssetType.ASSET_MANAGER, prefix, true, out);
+ }
+
+ /** Removes a certain texture, optionally disposing it. */
+ public function removeTexture(name:String, dispose:Boolean=true):void
+ {
+ removeAsset(AssetType.TEXTURE, name, dispose);
+ }
+
+ /** Removes a certain texture atlas, optionally disposing it. */
+ public function removeTextureAtlas(name:String, dispose:Boolean=true):void
+ {
+ removeAsset(AssetType.TEXTURE_ATLAS, name, dispose);
+ }
+
+ /** Removes a certain sound. */
+ public function removeSound(name:String):void
+ {
+ removeAsset(AssetType.SOUND, name);
+ }
+
+ /** Removes a certain Xml object, optionally disposing it. */
+ public function removeXml(name:String, dispose:Boolean=true):void
+ {
+ removeAsset(AssetType.XML_DOCUMENT, name, dispose);
+ }
+
+ /** Removes a certain object. */
+ public function removeObject(name:String):void
+ {
+ removeAsset(AssetType.OBJECT, name);
+ }
+
+ /** Removes a certain byte array, optionally disposing its memory right away. */
+ public function removeByteArray(name:String, dispose:Boolean=true):void
+ {
+ removeAsset(AssetType.BYTE_ARRAY, name, dispose);
+ }
+
+ /** Removes a certain bitmap font, optionally disposing it. */
+ public function removeBitmapFont(name:String, dispose:Boolean=true):void
+ {
+ removeAsset(AssetType.BITMAP_FONT, name, dispose);
+ }
+
+ /** Removes a certain asset manager and optionally disposes it right away. */
+ public function removeAssetManager(name:String, dispose:Boolean=true):void
+ {
+ removeAsset(AssetType.ASSET_MANAGER, name, dispose);
+ }
+
+ // registration of factories
+
+ /** Registers a custom AssetFactory. If you use any priority > 0, the factory will
+ * be called before the default factories. The final factory to be invoked is the
+ * 'ByteArrayFactory', which is using a priority of '-100'. */
+ public function registerFactory(factory:AssetFactory, priority:int=0):void
+ {
+ factory.priority = priority;
+
+ _assetFactories.push(factory);
+ _assetFactories.sort(comparePriorities);
+ }
+
+ /** Unregisters the specified AssetFactory. */
+ public function unregisterFactory(factory:AssetFactory):void
+ {
+ var index:int = _assetFactories.indexOf(factory);
+ if (index != -1) _assetFactories.removeAt(index);
+ }
+
+ private static function comparePriorities(a:Object, b:Object):int
+ {
+ if (a.priority == b.priority) return 0;
+ return a.priority > b.priority ? -1 : 1;
+ }
+
+ // helpers
+
+ private function getFilenameFromUrl(url:String):String
+ {
+ if (url)
+ {
+ var matches:Array = NAME_REGEX.exec(decodeURIComponent(url));
+ if (matches && matches.length > 1) return matches[1];
+ }
+ return null;
+ }
+
+ /** This method is called internally to determine the name under which an asset will be
+ * accessible; override it if you need a custom naming scheme.
+ *
+ * @return the name to be used for the asset, or 'null' if it can't be determined. */
+ protected function getNameFromUrl(url:String):String
+ {
+ if (url)
+ {
+ var matches:Array = NAME_REGEX.exec(decodeURIComponent(url));
+ if (matches && matches.length > 2) return matches[2];
+ }
+ return null;
+ }
+
+ /** This method is called internally to determine the extension that's passed to the
+ * 'AssetFactory' (via the 'AssetReference'). Override it if you need to customize
+ * e.g. the extension of a server URL.
+ *
+ * @return the extension to be used for the asset, or an empty string if it can't be
+ * determined. */
+ protected function getExtensionFromUrl(url:String):String
+ {
+ if (url)
+ {
+ var matches:Array = NAME_REGEX.exec(decodeURIComponent(url));
+ if (matches && matches.length > 3) return matches[3];
+ }
+ return "";
+ }
+
+ /** Disposes the given asset. ByteArrays are cleared, XMLs are disposed using
+ * 'System.disposeXML'. If the object contains a 'dispose' method, it will be called.
+ * Override if you need to add custom cleanup code for a certain asset. */
+ protected function disposeAsset(asset:Object):void
+ {
+ if (asset is ByteArray) (asset as ByteArray).clear();
+ if (asset is XML) System.disposeXML(asset as XML);
+ if ("dispose" in asset) asset["dispose"]();
+ }
+
+ /** This method is called during loading of assets when 'verbose' is activated. Per
+ * default, it traces 'message' to the console. */
+ protected function log(message:String):void
+ {
+ if (_verbose) trace("[AssetManager]", message);
+ }
+
+ private static function getDictionaryKeys(dictionary:Dictionary, prefix:String="",
+ out:Vector.=null):Vector.
+ {
+ if (out == null) out = new [];
+ if (dictionary)
+ {
+ for (var name:String in dictionary)
+ if (name.indexOf(prefix) == 0)
+ out[out.length] = name; // avoid 'push'
+
+ out.sort(Array.CASEINSENSITIVE);
+ }
+ return out;
+ }
+
+ private static function getUniqueName():String
+ {
+ return NO_NAME + "-" + sNoNameCount++;
+ }
+
+ // properties
+
+ /** When activated, the class will trace information about added/enqueued assets.
+ * @default true */
+ public function get verbose():Boolean { return _verbose; }
+ public function set verbose(value:Boolean):void { _verbose = value; }
+
+ /** Returns the number of raw assets that have been enqueued, but not yet loaded. */
+ public function get numQueuedAssets():int { return _queue.length; }
+
+ /** The maximum number of parallel connections that are spawned when loading the queue.
+ * More connections can reduce loading times, but require more memory. @default 3. */
+ public function get numConnections():int { return _numConnections; }
+ public function set numConnections(value:int):void
+ {
+ _numConnections = MathUtil.min(1, value);
+ }
+
+ /** Textures will be created with the options set up in this object at the time of
+ * enqueuing. */
+ public function get textureOptions():TextureOptions { return _textureOptions; }
+ public function set textureOptions(value:TextureOptions):void { _textureOptions.copyFrom(value); }
+
+ /** The DataLoader is used to load any data from files or URLs. If you need to customize
+ * its behavior (e.g. to add a caching mechanism), assign your custom instance here. */
+ public function get dataLoader():DataLoader { return _dataLoader; }
+ public function set dataLoader(value:DataLoader):void { _dataLoader = value; }
+
+ /** Indicates if bitmap fonts should be registered with their "face" attribute from the
+ * font XML file. Per default, they are registered with the name of the texture file.
+ * @default false */
+ public function get registerBitmapFontsWithFontFace():Boolean
+ {
+ return _registerBitmapFontsWithFontFace;
+ }
+
+ public function set registerBitmapFontsWithFontFace(value:Boolean):void
+ {
+ _registerBitmapFontsWithFontFace = value;
+ }
+ }
+}
+
+import starling.assets.AssetManager;
+
+class AssetPostProcessor
+{
+ private var _priority:int;
+ private var _callback:Function;
+
+ public function AssetPostProcessor(callback:Function, priority:int)
+ {
+ if (callback == null || callback.length != 1)
+ throw new ArgumentError("callback must be a function " +
+ "accepting one 'AssetStore' parameter");
+
+ _callback = callback;
+ _priority = priority;
+ }
+
+ internal function execute(store:AssetManager):void
+ {
+ _callback(store);
+ }
+
+ public function get priority():int { return _priority; }
+}
\ No newline at end of file
diff --git a/mobile_version/src/starling/assets/AssetReference.as b/mobile_version/src/starling/assets/AssetReference.as
new file mode 100644
index 00000000..d978f100
--- /dev/null
+++ b/mobile_version/src/starling/assets/AssetReference.as
@@ -0,0 +1,56 @@
+package starling.assets
+{
+ import starling.textures.TextureOptions;
+
+ /** The description of an asset to be created by an AssetFactory. */
+ public class AssetReference
+ {
+ private var _name:String;
+ private var _url:String;
+ private var _data:Object;
+ private var _mimeType:String;
+ private var _extension:String;
+ private var _textureOptions:TextureOptions;
+
+ /** Creates a new instance with the given data, which is typically some kind of file
+ * reference / URL or an instance of an asset class. If 'data' contains an URL, an
+ * equivalent value will be assigned to the 'url' property. */
+ public function AssetReference(data:Object)
+ {
+ _data = data;
+ _textureOptions = new TextureOptions();
+
+ if (data is String) _url = data as String;
+ else if ("url" in data) _url = data["url"] as String;
+ }
+
+ /** The name with which the asset should be added to the AssetManager. */
+ public function get name():String { return _name; }
+ public function set name(value:String):void { _name = value; }
+
+ /** The url from which the asset needs to be / has been loaded. */
+ public function get url():String { return _url; }
+ public function set url(value:String):void { _url = value; }
+
+ /** The raw data of the asset. This property often contains an URL; when it's passed
+ * to an AssetFactory, loading has already completed, and the property contains a
+ * ByteArray with the loaded data. */
+ public function get data():Object { return _data; }
+ public function set data(value:Object):void { _data = value; }
+
+ /** The mime type of the asset, if loaded from a server. */
+ public function get mimeType():String { return _mimeType; }
+ public function set mimeType(value:String):void { _mimeType = value; }
+
+ /** The file extension of the asset, if the filename or URL contains one. */
+ public function get extension():String { return _extension; }
+ public function set extension(value:String):void { _extension = value; }
+
+ /** The TextureOptions describing how to create a texture, if the asset references one. */
+ public function get textureOptions():TextureOptions { return _textureOptions; }
+ public function set textureOptions(value:TextureOptions):void
+ {
+ _textureOptions.copyFrom(value);
+ }
+ }
+}
diff --git a/mobile_version/src/starling/assets/AssetType.as b/mobile_version/src/starling/assets/AssetType.as
new file mode 100644
index 00000000..68631d28
--- /dev/null
+++ b/mobile_version/src/starling/assets/AssetType.as
@@ -0,0 +1,40 @@
+package starling.assets
+{
+ import flash.media.Sound;
+ import flash.media.Video;
+ import flash.utils.ByteArray;
+
+ import starling.errors.AbstractClassError;
+ import starling.text.BitmapFont;
+ import starling.textures.Texture;
+ import starling.textures.TextureAtlas;
+
+ /** An enumeration class containing all the asset types supported by the AssetManager. */
+ public class AssetType
+ {
+ /** @private */
+ public function AssetType() { throw new AbstractClassError(); }
+
+ public static const TEXTURE:String = "texture";
+ public static const TEXTURE_ATLAS:String = "textureAtlas";
+ public static const SOUND:String = "sound";
+ public static const XML_DOCUMENT:String = "xml";
+ public static const OBJECT:String = "object";
+ public static const BYTE_ARRAY:String = "byteArray";
+ public static const BITMAP_FONT:String = "bitmapFont";
+ public static const ASSET_MANAGER:String = "assetManager";
+
+ /** Figures out the asset type string from the type of the given instance. */
+ public static function fromAsset(asset:Object):String
+ {
+ if (asset is Texture) return TEXTURE;
+ else if (asset is TextureAtlas) return TEXTURE_ATLAS;
+ else if (asset is Sound) return SOUND;
+ else if (asset is XML) return XML_DOCUMENT;
+ else if (asset is ByteArray) return BYTE_ARRAY;
+ else if (asset is BitmapFont) return BITMAP_FONT;
+ else if (asset is AssetManager) return ASSET_MANAGER;
+ else return OBJECT;
+ }
+ }
+}
diff --git a/mobile_version/src/starling/assets/AtfTextureFactory.as b/mobile_version/src/starling/assets/AtfTextureFactory.as
new file mode 100644
index 00000000..9e587170
--- /dev/null
+++ b/mobile_version/src/starling/assets/AtfTextureFactory.as
@@ -0,0 +1,73 @@
+package starling.assets
+{
+ import flash.utils.ByteArray;
+
+ import starling.textures.AtfData;
+ import starling.textures.Texture;
+ import starling.utils.execute;
+
+ /** This AssetFactory creates texture assets from ATF files. */
+ public class AtfTextureFactory extends AssetFactory
+ {
+ /** Creates a new instance. */
+ public function AtfTextureFactory()
+ {
+ addExtensions("atf"); // not used, actually, since we can parse the ATF header, anyway.
+ }
+
+ /** @inheritDoc */
+ override public function canHandle(reference:AssetReference):Boolean
+ {
+ return (reference.data is ByteArray && AtfData.isAtfData(reference.data as ByteArray));
+ }
+
+ /** @inheritDoc */
+ override public function create(reference:AssetReference, helper:AssetFactoryHelper,
+ onComplete:Function, onError:Function):void
+ {
+ helper.executeWhenContextReady(createTexture);
+
+ function createTexture():void
+ {
+ var onReady:Function = reference.textureOptions.onReady as Function;
+ reference.textureOptions.onReady = function():void
+ {
+ execute(onReady, texture);
+ onComplete(reference.name, texture);
+ };
+
+ var texture:Texture = null;
+ var url:String = reference.url;
+
+ try { texture = Texture.fromData(reference.data, reference.textureOptions); }
+ catch (e:Error) { onError(e.message); }
+
+ if (url && texture)
+ {
+ texture.root.onRestore = function():void
+ {
+ helper.onBeginRestore();
+ helper.loadDataFromUrl(url, function(data:ByteArray):void
+ {
+ helper.executeWhenContextReady(function():void
+ {
+ try { texture.root.uploadAtfData(data); }
+ catch (e:Error) { helper.log("Texture restoration failed: " + e.message); }
+
+ helper.onEndRestore();
+ });
+ }, onReloadError);
+ };
+ }
+
+ reference.data = null; // prevent closures from keeping reference
+ }
+
+ function onReloadError(error:String):void
+ {
+ helper.log("Texture restoration failed for " + reference.url + ". " + error);
+ helper.onEndRestore();
+ }
+ }
+ }
+}
diff --git a/mobile_version/src/starling/assets/BitmapTextureFactory.as b/mobile_version/src/starling/assets/BitmapTextureFactory.as
new file mode 100644
index 00000000..24915e4e
--- /dev/null
+++ b/mobile_version/src/starling/assets/BitmapTextureFactory.as
@@ -0,0 +1,167 @@
+package starling.assets
+{
+ import flash.display.Bitmap;
+ import flash.display.BitmapData;
+ import flash.display.Loader;
+ import flash.display.LoaderInfo;
+ import flash.events.Event;
+ import flash.events.IOErrorEvent;
+ import flash.system.ImageDecodingPolicy;
+ import flash.system.LoaderContext;
+ import flash.utils.ByteArray;
+
+ import starling.textures.Texture;
+ import starling.textures.TextureOptions;
+ import starling.utils.ByteArrayUtil;
+ import starling.utils.execute;
+
+ /** This AssetFactory creates texture assets from bitmaps and image files. */
+ public class BitmapTextureFactory extends AssetFactory
+ {
+ private static const MAGIC_NUMBERS_JPG:Array = [0xff, 0xd8];
+ private static const MAGIC_NUMBERS_PNG:Array = [0x89, 0x50, 0x4E, 0x47, 0x0D, 0x0A, 0x1A, 0x0A];
+ private static const MAGIC_NUMBERS_GIF:Array = [0x47, 0x49, 0x46, 0x38];
+
+ /** Creates a new instance. */
+ public function BitmapTextureFactory()
+ {
+ addMimeTypes("image/png", "image/jpg", "image/jpeg", "image/gif");
+ addExtensions("png", "jpg", "jpeg", "gif");
+ }
+
+ /** @inheritDoc */
+ override public function canHandle(reference:AssetReference):Boolean
+ {
+ if (super.canHandle(reference) ||
+ reference.data is Bitmap || reference.data is BitmapData)
+ {
+ return true;
+ }
+ else if (reference.data is ByteArray)
+ {
+ var byteData:ByteArray = reference.data as ByteArray;
+ return ByteArrayUtil.startsWithBytes(byteData, MAGIC_NUMBERS_PNG) ||
+ ByteArrayUtil.startsWithBytes(byteData, MAGIC_NUMBERS_JPG) ||
+ ByteArrayUtil.startsWithBytes(byteData, MAGIC_NUMBERS_GIF);
+ }
+ else return false;
+ }
+
+ /** @inheritDoc */
+ override public function create(reference:AssetReference, helper:AssetFactoryHelper,
+ onComplete:Function, onError:Function):void
+ {
+ var texture:Texture = null;
+ var url:String = reference.url;
+ var data:Object = reference.data;
+ var name:String = reference.name;
+ var options:TextureOptions = reference.textureOptions;
+ var onReady:Function = reference.textureOptions.onReady as Function;
+
+ if (data is Bitmap)
+ onBitmapDataCreated((data as Bitmap).bitmapData);
+ else if (data is BitmapData)
+ onBitmapDataCreated(data as BitmapData);
+ else if (data is ByteArray)
+ createBitmapDataFromByteArray(data as ByteArray, onBitmapDataCreated, onError);
+
+ // prevent closures from keeping references
+ reference.data = data = null;
+
+ function onBitmapDataCreated(bitmapData:BitmapData):void
+ {
+ helper.executeWhenContextReady(createFromBitmapData, bitmapData);
+ }
+
+ function createFromBitmapData(bitmapData:BitmapData):void
+ {
+ options.onReady = complete;
+
+ try { texture = Texture.fromData(bitmapData, options); }
+ catch (e:Error) { onError(e.message); }
+
+ if (texture && url) texture.root.onRestore = restoreTexture;
+ }
+
+ function complete():void
+ {
+ execute(onReady, texture);
+ onComplete(name, texture);
+ }
+
+ function restoreTexture():void
+ {
+ helper.onBeginRestore();
+
+ reload(url, function(bitmapData:BitmapData):void
+ {
+ helper.executeWhenContextReady(function():void
+ {
+ try { texture.root.uploadBitmapData(bitmapData); }
+ catch (e:Error) { helper.log("Texture restoration failed: " + e.message); }
+
+ helper.onEndRestore();
+ });
+ });
+ }
+
+ function reload(url:String, onComplete:Function):void
+ {
+ helper.loadDataFromUrl(url, function(data:ByteArray):void
+ {
+ createBitmapDataFromByteArray(data, onComplete, onReloadError);
+ }, onReloadError);
+ }
+
+ function onReloadError(error:String):void
+ {
+ helper.log("Texture restoration failed for " + url + ". " + error);
+ helper.onEndRestore();
+ }
+ }
+
+ /** Called by 'create' to convert a ByteArray to a BitmapData.
+ *
+ * @param data A ByteArray that contains image data
+ * (like the contents of a PNG or JPG file).
+ * @param onComplete Called with the BitmapData when successful.
+ *
function(bitmapData:BitmapData):void;
+ * @param onError To be called when creation fails for some reason.
+ *
function(error:String):void
+ */
+ protected function createBitmapDataFromByteArray(data:ByteArray,
+ onComplete:Function, onError:Function):void
+ {
+ var loader:Loader = new Loader();
+ var loaderInfo:LoaderInfo = loader.contentLoaderInfo;
+ loaderInfo.addEventListener(IOErrorEvent.IO_ERROR, onIoError);
+ loaderInfo.addEventListener(Event.COMPLETE, onLoaderComplete);
+ var loaderContext:LoaderContext = new LoaderContext();
+ loaderContext.imageDecodingPolicy = ImageDecodingPolicy.ON_LOAD;
+ loader.loadBytes(data, loaderContext);
+
+ function onIoError(event:IOErrorEvent):void
+ {
+ cleanup();
+ execute(onError, event.text);
+ }
+
+ function onLoaderComplete(event:Object):void
+ {
+ complete(event.target.content.bitmapData);
+ }
+
+ function complete(bitmapData:BitmapData):void
+ {
+ cleanup();
+ execute(onComplete, bitmapData);
+ }
+
+ function cleanup():void
+ {
+ loaderInfo.removeEventListener(IOErrorEvent.IO_ERROR, onIoError);
+ loaderInfo.removeEventListener(Event.COMPLETE, onLoaderComplete);
+ }
+ }
+ }
+}
diff --git a/mobile_version/src/starling/assets/ByteArrayFactory.as b/mobile_version/src/starling/assets/ByteArrayFactory.as
new file mode 100644
index 00000000..79d02371
--- /dev/null
+++ b/mobile_version/src/starling/assets/ByteArrayFactory.as
@@ -0,0 +1,30 @@
+package starling.assets
+{
+ import flash.utils.ByteArray;
+
+ /** This AssetFactory forwards ByteArrays to the AssetManager. It's the fallback when
+ * no other factory can handle an asset reference (default priority: -100). */
+ public class ByteArrayFactory extends AssetFactory
+ {
+ /** Creates a new instance. */
+ public function ByteArrayFactory()
+ {
+ // not used, actually - this factory is used as a fallback with low priority
+ addExtensions("bin");
+ addMimeTypes("application/octet-stream");
+ }
+
+ /** @inheritDoc */
+ override public function canHandle(reference:AssetReference):Boolean
+ {
+ return reference.data is ByteArray;
+ }
+
+ /** @inheritDoc */
+ override public function create(reference:AssetReference, helper:AssetFactoryHelper,
+ onComplete:Function, onError:Function):void
+ {
+ onComplete(reference.name, reference.data as ByteArray);
+ }
+ }
+}
diff --git a/mobile_version/src/starling/assets/DataLoader.as b/mobile_version/src/starling/assets/DataLoader.as
new file mode 100644
index 00000000..4fe81f7b
--- /dev/null
+++ b/mobile_version/src/starling/assets/DataLoader.as
@@ -0,0 +1,138 @@
+package starling.assets
+{
+ import flash.events.ErrorEvent;
+ import flash.events.Event;
+ import flash.events.HTTPStatusEvent;
+ import flash.events.IOErrorEvent;
+ import flash.events.ProgressEvent;
+ import flash.events.SecurityErrorEvent;
+ import flash.net.URLLoader;
+ import flash.net.URLLoaderDataFormat;
+ import flash.net.URLRequest;
+ import flash.utils.Dictionary;
+
+ import starling.utils.execute;
+
+ /** Loads binary data from a local or remote URL with a very simple callback system.
+ *
+ *
The DataLoader is used by the AssetManager to load any local or remote data.
+ * Its single purpose is to get the binary data that's stored at a specific URL.
+ *
+ *
You can use this class for your own purposes (as an easier to use 'URLLoader'
+ * alternative), or you can extend the class to modify the AssetManager's behavior.
+ * E.g. you could extend this class to add a caching mechanism for remote assets.
+ * Assign an instance of your extended class to the AssetManager's dataLoader
+ * property.
+ */
+ public class DataLoader
+ {
+ // This HTTPStatusEvent is only available in AIR
+ private static const HTTP_RESPONSE_STATUS:String = "httpResponseStatus";
+
+ private var _urlLoaders:Dictionary;
+
+ /** Creates a new DataLoader instance. */
+ public function DataLoader()
+ {
+ _urlLoaders = new Dictionary(true);
+ }
+
+ /** Loads the binary data from a specific URL. Always supply both 'onComplete' and
+ * 'onError' parameters; in case of an error, only the latter will be called.
+ *
+ *
The 'onComplete' callback may have up to four parameters, all of them being optional.
+ * If you pass a callback that just takes zero or one, it will work just as well. The
+ * additional parameters may be used to describe the name and type of the downloaded
+ * data. They are not provided by the base class, but the AssetManager will check
+ * if they are available.
+ *
+ * @param url a String containing an URL.
+ * @param onComplete will be called when the data has been loaded.
+ * function(data:ByteArray, mimeType:String, name:String, extension:String):void
+ * @param onError will be called in case of an error. The 2nd parameter is optional.
+ * function(error:String, httpStatus:int):void
+ * @param onProgress will be called multiple times with the current load ratio (0-1).
+ * function(ratio:Number):void
+ */
+ public function load(url:String, onComplete:Function,
+ onError:Function, onProgress:Function=null):void
+ {
+ var message:String;
+ var mimeType:String = null;
+ var httpStatus:int = 0;
+ var request:URLRequest = new URLRequest(url);
+ var loader:URLLoader = new URLLoader();
+ loader.dataFormat = URLLoaderDataFormat.BINARY;
+ loader.addEventListener(IOErrorEvent.IO_ERROR, onLoadError);
+ loader.addEventListener(SecurityErrorEvent.SECURITY_ERROR, onLoadError);
+ loader.addEventListener(HTTP_RESPONSE_STATUS, onHttpResponseStatus);
+ loader.addEventListener(ProgressEvent.PROGRESS, onLoadProgress);
+ loader.addEventListener(Event.COMPLETE, onLoadComplete);
+ loader.load(request);
+
+ _urlLoaders[loader] = true;
+
+ function onHttpResponseStatus(event:HTTPStatusEvent):void
+ {
+ httpStatus = event.status;
+ mimeType = getHttpHeader(event["responseHeaders"], "Content-Type");
+ }
+
+ function onLoadError(event:ErrorEvent):void
+ {
+ cleanup();
+ message = event.type + " - " + event.text;
+ execute(onError, message);
+ }
+
+ function onLoadProgress(event:ProgressEvent):void
+ {
+ if (onProgress != null && event.bytesTotal > 0)
+ onProgress(event.bytesLoaded / event.bytesTotal);
+ }
+
+ function onLoadComplete(event:Object):void
+ {
+ cleanup();
+
+ if (httpStatus < 400)
+ execute(onComplete, loader.data, mimeType);
+ else
+ execute(onError, "Unexpected HTTP status '" + httpStatus + "'. URL: " +
+ request.url, httpStatus);
+ }
+
+ function cleanup():void
+ {
+ loader.removeEventListener(IOErrorEvent.IO_ERROR, onLoadError);
+ loader.removeEventListener(SecurityErrorEvent.SECURITY_ERROR, onLoadError);
+ loader.removeEventListener(HTTP_RESPONSE_STATUS, onHttpResponseStatus);
+ loader.removeEventListener(ProgressEvent.PROGRESS, onLoadProgress);
+ loader.removeEventListener(Event.COMPLETE, onLoadComplete);
+ delete _urlLoaders[loader];
+ }
+ }
+
+ /** Aborts all current load operations. The loader can still be used, though. */
+ public function close():void
+ {
+ for (var loader:* in _urlLoaders)
+ {
+ try { loader.close(); }
+ catch (e:Error) {}
+ }
+
+ _urlLoaders = new Dictionary(true);
+ }
+
+ private static function getHttpHeader(headers:Array, headerName:String):String
+ {
+ if (headers)
+ {
+ for each (var header:Object in headers)
+ if (header.name == headerName) return header.value;
+ }
+ return null;
+ }
+ }
+}
diff --git a/mobile_version/src/starling/assets/JsonFactory.as b/mobile_version/src/starling/assets/JsonFactory.as
new file mode 100644
index 00000000..8f8494c9
--- /dev/null
+++ b/mobile_version/src/starling/assets/JsonFactory.as
@@ -0,0 +1,40 @@
+package starling.assets
+{
+ import flash.utils.ByteArray;
+
+ import starling.utils.ByteArrayUtil;
+
+ /** This AssetFactory creates objects from JSON data. */
+ public class JsonFactory extends AssetFactory
+ {
+ /** Creates a new instance. */
+ public function JsonFactory()
+ {
+ addExtensions("json");
+ addMimeTypes("application/json", "text/json");
+ }
+
+ /** @inheritDoc */
+ override public function canHandle(reference:AssetReference):Boolean
+ {
+ return super.canHandle(reference) || (reference.data is ByteArray &&
+ ByteArrayUtil.startsWithString(reference.data as ByteArray, "{"));
+ }
+
+ /** @inheritDoc */
+ override public function create(reference:AssetReference, helper:AssetFactoryHelper,
+ onComplete:Function, onError:Function):void
+ {
+ try
+ {
+ var bytes:ByteArray = reference.data as ByteArray;
+ var object:Object = JSON.parse(bytes.readUTFBytes(bytes.length));
+ onComplete(reference.name, object);
+ }
+ catch (e:Error)
+ {
+ onError("Could not parse JSON: " + e.message);
+ }
+ }
+ }
+}
diff --git a/mobile_version/src/starling/assets/SoundFactory.as b/mobile_version/src/starling/assets/SoundFactory.as
new file mode 100644
index 00000000..84e097b6
--- /dev/null
+++ b/mobile_version/src/starling/assets/SoundFactory.as
@@ -0,0 +1,60 @@
+package starling.assets
+{
+ import flash.media.Sound;
+ import flash.utils.ByteArray;
+
+ import starling.utils.ByteArrayUtil;
+
+ /** This AssetFactory creates sound assets. */
+ public class SoundFactory extends AssetFactory
+ {
+ private static const MAGIC_NUMBERS_A:Array = [0xFF, 0xFB];
+ private static const MAGIC_NUMBERS_B:Array = [0x49, 0x44, 0x33];
+
+ /** Creates a new instance. */
+ public function SoundFactory()
+ {
+ addMimeTypes("audio/mp3", "audio/mpeg3", "audio/mpeg");
+ addExtensions("mp3");
+ }
+
+ /** @inheritDoc */
+ override public function canHandle(reference:AssetReference):Boolean
+ {
+ if (reference.data is Sound || super.canHandle(reference))
+ return true;
+ else if (reference.data is ByteArray)
+ {
+ var byteData:ByteArray = reference.data as ByteArray;
+ return ByteArrayUtil.startsWithBytes(byteData, MAGIC_NUMBERS_A) ||
+ ByteArrayUtil.startsWithBytes(byteData, MAGIC_NUMBERS_B);
+ }
+ else return false;
+ }
+
+ /** @inheritDoc */
+ override public function create(reference:AssetReference, helper:AssetFactoryHelper,
+ onComplete:Function, onError:Function):void
+ {
+ var sound:Sound = reference.data as Sound;
+ var bytes:ByteArray = reference.data as ByteArray;
+
+ if (bytes)
+ {
+ try
+ {
+ sound = new Sound();
+ sound.loadCompressedDataFromByteArray(bytes, bytes.length);
+ }
+ catch (e:Error)
+ {
+ onError("Could not load sound data: " + e.message);
+ return;
+ }
+
+ }
+
+ onComplete(reference.name, sound);
+ }
+ }
+}
diff --git a/mobile_version/src/starling/assets/XmlFactory.as b/mobile_version/src/starling/assets/XmlFactory.as
new file mode 100644
index 00000000..54af6099
--- /dev/null
+++ b/mobile_version/src/starling/assets/XmlFactory.as
@@ -0,0 +1,84 @@
+package starling.assets
+{
+ import flash.utils.ByteArray;
+
+ import starling.text.BitmapFont;
+ import starling.text.TextField;
+ import starling.textures.Texture;
+ import starling.textures.TextureAtlas;
+ import starling.utils.ByteArrayUtil;
+
+ /** This AssetFactory creates XML assets, texture atlases and bitmap fonts. */
+ public class XmlFactory extends AssetFactory
+ {
+ /** Creates a new instance. */
+ public function XmlFactory()
+ {
+ addMimeTypes("application/xml", "text/xml");
+ addExtensions("xml", "fnt");
+ }
+
+ /** Returns true if mime type or extension fit for XML data, or if the data starts
+ * with a "<" character. */
+ override public function canHandle(reference:AssetReference):Boolean
+ {
+ return super.canHandle(reference) || (reference.data is ByteArray &&
+ ByteArrayUtil.startsWithString(reference.data as ByteArray, "<"));
+ }
+
+ /** Creates the XML asset and passes it to 'onComplete'. If the XML contains a
+ * TextureAtlas or a BitmapFont, adds suitable post processors. */
+ override public function create(reference:AssetReference, helper:AssetFactoryHelper,
+ onComplete:Function, onError:Function):void
+ {
+ var xml:XML = reference.data as XML;
+ var bytes:ByteArray = reference.data as ByteArray;
+
+ if (bytes)
+ {
+ try { xml = new XML(bytes); }
+ catch (e:Error)
+ {
+ onError("Could not parse XML: " + e.message);
+ return;
+ }
+ }
+
+ var rootNode:String = xml.localName();
+
+ if (rootNode == "TextureAtlas")
+ helper.addPostProcessor(textureAtlasPostProcessor, 100);
+ else if (rootNode == "font")
+ helper.addPostProcessor(bitmapFontPostProcessor);
+
+ onComplete(reference.name, xml);
+
+ // prevent closures from keeping references
+ reference.data = bytes = null;
+
+ function textureAtlasPostProcessor(store:AssetManager):void
+ {
+ var name:String = helper.getNameFromUrl(xml.@imagePath.toString());
+ var texture:Texture = store.getTexture(name);
+ if (texture) store.addAsset(name, new TextureAtlas(texture, xml));
+ else helper.log("Cannot create atlas: texture '" + name + "' is missing.");
+ }
+
+ function bitmapFontPostProcessor(store:AssetManager):void
+ {
+ var textureName:String = helper.getNameFromUrl(xml.pages.page.@file.toString());
+ var texture:Texture = store.getTexture(textureName);
+ var fontName:String = store.registerBitmapFontsWithFontFace ?
+ xml.info.@face.toString() : textureName;
+
+ if (texture)
+ {
+ var bitmapFont:BitmapFont = new BitmapFont(texture, xml);
+ store.addAsset(fontName, bitmapFont);
+ TextField.registerCompositor(bitmapFont, fontName);
+ }
+ else helper.log("Cannot create bitmap font: texture '" + textureName + "' is missing.");
+ }
+ }
+ }
+}
diff --git a/mobile_version/src/starling/core/Starling.as b/mobile_version/src/starling/core/Starling.as
new file mode 100644
index 00000000..042eedc1
--- /dev/null
+++ b/mobile_version/src/starling/core/Starling.as
@@ -0,0 +1,1051 @@
+// =================================================================================================
+//
+// Starling Framework
+// Copyright Gamua GmbH. All Rights Reserved.
+//
+// This program is free software. You can redistribute and/or modify it
+// in accordance with the terms of the accompanying license agreement.
+//
+// =================================================================================================
+
+package starling.core
+{
+ import flash.display.Shape;
+ import flash.display.Sprite;
+ import flash.display.Stage3D;
+ import flash.display.StageAlign;
+ import flash.display.StageScaleMode;
+ import flash.display3D.Context3D;
+ import flash.display3D.Context3DProfile;
+ import flash.errors.IllegalOperationError;
+ import flash.events.ErrorEvent;
+ import flash.events.Event;
+ import flash.events.KeyboardEvent;
+ import flash.events.MouseEvent;
+ import flash.events.TouchEvent;
+ import flash.geom.Rectangle;
+ import flash.system.Capabilities;
+ import flash.text.TextField;
+ import flash.text.TextFieldAutoSize;
+ import flash.text.TextFormat;
+ import flash.text.TextFormatAlign;
+ import flash.ui.Mouse;
+ import flash.ui.Multitouch;
+ import flash.ui.MultitouchInputMode;
+ import flash.utils.getTimer;
+ import flash.utils.setTimeout;
+
+ import starling.animation.Juggler;
+ import starling.display.DisplayObject;
+ import starling.display.Stage;
+ import starling.events.EventDispatcher;
+ import starling.events.ResizeEvent;
+ import starling.events.TouchPhase;
+ import starling.events.TouchProcessor;
+ import starling.rendering.Painter;
+ import starling.utils.Align;
+ import starling.utils.RectangleUtil;
+ import starling.utils.SystemUtil;
+
+ /** Dispatched when a new render context is created. The 'data' property references the context. */
+ [Event(name="context3DCreate", type="starling.events.Event")]
+
+ /** Dispatched when the root class has been created. The 'data' property references that object. */
+ [Event(name="rootCreated", type="starling.events.Event")]
+
+ /** Dispatched when a fatal error is encountered. The 'data' property contains an error string. */
+ [Event(name="fatalError", type="starling.events.Event")]
+
+ /** Dispatched when the display list is about to be rendered. This event provides the last
+ * opportunity to make changes before the display list is rendered. */
+ [Event(name="render", type="starling.events.Event")]
+
+ /** The Starling class represents the core of the Starling framework.
+ *
+ *
The Starling framework makes it possible to create 2D applications and games that make
+ * use of the Stage3D architecture introduced in Flash Player 11. It implements a display tree
+ * system that is very similar to that of conventional Flash, while leveraging modern GPUs
+ * to speed up rendering.
+ *
+ *
The Starling class represents the link between the conventional Flash display tree and
+ * the Starling display tree. To create a Starling-powered application, you have to create
+ * an instance of the Starling class:
+ *
+ *
var starling:Starling = new Starling(Game, stage);
+ *
+ *
The first parameter has to be a Starling display object class, e.g. a subclass of
+ * starling.display.Sprite. In the sample above, the class "Game" is the
+ * application root. An instance of "Game" will be created as soon as Starling is initialized.
+ * The second parameter is the conventional (Flash) stage object. Per default, Starling will
+ * display its contents directly below the stage.
+ *
+ *
It is recommended to store the Starling instance as a member variable, to make sure
+ * that the Garbage Collector does not destroy it. After creating the Starling object, you
+ * have to start it up like this:
+ *
+ *
starling.start();
+ *
+ *
It will now render the contents of the "Game" class in the frame rate that is set up for
+ * the application (as defined in the Flash stage).
+ *
+ * Context3D Profiles
+ *
+ *
Stage3D supports different rendering profiles, and Starling works with all of them. The
+ * last parameter of the Starling constructor allows you to choose which profile you want.
+ * The following profiles are available:
+ *
+ *
+ *
BASELINE_CONSTRAINED: provides the broadest hardware reach. If you develop for the
+ * browser, this is the profile you should test with.
+ *
BASELINE: recommend for any mobile application, as it allows Starling to use a more
+ * memory efficient texture type (RectangleTextures). It also supports more complex
+ * AGAL code.
+ *
BASELINE_EXTENDED: adds support for textures up to 4096x4096 pixels. This is
+ * especially useful on mobile devices with very high resolutions.
+ *
STANDARD_CONSTRAINED, STANDARD, STANDARD_EXTENDED: each provide more AGAL features,
+ * among other things. Most Starling games will not gain much from them.
+ *
+ *
+ *
The recommendation is to deploy your app with the profile "auto" (which makes Starling
+ * pick the best available of those), but to test it in all available profiles.
+ *
+ * Accessing the Starling object
+ *
+ *
From within your application, you can access the current Starling object anytime
+ * through the static method Starling.current. It will return the active Starling
+ * instance (most applications will only have one Starling object, anyway).
+ *
+ * Viewport
+ *
+ *
The area the Starling content is rendered into is, per default, the complete size of the
+ * stage. You can, however, use the "viewPort" property to change it. This can be useful
+ * when you want to render only into a part of the screen, or if the player size changes. For
+ * the latter, you can listen to the RESIZE-event dispatched by the Starling
+ * stage.
+ *
+ * Native overlay
+ *
+ *
Sometimes you will want to display native Flash content on top of Starling. That's what the
+ * nativeOverlay property is for. It returns a Flash Sprite lying directly
+ * on top of the Starling content. You can add conventional Flash objects to that overlay.
+ *
+ *
Beware, though, that conventional Flash content on top of 3D content can lead to
+ * performance penalties on some (mobile) platforms. For that reason, always remove all child
+ * objects from the overlay when you don't need them any longer.
+ *
+ * Multitouch
+ *
+ *
Starling supports multitouch input on devices that provide it. During development,
+ * where most of us are working with a conventional mouse and keyboard, Starling can simulate
+ * multitouch events with the help of the "Shift" and "Ctrl" (Mac: "Cmd") keys. Activate
+ * this feature by enabling the simulateMultitouch property.
+ *
+ * Skipping Unchanged Frames
+ *
+ *
It happens surprisingly often in an app or game that a scene stays completely static for
+ * several frames. So why redraw the stage at all in those situations? That's exactly the
+ * point of the skipUnchangedFrames-property. If enabled, static scenes are
+ * recognized as such and the back buffer is simply left as it is. On a mobile device, the
+ * impact of this feature can't be overestimated! There's simply no better way to enhance
+ * battery life. Make it a habit to always activate it; look at the documentation of the
+ * corresponding property for details.
+ *
+ * Handling a lost render context
+ *
+ *
On some operating systems and under certain conditions (e.g. returning from system
+ * sleep), Starling's stage3D render context may be lost. Starling will try to recover
+ * from a lost context automatically; to be able to do this, it will cache textures in
+ * RAM. This will take up quite a bit of extra memory, though, which might be problematic
+ * especially on mobile platforms. To avoid the higher memory footprint, it's recommended
+ * to load your textures with Starling's "AssetManager"; it is smart enough to recreate a
+ * texture directly from its origin.
+ *
+ *
In case you want to react to a context loss manually, Starling dispatches an event with
+ * the type "Event.CONTEXT3D_CREATE" when the context is restored, and textures will execute
+ * their root.onRestore callback, to which you can attach your own logic.
+ * Refer to the "Texture" class for more information.
+ *
+ * Sharing a 3D Context
+ *
+ *
Per default, Starling handles the Stage3D context itself. If you want to combine
+ * Starling with another Stage3D engine, however, this may not be what you want. In this case,
+ * you can make use of the shareContext property:
+ *
+ *
+ *
Manually create and configure a context3D object that both frameworks can work with
+ * (ideally through RenderUtil.requestContext3D and
+ * context.configureBackBuffer).
+ *
Initialize Starling with the stage3D instance that contains that configured context.
+ * This will automatically enable shareContext.
+ *
Call start() on your Starling instance (as usual). This will make
+ * Starling queue input events (keyboard/mouse/touch).
+ *
Create a game loop (e.g. using the native ENTER_FRAME event) and let it
+ * call Starling's nextFrame as well as the equivalent method of the other
+ * Stage3D engine. Surround those calls with context.clear() and
+ * context.present().
+ *
+ *
+ *
The Starling wiki contains a tutorial with more
+ * information about this topic.
+ *
+ * @see starling.utils.AssetManager
+ * @see starling.textures.Texture
+ *
+ */
+ public class Starling extends EventDispatcher
+ {
+ /** The version of the Starling framework. */
+ public static const VERSION:String = "2.1";
+
+ // members
+
+ private var _stage:Stage; // starling.display.stage!
+ private var _rootClass:Class;
+ private var _root:DisplayObject;
+ private var _juggler:Juggler;
+ private var _painter:Painter;
+ private var _touchProcessor:TouchProcessor;
+ private var _antiAliasing:int;
+ private var _frameTimestamp:Number;
+ private var _frameID:uint;
+ private var _leftMouseDown:Boolean;
+ private var _statsDisplay:StatsDisplay;
+ private var _started:Boolean;
+ private var _rendering:Boolean;
+ private var _supportHighResolutions:Boolean;
+ private var _skipUnchangedFrames:Boolean;
+ private var _showStats:Boolean;
+
+ private var _viewPort:Rectangle;
+ private var _previousViewPort:Rectangle;
+ private var _clippedViewPort:Rectangle;
+
+ private var _nativeStage:flash.display.Stage;
+ private var _nativeStageEmpty:Boolean;
+ private var _nativeOverlay:Sprite;
+
+ private static var sCurrent:Starling;
+ private static var sAll:Vector. = new [];
+
+ // construction
+
+ /** Creates a new Starling instance.
+ * @param rootClass A subclass of 'starling.display.DisplayObject'. It will be created
+ * as soon as initialization is finished and will become the first child
+ * of the Starling stage. Pass null if you don't want to
+ * create a root object right away. (You can use the
+ * rootClass property later to make that happen.)
+ * @param stage The Flash (2D) stage.
+ * @param viewPort A rectangle describing the area into which the content will be
+ * rendered. Default: stage size
+ * @param stage3D The Stage3D object into which the content will be rendered. If it
+ * already contains a context, sharedContext will be set
+ * to true. Default: the first available Stage3D.
+ * @param renderMode The Context3D render mode that should be requested.
+ * Use this parameter if you want to force "software" rendering.
+ * @param profile The Context3D profile that should be requested.
+ *
+ *
+ *
If you pass a profile String, this profile is enforced.
+ *
Pass an Array of profiles to make Starling pick the first
+ * one that works (starting with the first array element).
+ *
Pass the String "auto" to make Starling pick the best available
+ * profile automatically.
+ *
+ */
+ public function Starling(rootClass:Class, stage:flash.display.Stage,
+ viewPort:Rectangle=null, stage3D:Stage3D=null,
+ renderMode:String="auto", profile:Object="auto")
+ {
+ if (stage == null) throw new ArgumentError("Stage must not be null");
+ if (viewPort == null) viewPort = new Rectangle(0, 0, stage.stageWidth, stage.stageHeight);
+ if (stage3D == null) stage3D = stage.stage3Ds[0];
+
+ // TODO it might make sense to exchange the 'renderMode' and 'profile' parameters.
+
+ SystemUtil.initialize();
+ sAll.push(this);
+ makeCurrent();
+
+ _rootClass = rootClass;
+ _viewPort = viewPort;
+ _previousViewPort = new Rectangle();
+ _stage = new Stage(viewPort.width, viewPort.height, stage.color);
+ _nativeOverlay = new Sprite();
+ _nativeStage = stage;
+ _nativeStage.addChild(_nativeOverlay);
+ _touchProcessor = new TouchProcessor(_stage);
+ _juggler = new Juggler();
+ _antiAliasing = 0;
+ _supportHighResolutions = false;
+ _painter = new Painter(stage3D);
+ _frameTimestamp = getTimer() / 1000.0;
+ _frameID = 1;
+
+ // all other modes are problematic in Starling, so we force those here
+ stage.scaleMode = StageScaleMode.NO_SCALE;
+ stage.align = StageAlign.TOP_LEFT;
+
+ // register touch/mouse event handlers
+ for each (var touchEventType:String in touchEventTypes)
+ stage.addEventListener(touchEventType, onTouch, false, 0, true);
+
+ // register other event handlers
+ stage.addEventListener(Event.ENTER_FRAME, onEnterFrame, false, 0, true);
+ stage.addEventListener(KeyboardEvent.KEY_DOWN, onKey, false, 0, true);
+ stage.addEventListener(KeyboardEvent.KEY_UP, onKey, false, 0, true);
+ stage.addEventListener(Event.RESIZE, onResize, false, 0, true);
+ stage.addEventListener(Event.MOUSE_LEAVE, onMouseLeave, false, 0, true);
+
+ stage3D.addEventListener(Event.CONTEXT3D_CREATE, onContextCreated, false, 10, true);
+ stage3D.addEventListener(ErrorEvent.ERROR, onStage3DError, false, 10, true);
+
+ if (_painter.shareContext)
+ {
+ setTimeout(initialize, 1); // we don't call it right away, because Starling should
+ // behave the same way with or without a shared context
+ }
+ else
+ {
+ if (!SystemUtil.supportsDepthAndStencil)
+ trace("[Starling] Mask support requires 'depthAndStencil' to be enabled" +
+ " in the application descriptor.");
+
+ _painter.requestContext3D(renderMode, profile);
+ }
+ }
+
+ /** Disposes all children of the stage and the render context; removes all registered
+ * event listeners. */
+ public function dispose():void
+ {
+ stop(true);
+
+ _nativeStage.removeEventListener(Event.ENTER_FRAME, onEnterFrame, false);
+ _nativeStage.removeEventListener(KeyboardEvent.KEY_DOWN, onKey, false);
+ _nativeStage.removeEventListener(KeyboardEvent.KEY_UP, onKey, false);
+ _nativeStage.removeEventListener(Event.RESIZE, onResize, false);
+ _nativeStage.removeEventListener(Event.MOUSE_LEAVE, onMouseLeave, false);
+ _nativeStage.removeChild(_nativeOverlay);
+
+ stage3D.removeEventListener(Event.CONTEXT3D_CREATE, onContextCreated, false);
+ stage3D.removeEventListener(Event.CONTEXT3D_CREATE, onContextRestored, false);
+ stage3D.removeEventListener(ErrorEvent.ERROR, onStage3DError, false);
+
+ for each (var touchEventType:String in touchEventTypes)
+ _nativeStage.removeEventListener(touchEventType, onTouch, false);
+
+ _touchProcessor.dispose();
+ _painter.dispose();
+ _stage.dispose();
+
+ var index:int = sAll.indexOf(this);
+ if (index != -1) sAll.removeAt(index);
+ if (sCurrent == this) sCurrent = null;
+ }
+
+ // functions
+
+ private function initialize():void
+ {
+ makeCurrent();
+ updateViewPort(true);
+
+ // ideal time: after viewPort setup, before root creation
+ dispatchEventWith(Event.CONTEXT3D_CREATE, false, context);
+
+ initializeRoot();
+ _frameTimestamp = getTimer() / 1000.0;
+ }
+
+ private function initializeRoot():void
+ {
+ if (_root == null && _rootClass != null)
+ {
+ _root = new _rootClass() as DisplayObject;
+ if (_root == null) throw new Error("Invalid root class: " + _rootClass);
+ _stage.addChildAt(_root, 0);
+
+ dispatchEventWith(starling.events.Event.ROOT_CREATED, false, _root);
+ }
+ }
+
+ /** Calls advanceTime() (with the time that has passed since the last frame)
+ * and render(). */
+ public function nextFrame():void
+ {
+ var now:Number = getTimer() / 1000.0;
+ var passedTime:Number = now - _frameTimestamp;
+ _frameTimestamp = now;
+
+ // to avoid overloading time-based animations, the maximum delta is truncated.
+ if (passedTime > 1.0) passedTime = 1.0;
+
+ // after about 25 days, 'getTimer()' will roll over. A rare event, but still ...
+ if (passedTime < 0.0) passedTime = 1.0 / _nativeStage.frameRate;
+
+ advanceTime(passedTime);
+ render();
+ }
+
+ /** Dispatches ENTER_FRAME events on the display list, advances the Juggler
+ * and processes touches. */
+ public function advanceTime(passedTime:Number):void
+ {
+ if (!contextValid)
+ return;
+
+ makeCurrent();
+
+ _touchProcessor.advanceTime(passedTime);
+ _stage.advanceTime(passedTime);
+ _juggler.advanceTime(passedTime);
+ }
+
+ /** Renders the complete display list. Before rendering, the context is cleared; afterwards,
+ * it is presented (to avoid this, enable shareContext).
+ *
+ *
This method also dispatches an Event.RENDER-event on the Starling
+ * instance. That's the last opportunity to make changes before the display list is
+ * rendered.
*/
+ public function render():void
+ {
+ if (!contextValid)
+ return;
+
+ makeCurrent();
+ updateViewPort();
+
+ var doRedraw:Boolean = _stage.requiresRedraw || mustAlwaysRender;
+ if (doRedraw)
+ {
+ dispatchEventWith(starling.events.Event.RENDER);
+
+ var shareContext:Boolean = _painter.shareContext;
+ var scaleX:Number = _viewPort.width / _stage.stageWidth;
+ var scaleY:Number = _viewPort.height / _stage.stageHeight;
+
+ _painter.nextFrame();
+ _painter.pixelSize = 1.0 / contentScaleFactor;
+ _painter.state.setProjectionMatrix(
+ _viewPort.x < 0 ? -_viewPort.x / scaleX : 0.0,
+ _viewPort.y < 0 ? -_viewPort.y / scaleY : 0.0,
+ _clippedViewPort.width / scaleX,
+ _clippedViewPort.height / scaleY,
+ _stage.stageWidth, _stage.stageHeight, _stage.cameraPosition);
+
+ if (!shareContext)
+ _painter.clear(_stage.color, 0.0);
+
+ _stage.render(_painter);
+ _painter.finishFrame();
+ _painter.frameID = ++_frameID;
+
+ if (!shareContext)
+ _painter.present();
+ }
+
+ if (_statsDisplay)
+ {
+ _statsDisplay.drawCount = _painter.drawCount;
+ if (!doRedraw) _statsDisplay.markFrameAsSkipped();
+ }
+ }
+
+ private function updateViewPort(forceUpdate:Boolean=false):void
+ {
+ // the last set viewport is stored in a variable; that way, people can modify the
+ // viewPort directly (without a copy) and we still know if it has changed.
+
+ if (forceUpdate || !RectangleUtil.compare(_viewPort, _previousViewPort))
+ {
+ _previousViewPort.setTo(_viewPort.x, _viewPort.y, _viewPort.width, _viewPort.height);
+
+ // Constrained mode requires that the viewport is within the native stage bounds;
+ // thus, we use a clipped viewport when configuring the back buffer. (In baseline
+ // mode, that's not necessary, but it does not hurt either.)
+
+ _clippedViewPort = _viewPort.intersection(
+ new Rectangle(0, 0, _nativeStage.stageWidth, _nativeStage.stageHeight));
+
+ var contentScaleFactor:Number =
+ _supportHighResolutions ? _nativeStage.contentsScaleFactor : 1.0;
+
+ _painter.configureBackBuffer(_clippedViewPort, contentScaleFactor,
+ _antiAliasing, true);
+ }
+ }
+
+ private function updateNativeOverlay():void
+ {
+ _nativeOverlay.x = _viewPort.x;
+ _nativeOverlay.y = _viewPort.y;
+ _nativeOverlay.scaleX = _viewPort.width / _stage.stageWidth;
+ _nativeOverlay.scaleY = _viewPort.height / _stage.stageHeight;
+ }
+
+ /** Stops Starling right away and displays an error message on the native overlay.
+ * This method will also cause Starling to dispatch a FATAL_ERROR event. */
+ public function stopWithFatalError(message:String):void
+ {
+ var background:Shape = new Shape();
+ background.graphics.beginFill(0x0, 0.8);
+ background.graphics.drawRect(0, 0, _stage.stageWidth, _stage.stageHeight);
+ background.graphics.endFill();
+
+ var textField:TextField = new TextField();
+ var textFormat:TextFormat = new TextFormat("Verdana", 14, 0xFFFFFF);
+ textFormat.align = TextFormatAlign.CENTER;
+ textField.defaultTextFormat = textFormat;
+ textField.wordWrap = true;
+ textField.width = _stage.stageWidth * 0.75;
+ textField.autoSize = TextFieldAutoSize.CENTER;
+ textField.text = message;
+ textField.x = (_stage.stageWidth - textField.width) / 2;
+ textField.y = (_stage.stageHeight - textField.height) / 2;
+ textField.background = true;
+ textField.backgroundColor = 0x550000;
+
+ updateNativeOverlay();
+ nativeOverlay.addChild(background);
+ nativeOverlay.addChild(textField);
+ stop(true);
+
+ trace("[Starling]", message);
+ dispatchEventWith(starling.events.Event.FATAL_ERROR, false, message);
+ }
+
+ /** Make this Starling instance the current one. */
+ public function makeCurrent():void
+ {
+ sCurrent = this;
+ }
+
+ /** As soon as Starling is started, it will queue input events (keyboard/mouse/touch);
+ * furthermore, the method nextFrame will be called once per Flash Player
+ * frame. (Except when shareContext is enabled: in that case, you have to
+ * call that method manually.) */
+ public function start():void
+ {
+ _started = _rendering = true;
+ _frameTimestamp = getTimer() / 1000.0;
+
+ // mainly for Android: force redraw when app moves into foreground
+ setTimeout(setRequiresRedraw, 100);
+ }
+
+ /** Stops all logic and input processing, effectively freezing the app in its current state.
+ * Per default, rendering will continue: that's because the classic display list
+ * is only updated when stage3D is. (If Starling stopped rendering, conventional Flash
+ * contents would freeze, as well.)
+ *
+ *
However, if you don't need classic Flash contents, you can stop rendering, too.
+ * On some mobile systems (e.g. iOS), you are even required to do so if you have
+ * activated background code execution.
+ */
+ public function stop(suspendRendering:Boolean=false):void
+ {
+ _started = false;
+ _rendering = !suspendRendering;
+ }
+
+ /** Makes sure that the next frame is actually rendered.
+ *
+ *
When skipUnchangedFrames is enabled, some situations require that you
+ * manually force a redraw, e.g. when a RenderTexture is changed. This method is the
+ * easiest way to do so; it's just a shortcut to stage.setRequiresRedraw().
+ *
+ */
+ public function setRequiresRedraw():void
+ {
+ _stage.setRequiresRedraw();
+ }
+
+ // event handlers
+
+ private function onStage3DError(event:ErrorEvent):void
+ {
+ if (event.errorID == 3702)
+ {
+ var mode:String = Capabilities.playerType == "Desktop" ? "renderMode" : "wmode";
+ stopWithFatalError("Context3D not available! Possible reasons: wrong " + mode +
+ " or missing device support.");
+ }
+ else
+ stopWithFatalError("Stage3D error: " + event.text);
+ }
+
+ private function onContextCreated(event:Event):void
+ {
+ stage3D.removeEventListener(Event.CONTEXT3D_CREATE, onContextCreated);
+ stage3D.addEventListener(Event.CONTEXT3D_CREATE, onContextRestored, false, 10, true);
+
+ trace("[Starling] Context ready. Display Driver:", context.driverInfo);
+ initialize();
+ }
+
+ private function onContextRestored(event:Event):void
+ {
+ trace("[Starling] Context restored.");
+ updateViewPort(true);
+ dispatchEventWith(Event.CONTEXT3D_CREATE, false, context);
+ }
+
+ private function onEnterFrame(event:Event):void
+ {
+ // On mobile, the native display list is only updated on stage3D draw calls.
+ // Thus, we render even when Starling is paused.
+
+ if (!shareContext)
+ {
+ if (_started) nextFrame();
+ else if (_rendering) render();
+ }
+
+ updateNativeOverlay();
+ }
+
+ private function onKey(event:KeyboardEvent):void
+ {
+ if (!_started) return;
+
+ var keyEvent:starling.events.KeyboardEvent = new starling.events.KeyboardEvent(
+ event.type, event.charCode, event.keyCode, event.keyLocation,
+ event.ctrlKey, event.altKey, event.shiftKey);
+
+ makeCurrent();
+ _stage.dispatchEvent(keyEvent);
+
+ if (keyEvent.isDefaultPrevented())
+ event.preventDefault();
+ }
+
+ private function onResize(event:Event):void
+ {
+ var stageWidth:int = event.target.stageWidth;
+ var stageHeight:int = event.target.stageHeight;
+
+ if (contextValid)
+ dispatchResizeEvent();
+ else
+ addEventListener(Event.CONTEXT3D_CREATE, dispatchResizeEvent);
+
+ function dispatchResizeEvent():void
+ {
+ // on Android, the context is not valid while we're resizing. To avoid problems
+ // with user code, we delay the event dispatching until it becomes valid again.
+
+ makeCurrent();
+ removeEventListener(Event.CONTEXT3D_CREATE, dispatchResizeEvent);
+ _stage.dispatchEvent(new ResizeEvent(Event.RESIZE, stageWidth, stageHeight));
+ }
+ }
+
+ private function onMouseLeave(event:Event):void
+ {
+ _touchProcessor.enqueueMouseLeftStage();
+ }
+
+ private function onTouch(event:Event):void
+ {
+ if (!_started) return;
+
+ var globalX:Number;
+ var globalY:Number;
+ var touchID:int;
+ var phase:String;
+ var pressure:Number = 1.0;
+ var width:Number = 1.0;
+ var height:Number = 1.0;
+
+ // figure out general touch properties
+ if (event is MouseEvent)
+ {
+ var mouseEvent:MouseEvent = event as MouseEvent;
+ globalX = mouseEvent.stageX;
+ globalY = mouseEvent.stageY;
+ touchID = 0;
+
+ // MouseEvent.buttonDown returns true for both left and right button (AIR supports
+ // the right mouse button). We only want to react on the left button for now,
+ // so we have to save the state for the left button manually.
+ if (event.type == MouseEvent.MOUSE_DOWN) _leftMouseDown = true;
+ else if (event.type == MouseEvent.MOUSE_UP) _leftMouseDown = false;
+ }
+ else
+ {
+ var touchEvent:TouchEvent = event as TouchEvent;
+
+ // On a system that supports both mouse and touch input, the primary touch point
+ // is dispatched as mouse event as well. Since we don't want to listen to that
+ // event twice, we ignore the primary touch in that case.
+
+ if (Mouse.supportsCursor && touchEvent.isPrimaryTouchPoint) return;
+ else
+ {
+ globalX = touchEvent.stageX;
+ globalY = touchEvent.stageY;
+ touchID = touchEvent.touchPointID;
+ pressure = touchEvent.pressure;
+ width = touchEvent.sizeX;
+ height = touchEvent.sizeY;
+ }
+ }
+
+ // figure out touch phase
+ switch (event.type)
+ {
+ case TouchEvent.TOUCH_BEGIN: phase = TouchPhase.BEGAN; break;
+ case TouchEvent.TOUCH_MOVE: phase = TouchPhase.MOVED; break;
+ case TouchEvent.TOUCH_END: phase = TouchPhase.ENDED; break;
+ case MouseEvent.MOUSE_DOWN: phase = TouchPhase.BEGAN; break;
+ case MouseEvent.MOUSE_UP: phase = TouchPhase.ENDED; break;
+ case MouseEvent.MOUSE_MOVE:
+ phase = (_leftMouseDown ? TouchPhase.MOVED : TouchPhase.HOVER); break;
+ }
+
+ // move position into viewport bounds
+ globalX = _stage.stageWidth * (globalX - _viewPort.x) / _viewPort.width;
+ globalY = _stage.stageHeight * (globalY - _viewPort.y) / _viewPort.height;
+
+ // enqueue touch in touch processor
+ _touchProcessor.enqueue(touchID, phase, globalX, globalY, pressure, width, height);
+
+ // allow objects that depend on mouse-over state to be updated immediately
+ if (event.type == MouseEvent.MOUSE_UP && Mouse.supportsCursor)
+ _touchProcessor.enqueue(touchID, TouchPhase.HOVER, globalX, globalY);
+ }
+
+ private function get touchEventTypes():Array
+ {
+ var types:Array = [];
+
+ if (multitouchEnabled)
+ types.push(TouchEvent.TOUCH_BEGIN, TouchEvent.TOUCH_MOVE, TouchEvent.TOUCH_END);
+
+ if (!multitouchEnabled || Mouse.supportsCursor)
+ types.push(MouseEvent.MOUSE_DOWN, MouseEvent.MOUSE_MOVE, MouseEvent.MOUSE_UP);
+
+ return types;
+ }
+
+ private function get mustAlwaysRender():Boolean
+ {
+ // On mobile, and in some browsers with the "baselineConstrained" profile, the
+ // standard display list is only rendered after calling "context.present()".
+ // In such a case, we cannot omit frames if there is any content on the stage.
+
+ if (!_skipUnchangedFrames || _painter.shareContext)
+ return true;
+ else if (SystemUtil.isDesktop && profile != Context3DProfile.BASELINE_CONSTRAINED)
+ return false;
+ else
+ {
+ // Rendering can be skipped when both this and previous frame are empty.
+ var nativeStageEmpty:Boolean = isNativeDisplayObjectEmpty(_nativeStage);
+ var mustAlwaysRender:Boolean = !nativeStageEmpty || !_nativeStageEmpty;
+ _nativeStageEmpty = nativeStageEmpty;
+
+ return mustAlwaysRender;
+ }
+ }
+
+ // properties
+
+ /** Indicates if this Starling instance is started. */
+ public function get isStarted():Boolean { return _started; }
+
+ /** The default juggler of this instance. Will be advanced once per frame. */
+ public function get juggler():Juggler { return _juggler; }
+
+ /** The painter, which is used for all rendering. The same instance is passed to all
+ * rendermethods each frame. */
+ public function get painter():Painter { return _painter; }
+
+ /** The render context of this instance. */
+ public function get context():Context3D { return _painter.context; }
+
+ /** Indicates if multitouch simulation with "Shift" and "Ctrl"/"Cmd"-keys is enabled.
+ * @default false */
+ public function get simulateMultitouch():Boolean { return _touchProcessor.simulateMultitouch; }
+ public function set simulateMultitouch(value:Boolean):void
+ {
+ _touchProcessor.simulateMultitouch = value;
+ }
+
+ /** Indicates if Stage3D render methods will report errors. It's recommended to activate
+ * this when writing custom rendering code (shaders, etc.), since you'll get more detailed
+ * error messages. However, it has a very negative impact on performance, and it prevents
+ * ATF textures from being restored on a context loss. Never activate for release builds!
+ *
+ * @default false */
+ public function get enableErrorChecking():Boolean { return _painter.enableErrorChecking; }
+ public function set enableErrorChecking(value:Boolean):void
+ {
+ _painter.enableErrorChecking = value;
+ }
+
+ /** The anti-aliasing level. 0 - none, 16 - maximum. @default 0 */
+ public function get antiAliasing():int { return _antiAliasing; }
+ public function set antiAliasing(value:int):void
+ {
+ if (_antiAliasing != value)
+ {
+ _antiAliasing = value;
+ if (contextValid) updateViewPort(true);
+ }
+ }
+
+ /** The viewport into which Starling contents will be rendered. */
+ public function get viewPort():Rectangle { return _viewPort; }
+ public function set viewPort(value:Rectangle):void { _viewPort = value.clone(); }
+
+ /** The ratio between viewPort width and stage width. Useful for choosing a different
+ * set of textures depending on the display resolution. */
+ public function get contentScaleFactor():Number
+ {
+ return (_viewPort.width * _painter.backBufferScaleFactor) / _stage.stageWidth;
+ }
+
+ /** A Flash Sprite placed directly on top of the Starling content. Use it to display native
+ * Flash components. */
+ public function get nativeOverlay():Sprite { return _nativeOverlay; }
+
+ /** Indicates if a small statistics box (with FPS, memory usage and draw count) is
+ * displayed.
+ *
+ *
When the box turns dark green, more than 50% of the frames since the box' last
+ * update could skip rendering altogether. This will only happen if the property
+ * skipUnchangedFrames is enabled.
+ *
+ *
Beware that the memory usage should be taken with a grain of salt. The value is
+ * determined via System.totalMemory and does not take texture memory
+ * into account. It is recommended to use Adobe Scout for reliable and comprehensive
+ * memory analysis.
+ */
+ public function get showStats():Boolean { return _showStats; }
+ public function set showStats(value:Boolean):void
+ {
+ _showStats = value;
+
+ if (value)
+ {
+ if (_statsDisplay) _stage.addChild(_statsDisplay);
+ else showStatsAt();
+ }
+ else if (_statsDisplay)
+ {
+ _statsDisplay.removeFromParent();
+ }
+ }
+
+ /** Displays the statistics box at a certain position. */
+ public function showStatsAt(horizontalAlign:String="left",
+ verticalAlign:String="top", scale:Number=1):void
+ {
+ _showStats = true;
+
+ if (context == null)
+ {
+ // Starling is not yet ready - we postpone this until it's initialized.
+ addEventListener(starling.events.Event.ROOT_CREATED, onRootCreated);
+ }
+ else
+ {
+ var stageWidth:int = _stage.stageWidth;
+ var stageHeight:int = _stage.stageHeight;
+
+ if (_statsDisplay == null)
+ {
+ _statsDisplay = new StatsDisplay();
+ _statsDisplay.touchable = false;
+ }
+
+ _stage.addChild(_statsDisplay);
+ _statsDisplay.scaleX = _statsDisplay.scaleY = scale;
+
+ if (horizontalAlign == Align.LEFT) _statsDisplay.x = 0;
+ else if (horizontalAlign == Align.RIGHT) _statsDisplay.x = stageWidth - _statsDisplay.width;
+ else if (horizontalAlign == Align.CENTER) _statsDisplay.x = (stageWidth - _statsDisplay.width) / 2;
+ else throw new ArgumentError("Invalid horizontal alignment: " + horizontalAlign);
+
+ if (verticalAlign == Align.TOP) _statsDisplay.y = 0;
+ else if (verticalAlign == Align.BOTTOM) _statsDisplay.y = stageHeight - _statsDisplay.height;
+ else if (verticalAlign == Align.CENTER) _statsDisplay.y = (stageHeight - _statsDisplay.height) / 2;
+ else throw new ArgumentError("Invalid vertical alignment: " + verticalAlign);
+ }
+
+ function onRootCreated():void
+ {
+ if (_showStats) showStatsAt(horizontalAlign, verticalAlign, scale);
+ removeEventListener(starling.events.Event.ROOT_CREATED, onRootCreated);
+ }
+ }
+
+ /** The Starling stage object, which is the root of the display tree that is rendered. */
+ public function get stage():Stage { return _stage; }
+
+ /** The Flash Stage3D object Starling renders into. */
+ public function get stage3D():Stage3D { return _painter.stage3D; }
+
+ /** The Flash (2D) stage object Starling renders beneath. */
+ public function get nativeStage():flash.display.Stage { return _nativeStage; }
+
+ /** The instance of the root class provided in the constructor. Available as soon as
+ * the event 'ROOT_CREATED' has been dispatched. */
+ public function get root():DisplayObject { return _root; }
+
+ /** The class that will be instantiated by Starling as the 'root' display object.
+ * Must be a subclass of 'starling.display.DisplayObject'.
+ *
+ *
If you passed null as first parameter to the Starling constructor,
+ * you can use this property to set the root class at a later time. As soon as the class
+ * is instantiated, Starling will dispatch a ROOT_CREATED event.
+ *
+ *
Beware: you cannot change the root class once the root object has been
+ * instantiated.
+ */
+ public function get rootClass():Class { return _rootClass; }
+ public function set rootClass(value:Class):void
+ {
+ if (_rootClass != null && _root != null)
+ throw new Error("Root class may not change after root has been instantiated");
+ else if (_rootClass == null)
+ {
+ _rootClass = value;
+ if (context) initializeRoot();
+ }
+ }
+
+ /** Indicates if another Starling instance (or another Stage3D framework altogether)
+ * uses the same render context. If enabled, Starling will not execute any destructive
+ * context operations (e.g. not call 'configureBackBuffer', 'clear', 'present', etc.
+ * This has to be done manually, then. @default false */
+ public function get shareContext() : Boolean { return _painter.shareContext; }
+ public function set shareContext(value : Boolean) : void { _painter.shareContext = value; }
+
+ /** The Context3D profile of the current render context, or null
+ * if the context has not been created yet. */
+ public function get profile():String { return _painter.profile; }
+
+ /** Indicates that if the device supports HiDPI screens Starling will attempt to allocate
+ * a larger back buffer than indicated via the viewPort size. Note that this is used
+ * on Desktop only; mobile AIR apps still use the "requestedDisplayResolution" parameter
+ * the application descriptor XML. @default false */
+ public function get supportHighResolutions():Boolean { return _supportHighResolutions; }
+ public function set supportHighResolutions(value:Boolean):void
+ {
+ if (_supportHighResolutions != value)
+ {
+ _supportHighResolutions = value;
+ if (contextValid) updateViewPort(true);
+ }
+ }
+
+ /** When enabled, Starling will skip rendering the stage if it hasn't changed since the
+ * last frame. This is great for apps that remain static from time to time, since it will
+ * greatly reduce power consumption. You should activate this whenever possible!
+ *
+ *
The reason why it's disabled by default is just that it causes problems with Render-
+ * and VideoTextures. When you use those, you either have to disable this property
+ * temporarily, or call setRequiresRedraw() (ideally on the stage) whenever
+ * those textures are changing. Otherwise, the changes won't show up.
+ *
+ * @default false
+ */
+ public function get skipUnchangedFrames():Boolean { return _skipUnchangedFrames; }
+ public function set skipUnchangedFrames(value:Boolean):void
+ {
+ _skipUnchangedFrames = value;
+ _nativeStageEmpty = false; // required by 'mustAlwaysRender'
+ }
+
+ /** The TouchProcessor is passed all mouse and touch input and is responsible for
+ * dispatching TouchEvents to the Starling display tree. If you want to handle these
+ * types of input manually, pass your own custom subclass to this property. */
+ public function get touchProcessor():TouchProcessor { return _touchProcessor; }
+ public function set touchProcessor(value:TouchProcessor):void
+ {
+ if (value == null) throw new ArgumentError("TouchProcessor must not be null");
+ else if (value != _touchProcessor)
+ {
+ _touchProcessor.dispose();
+ _touchProcessor = value;
+ }
+ }
+
+ /** The number of frames that have been rendered since this instance was created. */
+ public function get frameID():uint { return _frameID; }
+
+ /** Indicates if the Context3D object is currently valid (i.e. it hasn't been lost or
+ * disposed). */
+ public function get contextValid():Boolean { return _painter.contextValid; }
+
+ // static properties
+
+ /** The currently active Starling instance. */
+ public static function get current():Starling { return sCurrent; }
+
+ /** All Starling instances.
CAUTION: not a copy, but the actual object! Do not modify!
*/
+ public static function get all():Vector. { return sAll; }
+
+ /** The render context of the currently active Starling instance. */
+ public static function get context():Context3D { return sCurrent ? sCurrent.context : null; }
+
+ /** The default juggler of the currently active Starling instance. */
+ public static function get juggler():Juggler { return sCurrent ? sCurrent._juggler : null; }
+
+ /** The painter used for all rendering of the currently active Starling instance. */
+ public static function get painter():Painter { return sCurrent ? sCurrent._painter : null; }
+
+ /** The contentScaleFactor of the currently active Starling instance. */
+ public static function get contentScaleFactor():Number
+ {
+ return sCurrent ? sCurrent.contentScaleFactor : 1.0;
+ }
+
+ /** Indicates if multitouch input should be supported. */
+ public static function get multitouchEnabled():Boolean
+ {
+ return Multitouch.inputMode == MultitouchInputMode.TOUCH_POINT;
+ }
+
+ public static function set multitouchEnabled(value:Boolean):void
+ {
+ if (sCurrent) throw new IllegalOperationError(
+ "'multitouchEnabled' must be set before Starling instance is created");
+ else
+ Multitouch.inputMode = value ? MultitouchInputMode.TOUCH_POINT :
+ MultitouchInputMode.NONE;
+ }
+
+ /** The number of frames that have been rendered since the current instance was created. */
+ public static function get frameID():uint
+ {
+ return sCurrent ? sCurrent._frameID : 0;
+ }
+ }
+}
+
+import flash.display.DisplayObject;
+import flash.display.DisplayObjectContainer;
+
+// put here to avoid naming conflicts
+function isNativeDisplayObjectEmpty(object:DisplayObject):Boolean
+{
+ if (object == null) return true;
+ else if (object is DisplayObjectContainer)
+ {
+ var container:DisplayObjectContainer = object as DisplayObjectContainer;
+ var numChildren:int = container.numChildren;
+
+ for (var i:int=0; i UPDATE_INTERVAL)
+ {
+ update();
+ _frameCount = _skipCount = _totalTime = 0;
+ }
+ }
+
+ /** Updates the displayed values. */
+ public function update():void
+ {
+ _background.color = _skipCount > _frameCount / 2 ? 0x003F00 : 0x0;
+ _fps = _totalTime > 0 ? _frameCount / _totalTime : 0;
+ _memory = System.totalMemory * B_TO_MB;
+ _gpuMemory = supportsGpuMem ? Starling.context['totalGPUMemory'] * B_TO_MB : -1;
+
+ var fpsText:String = _fps.toFixed(_fps < 100 ? 1 : 0);
+ var memText:String = _memory.toFixed(_memory < 100 ? 1 : 0);
+ var gpuMemText:String = _gpuMemory.toFixed(_gpuMemory < 100 ? 1 : 0);
+ var drwText:String = (_totalTime > 0 ? _drawCount-2 : _drawCount).toString(); // ignore self
+
+ _values.text = fpsText + "\n" + memText + "\n" +
+ (_gpuMemory >= 0 ? gpuMemText + "\n" : "") + drwText;
+ }
+
+ /** Call this once in every frame that can skip rendering because nothing changed. */
+ public function markFrameAsSkipped():void
+ {
+ _skipCount += 1;
+ }
+
+ public override function render(painter:Painter):void
+ {
+ // By calling 'finishQuadBatch' and 'excludeFromCache', we can make sure that the stats
+ // display is always rendered with exactly two draw calls. That is taken into account
+ // when showing the drawCount value (see 'ignore self' comment above)
+
+ painter.excludeFromCache(this);
+ painter.finishMeshBatch();
+ super.render(painter);
+ }
+
+ /** Indicates if the current runtime supports the 'totalGPUMemory' API. */
+ private function get supportsGpuMem():Boolean
+ {
+ return "totalGPUMemory" in Starling.context;
+ }
+
+ /** The number of Stage3D draw calls per second. */
+ public function get drawCount():int { return _drawCount; }
+ public function set drawCount(value:int):void { _drawCount = value; }
+
+ /** The current frames per second (updated twice per second). */
+ public function get fps():Number { return _fps; }
+ public function set fps(value:Number):void { _fps = value; }
+
+ /** The currently used system memory in MB. */
+ public function get memory():Number { return _memory; }
+ public function set memory(value:Number):void { _memory = value; }
+
+ /** The currently used graphics memory in MB. */
+ public function get gpuMemory():Number { return _gpuMemory; }
+ public function set gpuMemory(value:Number):void { _gpuMemory = value; }
+ }
+}
\ No newline at end of file
diff --git a/mobile_version/src/starling/core/starling_internal.as b/mobile_version/src/starling/core/starling_internal.as
new file mode 100644
index 00000000..2fa3be73
--- /dev/null
+++ b/mobile_version/src/starling/core/starling_internal.as
@@ -0,0 +1,22 @@
+// =================================================================================================
+//
+// Starling Framework
+// Copyright Gamua GmbH. All Rights Reserved.
+//
+// This program is free software. You can redistribute and/or modify it
+// in accordance with the terms of the accompanying license agreement.
+//
+// =================================================================================================
+
+package starling.core
+{
+ /**
+ * This namespace is used for undocumented APIs -- usually implementation
+ * details -- which can't be private because they need to visible
+ * to other classes.
+ *
+ * APIs in this namespace are completely unsupported and are likely to
+ * change in future versions of Starling.
+ */
+ public namespace starling_internal;
+}
\ No newline at end of file
diff --git a/mobile_version/src/starling/display/BlendMode.as b/mobile_version/src/starling/display/BlendMode.as
new file mode 100644
index 00000000..3794e2df
--- /dev/null
+++ b/mobile_version/src/starling/display/BlendMode.as
@@ -0,0 +1,136 @@
+// =================================================================================================
+//
+// Starling Framework
+// Copyright Gamua GmbH. All Rights Reserved.
+//
+// This program is free software. You can redistribute and/or modify it
+// in accordance with the terms of the accompanying license agreement.
+//
+// =================================================================================================
+
+package starling.display
+{
+ import flash.display3D.Context3DBlendFactor;
+
+ import starling.core.Starling;
+
+ /** A class that provides constant values for visual blend mode effects.
+ *
+ *
A blend mode is always defined by two 'Context3DBlendFactor' values. A blend factor
+ * represents a particular four-value vector that is multiplied with the source or destination
+ * color in the blending formula. The blending formula is:
+ *
+ *
result = source × sourceFactor + destination × destinationFactor
+ *
+ *
In the formula, the source color is the output color of the pixel shader program. The
+ * destination color is the color that currently exists in the color buffer, as set by
+ * previous clear and draw operations.
+ *
+ *
You can add your own blend modes via BlendMode.register.
+ * To get the math right, remember that all colors in Starling use premultiplied alpha (PMA),
+ * which means that their RGB values were multiplied with the alpha value.
+ *
+ * @see flash.display3D.Context3DBlendFactor
+ */
+ public class BlendMode
+ {
+ private var _name:String;
+ private var _sourceFactor:String;
+ private var _destinationFactor:String;
+
+ private static var sBlendModes:Object;
+
+ /** Creates a new BlendMode instance. Don't call this method directly; instead,
+ * register a new blend mode using BlendMode.register. */
+ public function BlendMode(name:String, sourceFactor:String, destinationFactor:String)
+ {
+ _name = name;
+ _sourceFactor = sourceFactor;
+ _destinationFactor = destinationFactor;
+ }
+
+ /** Inherits the blend mode from this display object's parent. */
+ public static const AUTO:String = "auto";
+
+ /** Deactivates blending, i.e. disabling any transparency. */
+ public static const NONE:String = "none";
+
+ /** The display object appears in front of the background. */
+ public static const NORMAL:String = "normal";
+
+ /** Adds the values of the colors of the display object to the colors of its background. */
+ public static const ADD:String = "add";
+
+ /** Multiplies the values of the display object colors with the the background color. */
+ public static const MULTIPLY:String = "multiply";
+
+ /** Multiplies the complement (inverse) of the display object color with the complement of
+ * the background color, resulting in a bleaching effect. */
+ public static const SCREEN:String = "screen";
+
+ /** Erases the background when drawn on a RenderTexture. */
+ public static const ERASE:String = "erase";
+
+ /** When used on a RenderTexture, the drawn object will act as a mask for the current
+ * content, i.e. the source alpha overwrites the destination alpha. */
+ public static const MASK:String = "mask";
+
+ /** Draws under/below existing objects; useful especially on RenderTextures. */
+ public static const BELOW:String = "below";
+
+ // static access methods
+
+ /** Returns the blend mode with the given name.
+ * Throws an ArgumentError if the mode does not exist. */
+ public static function get(modeName:String):BlendMode
+ {
+ if (sBlendModes == null) registerDefaults();
+ if (modeName in sBlendModes) return sBlendModes[modeName];
+ else throw new ArgumentError("Blend mode not found: " + modeName);
+ }
+
+ /** Registers a blending mode under a certain name. */
+ public static function register(name:String, srcFactor:String, dstFactor:String):BlendMode
+ {
+ if (sBlendModes == null) registerDefaults();
+ var blendMode:BlendMode = new BlendMode(name, srcFactor, dstFactor);
+ sBlendModes[name] = blendMode;
+ return blendMode;
+ }
+
+ private static function registerDefaults():void
+ {
+ if (sBlendModes) return;
+
+ sBlendModes = {};
+ register("none" , Context3DBlendFactor.ONE, Context3DBlendFactor.ZERO);
+ register("normal", Context3DBlendFactor.ONE, Context3DBlendFactor.ONE_MINUS_SOURCE_ALPHA);
+ register("add", Context3DBlendFactor.ONE, Context3DBlendFactor.ONE);
+ register("multiply", Context3DBlendFactor.DESTINATION_COLOR, Context3DBlendFactor.ONE_MINUS_SOURCE_ALPHA);
+ register("screen", Context3DBlendFactor.ONE, Context3DBlendFactor.ONE_MINUS_SOURCE_COLOR);
+ register("erase", Context3DBlendFactor.ZERO, Context3DBlendFactor.ONE_MINUS_SOURCE_ALPHA);
+ register("mask", Context3DBlendFactor.ZERO, Context3DBlendFactor.SOURCE_ALPHA);
+ register("below", Context3DBlendFactor.ONE_MINUS_DESTINATION_ALPHA, Context3DBlendFactor.DESTINATION_ALPHA);
+ }
+
+ // instance methods / properties
+
+ /** Sets the appropriate blend factors for source and destination on the current context. */
+ public function activate():void
+ {
+ Starling.context.setBlendFactors(_sourceFactor, _destinationFactor);
+ }
+
+ /** Returns the name of the blend mode. */
+ public function toString():String { return _name; }
+
+ /** The source blend factor of this blend mode. */
+ public function get sourceFactor():String { return _sourceFactor; }
+
+ /** The destination blend factor of this blend mode. */
+ public function get destinationFactor():String { return _destinationFactor; }
+
+ /** Returns the name of the blend mode. */
+ public function get name():String { return _name; }
+ }
+}
\ No newline at end of file
diff --git a/mobile_version/src/starling/display/Button.as b/mobile_version/src/starling/display/Button.as
new file mode 100644
index 00000000..54c84330
--- /dev/null
+++ b/mobile_version/src/starling/display/Button.as
@@ -0,0 +1,455 @@
+// =================================================================================================
+//
+// Starling Framework
+// Copyright Gamua GmbH. All Rights Reserved.
+//
+// This program is free software. You can redistribute and/or modify it
+// in accordance with the terms of the accompanying license agreement.
+//
+// =================================================================================================
+
+package starling.display
+{
+ import flash.geom.Rectangle;
+ import flash.ui.Mouse;
+ import flash.ui.MouseCursor;
+
+ import starling.events.Event;
+ import starling.events.Touch;
+ import starling.events.TouchEvent;
+ import starling.events.TouchPhase;
+ import starling.styles.MeshStyle;
+ import starling.text.TextField;
+ import starling.text.TextFormat;
+ import starling.textures.Texture;
+
+ /** Dispatched when the user triggers the button. Bubbles. */
+ [Event(name="triggered", type="starling.events.Event")]
+
+ /** A simple button composed of an image and, optionally, text.
+ *
+ *
You can use different textures for various states of the button. If you're providing
+ * only an up state, the button is simply scaled a little when it is touched.
+ *
+ *
In addition, you can overlay text on the button. To customize the text, you can use
+ * properties equivalent to those of the TextField class. Move the text to a certain position
+ * by updating the textBounds property.
+ *
+ *
To react on touches on a button, there is special Event.TRIGGERED event.
+ * Use this event instead of normal touch events. That way, users can cancel button
+ * activation by moving the mouse/finger away from the button before releasing.
+ */
+ public class Button extends DisplayObjectContainer
+ {
+ private static const MAX_DRAG_DIST:Number = 50;
+
+ private var _upState:Texture;
+ private var _downState:Texture;
+ private var _overState:Texture;
+ private var _disabledState:Texture;
+
+ private var _contents:Sprite;
+ private var _body:Image;
+ private var _textField:TextField;
+ private var _textBounds:Rectangle;
+ private var _overlay:Sprite;
+
+ private var _scaleWhenDown:Number;
+ private var _scaleWhenOver:Number;
+ private var _alphaWhenDown:Number;
+ private var _alphaWhenDisabled:Number;
+ private var _useHandCursor:Boolean;
+ private var _enabled:Boolean;
+ private var _state:String;
+ private var _triggerBounds:Rectangle;
+
+ /** Creates a button with a set of state-textures and (optionally) some text.
+ * Any state that is left 'null' will display the up-state texture. Beware that all
+ * state textures should have the same dimensions. */
+ public function Button(upState:Texture, text:String="", downState:Texture=null,
+ overState:Texture=null, disabledState:Texture=null)
+ {
+ if (upState == null) throw new ArgumentError("Texture 'upState' cannot be null");
+
+ _upState = upState;
+ _downState = downState;
+ _overState = overState;
+ _disabledState = disabledState;
+
+ _state = ButtonState.UP;
+ _body = new Image(upState);
+ _body.pixelSnapping = true;
+ _scaleWhenDown = downState ? 1.0 : 0.9;
+ _scaleWhenOver = _alphaWhenDown = 1.0;
+ _alphaWhenDisabled = disabledState ? 1.0: 0.5;
+ _enabled = true;
+ _useHandCursor = true;
+ _textBounds = new Rectangle(0, 0, _body.width, _body.height);
+ _triggerBounds = new Rectangle();
+
+ _contents = new Sprite();
+ _contents.addChild(_body);
+ addChild(_contents);
+ addEventListener(TouchEvent.TOUCH, onTouch);
+
+ this.touchGroup = true;
+ this.text = text;
+ }
+
+ /** @inheritDoc */
+ public override function dispose():void
+ {
+ // text field might be disconnected from parent, so we have to dispose it manually
+ if (_textField)
+ _textField.dispose();
+
+ super.dispose();
+ }
+
+ /** Readjusts the dimensions of the button according to its current state texture.
+ * Call this method to synchronize button and texture size after assigning a texture
+ * with a different size. */
+ public function readjustSize():void
+ {
+ var prevWidth:Number = _body.width;
+ var prevHeight:Number = _body.height;
+
+ _body.readjustSize();
+
+ var scaleX:Number = _body.width / prevWidth;
+ var scaleY:Number = _body.height / prevHeight;
+
+ _textBounds.x *= scaleX;
+ _textBounds.y *= scaleY;
+ _textBounds.width *= scaleX;
+ _textBounds.height *= scaleY;
+
+ if (_textField) createTextField();
+ }
+
+ private function createTextField():void
+ {
+ if (_textField == null)
+ {
+ _textField = new TextField(_textBounds.width, _textBounds.height);
+ _textField.pixelSnapping = _body.pixelSnapping;
+ _textField.touchable = false;
+ _textField.autoScale = true;
+ _textField.batchable = true;
+ }
+
+ _textField.width = _textBounds.width;
+ _textField.height = _textBounds.height;
+ _textField.x = _textBounds.x;
+ _textField.y = _textBounds.y;
+ }
+
+ private function onTouch(event:TouchEvent):void
+ {
+ Mouse.cursor = (_useHandCursor && _enabled && event.interactsWith(this)) ?
+ MouseCursor.BUTTON : MouseCursor.AUTO;
+
+ var touch:Touch = event.getTouch(this);
+ var isWithinBounds:Boolean;
+
+ if (!_enabled)
+ {
+ return;
+ }
+ else if (touch == null)
+ {
+ state = ButtonState.UP;
+ }
+ else if (touch.phase == TouchPhase.HOVER)
+ {
+ state = ButtonState.OVER;
+ }
+ else if (touch.phase == TouchPhase.BEGAN && _state != ButtonState.DOWN)
+ {
+ _triggerBounds = getBounds(stage, _triggerBounds);
+ _triggerBounds.inflate(MAX_DRAG_DIST, MAX_DRAG_DIST);
+
+ state = ButtonState.DOWN;
+ }
+ else if (touch.phase == TouchPhase.MOVED)
+ {
+ isWithinBounds = _triggerBounds.contains(touch.globalX, touch.globalY);
+
+ if (_state == ButtonState.DOWN && !isWithinBounds)
+ {
+ // reset button when finger is moved too far away ...
+ state = ButtonState.UP;
+ }
+ else if (_state == ButtonState.UP && isWithinBounds)
+ {
+ // ... and reactivate when the finger moves back into the bounds.
+ state = ButtonState.DOWN;
+ }
+ }
+ else if (touch.phase == TouchPhase.ENDED && _state == ButtonState.DOWN)
+ {
+ state = ButtonState.UP;
+ if (!touch.cancelled) dispatchEventWith(Event.TRIGGERED, true);
+ }
+ }
+
+ /** The current state of the button. The corresponding strings are found
+ * in the ButtonState class. */
+ public function get state():String { return _state; }
+ public function set state(value:String):void
+ {
+ _state = value;
+ _contents.x = _contents.y = 0;
+ _contents.scaleX = _contents.scaleY = _contents.alpha = 1.0;
+
+ switch (_state)
+ {
+ case ButtonState.DOWN:
+ setStateTexture(_downState);
+ _contents.alpha = _alphaWhenDown;
+ _contents.scaleX = _contents.scaleY = _scaleWhenDown;
+ _contents.x = (1.0 - _scaleWhenDown) / 2.0 * _body.width;
+ _contents.y = (1.0 - _scaleWhenDown) / 2.0 * _body.height;
+ break;
+ case ButtonState.UP:
+ setStateTexture(_upState);
+ break;
+ case ButtonState.OVER:
+ setStateTexture(_overState);
+ _contents.scaleX = _contents.scaleY = _scaleWhenOver;
+ _contents.x = (1.0 - _scaleWhenOver) / 2.0 * _body.width;
+ _contents.y = (1.0 - _scaleWhenOver) / 2.0 * _body.height;
+ break;
+ case ButtonState.DISABLED:
+ setStateTexture(_disabledState);
+ _contents.alpha = _alphaWhenDisabled;
+ break;
+ default:
+ throw new ArgumentError("Invalid button state: " + _state);
+ }
+ }
+
+ private function setStateTexture(texture:Texture):void
+ {
+ _body.texture = texture ? texture : _upState;
+ }
+
+ /** The scale factor of the button on touch. Per default, a button without a down state
+ * texture will be made slightly smaller, while a button with a down state texture
+ * remains unscaled. */
+ public function get scaleWhenDown():Number { return _scaleWhenDown; }
+ public function set scaleWhenDown(value:Number):void { _scaleWhenDown = value; }
+
+ /** The scale factor of the button while the mouse cursor hovers over it. @default 1.0 */
+ public function get scaleWhenOver():Number { return _scaleWhenOver; }
+ public function set scaleWhenOver(value:Number):void { _scaleWhenOver = value; }
+
+ /** The alpha value of the button on touch. @default 1.0 */
+ public function get alphaWhenDown():Number { return _alphaWhenDown; }
+ public function set alphaWhenDown(value:Number):void { _alphaWhenDown = value; }
+
+ /** The alpha value of the button when it is disabled. @default 0.5 */
+ public function get alphaWhenDisabled():Number { return _alphaWhenDisabled; }
+ public function set alphaWhenDisabled(value:Number):void { _alphaWhenDisabled = value; }
+
+ /** Indicates if the button can be triggered. */
+ public function get enabled():Boolean { return _enabled; }
+ public function set enabled(value:Boolean):void
+ {
+ if (_enabled != value)
+ {
+ _enabled = value;
+ state = value ? ButtonState.UP : ButtonState.DISABLED;
+ }
+ }
+
+ /** The text that is displayed on the button. */
+ public function get text():String { return _textField ? _textField.text : ""; }
+ public function set text(value:String):void
+ {
+ if (value.length == 0)
+ {
+ if (_textField)
+ {
+ _textField.text = value;
+ _textField.removeFromParent();
+ }
+ }
+ else
+ {
+ createTextField();
+ _textField.text = value;
+
+ if (_textField.parent == null)
+ _contents.addChild(_textField);
+ }
+ }
+
+ /** The format of the button's TextField. */
+ public function get textFormat():TextFormat
+ {
+ if (_textField == null) createTextField();
+ return _textField.format;
+ }
+
+ public function set textFormat(value:TextFormat):void
+ {
+ if (_textField == null) createTextField();
+ _textField.format = value;
+ }
+
+ /** The style that is used to render the button's TextField. */
+ public function get textStyle():MeshStyle
+ {
+ if (_textField == null) createTextField();
+ return _textField.style;
+ }
+
+ public function set textStyle(value:MeshStyle):void
+ {
+ if (_textField == null) createTextField();
+ _textField.style = value;
+ }
+
+ /** The style that is used to render the Button. */
+ public function get style():MeshStyle { return _body.style; }
+ public function set style(value:MeshStyle):void { _body.style = value; }
+
+ /** The texture that is displayed when the button is not being touched. */
+ public function get upState():Texture { return _upState; }
+ public function set upState(value:Texture):void
+ {
+ if (value == null)
+ throw new ArgumentError("Texture 'upState' cannot be null");
+
+ if (_upState != value)
+ {
+ _upState = value;
+ if ( _state == ButtonState.UP ||
+ (_state == ButtonState.DISABLED && _disabledState == null) ||
+ (_state == ButtonState.DOWN && _downState == null) ||
+ (_state == ButtonState.OVER && _overState == null))
+ {
+ setStateTexture(value);
+ }
+ }
+ }
+
+ /** The texture that is displayed while the button is touched. */
+ public function get downState():Texture { return _downState; }
+ public function set downState(value:Texture):void
+ {
+ if (_downState != value)
+ {
+ _downState = value;
+ if (_state == ButtonState.DOWN) setStateTexture(value);
+ }
+ }
+
+ /** The texture that is displayed while mouse hovers over the button. */
+ public function get overState():Texture { return _overState; }
+ public function set overState(value:Texture):void
+ {
+ if (_overState != value)
+ {
+ _overState = value;
+ if (_state == ButtonState.OVER) setStateTexture(value);
+ }
+ }
+
+ /** The texture that is displayed when the button is disabled. */
+ public function get disabledState():Texture { return _disabledState; }
+ public function set disabledState(value:Texture):void
+ {
+ if (_disabledState != value)
+ {
+ _disabledState = value;
+ if (_state == ButtonState.DISABLED) setStateTexture(value);
+ }
+ }
+
+ /** The bounds of the button's TextField. Allows moving the text to a custom position.
+ * CAUTION: not a copy, but the actual object! Text will only update on re-assignment.
+ */
+ public function get textBounds():Rectangle { return _textBounds; }
+ public function set textBounds(value:Rectangle):void
+ {
+ _textBounds.copyFrom(value);
+ createTextField();
+ }
+
+ /** The color of the button's state image. Just like every image object, each pixel's
+ * color is multiplied with this value. @default white */
+ public function get color():uint { return _body.color; }
+ public function set color(value:uint):void { _body.color = value; }
+
+ /** The smoothing type used for the button's state image. */
+ public function get textureSmoothing():String { return _body.textureSmoothing; }
+ public function set textureSmoothing(value:String):void { _body.textureSmoothing = value; }
+
+ /** The overlay sprite is displayed on top of the button contents. It scales with the
+ * button when pressed. Use it to add additional objects to the button (e.g. an icon). */
+ public function get overlay():Sprite
+ {
+ if (_overlay == null)
+ _overlay = new Sprite();
+
+ _contents.addChild(_overlay); // make sure it's always on top
+ return _overlay;
+ }
+
+ /** Indicates if the mouse cursor should transform into a hand while it's over the button.
+ * @default true */
+ public override function get useHandCursor():Boolean { return _useHandCursor; }
+ public override function set useHandCursor(value:Boolean):void { _useHandCursor = value; }
+
+ /** Controls whether or not the instance snaps to the nearest pixel. This can prevent the
+ * object from looking blurry when it's not exactly aligned with the pixels of the screen.
+ * @default true */
+ public function get pixelSnapping():Boolean { return _body.pixelSnapping; }
+ public function set pixelSnapping(value:Boolean):void
+ {
+ _body.pixelSnapping = value;
+ if (_textField) _textField.pixelSnapping = value;
+ }
+
+ /** @private */
+ override public function set width(value:Number):void
+ {
+ // The Button might use a Scale9Grid ->
+ // we must update the body width/height manually for the grid to scale properly.
+
+ var newWidth:Number = value / (this.scaleX || 1.0);
+ var scale:Number = newWidth / (_body.width || 1.0);
+
+ _body.width = newWidth;
+ _textBounds.x *= scale;
+ _textBounds.width *= scale;
+
+ if (_textField) _textField.width = newWidth;
+ }
+
+ /** @private */
+ override public function set height(value:Number):void
+ {
+ var newHeight:Number = value / (this.scaleY || 1.0);
+ var scale:Number = newHeight / (_body.height || 1.0);
+
+ _body.height = newHeight;
+ _textBounds.y *= scale;
+ _textBounds.height *= scale;
+
+ if (_textField) _textField.height = newHeight;
+ }
+
+ /** The current scaling grid used for the button's state image. Use this property to create
+ * buttons that resize in a smart way, i.e. with the four corners keeping the same size
+ * and only stretching the center area.
+ *
+ * @see Image#scale9Grid
+ * @default null
+ */
+ public function get scale9Grid():Rectangle { return _body.scale9Grid; }
+ public function set scale9Grid(value:Rectangle):void { _body.scale9Grid = value; }
+ }
+}
\ No newline at end of file
diff --git a/mobile_version/src/starling/display/ButtonState.as b/mobile_version/src/starling/display/ButtonState.as
new file mode 100644
index 00000000..151b8f62
--- /dev/null
+++ b/mobile_version/src/starling/display/ButtonState.as
@@ -0,0 +1,33 @@
+// =================================================================================================
+//
+// Starling Framework
+// Copyright Gamua GmbH. All Rights Reserved.
+//
+// This program is free software. You can redistribute and/or modify it
+// in accordance with the terms of the accompanying license agreement.
+//
+// =================================================================================================
+
+package starling.display
+{
+ import starling.errors.AbstractClassError;
+
+ /** A class that provides constant values for the states of the Button class. */
+ public class ButtonState
+ {
+ /** @private */
+ public function ButtonState() { throw new AbstractClassError(); }
+
+ /** The button's default state. */
+ public static const UP:String = "up";
+
+ /** The button is pressed. */
+ public static const DOWN:String = "down";
+
+ /** The mouse hovers over the button. */
+ public static const OVER:String = "over";
+
+ /** The button was disabled altogether. */
+ public static const DISABLED:String = "disabled";
+ }
+}
\ No newline at end of file
diff --git a/mobile_version/src/starling/display/Canvas.as b/mobile_version/src/starling/display/Canvas.as
new file mode 100644
index 00000000..9e5cf299
--- /dev/null
+++ b/mobile_version/src/starling/display/Canvas.as
@@ -0,0 +1,121 @@
+// =================================================================================================
+//
+// Starling Framework
+// Copyright Gamua GmbH. All Rights Reserved.
+//
+// This program is free software. You can redistribute and/or modify it
+// in accordance with the terms of the accompanying license agreement.
+//
+// =================================================================================================
+
+package starling.display
+{
+ import flash.geom.Point;
+
+ import starling.geom.Polygon;
+ import starling.rendering.IndexData;
+ import starling.rendering.VertexData;
+
+ /** A display object supporting basic vector drawing functionality. In its current state,
+ * the main use of this class is to provide a range of forms that can be used as masks.
+ */
+ public class Canvas extends DisplayObjectContainer
+ {
+ private var _polygons:Vector.;
+ private var _fillColor:uint;
+ private var _fillAlpha:Number;
+
+ /** Creates a new (empty) Canvas. Call one or more of the 'draw' methods to add content. */
+ public function Canvas()
+ {
+ _polygons = new [];
+ _fillColor = 0xffffff;
+ _fillAlpha = 1.0;
+ touchGroup = true;
+ }
+
+ /** @inheritDoc */
+ public override function dispose():void
+ {
+ _polygons.length = 0;
+ super.dispose();
+ }
+
+ /** @inheritDoc */
+ public override function hitTest(localPoint:Point):DisplayObject
+ {
+ if (!visible || !touchable || !hitTestMask(localPoint)) return null;
+
+ // we could also use the standard hit test implementation, but the polygon class can
+ // do that much more efficiently (it contains custom implementations for circles, etc).
+
+ for (var i:int = 0, len:int = _polygons.length; i < len; ++i)
+ if (_polygons[i].containsPoint(localPoint)) return this;
+
+ return null;
+ }
+
+ /** Draws a circle. */
+ public function drawCircle(x:Number, y:Number, radius:Number):void
+ {
+ appendPolygon(Polygon.createCircle(x, y, radius));
+ }
+
+ /** Draws an ellipse. */
+ public function drawEllipse(x:Number, y:Number, width:Number, height:Number):void
+ {
+ var radiusX:Number = width / 2.0;
+ var radiusY:Number = height / 2.0;
+
+ appendPolygon(Polygon.createEllipse(x + radiusX, y + radiusY, radiusX, radiusY));
+ }
+
+ /** Draws a rectangle. */
+ public function drawRectangle(x:Number, y:Number, width:Number, height:Number):void
+ {
+ appendPolygon(Polygon.createRectangle(x, y, width, height));
+ }
+
+ /** Draws an arbitrary polygon. */
+ public function drawPolygon(polygon:Polygon):void
+ {
+ appendPolygon(polygon);
+ }
+
+ /** Specifies a simple one-color fill that subsequent calls to drawing methods
+ * (such as drawCircle()) will use. */
+ public function beginFill(color:uint=0xffffff, alpha:Number=1.0):void
+ {
+ _fillColor = color;
+ _fillAlpha = alpha;
+ }
+
+ /** Resets the color to 'white' and alpha to '1'. */
+ public function endFill():void
+ {
+ _fillColor = 0xffffff;
+ _fillAlpha = 1.0;
+ }
+
+ /** Removes all existing vertices. */
+ public function clear():void
+ {
+ removeChildren(0, -1, true);
+ _polygons.length = 0;
+ }
+
+ private function appendPolygon(polygon:Polygon):void
+ {
+ var vertexData:VertexData = new VertexData();
+ var indexData:IndexData = new IndexData(polygon.numTriangles * 3);
+
+ polygon.triangulate(indexData);
+ polygon.copyToVertexData(vertexData);
+
+ vertexData.colorize("color", _fillColor, _fillAlpha);
+
+ addChild(new Mesh(vertexData, indexData));
+ _polygons[_polygons.length] = polygon;
+ }
+ }
+}
diff --git a/mobile_version/src/starling/display/DisplayObject.as b/mobile_version/src/starling/display/DisplayObject.as
new file mode 100644
index 00000000..34b1d179
--- /dev/null
+++ b/mobile_version/src/starling/display/DisplayObject.as
@@ -0,0 +1,1111 @@
+// =================================================================================================
+//
+// Starling Framework
+// Copyright Gamua GmbH. All Rights Reserved.
+//
+// This program is free software. You can redistribute and/or modify it
+// in accordance with the terms of the accompanying license agreement.
+//
+// =================================================================================================
+
+package starling.display
+{
+ import flash.errors.IllegalOperationError;
+ import flash.geom.Matrix;
+ import flash.geom.Matrix3D;
+ import flash.geom.Point;
+ import flash.geom.Rectangle;
+ import flash.geom.Vector3D;
+ import flash.system.Capabilities;
+ import flash.ui.Mouse;
+ import flash.ui.MouseCursor;
+ import flash.utils.getQualifiedClassName;
+
+ import starling.core.Starling;
+ import starling.core.starling_internal;
+ import starling.errors.AbstractClassError;
+ import starling.errors.AbstractMethodError;
+ import starling.events.Event;
+ import starling.events.EventDispatcher;
+ import starling.events.TouchEvent;
+ import starling.filters.FragmentFilter;
+ import starling.rendering.BatchToken;
+ import starling.rendering.Painter;
+ import starling.utils.Align;
+ import starling.utils.MathUtil;
+ import starling.utils.MatrixUtil;
+
+ use namespace starling_internal;
+
+ /** Dispatched when an object is added to a parent. */
+ [Event(name="added", type="starling.events.Event")]
+
+ /** Dispatched when an object is connected to the stage (directly or indirectly). */
+ [Event(name="addedToStage", type="starling.events.Event")]
+
+ /** Dispatched when an object is removed from its parent. */
+ [Event(name="removed", type="starling.events.Event")]
+
+ /** Dispatched when an object is removed from the stage and won't be rendered any longer. */
+ [Event(name="removedFromStage", type="starling.events.Event")]
+
+ /** Dispatched once every frame on every object that is connected to the stage. */
+ [Event(name="enterFrame", type="starling.events.EnterFrameEvent")]
+
+ /** Dispatched when an object is touched. Bubbles. */
+ [Event(name="touch", type="starling.events.TouchEvent")]
+
+ /** Dispatched when a key on the keyboard is released. */
+ [Event(name="keyUp", type="starling.events.KeyboardEvent")]
+
+ /** Dispatched when a key on the keyboard is pressed. */
+ [Event(name="keyDown", type="starling.events.KeyboardEvent")]
+
+ /**
+ * The DisplayObject class is the base class for all objects that are rendered on the
+ * screen.
+ *
+ *
The Display Tree
+ *
+ *
In Starling, all displayable objects are organized in a display tree. Only objects that
+ * are part of the display tree will be displayed (rendered).
+ *
+ *
The display tree consists of leaf nodes (Image, Quad) that will be rendered directly to
+ * the screen, and of container nodes (subclasses of "DisplayObjectContainer", like "Sprite").
+ * A container is simply a display object that has child nodes - which can, again, be either
+ * leaf nodes or other containers.
+ *
+ *
At the base of the display tree, there is the Stage, which is a container, too. To create
+ * a Starling application, you create a custom Sprite subclass, and Starling will add an
+ * instance of this class to the stage.
+ *
+ *
A display object has properties that define its position in relation to its parent
+ * (x, y), as well as its rotation and scaling factors (scaleX, scaleY). Use the
+ * alpha and visible properties to make an object translucent or
+ * invisible.
+ *
+ *
Every display object may be the target of touch events. If you don't want an object to be
+ * touchable, you can disable the "touchable" property. When it's disabled, neither the object
+ * nor its children will receive any more touch events.
+ *
+ * Transforming coordinates
+ *
+ *
Within the display tree, each object has its own local coordinate system. If you rotate
+ * a container, you rotate that coordinate system - and thus all the children of the
+ * container.
+ *
+ *
Sometimes you need to know where a certain point lies relative to another coordinate
+ * system. That's the purpose of the method getTransformationMatrix. It will
+ * create a matrix that represents the transformation of a point in one coordinate system to
+ * another.
+ *
+ * Customization
+ *
+ *
DisplayObject is an abstract class, which means you cannot instantiate it directly,
+ * but have to use one of its many subclasses instead. For leaf nodes, this is typically
+ * 'Mesh' or its subclasses 'Quad' and 'Image'. To customize rendering of these objects,
+ * you can use fragment filters (via the filter-property on 'DisplayObject')
+ * or mesh styles (via the style-property on 'Mesh'). Look at the respective
+ * class documentation for more information.
+ *
+ * @see DisplayObjectContainer
+ * @see Sprite
+ * @see Stage
+ * @see Mesh
+ * @see starling.filters.FragmentFilter
+ * @see starling.styles.MeshStyle
+ */
+ public class DisplayObject extends EventDispatcher
+ {
+ // private members
+
+ private var _x:Number;
+ private var _y:Number;
+ private var _pivotX:Number;
+ private var _pivotY:Number;
+ private var _scaleX:Number;
+ private var _scaleY:Number;
+ private var _skewX:Number;
+ private var _skewY:Number;
+ private var _rotation:Number;
+ private var _alpha:Number;
+ private var _visible:Boolean;
+ private var _touchable:Boolean;
+ private var _blendMode:String;
+ private var _name:String;
+ private var _useHandCursor:Boolean;
+ private var _transformationMatrix:Matrix;
+ private var _transformationMatrix3D:Matrix3D;
+ private var _orientationChanged:Boolean;
+ private var _is3D:Boolean;
+ private var _maskee:DisplayObject;
+
+ // internal members (for fast access on rendering)
+
+ /** @private */ internal var _parent:DisplayObjectContainer;
+ /** @private */ internal var _lastParentOrSelfChangeFrameID:uint;
+ /** @private */ internal var _lastChildChangeFrameID:uint;
+ /** @private */ internal var _tokenFrameID:uint;
+ /** @private */ internal var _pushToken:BatchToken = new BatchToken();
+ /** @private */ internal var _popToken:BatchToken = new BatchToken();
+ /** @private */ internal var _hasVisibleArea:Boolean;
+ /** @private */ internal var _filter:FragmentFilter;
+ /** @private */ internal var _mask:DisplayObject;
+
+ // helper objects
+
+ private static var sAncestors:Vector. = new [];
+ private static var sHelperPoint:Point = new Point();
+ private static var sHelperPoint3D:Vector3D = new Vector3D();
+ private static var sHelperPointAlt3D:Vector3D = new Vector3D();
+ private static var sHelperRect:Rectangle = new Rectangle();
+ private static var sHelperMatrix:Matrix = new Matrix();
+ private static var sHelperMatrixAlt:Matrix = new Matrix();
+ private static var sHelperMatrix3D:Matrix3D = new Matrix3D();
+ private static var sHelperMatrixAlt3D:Matrix3D = new Matrix3D();
+
+ /** @private */
+ public function DisplayObject()
+ {
+ if (Capabilities.isDebugger &&
+ getQualifiedClassName(this) == "starling.display::DisplayObject")
+ {
+ throw new AbstractClassError();
+ }
+
+ _x = _y = _pivotX = _pivotY = _rotation = _skewX = _skewY = 0.0;
+ _scaleX = _scaleY = _alpha = 1.0;
+ _visible = _touchable = _hasVisibleArea = true;
+ _blendMode = BlendMode.AUTO;
+ _transformationMatrix = new Matrix();
+ }
+
+ /** Disposes all resources of the display object.
+ * GPU buffers are released, event listeners are removed, filters and masks are disposed. */
+ public function dispose():void
+ {
+ if (_filter) _filter.dispose();
+ if (_mask) _mask.dispose();
+ removeEventListeners();
+ mask = null; // clear 'mask._maskee', just to be sure.
+ }
+
+ /** Removes the object from its parent, if it has one, and optionally disposes it. */
+ public function removeFromParent(dispose:Boolean=false):void
+ {
+ if (_parent) _parent.removeChild(this, dispose);
+ else if (dispose) this.dispose();
+ }
+
+ /** Creates a matrix that represents the transformation from the local coordinate system
+ * to another. If you pass an out-matrix, the result will be stored in this
+ * matrix instead of creating a new object. */
+ public function getTransformationMatrix(targetSpace:DisplayObject,
+ out:Matrix=null):Matrix
+ {
+ var commonParent:DisplayObject;
+ var currentObject:DisplayObject;
+
+ if (out) out.identity();
+ else out = new Matrix();
+
+ if (targetSpace == this)
+ {
+ return out;
+ }
+ else if (targetSpace == _parent || (targetSpace == null && _parent == null))
+ {
+ out.copyFrom(transformationMatrix);
+ return out;
+ }
+ else if (targetSpace == null || targetSpace == base)
+ {
+ // targetCoordinateSpace 'null' represents the target space of the base object.
+ // -> move up from this to base
+
+ currentObject = this;
+ while (currentObject != targetSpace)
+ {
+ out.concat(currentObject.transformationMatrix);
+ currentObject = currentObject._parent;
+ }
+
+ return out;
+ }
+ else if (targetSpace._parent == this) // optimization
+ {
+ targetSpace.getTransformationMatrix(this, out);
+ out.invert();
+
+ return out;
+ }
+
+ // 1. find a common parent of this and the target space
+
+ commonParent = findCommonParent(this, targetSpace);
+
+ // 2. move up from this to common parent
+
+ currentObject = this;
+ while (currentObject != commonParent)
+ {
+ out.concat(currentObject.transformationMatrix);
+ currentObject = currentObject._parent;
+ }
+
+ if (commonParent == targetSpace)
+ return out;
+
+ // 3. now move up from target until we reach the common parent
+
+ sHelperMatrix.identity();
+ currentObject = targetSpace;
+ while (currentObject != commonParent)
+ {
+ sHelperMatrix.concat(currentObject.transformationMatrix);
+ currentObject = currentObject._parent;
+ }
+
+ // 4. now combine the two matrices
+
+ sHelperMatrix.invert();
+ out.concat(sHelperMatrix);
+
+ return out;
+ }
+
+ /** Returns a rectangle that completely encloses the object as it appears in another
+ * coordinate system. If you pass an out-rectangle, the result will be
+ * stored in this rectangle instead of creating a new object. */
+ public function getBounds(targetSpace:DisplayObject, out:Rectangle=null):Rectangle
+ {
+ throw new AbstractMethodError();
+ }
+
+ /** Returns the object that is found topmost beneath a point in local coordinates, or nil
+ * if the test fails. Untouchable and invisible objects will cause the test to fail. */
+ public function hitTest(localPoint:Point):DisplayObject
+ {
+ // on a touch test, invisible or untouchable objects cause the test to fail
+ if (!_visible || !_touchable) return null;
+
+ // if we've got a mask and the hit occurs outside, fail
+ if (_mask && !hitTestMask(localPoint)) return null;
+
+ // otherwise, check bounding box
+ if (getBounds(this, sHelperRect).containsPoint(localPoint)) return this;
+ else return null;
+ }
+
+ /** Checks if a certain point is inside the display object's mask. If there is no mask,
+ * this method always returns true (because having no mask is equivalent
+ * to having one that's infinitely big). */
+ public function hitTestMask(localPoint:Point):Boolean
+ {
+ if (_mask)
+ {
+ if (_mask.stage) getTransformationMatrix(_mask, sHelperMatrixAlt);
+ else
+ {
+ sHelperMatrixAlt.copyFrom(_mask.transformationMatrix);
+ sHelperMatrixAlt.invert();
+ }
+
+ var helperPoint:Point = localPoint == sHelperPoint ? new Point() : sHelperPoint;
+ MatrixUtil.transformPoint(sHelperMatrixAlt, localPoint, helperPoint);
+ return _mask.hitTest(helperPoint) != null;
+ }
+ else return true;
+ }
+
+ /** Transforms a point from the local coordinate system to global (stage) coordinates.
+ * If you pass an out-point, the result will be stored in this point instead
+ * of creating a new object. */
+ public function localToGlobal(localPoint:Point, out:Point=null):Point
+ {
+ if (is3D)
+ {
+ sHelperPoint3D.setTo(localPoint.x, localPoint.y, 0);
+ return local3DToGlobal(sHelperPoint3D, out);
+ }
+ else
+ {
+ getTransformationMatrix(base, sHelperMatrixAlt);
+ return MatrixUtil.transformPoint(sHelperMatrixAlt, localPoint, out);
+ }
+ }
+
+ /** Transforms a point from global (stage) coordinates to the local coordinate system.
+ * If you pass an out-point, the result will be stored in this point instead
+ * of creating a new object. */
+ public function globalToLocal(globalPoint:Point, out:Point=null):Point
+ {
+ if (is3D)
+ {
+ globalToLocal3D(globalPoint, sHelperPoint3D);
+ stage.getCameraPosition(this, sHelperPointAlt3D);
+ return MathUtil.intersectLineWithXYPlane(sHelperPointAlt3D, sHelperPoint3D, out);
+ }
+ else
+ {
+ getTransformationMatrix(base, sHelperMatrixAlt);
+ sHelperMatrixAlt.invert();
+ return MatrixUtil.transformPoint(sHelperMatrixAlt, globalPoint, out);
+ }
+ }
+
+ /** Renders the display object with the help of a painter object. Never call this method
+ * directly, except from within another render method.
+ *
+ * @param painter Captures the current render state and provides utility functions
+ * for rendering.
+ */
+ public function render(painter:Painter):void
+ {
+ throw new AbstractMethodError();
+ }
+
+ /** Moves the pivot point to a certain position within the local coordinate system
+ * of the object. If you pass no arguments, it will be centered. */
+ public function alignPivot(horizontalAlign:String="center",
+ verticalAlign:String="center"):void
+ {
+ var bounds:Rectangle = getBounds(this, sHelperRect);
+ setOrientationChanged();
+
+ if (horizontalAlign == Align.LEFT) _pivotX = bounds.x;
+ else if (horizontalAlign == Align.CENTER) _pivotX = bounds.x + bounds.width / 2.0;
+ else if (horizontalAlign == Align.RIGHT) _pivotX = bounds.x + bounds.width;
+ else throw new ArgumentError("Invalid horizontal alignment: " + horizontalAlign);
+
+ if (verticalAlign == Align.TOP) _pivotY = bounds.y;
+ else if (verticalAlign == Align.CENTER) _pivotY = bounds.y + bounds.height / 2.0;
+ else if (verticalAlign == Align.BOTTOM) _pivotY = bounds.y + bounds.height;
+ else throw new ArgumentError("Invalid vertical alignment: " + verticalAlign);
+ }
+
+ // 3D transformation
+
+ /** Creates a matrix that represents the transformation from the local coordinate system
+ * to another. This method supports three dimensional objects created via 'Sprite3D'.
+ * If you pass an out-matrix, the result will be stored in this matrix
+ * instead of creating a new object. */
+ public function getTransformationMatrix3D(targetSpace:DisplayObject,
+ out:Matrix3D=null):Matrix3D
+ {
+ var commonParent:DisplayObject;
+ var currentObject:DisplayObject;
+
+ if (out) out.identity();
+ else out = new Matrix3D();
+
+ if (targetSpace == this)
+ {
+ return out;
+ }
+ else if (targetSpace == _parent || (targetSpace == null && _parent == null))
+ {
+ out.copyFrom(transformationMatrix3D);
+ return out;
+ }
+ else if (targetSpace == null || targetSpace == base)
+ {
+ // targetCoordinateSpace 'null' represents the target space of the base object.
+ // -> move up from this to base
+
+ currentObject = this;
+ while (currentObject != targetSpace)
+ {
+ out.append(currentObject.transformationMatrix3D);
+ currentObject = currentObject._parent;
+ }
+
+ return out;
+ }
+ else if (targetSpace._parent == this) // optimization
+ {
+ targetSpace.getTransformationMatrix3D(this, out);
+ out.invert();
+
+ return out;
+ }
+
+ // 1. find a common parent of this and the target space
+
+ commonParent = findCommonParent(this, targetSpace);
+
+ // 2. move up from this to common parent
+
+ currentObject = this;
+ while (currentObject != commonParent)
+ {
+ out.append(currentObject.transformationMatrix3D);
+ currentObject = currentObject._parent;
+ }
+
+ if (commonParent == targetSpace)
+ return out;
+
+ // 3. now move up from target until we reach the common parent
+
+ sHelperMatrix3D.identity();
+ currentObject = targetSpace;
+ while (currentObject != commonParent)
+ {
+ sHelperMatrix3D.append(currentObject.transformationMatrix3D);
+ currentObject = currentObject._parent;
+ }
+
+ // 4. now combine the two matrices
+
+ sHelperMatrix3D.invert();
+ out.append(sHelperMatrix3D);
+
+ return out;
+ }
+
+ /** Transforms a 3D point from the local coordinate system to global (stage) coordinates.
+ * This is achieved by projecting the 3D point onto the (2D) view plane.
+ *
+ *
If you pass an out-point, the result will be stored in this point
+ * instead of creating a new object.
*/
+ public function local3DToGlobal(localPoint:Vector3D, out:Point=null):Point
+ {
+ var stage:Stage = this.stage;
+ if (stage == null) throw new IllegalOperationError("Object not connected to stage");
+
+ getTransformationMatrix3D(stage, sHelperMatrixAlt3D);
+ MatrixUtil.transformPoint3D(sHelperMatrixAlt3D, localPoint, sHelperPoint3D);
+ return MathUtil.intersectLineWithXYPlane(stage.cameraPosition, sHelperPoint3D, out);
+ }
+
+ /** Transforms a point from global (stage) coordinates to the 3D local coordinate system.
+ * If you pass an out-vector, the result will be stored in this vector
+ * instead of creating a new object. */
+ public function globalToLocal3D(globalPoint:Point, out:Vector3D=null):Vector3D
+ {
+ var stage:Stage = this.stage;
+ if (stage == null) throw new IllegalOperationError("Object not connected to stage");
+
+ getTransformationMatrix3D(stage, sHelperMatrixAlt3D);
+ sHelperMatrixAlt3D.invert();
+ return MatrixUtil.transformCoords3D(
+ sHelperMatrixAlt3D, globalPoint.x, globalPoint.y, 0, out);
+ }
+
+ // internal methods
+
+ /** @private */
+ starling_internal function setParent(value:DisplayObjectContainer):void
+ {
+ // check for a recursion
+ var ancestor:DisplayObject = value;
+ while (ancestor != this && ancestor != null)
+ ancestor = ancestor._parent;
+
+ if (ancestor == this)
+ throw new ArgumentError("An object cannot be added as a child to itself or one " +
+ "of its children (or children's children, etc.)");
+ else
+ _parent = value;
+ }
+
+ /** @private */
+ internal function setIs3D(value:Boolean):void
+ {
+ _is3D = value;
+ }
+
+ /** @private */
+ internal function get isMask():Boolean
+ {
+ return _maskee != null;
+ }
+
+ // render cache
+
+ /** Forces the object to be redrawn in the next frame.
+ * This will prevent the object to be drawn from the render cache.
+ *
+ *
This method is called every time the object changes in any way. When creating
+ * custom mesh styles or any other custom rendering code, call this method if the object
+ * needs to be redrawn.
+ *
+ *
If the object needs to be redrawn just because it does not support the render cache,
+ * call painter.excludeFromCache() in the object's render method instead.
+ * That way, Starling's skipUnchangedFrames policy won't be disrupted.
+ */
+ public function setRequiresRedraw():void
+ {
+ var parent:DisplayObject = _parent || _maskee;
+ var frameID:int = Starling.frameID;
+
+ _lastParentOrSelfChangeFrameID = frameID;
+ _hasVisibleArea = _alpha != 0.0 && _visible && _maskee == null &&
+ _scaleX != 0.0 && _scaleY != 0.0;
+
+ while (parent && parent._lastChildChangeFrameID != frameID)
+ {
+ parent._lastChildChangeFrameID = frameID;
+ parent = parent._parent || parent._maskee;
+ }
+ }
+
+ /** Indicates if the object needs to be redrawn in the upcoming frame, i.e. if it has
+ * changed its location relative to the stage or some other aspect of its appearance
+ * since it was last rendered. */
+ public function get requiresRedraw():Boolean
+ {
+ var frameID:uint = Starling.frameID;
+
+ return _lastParentOrSelfChangeFrameID == frameID ||
+ _lastChildChangeFrameID == frameID;
+ }
+
+ /** @private Makes sure the object is not drawn from cache in the next frame.
+ * This method is meant to be called only from Painter.finishFrame(),
+ * since it requires rendering to be concluded. */
+ starling_internal function excludeFromCache():void
+ {
+ var object:DisplayObject = this;
+ var max:uint = 0xffffffff;
+
+ while (object && object._tokenFrameID != max)
+ {
+ object._tokenFrameID = max;
+ object = object._parent;
+ }
+ }
+
+ // helpers
+
+ private function setOrientationChanged():void
+ {
+ _orientationChanged = true;
+ setRequiresRedraw();
+ }
+
+ private static function findCommonParent(object1:DisplayObject,
+ object2:DisplayObject):DisplayObject
+ {
+ var currentObject:DisplayObject = object1;
+
+ while (currentObject)
+ {
+ sAncestors[sAncestors.length] = currentObject; // avoiding 'push'
+ currentObject = currentObject._parent;
+ }
+
+ currentObject = object2;
+ while (currentObject && sAncestors.indexOf(currentObject) == -1)
+ currentObject = currentObject._parent;
+
+ sAncestors.length = 0;
+
+ if (currentObject) return currentObject;
+ else throw new ArgumentError("Object not connected to target");
+ }
+
+ // stage event handling
+
+ /** @private */
+ public override function dispatchEvent(event:Event):void
+ {
+ if (event.type == Event.REMOVED_FROM_STAGE && stage == null)
+ return; // special check to avoid double-dispatch of RfS-event.
+ else
+ super.dispatchEvent(event);
+ }
+
+ // enter frame event optimization
+
+ // To avoid looping through the complete display tree each frame to find out who's
+ // listening to ENTER_FRAME events, we manage a list of them manually in the Stage class.
+ // We need to take care that (a) it must be dispatched only when the object is
+ // part of the stage, (b) it must not cause memory leaks when the user forgets to call
+ // dispose and (c) there might be multiple listeners for this event.
+
+ /** @inheritDoc */
+ public override function addEventListener(type:String, listener:Function):void
+ {
+ if (type == Event.ENTER_FRAME && !hasEventListener(type))
+ {
+ addEventListener(Event.ADDED_TO_STAGE, addEnterFrameListenerToStage);
+ addEventListener(Event.REMOVED_FROM_STAGE, removeEnterFrameListenerFromStage);
+ if (this.stage) addEnterFrameListenerToStage();
+ }
+
+ super.addEventListener(type, listener);
+ }
+
+ /** @inheritDoc */
+ public override function removeEventListener(type:String, listener:Function):void
+ {
+ super.removeEventListener(type, listener);
+
+ if (type == Event.ENTER_FRAME && !hasEventListener(type))
+ {
+ removeEventListener(Event.ADDED_TO_STAGE, addEnterFrameListenerToStage);
+ removeEventListener(Event.REMOVED_FROM_STAGE, removeEnterFrameListenerFromStage);
+ removeEnterFrameListenerFromStage();
+ }
+ }
+
+ /** @inheritDoc */
+ public override function removeEventListeners(type:String=null):void
+ {
+ if ((type == null || type == Event.ENTER_FRAME) && hasEventListener(Event.ENTER_FRAME))
+ {
+ removeEventListener(Event.ADDED_TO_STAGE, addEnterFrameListenerToStage);
+ removeEventListener(Event.REMOVED_FROM_STAGE, removeEnterFrameListenerFromStage);
+ removeEnterFrameListenerFromStage();
+ }
+
+ super.removeEventListeners(type);
+ }
+
+ private function addEnterFrameListenerToStage():void
+ {
+ Starling.current.stage.addEnterFrameListener(this);
+ }
+
+ private function removeEnterFrameListenerFromStage():void
+ {
+ Starling.current.stage.removeEnterFrameListener(this);
+ }
+
+ // properties
+
+ /** The transformation matrix of the object relative to its parent.
+ *
+ *
If you assign a custom transformation matrix, Starling will try to figure out
+ * suitable values for x, y, scaleX, scaleY, and rotation.
+ * However, if the matrix was created in a different way, this might not be possible.
+ * In that case, Starling will apply the matrix, but not update the corresponding
+ * properties.
For 2D objects, this property returns just a 3D version of the 2D transformation
+ * matrix. Only the 'Sprite3D' class supports real 3D transformations.
+ *
+ *
CAUTION: not a copy, but the actual object!
*/
+ public function get transformationMatrix3D():Matrix3D
+ {
+ // this method needs to be overridden in 3D-supporting subclasses (like Sprite3D).
+
+ if (_transformationMatrix3D == null)
+ _transformationMatrix3D = new Matrix3D();
+
+ return MatrixUtil.convertTo3D(transformationMatrix, _transformationMatrix3D);
+ }
+
+ /** Indicates if this object or any of its parents is a 'Sprite3D' object. */
+ public function get is3D():Boolean { return _is3D; }
+
+ /** Indicates if the mouse cursor should transform into a hand while it's over the sprite.
+ * @default false */
+ public function get useHandCursor():Boolean { return _useHandCursor; }
+ public function set useHandCursor(value:Boolean):void
+ {
+ if (value == _useHandCursor) return;
+ _useHandCursor = value;
+
+ if (_useHandCursor)
+ addEventListener(TouchEvent.TOUCH, onTouch);
+ else
+ removeEventListener(TouchEvent.TOUCH, onTouch);
+ }
+
+ private function onTouch(event:TouchEvent):void
+ {
+ Mouse.cursor = event.interactsWith(this) ? MouseCursor.BUTTON : MouseCursor.AUTO;
+ }
+
+ /** The bounds of the object relative to the local coordinates of the parent. */
+ public function get bounds():Rectangle
+ {
+ return getBounds(_parent);
+ }
+
+ /** The width of the object in pixels.
+ * Note that for objects in a 3D space (connected to a Sprite3D), this value might not
+ * be accurate until the object is part of the display list. */
+ public function get width():Number { return getBounds(_parent, sHelperRect).width; }
+ public function set width(value:Number):void
+ {
+ // this method calls 'this.scaleX' instead of changing _scaleX directly.
+ // that way, subclasses reacting on size changes need to override only the scaleX method.
+
+ var actualWidth:Number;
+ var scaleIsNaN:Boolean = _scaleX != _scaleX; // avoid 'isNaN' call
+
+ if (_scaleX == 0.0 || scaleIsNaN) { scaleX = 1.0; actualWidth = width; }
+ else actualWidth = Math.abs(width / _scaleX);
+
+ if (actualWidth) scaleX = value / actualWidth;
+ }
+
+ /** The height of the object in pixels.
+ * Note that for objects in a 3D space (connected to a Sprite3D), this value might not
+ * be accurate until the object is part of the display list. */
+ public function get height():Number { return getBounds(_parent, sHelperRect).height; }
+ public function set height(value:Number):void
+ {
+ var actualHeight:Number;
+ var scaleIsNaN:Boolean = _scaleY != _scaleY; // avoid 'isNaN' call
+
+ if (_scaleY == 0.0 || scaleIsNaN) { scaleY = 1.0; actualHeight = height; }
+ else actualHeight = Math.abs(height / _scaleY);
+
+ if (actualHeight) scaleY = value / actualHeight;
+ }
+
+ /** The x coordinate of the object relative to the local coordinates of the parent. */
+ public function get x():Number { return _x; }
+ public function set x(value:Number):void
+ {
+ if (_x != value)
+ {
+ _x = value;
+ setOrientationChanged();
+ }
+ }
+
+ /** The y coordinate of the object relative to the local coordinates of the parent. */
+ public function get y():Number { return _y; }
+ public function set y(value:Number):void
+ {
+ if (_y != value)
+ {
+ _y = value;
+ setOrientationChanged();
+ }
+ }
+
+ /** The x coordinate of the object's origin in its own coordinate space (default: 0). */
+ public function get pivotX():Number { return _pivotX; }
+ public function set pivotX(value:Number):void
+ {
+ if (_pivotX != value)
+ {
+ _pivotX = value;
+ setOrientationChanged();
+ }
+ }
+
+ /** The y coordinate of the object's origin in its own coordinate space (default: 0). */
+ public function get pivotY():Number { return _pivotY; }
+ public function set pivotY(value:Number):void
+ {
+ if (_pivotY != value)
+ {
+ _pivotY = value;
+ setOrientationChanged();
+ }
+ }
+
+ /** The horizontal scale factor. '1' means no scale, negative values flip the object.
+ * @default 1 */
+ public function get scaleX():Number { return _scaleX; }
+ public function set scaleX(value:Number):void
+ {
+ if (_scaleX != value)
+ {
+ _scaleX = value;
+ setOrientationChanged();
+ }
+ }
+
+ /** The vertical scale factor. '1' means no scale, negative values flip the object.
+ * @default 1 */
+ public function get scaleY():Number { return _scaleY; }
+ public function set scaleY(value:Number):void
+ {
+ if (_scaleY != value)
+ {
+ _scaleY = value;
+ setOrientationChanged();
+ }
+ }
+
+ /** Sets both 'scaleX' and 'scaleY' to the same value. The getter simply returns the
+ * value of 'scaleX' (even if the scaling values are different). @default 1 */
+ public function get scale():Number { return scaleX; }
+ public function set scale(value:Number):void { scaleX = scaleY = value; }
+
+ /** The horizontal skew angle in radians. */
+ public function get skewX():Number { return _skewX; }
+ public function set skewX(value:Number):void
+ {
+ value = MathUtil.normalizeAngle(value);
+
+ if (_skewX != value)
+ {
+ _skewX = value;
+ setOrientationChanged();
+ }
+ }
+
+ /** The vertical skew angle in radians. */
+ public function get skewY():Number { return _skewY; }
+ public function set skewY(value:Number):void
+ {
+ value = MathUtil.normalizeAngle(value);
+
+ if (_skewY != value)
+ {
+ _skewY = value;
+ setOrientationChanged();
+ }
+ }
+
+ /** The rotation of the object in radians. (In Starling, all angles are measured
+ * in radians.) */
+ public function get rotation():Number { return _rotation; }
+ public function set rotation(value:Number):void
+ {
+ value = MathUtil.normalizeAngle(value);
+
+ if (_rotation != value)
+ {
+ _rotation = value;
+ setOrientationChanged();
+ }
+ }
+
+ /** @private Indicates if the object is rotated or skewed in any way. */
+ internal function get isRotated():Boolean
+ {
+ return _rotation != 0.0 || _skewX != 0.0 || _skewY != 0.0;
+ }
+
+ /** The opacity of the object. 0 = transparent, 1 = opaque. @default 1 */
+ public function get alpha():Number { return _alpha; }
+ public function set alpha(value:Number):void
+ {
+ if (value != _alpha)
+ {
+ _alpha = value < 0.0 ? 0.0 : (value > 1.0 ? 1.0 : value);
+ setRequiresRedraw();
+ }
+ }
+
+ /** The visibility of the object. An invisible object will be untouchable. */
+ public function get visible():Boolean { return _visible; }
+ public function set visible(value:Boolean):void
+ {
+ if (value != _visible)
+ {
+ _visible = value;
+ setRequiresRedraw();
+ }
+ }
+
+ /** Indicates if this object (and its children) will receive touch events. */
+ public function get touchable():Boolean { return _touchable; }
+ public function set touchable(value:Boolean):void { _touchable = value; }
+
+ /** The blend mode determines how the object is blended with the objects underneath.
+ * @default auto
+ * @see starling.display.BlendMode */
+ public function get blendMode():String { return _blendMode; }
+ public function set blendMode(value:String):void
+ {
+ if (value != _blendMode)
+ {
+ _blendMode = value;
+ setRequiresRedraw();
+ }
+ }
+
+ /** The name of the display object (default: null). Used by 'getChildByName()' of
+ * display object containers. */
+ public function get name():String { return _name; }
+ public function set name(value:String):void { _name = value; }
+
+ /** The filter that is attached to the display object. The starling.filters
+ * package contains several classes that define specific filters you can use. To combine
+ * several filters, assign an instance of the FilterChain class; to remove
+ * all filters, assign null.
+ *
+ *
Beware that a filter instance may only be used on one object at a time! Furthermore,
+ * when you remove or replace a filter, it is NOT disposed automatically (since you might
+ * want to reuse it on a different object).
+ *
+ * @default null
+ * @see starling.filters.FragmentFilter
+ * @see starling.filters.FilterChain
+ */
+ public function get filter():FragmentFilter { return _filter; }
+ public function set filter(value:FragmentFilter):void
+ {
+ if (value != _filter)
+ {
+ if (_filter) _filter.setTarget(null);
+ if (value) value.setTarget(this);
+
+ _filter = value;
+ setRequiresRedraw();
+ }
+ }
+
+ /** The display object that acts as a mask for the current object.
+ * Assign null to remove it.
+ *
+ *
A pixel of the masked display object will only be drawn if it is within one of the
+ * mask's polygons. Texture pixels and alpha values of the mask are not taken into
+ * account. The mask object itself is never visible.
+ *
+ *
If the mask is part of the display list, masking will occur at exactly the
+ * location it occupies on the stage. If it is not, the mask will be placed in the local
+ * coordinate system of the target object (as if it was one of its children).
+ *
+ *
For rectangular masks, you can use simple quads; for other forms (like circles
+ * or arbitrary shapes) it is recommended to use a 'Canvas' instance.
+ *
+ *
Beware that a mask will typically cause at least two additional draw calls:
+ * one to draw the mask to the stencil buffer and one to erase it. However, if the
+ * mask object is an instance of starling.display.Quad and is aligned
+ * parallel to the stage axes, rendering will be optimized: instead of using the
+ * stencil buffer, the object will be clipped using the scissor rectangle. That's
+ * faster and reduces the number of draw calls, so make use of this when possible.
+ *
+ * @see Canvas
+ * @default null
+ */
+ public function get mask():DisplayObject { return _mask; }
+ public function set mask(value:DisplayObject):void
+ {
+ if (_mask != value)
+ {
+ if (_mask) _mask._maskee = null;
+ if (value)
+ {
+ value._maskee = this;
+ value._hasVisibleArea = false;
+ }
+
+ _mask = value;
+ setRequiresRedraw();
+ }
+ }
+
+ /** The display object container that contains this display object. */
+ public function get parent():DisplayObjectContainer { return _parent; }
+
+ /** The topmost object in the display tree the object is part of. */
+ public function get base():DisplayObject
+ {
+ var currentObject:DisplayObject = this;
+ while (currentObject._parent) currentObject = currentObject._parent;
+ return currentObject;
+ }
+
+ /** The root object the display object is connected to (i.e. an instance of the class
+ * that was passed to the Starling constructor), or null if the object is not connected
+ * to the stage. */
+ public function get root():DisplayObject
+ {
+ var currentObject:DisplayObject = this;
+ while (currentObject._parent)
+ {
+ if (currentObject._parent is Stage) return currentObject;
+ else currentObject = currentObject.parent;
+ }
+
+ return null;
+ }
+
+ /** The stage the display object is connected to, or null if it is not connected
+ * to the stage. */
+ public function get stage():Stage { return this.base as Stage; }
+ }
+}
diff --git a/mobile_version/src/starling/display/DisplayObjectContainer.as b/mobile_version/src/starling/display/DisplayObjectContainer.as
new file mode 100644
index 00000000..c3962bca
--- /dev/null
+++ b/mobile_version/src/starling/display/DisplayObjectContainer.as
@@ -0,0 +1,508 @@
+// =================================================================================================
+//
+// Starling Framework
+// Copyright Gamua GmbH. All Rights Reserved.
+//
+// This program is free software. You can redistribute and/or modify it
+// in accordance with the terms of the accompanying license agreement.
+//
+// =================================================================================================
+
+package starling.display
+{
+ import flash.geom.Matrix;
+ import flash.geom.Point;
+ import flash.geom.Rectangle;
+ import flash.system.Capabilities;
+ import flash.utils.getQualifiedClassName;
+
+ import starling.core.starling_internal;
+ import starling.errors.AbstractClassError;
+ import starling.events.Event;
+ import starling.filters.FragmentFilter;
+ import starling.rendering.BatchToken;
+ import starling.rendering.Painter;
+ import starling.utils.MatrixUtil;
+
+ use namespace starling_internal;
+
+ /**
+ * A DisplayObjectContainer represents a collection of display objects.
+ * It is the base class of all display objects that act as a container for other objects. By
+ * maintaining an ordered list of children, it defines the back-to-front positioning of the
+ * children within the display tree.
+ *
+ *
A container does not a have size in itself. The width and height properties represent the
+ * extents of its children. Changing those properties will scale all children accordingly.
+ *
+ *
As this is an abstract class, you can't instantiate it directly, but have to
+ * use a subclass instead. The most lightweight container class is "Sprite".
+ *
+ * Adding and removing children
+ *
+ *
The class defines methods that allow you to add or remove children. When you add a child,
+ * it will be added at the frontmost position, possibly occluding a child that was added
+ * before. You can access the children via an index. The first child will have index 0, the
+ * second child index 1, etc.
+ *
+ * Adding and removing objects from a container triggers non-bubbling events.
+ *
+ *
+ *
Event.ADDED: the object was added to a parent.
+ *
Event.ADDED_TO_STAGE: the object was added to a parent that is
+ * connected to the stage, thus becoming visible now.
+ *
Event.REMOVED: the object was removed from a parent.
+ *
Event.REMOVED_FROM_STAGE: the object was removed from a parent that
+ * is connected to the stage, thus becoming invisible now.
+ *
+ *
+ * Especially the ADDED_TO_STAGE event is very helpful, as it allows you to
+ * automatically execute some logic (e.g. start an animation) when an object is rendered the
+ * first time.
+ *
+ * @see Sprite
+ * @see DisplayObject
+ */
+ public class DisplayObjectContainer extends DisplayObject
+ {
+ // members
+
+ private var _children:Vector.;
+ private var _touchGroup:Boolean;
+
+ // helper objects
+ private static var sHelperMatrix:Matrix = new Matrix();
+ private static var sHelperPoint:Point = new Point();
+ private static var sBroadcastListeners:Vector. = new [];
+ private static var sSortBuffer:Vector. = new [];
+ private static var sCacheToken:BatchToken = new BatchToken();
+
+ // construction
+
+ /** @private */
+ public function DisplayObjectContainer()
+ {
+ if (Capabilities.isDebugger &&
+ getQualifiedClassName(this) == "starling.display::DisplayObjectContainer")
+ {
+ throw new AbstractClassError();
+ }
+
+ _children = new [];
+ }
+
+ /** Disposes the resources of all children. */
+ public override function dispose():void
+ {
+ for (var i:int=_children.length-1; i>=0; --i)
+ _children[i].dispose();
+
+ super.dispose();
+ }
+
+ // child management
+
+ /** Adds a child to the container. It will be at the frontmost position. */
+ public function addChild(child:DisplayObject):DisplayObject
+ {
+ return addChildAt(child, _children.length);
+ }
+
+ /** Adds a child to the container at a certain index. */
+ public function addChildAt(child:DisplayObject, index:int):DisplayObject
+ {
+ var numChildren:int = _children.length;
+
+ if (index >= 0 && index <= numChildren)
+ {
+ setRequiresRedraw();
+
+ if (child.parent == this)
+ {
+ setChildIndex(child, index); // avoids dispatching events
+ }
+ else
+ {
+ _children.insertAt(index, child);
+
+ child.removeFromParent();
+ child.setParent(this);
+ child.dispatchEventWith(Event.ADDED, true);
+
+ if (stage)
+ {
+ var container:DisplayObjectContainer = child as DisplayObjectContainer;
+ if (container) container.broadcastEventWith(Event.ADDED_TO_STAGE);
+ else child.dispatchEventWith(Event.ADDED_TO_STAGE);
+ }
+ }
+
+ return child;
+ }
+ else
+ {
+ throw new RangeError("Invalid child index");
+ }
+ }
+
+ /** Removes a child from the container. If the object is not a child, the method returns
+ * null. If requested, the child will be disposed right away. */
+ public function removeChild(child:DisplayObject, dispose:Boolean=false):DisplayObject
+ {
+ var childIndex:int = getChildIndex(child);
+ if (childIndex != -1) return removeChildAt(childIndex, dispose);
+ else return null;
+ }
+
+ /** Removes a child at a certain index. The index positions of any display objects above
+ * the child are decreased by 1. If requested, the child will be disposed right away. */
+ public function removeChildAt(index:int, dispose:Boolean=false):DisplayObject
+ {
+ if (index >= 0 && index < _children.length)
+ {
+ setRequiresRedraw();
+
+ var child:DisplayObject = _children[index];
+ child.dispatchEventWith(Event.REMOVED, true);
+
+ if (stage)
+ {
+ var container:DisplayObjectContainer = child as DisplayObjectContainer;
+ if (container) container.broadcastEventWith(Event.REMOVED_FROM_STAGE);
+ else child.dispatchEventWith(Event.REMOVED_FROM_STAGE);
+ }
+
+ child.setParent(null);
+ index = _children.indexOf(child); // index might have changed by event handler
+ if (index >= 0) _children.removeAt(index);
+ if (dispose) child.dispose();
+
+ return child;
+ }
+ else
+ {
+ throw new RangeError("Invalid child index");
+ }
+ }
+
+ /** Removes a range of children from the container (endIndex included).
+ * If no arguments are given, all children will be removed. */
+ public function removeChildren(beginIndex:int=0, endIndex:int=-1, dispose:Boolean=false):void
+ {
+ if (endIndex < 0 || endIndex >= numChildren)
+ endIndex = numChildren - 1;
+
+ for (var i:int=beginIndex; i<=endIndex; ++i)
+ removeChildAt(beginIndex, dispose);
+ }
+
+ /** Returns a child object at a certain index. If you pass a negative index,
+ * '-1' will return the last child, '-2' the second to last child, etc. */
+ public function getChildAt(index:int):DisplayObject
+ {
+ var numChildren:int = _children.length;
+
+ if (index < 0)
+ index = numChildren + index;
+
+ if (index >= 0 && index < numChildren)
+ return _children[index];
+ else
+ throw new RangeError("Invalid child index");
+ }
+
+ /** Returns a child object with a certain name (non-recursively). */
+ public function getChildByName(name:String):DisplayObject
+ {
+ var numChildren:int = _children.length;
+ for (var i:int=0; i out.x) minX = out.x;
+ if (maxX < out.right) maxX = out.right;
+ if (minY > out.y) minY = out.y;
+ if (maxY < out.bottom) maxY = out.bottom;
+ }
+
+ out.setTo(minX, minY, maxX - minX, maxY - minY);
+ }
+
+ return out;
+ }
+
+ /** @inheritDoc */
+ public override function hitTest(localPoint:Point):DisplayObject
+ {
+ if (!visible || !touchable || !hitTestMask(localPoint)) return null;
+
+ var target:DisplayObject = null;
+ var localX:Number = localPoint.x;
+ var localY:Number = localPoint.y;
+ var numChildren:int = _children.length;
+
+ for (var i:int = numChildren - 1; i >= 0; --i) // front to back!
+ {
+ var child:DisplayObject = _children[i];
+ if (child.isMask) continue;
+
+ sHelperMatrix.copyFrom(child.transformationMatrix);
+ sHelperMatrix.invert();
+
+ MatrixUtil.transformCoords(sHelperMatrix, localX, localY, sHelperPoint);
+ target = child.hitTest(sHelperPoint);
+
+ if (target) return _touchGroup ? this : target;
+ }
+
+ return null;
+ }
+
+ /** @inheritDoc */
+ public override function render(painter:Painter):void
+ {
+ var numChildren:int = _children.length;
+ var frameID:uint = painter.frameID;
+ var cacheEnabled:Boolean = frameID !=0;
+ var selfOrParentChanged:Boolean = _lastParentOrSelfChangeFrameID == frameID;
+
+ for (var i:int=0; i, compareFunc:Function,
+ startIndex:int, length:int,
+ buffer:Vector.):void
+ {
+ // This is a port of the C++ merge sort algorithm shown here:
+ // http://www.cprogramming.com/tutorial/computersciencetheory/mergesort.html
+
+ if (length > 1)
+ {
+ var i:int;
+ var endIndex:int = startIndex + length;
+ var halfLength:int = length / 2;
+ var l:int = startIndex; // current position in the left subvector
+ var r:int = startIndex + halfLength; // current position in the right subvector
+
+ // sort each subvector
+ mergeSort(input, compareFunc, startIndex, halfLength, buffer);
+ mergeSort(input, compareFunc, startIndex + halfLength, length - halfLength, buffer);
+
+ // merge the vectors, using the buffer vector for temporary storage
+ for (i = 0; i < length; i++)
+ {
+ // Check to see if any elements remain in the left vector;
+ // if so, we check if there are any elements left in the right vector;
+ // if so, we compare them. Otherwise, we know that the merge must
+ // take the element from the left vector. */
+ if (l < startIndex + halfLength &&
+ (r == endIndex || compareFunc(input[l], input[r]) <= 0))
+ {
+ buffer[i] = input[l];
+ l++;
+ }
+ else
+ {
+ buffer[i] = input[r];
+ r++;
+ }
+ }
+
+ // copy the sorted subvector back to the input
+ for(i = startIndex; i < endIndex; i++)
+ input[i] = buffer[int(i - startIndex)];
+ }
+ }
+
+ /** @private */
+ internal function getChildEventListeners(object:DisplayObject, eventType:String,
+ listeners:Vector.):void
+ {
+ var container:DisplayObjectContainer = object as DisplayObjectContainer;
+
+ if (object.hasEventListener(eventType))
+ listeners[listeners.length] = object; // avoiding 'push'
+
+ if (container)
+ {
+ var children:Vector. = container._children;
+ var numChildren:int = children.length;
+
+ for (var i:int=0; iTypically, the Image class will act as an equivalent of Flash's Bitmap class. Instead
+ * of BitmapData, Starling uses textures to represent the pixels of an image. To display a
+ * texture, you have to map it onto a quad - and that's what the Image class is for.
+ *
+ *
While the base class Quad already supports textures, the Image
+ * class adds some additional functionality.
+ *
+ *
First of all, it provides a convenient constructor that will automatically synchronize
+ * the size of the image with the displayed texture.
+ *
+ *
Furthermore, it adds support for a "Scale9" grid. This splits up the image into
+ * nine regions, the corners of which will always maintain their original size.
+ * The center region stretches in both directions to fill the remaining space; the side
+ * regions will stretch accordingly in either horizontal or vertical direction.
+ *
+ *
Finally, you can repeat a texture horizontally and vertically within the image's region,
+ * just like the tiles of a wallpaper. Use the tileGrid property to do that.
+ *
+ * @see starling.textures.Texture
+ * @see Quad
+ */
+ public class Image extends Quad
+ {
+ private var _scale9Grid:Rectangle;
+ private var _tileGrid:Rectangle;
+
+ // helper objects
+ private static var sPadding:Padding = new Padding();
+ private static var sBounds:Rectangle = new Rectangle();
+ private static var sBasCols:Vector. = new Vector.(3, true);
+ private static var sBasRows:Vector. = new Vector.(3, true);
+ private static var sPosCols:Vector. = new Vector.(3, true);
+ private static var sPosRows:Vector. = new Vector.(3, true);
+ private static var sTexCols:Vector. = new Vector.(3, true);
+ private static var sTexRows:Vector. = new Vector.(3, true);
+
+ /** Creates an image with a texture mapped onto it. */
+ public function Image(texture:Texture)
+ {
+ super(100, 100);
+ this.texture = texture;
+ readjustSize();
+ }
+
+ /** The current scaling grid that is in effect. If set to null, the image is scaled just
+ * like any other display object; assigning a rectangle will divide the image into a grid
+ * of nine regions, based on the center rectangle. The four corners of this grid will
+ * always maintain their original size; the other regions will stretch (horizontally,
+ * vertically, or both) to fill the complete area.
+ *
+ *
Notes:
+ *
+ *
+ *
Assigning a Scale9 rectangle will change the number of vertices to a maximum of 16
+ * (less if possible) and all vertices will be colored like vertex 0 (the top left vertex).
+ *
+ *
For Scale3-grid behavior, assign a zero size for all but the center row / column.
+ * This will cause the 'caps' to scale in a way that leaves the aspect ratio intact.
+ *
An image can have either a scale9Grid or a tileGrid, but
+ * not both. Assigning one will delete the other.
+ *
Changes will only be applied on assignment. To force an update, simply call
+ * image.scale9Grid = image.scale9Grid.
+ *
Assignment causes an implicit call to readjustSize(),
+ * and the same will happen when the texture is changed afterwards.
+ *
+ *
+ * @default null
+ */
+ public function get scale9Grid():Rectangle { return _scale9Grid; }
+ public function set scale9Grid(value:Rectangle):void
+ {
+ if (value)
+ {
+ if (_scale9Grid == null) _scale9Grid = value.clone();
+ else _scale9Grid.copyFrom(value);
+
+ readjustSize();
+ _tileGrid = null;
+ }
+ else _scale9Grid = null;
+
+ setupVertices();
+ }
+
+ /** The current tiling grid that is in effect. If set to null, the image is scaled just
+ * like any other display object; assigning a rectangle will divide the image into a grid
+ * displaying the current texture in each and every cell. The assigned rectangle points
+ * to the bounds of one cell; all other elements will be calculated accordingly. A zero
+ * or negative value for the rectangle's width or height will be replaced with the actual
+ * texture size. Thus, you can make a 2x2 grid simply like this:
+ *
+ *
+ * var image:Image = new Image(texture);
+ * image.tileGrid = new Rectangle();
+ * image.scale = 2;
+ *
+ *
Notes:
+ *
+ *
+ *
Assigning a tile rectangle will change the number of vertices to whatever is
+ * required by the grid. New vertices will be colored just like vertex 0 (the top left
+ * vertex).
+ *
An image can have either a scale9Grid or a tileGrid, but
+ * not both. Assigning one will delete the other.
+ *
Changes will only be applied on assignment. To force an update, simply call
+ * image.tileGrid = image.tileGrid.
+ *
+ *
+ * @default null
+ */
+ public function get tileGrid():Rectangle { return _tileGrid; }
+ public function set tileGrid(value:Rectangle):void
+ {
+ if (value)
+ {
+ if (_tileGrid == null) _tileGrid = value.clone();
+ else _tileGrid.copyFrom(value);
+
+ _scale9Grid = null;
+ }
+ else _tileGrid = null;
+
+ setupVertices();
+ }
+
+ /** @private */
+ override protected function setupVertices():void
+ {
+ if (texture && _scale9Grid) setupScale9Grid();
+ else if (texture && _tileGrid) setupTileGrid();
+ else super.setupVertices();
+ }
+
+ /** @private */
+ override public function set scaleX(value:Number):void
+ {
+ super.scaleX = value;
+ if (texture && (_scale9Grid || _tileGrid)) setupVertices();
+ }
+
+ /** @private */
+ override public function set scaleY(value:Number):void
+ {
+ super.scaleY = value;
+ if (texture && (_scale9Grid || _tileGrid)) setupVertices();
+ }
+
+ /** @private */
+ override public function set texture(value:Texture):void
+ {
+ if (value != texture)
+ {
+ super.texture = value;
+ if (_scale9Grid && value) readjustSize();
+ }
+ }
+
+ // vertex setup
+
+ private function setupScale9Grid():void
+ {
+ var texture:Texture = this.texture;
+ var frame:Rectangle = texture.frame;
+ var absScaleX:Number = scaleX > 0 ? scaleX : -scaleX;
+ var absScaleY:Number = scaleY > 0 ? scaleY : -scaleY;
+
+ // If top and bottom row / left and right column are empty, this is actually
+ // a scale3 grid. In that case, we want the 'caps' to maintain their aspect ratio.
+
+ if (MathUtil.isEquivalent(_scale9Grid.width, texture.frameWidth))
+ absScaleY /= absScaleX;
+ else if (MathUtil.isEquivalent(_scale9Grid.height, texture.frameHeight))
+ absScaleX /= absScaleY;
+
+ var invScaleX:Number = 1.0 / absScaleX;
+ var invScaleY:Number = 1.0 / absScaleY;
+ var vertexData:VertexData = this.vertexData;
+ var indexData:IndexData = this.indexData;
+ var prevNumVertices:int = vertexData.numVertices;
+ var numVertices:int, numQuads:int;
+ var correction:Number;
+
+ // The following rectangles are used to figure everything out.
+ // The meaning of each is depicted in this sketch: http://i.imgur.com/KUcv71O.jpg
+
+ var gridCenter:Rectangle = Pool.getRectangle();
+ var textureBounds:Rectangle = Pool.getRectangle();
+ var pixelBounds:Rectangle = Pool.getRectangle();
+ var intersection:Rectangle = Pool.getRectangle();
+
+ gridCenter.copyFrom(_scale9Grid);
+ textureBounds.setTo(0, 0, texture.frameWidth, texture.frameHeight);
+
+ if (frame) pixelBounds.setTo(-frame.x, -frame.y, texture.width, texture.height);
+ else pixelBounds.copyFrom(textureBounds);
+
+ // calculate 3x3 grid according to texture and scale9 properties,
+ // taking special care about the texture frame (headache included)
+
+ RectangleUtil.intersect(gridCenter, pixelBounds, intersection);
+
+ sBasCols[0] = sBasCols[2] = 0;
+ sBasRows[0] = sBasRows[2] = 0;
+ sBasCols[1] = intersection.width;
+ sBasRows[1] = intersection.height;
+
+ if (pixelBounds.x < gridCenter.x)
+ sBasCols[0] = gridCenter.x - pixelBounds.x;
+
+ if (pixelBounds.y < gridCenter.y)
+ sBasRows[0] = gridCenter.y - pixelBounds.y;
+
+ if (pixelBounds.right > gridCenter.right)
+ sBasCols[2] = pixelBounds.right - gridCenter.right;
+
+ if (pixelBounds.bottom > gridCenter.bottom)
+ sBasRows[2] = pixelBounds.bottom - gridCenter.bottom;
+
+ // set vertex positions
+
+ if (pixelBounds.x < gridCenter.x)
+ sPadding.left = pixelBounds.x * invScaleX;
+ else
+ sPadding.left = gridCenter.x * invScaleX + pixelBounds.x - gridCenter.x;
+
+ if (pixelBounds.right > gridCenter.right)
+ sPadding.right = (textureBounds.width - pixelBounds.right) * invScaleX;
+ else
+ sPadding.right = (textureBounds.width - gridCenter.right) * invScaleX + gridCenter.right - pixelBounds.right;
+
+ if (pixelBounds.y < gridCenter.y)
+ sPadding.top = pixelBounds.y * invScaleY;
+ else
+ sPadding.top = gridCenter.y * invScaleY + pixelBounds.y - gridCenter.y;
+
+ if (pixelBounds.bottom > gridCenter.bottom)
+ sPadding.bottom = (textureBounds.height - pixelBounds.bottom) * invScaleY;
+ else
+ sPadding.bottom = (textureBounds.height - gridCenter.bottom) * invScaleY + gridCenter.bottom - pixelBounds.bottom;
+
+ sPosCols[0] = sBasCols[0] * invScaleX;
+ sPosCols[2] = sBasCols[2] * invScaleX;
+ sPosCols[1] = textureBounds.width - sPadding.left - sPadding.right - sPosCols[0] - sPosCols[2];
+
+ sPosRows[0] = sBasRows[0] * invScaleY;
+ sPosRows[2] = sBasRows[2] * invScaleY;
+ sPosRows[1] = textureBounds.height - sPadding.top - sPadding.bottom - sPosRows[0] - sPosRows[2];
+
+ // if the total width / height becomes smaller than the outer columns / rows,
+ // we hide the center column / row and scale the rest normally.
+
+ if (sPosCols[1] <= 0)
+ {
+ correction = textureBounds.width / (textureBounds.width - gridCenter.width) * absScaleX;
+ sPadding.left *= correction;
+ sPosCols[0] *= correction;
+ sPosCols[1] = 0.0;
+ sPosCols[2] *= correction;
+ }
+
+ if (sPosRows[1] <= 0)
+ {
+ correction = textureBounds.height / (textureBounds.height - gridCenter.height) * absScaleY;
+ sPadding.top *= correction;
+ sPosRows[0] *= correction;
+ sPosRows[1] = 0.0;
+ sPosRows[2] *= correction;
+ }
+
+ // now set the texture coordinates
+
+ sTexCols[0] = sBasCols[0] / pixelBounds.width;
+ sTexCols[2] = sBasCols[2] / pixelBounds.width;
+ sTexCols[1] = 1.0 - sTexCols[0] - sTexCols[2];
+
+ sTexRows[0] = sBasRows[0] / pixelBounds.height;
+ sTexRows[2] = sBasRows[2] / pixelBounds.height;
+ sTexRows[1] = 1.0 - sTexRows[0] - sTexRows[2];
+
+ numVertices = setupScale9GridAttributes(
+ sPadding.left, sPadding.top, sPosCols, sPosRows, sTexCols, sTexRows);
+
+ // update indices
+
+ numQuads = numVertices / 4;
+ vertexData.numVertices = numVertices;
+ indexData.numIndices = 0;
+
+ for (var i:int=0; i, posRows:Vector.,
+ texCols:Vector., texRows:Vector.):int
+ {
+ const posAttr:String = "position";
+ const texAttr:String = "texCoords";
+
+ var row:int, col:int;
+ var colWidthPos:Number, rowHeightPos:Number;
+ var colWidthTex:Number, rowHeightTex:Number;
+ var vertexData:VertexData = this.vertexData;
+ var texture:Texture = this.texture;
+ var currentX:Number = startX;
+ var currentY:Number = startY;
+ var currentU:Number = 0.0;
+ var currentV:Number = 0.0;
+ var vertexID:int = 0;
+
+ for (row = 0; row < 3; ++row)
+ {
+ rowHeightPos = posRows[row];
+ rowHeightTex = texRows[row];
+
+ if (rowHeightPos > 0)
+ {
+ for (col = 0; col < 3; ++col)
+ {
+ colWidthPos = posCols[col];
+ colWidthTex = texCols[col];
+
+ if (colWidthPos > 0)
+ {
+ vertexData.setPoint(vertexID, posAttr, currentX, currentY);
+ texture.setTexCoords(vertexData, vertexID, texAttr, currentU, currentV);
+ vertexID++;
+
+ vertexData.setPoint(vertexID, posAttr, currentX + colWidthPos, currentY);
+ texture.setTexCoords(vertexData, vertexID, texAttr, currentU + colWidthTex, currentV);
+ vertexID++;
+
+ vertexData.setPoint(vertexID, posAttr, currentX, currentY + rowHeightPos);
+ texture.setTexCoords(vertexData, vertexID, texAttr, currentU, currentV + rowHeightTex);
+ vertexID++;
+
+ vertexData.setPoint(vertexID, posAttr, currentX + colWidthPos, currentY + rowHeightPos);
+ texture.setTexCoords(vertexData, vertexID, texAttr, currentU + colWidthTex, currentV + rowHeightTex);
+ vertexID++;
+
+ currentX += colWidthPos;
+ }
+
+ currentU += colWidthTex;
+ }
+
+ currentY += rowHeightPos;
+ }
+
+ currentX = startX;
+ currentU = 0.0;
+ currentV += rowHeightTex;
+ }
+
+ return vertexID;
+ }
+
+ private function setupTileGrid():void
+ {
+ // calculate the grid of vertices simulating a repeating / tiled texture.
+ // again, texture frames make this somewhat more complicated than one would think.
+
+ var texture:Texture = this.texture;
+ var frame:Rectangle = texture.frame;
+ var vertexData:VertexData = this.vertexData;
+ var indexData:IndexData = this.indexData;
+ var bounds:Rectangle = getBounds(this, sBounds);
+ var prevNumVertices:int = vertexData.numVertices;
+ var color:uint = prevNumVertices ? vertexData.getColor(0) : 0xffffff;
+ var alpha:Number = prevNumVertices ? vertexData.getAlpha(0) : 1.0;
+ var invScaleX:Number = scaleX > 0 ? 1.0 / scaleX : -1.0 / scaleX;
+ var invScaleY:Number = scaleY > 0 ? 1.0 / scaleY : -1.0 / scaleY;
+ var frameWidth:Number = _tileGrid.width > 0 ? _tileGrid.width : texture.frameWidth;
+ var frameHeight:Number = _tileGrid.height > 0 ? _tileGrid.height : texture.frameHeight;
+
+ frameWidth *= invScaleX;
+ frameHeight *= invScaleY;
+
+ var tileX:Number = frame ? -frame.x * (frameWidth / frame.width) : 0;
+ var tileY:Number = frame ? -frame.y * (frameHeight / frame.height) : 0;
+ var tileWidth:Number = texture.width * (frameWidth / texture.frameWidth);
+ var tileHeight:Number = texture.height * (frameHeight / texture.frameHeight);
+ var modX:Number = (_tileGrid.x * invScaleX) % frameWidth;
+ var modY:Number = (_tileGrid.y * invScaleY) % frameHeight;
+
+ if (modX < 0) modX += frameWidth;
+ if (modY < 0) modY += frameHeight;
+
+ var startX:Number = modX + tileX;
+ var startY:Number = modY + tileY;
+
+ if (startX > (frameWidth - tileWidth)) startX -= frameWidth;
+ if (startY > (frameHeight - tileHeight)) startY -= frameHeight;
+
+ var posLeft:Number, posRight:Number, posTop:Number, posBottom:Number;
+ var texLeft:Number, texRight:Number, texTop:Number, texBottom:Number;
+ var posAttrName:String = "position";
+ var texAttrName:String = "texCoords";
+ var currentX:Number;
+ var currentY:Number = startY;
+ var vertexID:int = 0;
+
+ indexData.numIndices = 0;
+
+ while (currentY < bounds.height)
+ {
+ currentX = startX;
+
+ while (currentX < bounds.width)
+ {
+ indexData.addQuad(vertexID, vertexID + 1, vertexID + 2, vertexID + 3);
+
+ posLeft = currentX < 0 ? 0 : currentX;
+ posTop = currentY < 0 ? 0 : currentY;
+ posRight = currentX + tileWidth > bounds.width ? bounds.width : currentX + tileWidth;
+ posBottom = currentY + tileHeight > bounds.height ? bounds.height : currentY + tileHeight;
+
+ vertexData.setPoint(vertexID, posAttrName, posLeft, posTop);
+ vertexData.setPoint(vertexID + 1, posAttrName, posRight, posTop);
+ vertexData.setPoint(vertexID + 2, posAttrName, posLeft, posBottom);
+ vertexData.setPoint(vertexID + 3, posAttrName, posRight, posBottom);
+
+ texLeft = (posLeft - currentX) / tileWidth;
+ texTop = (posTop - currentY) / tileHeight;
+ texRight = (posRight - currentX) / tileWidth;
+ texBottom = (posBottom - currentY) / tileHeight;
+
+ texture.setTexCoords(vertexData, vertexID, texAttrName, texLeft, texTop);
+ texture.setTexCoords(vertexData, vertexID + 1, texAttrName, texRight, texTop);
+ texture.setTexCoords(vertexData, vertexID + 2, texAttrName, texLeft, texBottom);
+ texture.setTexCoords(vertexData, vertexID + 3, texAttrName, texRight, texBottom);
+
+ currentX += frameWidth;
+ vertexID += 4;
+ }
+
+ currentY += frameHeight;
+ }
+
+ // trim to actual size
+ vertexData.numVertices = vertexID;
+
+ for (var i:int = prevNumVertices; i < vertexID; ++i)
+ {
+ vertexData.setColor(i, "color", color);
+ vertexData.setAlpha(i, "color", alpha);
+ }
+
+ setRequiresRedraw();
+ }
+ }
+}
diff --git a/mobile_version/src/starling/display/Mesh.as b/mobile_version/src/starling/display/Mesh.as
new file mode 100644
index 00000000..82977fba
--- /dev/null
+++ b/mobile_version/src/starling/display/Mesh.as
@@ -0,0 +1,332 @@
+// =================================================================================================
+//
+// Starling Framework
+// Copyright Gamua GmbH. All Rights Reserved.
+//
+// This program is free software. You can redistribute and/or modify it
+// in accordance with the terms of the accompanying license agreement.
+//
+// =================================================================================================
+
+package starling.display
+{
+ import flash.geom.Point;
+ import flash.geom.Rectangle;
+
+ import starling.core.starling_internal;
+ import starling.geom.Polygon;
+ import starling.rendering.IndexData;
+ import starling.rendering.Painter;
+ import starling.rendering.VertexData;
+ import starling.rendering.VertexDataFormat;
+ import starling.styles.MeshStyle;
+ import starling.textures.Texture;
+ import starling.utils.MatrixUtil;
+ import starling.utils.MeshUtil;
+ import starling.utils.execute;
+
+ use namespace starling_internal;
+
+ /** The base class for all tangible (non-container) display objects, spawned up by a number
+ * of triangles.
+ *
+ *
Since Starling uses Stage3D for rendering, all rendered objects must be constructed
+ * from triangles. A mesh stores the information of its triangles through VertexData and
+ * IndexData structures. The default format stores position, color and texture coordinates
+ * for each vertex.
+ *
+ *
How a mesh is rendered depends on its style. Per default, this is an instance
+ * of the MeshStyle base class; however, subclasses may extend its behavior
+ * to add support for color transformations, normal mapping, etc.
+ *
+ * @see MeshBatch
+ * @see starling.styles.MeshStyle
+ * @see starling.rendering.VertexData
+ * @see starling.rendering.IndexData
+ */
+ public class Mesh extends DisplayObject
+ {
+ /** @private */ internal var _style:MeshStyle;
+ /** @private */ internal var _vertexData:VertexData;
+ /** @private */ internal var _indexData:IndexData;
+ /** @private */ internal var _pixelSnapping:Boolean;
+
+ private static var sDefaultStyle:Class = MeshStyle;
+ private static var sDefaultStyleFactory:Function = null;
+
+ /** Creates a new mesh with the given vertices and indices.
+ * If you don't pass a style, an instance of MeshStyle will be created
+ * for you. Note that the format of the vertex data will be matched to the
+ * given style right away. */
+ public function Mesh(vertexData:VertexData, indexData:IndexData, style:MeshStyle=null)
+ {
+ if (vertexData == null) throw new ArgumentError("VertexData must not be null");
+ if (indexData == null) throw new ArgumentError("IndexData must not be null");
+
+ _vertexData = vertexData;
+ _indexData = indexData;
+
+ setStyle(style, false);
+ }
+
+ /** @inheritDoc */
+ override public function dispose():void
+ {
+ _vertexData.clear();
+ _indexData.clear();
+
+ super.dispose();
+ }
+
+ /** @inheritDoc */
+ override public function hitTest(localPoint:Point):DisplayObject
+ {
+ if (!visible || !touchable || !hitTestMask(localPoint)) return null;
+ else return MeshUtil.containsPoint(_vertexData, _indexData, localPoint) ? this : null;
+ }
+
+ /** @inheritDoc */
+ override public function getBounds(targetSpace:DisplayObject, out:Rectangle=null):Rectangle
+ {
+ return MeshUtil.calculateBounds(_vertexData, this, targetSpace, out);
+ }
+
+ /** @inheritDoc */
+ override public function render(painter:Painter):void
+ {
+ if (_pixelSnapping)
+ MatrixUtil.snapToPixels(painter.state.modelviewMatrix, painter.pixelSize);
+
+ painter.batchMesh(this);
+ }
+
+ /** Sets the style that is used to render the mesh. Styles (which are always subclasses of
+ * MeshStyle) provide a means to completely modify the way a mesh is rendered.
+ * For example, they may add support for color transformations or normal mapping.
+ *
+ *
When assigning a new style, the vertex format will be changed to fit it.
+ * Do not use the same style instance on multiple objects! Instead, make use of
+ * style.clone() to assign an identical style to multiple meshes.
+ *
+ * @param meshStyle the style to assign. If null, the default
+ * style will be created.
+ * @param mergeWithPredecessor if enabled, all attributes of the previous style will be
+ * be copied to the new one, if possible.
+ * @see #defaultStyle
+ * @see #defaultStyleFactory
+ */
+ public function setStyle(meshStyle:MeshStyle=null, mergeWithPredecessor:Boolean=true):void
+ {
+ if (meshStyle == null) meshStyle = createDefaultMeshStyle();
+ else if (meshStyle == _style) return;
+ else if (meshStyle.target) meshStyle.target.setStyle();
+
+ if (_style)
+ {
+ if (mergeWithPredecessor) meshStyle.copyFrom(_style);
+ _style.setTarget(null);
+ }
+
+ _style = meshStyle;
+ _style.setTarget(this, _vertexData, _indexData);
+ }
+
+ private function createDefaultMeshStyle():MeshStyle
+ {
+ var meshStyle:MeshStyle;
+
+ if (sDefaultStyleFactory != null)
+ {
+ if (sDefaultStyleFactory.length == 0) meshStyle = sDefaultStyleFactory();
+ else meshStyle = sDefaultStyleFactory(this);
+ }
+
+ if (meshStyle == null)
+ meshStyle = new sDefaultStyle() as MeshStyle;
+
+ return meshStyle;
+ }
+
+ /** This method is called whenever the mesh's vertex data was changed.
+ * The base implementation simply forwards to setRequiresRedraw. */
+ public function setVertexDataChanged():void
+ {
+ setRequiresRedraw();
+ }
+
+ /** This method is called whenever the mesh's index data was changed.
+ * The base implementation simply forwards to setRequiresRedraw. */
+ public function setIndexDataChanged():void
+ {
+ setRequiresRedraw();
+ }
+
+ // vertex manipulation
+
+ /** The position of the vertex at the specified index, in the mesh's local coordinate
+ * system.
+ *
+ *
Only modify the position of a vertex if you know exactly what you're doing, as
+ * some classes might not work correctly when their vertices are moved. E.g. the
+ * Quad class expects its vertices to spawn up a perfectly rectangular
+ * area; some of its optimized methods won't work correctly if that premise is no longer
+ * fulfilled or the original bounds change.
+ */
+ public function getVertexPosition(vertexID:int, out:Point=null):Point
+ {
+ return _style.getVertexPosition(vertexID, out);
+ }
+
+ public function setVertexPosition(vertexID:int, x:Number, y:Number):void
+ {
+ _style.setVertexPosition(vertexID, x, y);
+ }
+
+ /** Returns the alpha value of the vertex at the specified index. */
+ public function getVertexAlpha(vertexID:int):Number
+ {
+ return _style.getVertexAlpha(vertexID);
+ }
+
+ /** Sets the alpha value of the vertex at the specified index to a certain value. */
+ public function setVertexAlpha(vertexID:int, alpha:Number):void
+ {
+ _style.setVertexAlpha(vertexID, alpha);
+ }
+
+ /** Returns the RGB color of the vertex at the specified index. */
+ public function getVertexColor(vertexID:int):uint
+ {
+ return _style.getVertexColor(vertexID);
+ }
+
+ /** Sets the RGB color of the vertex at the specified index to a certain value. */
+ public function setVertexColor(vertexID:int, color:uint):void
+ {
+ _style.setVertexColor(vertexID, color);
+ }
+
+ /** Returns the texture coordinates of the vertex at the specified index. */
+ public function getTexCoords(vertexID:int, out:Point = null):Point
+ {
+ return _style.getTexCoords(vertexID, out);
+ }
+
+ /** Sets the texture coordinates of the vertex at the specified index to the given values. */
+ public function setTexCoords(vertexID:int, u:Number, v:Number):void
+ {
+ _style.setTexCoords(vertexID, u, v);
+ }
+
+ // properties
+
+ /** The vertex data describing all vertices of the mesh.
+ * Any change requires a call to setRequiresRedraw. */
+ protected function get vertexData():VertexData { return _vertexData; }
+
+ /** The index data describing how the vertices are interconnected.
+ * Any change requires a call to setRequiresRedraw. */
+ protected function get indexData():IndexData { return _indexData; }
+
+ /** The style that is used to render the mesh. Styles (which are always subclasses of
+ * MeshStyle) provide a means to completely modify the way a mesh is rendered.
+ * For example, they may add support for color transformations or normal mapping.
+ *
+ *
The setter will simply forward the assignee to setStyle(value).
+ *
+ * @default MeshStyle
+ */
+ public function get style():MeshStyle { return _style; }
+ public function set style(value:MeshStyle):void
+ {
+ setStyle(value);
+ }
+
+ /** The texture that is mapped to the mesh (or null, if there is none). */
+ public function get texture():Texture { return _style.texture; }
+ public function set texture(value:Texture):void { _style.texture = value; }
+
+ /** Changes the color of all vertices to the same value.
+ * The getter simply returns the color of the first vertex. */
+ public function get color():uint { return _style.color; }
+ public function set color(value:uint):void { _style.color = value; }
+
+ /** The smoothing filter that is used for the texture.
+ * @default bilinear */
+ public function get textureSmoothing():String { return _style.textureSmoothing; }
+ public function set textureSmoothing(value:String):void { _style.textureSmoothing = value; }
+
+ /** Indicates if pixels at the edges will be repeated or clamped. Only works for
+ * power-of-two textures; for a solution that works with all kinds of textures,
+ * see Image.tileGrid. @default false */
+ public function get textureRepeat():Boolean { return _style.textureRepeat; }
+ public function set textureRepeat(value:Boolean):void { _style.textureRepeat = value; }
+
+ /** Controls whether or not the instance snaps to the nearest pixel. This can prevent the
+ * object from looking blurry when it's not exactly aligned with the pixels of the screen.
+ * @default false */
+ public function get pixelSnapping():Boolean { return _pixelSnapping; }
+ public function set pixelSnapping(value:Boolean):void { _pixelSnapping = value; }
+
+ /** The total number of vertices in the mesh. */
+ public function get numVertices():int { return _vertexData.numVertices; }
+
+ /** The total number of indices referencing vertices. */
+ public function get numIndices():int { return _indexData.numIndices; }
+
+ /** The total number of triangles in this mesh.
+ * (In other words: the number of indices divided by three.) */
+ public function get numTriangles():int { return _indexData.numTriangles; }
+
+ /** The format used to store the vertices. */
+ public function get vertexFormat():VertexDataFormat { return _style.vertexFormat; }
+
+ // static properties
+
+ /** The default style used for meshes if no specific style is provided. The default is
+ * starling.rendering.MeshStyle, and any assigned class must be a subclass
+ * of the same. */
+ public static function get defaultStyle():Class { return sDefaultStyle; }
+ public static function set defaultStyle(value:Class):void
+ {
+ sDefaultStyle = value;
+ }
+
+ /** A factory method that is used to create the 'MeshStyle' for a mesh if no specific
+ * style is provided. That's useful if you are creating a hierarchy of objects, all
+ * of which need to have a certain style. Different to the defaultStyle
+ * property, this method allows plugging in custom logic and passing arguments to the
+ * constructor. Return null to fall back to the default behavior (i.e.
+ * to instantiate defaultStyle). The mesh-parameter is optional
+ * and may be omitted.
+ *
+ *
+ * Mesh.defaultStyleFactory = function(mesh:Mesh):MeshStyle
+ * {
+ * return new ColorizeMeshStyle(Math.random() * 0xffffff);
+ * }
+ */
+ public static function get defaultStyleFactory():Function { return sDefaultStyleFactory; }
+ public static function set defaultStyleFactory(value:Function):void
+ {
+ sDefaultStyleFactory = value;
+ }
+
+ // static methods
+
+ /** Creates a mesh from the specified polygon.
+ * Vertex positions and indices will be set up according to the polygon;
+ * any other vertex attributes (e.g. texture coordinates) need to be set up manually.
+ */
+ public static function fromPolygon(polygon:Polygon, style:MeshStyle=null):Mesh
+ {
+ var vertexData:VertexData = new VertexData(null, polygon.numVertices);
+ var indexData:IndexData = new IndexData(polygon.numTriangles);
+
+ polygon.copyToVertexData(vertexData);
+ polygon.triangulate(indexData);
+
+ return new Mesh(vertexData, indexData, style);
+ }
+ }
+}
diff --git a/mobile_version/src/starling/display/MeshBatch.as b/mobile_version/src/starling/display/MeshBatch.as
new file mode 100644
index 00000000..50ae1c0e
--- /dev/null
+++ b/mobile_version/src/starling/display/MeshBatch.as
@@ -0,0 +1,300 @@
+// =================================================================================================
+//
+// Starling Framework
+// Copyright Gamua GmbH. All Rights Reserved.
+//
+// This program is free software. You can redistribute and/or modify it
+// in accordance with the terms of the accompanying license agreement.
+//
+// =================================================================================================
+
+package starling.display
+{
+ import flash.geom.Matrix;
+
+ import starling.rendering.IndexData;
+ import starling.rendering.MeshEffect;
+ import starling.rendering.Painter;
+ import starling.rendering.VertexData;
+ import starling.styles.MeshStyle;
+ import starling.utils.MatrixUtil;
+ import starling.utils.MeshSubset;
+
+ /** Combines a number of meshes to one display object and renders them efficiently.
+ *
+ *
The most basic tangible (non-container) display object in Starling is the Mesh.
+ * However, a mesh typically does not render itself; it just holds the data describing its
+ * geometry. Rendering is orchestrated by the "MeshBatch" class. As its name suggests, it
+ * acts as a batch for an arbitrary number of Mesh instances; add meshes to a batch and they
+ * are all rendered together, in one draw call.
+ *
+ *
You can only batch meshes that share similar properties, e.g. they need to have the
+ * same texture and the same blend mode. The first object you add to a batch will decide
+ * this state; call canAddMesh to find out if a new mesh shares that state.
+ * To reset the current state, you can call clear; this will also remove all
+ * geometry that has been added thus far.
+ *
+ *
Starling will use MeshBatch instances (or compatible objects) for all rendering.
+ * However, you can also instantiate MeshBatch instances yourself and add them to the display
+ * tree. That makes sense for an object containing a large number of meshes; that way, that
+ * object can be created once and then rendered very efficiently, without having to copy its
+ * vertices and indices between buffers and GPU memory.
+ *
+ * @see Mesh
+ * @see Sprite
+ */
+ public class MeshBatch extends Mesh
+ {
+ /** The maximum number of vertices that fit into one MeshBatch. */
+ public static const MAX_NUM_VERTICES:int = 65535;
+
+ private var _effect:MeshEffect;
+ private var _batchable:Boolean;
+ private var _vertexSyncRequired:Boolean;
+ private var _indexSyncRequired:Boolean;
+
+ // helper object
+ private static var sFullMeshSubset:MeshSubset = new MeshSubset();
+
+ /** Creates a new, empty MeshBatch instance. */
+ public function MeshBatch()
+ {
+ var vertexData:VertexData = new VertexData();
+ var indexData:IndexData = new IndexData();
+
+ super(vertexData, indexData);
+ }
+
+ /** @inheritDoc */
+ override public function dispose():void
+ {
+ if (_effect) _effect.dispose();
+ super.dispose();
+ }
+
+ /** This method must be called whenever the mesh's vertex data was changed. Makes
+ * sure that the vertex buffer is synchronized before rendering, and forces a redraw. */
+ override public function setVertexDataChanged():void
+ {
+ _vertexSyncRequired = true;
+ super.setVertexDataChanged();
+ }
+
+ /** This method must be called whenever the mesh's index data was changed. Makes
+ * sure that the index buffer is synchronized before rendering, and forces a redraw. */
+ override public function setIndexDataChanged():void
+ {
+ _indexSyncRequired = true;
+ super.setIndexDataChanged();
+ }
+
+ private function setVertexAndIndexDataChanged():void
+ {
+ _vertexSyncRequired = _indexSyncRequired = true;
+ }
+
+ private function syncVertexBuffer():void
+ {
+ _effect.uploadVertexData(_vertexData);
+ _vertexSyncRequired = false;
+ }
+
+ private function syncIndexBuffer():void
+ {
+ _effect.uploadIndexData(_indexData);
+ _indexSyncRequired = false;
+ }
+
+ /** Removes all geometry. */
+ public function clear():void
+ {
+ if (_parent) setRequiresRedraw();
+
+ _vertexData.numVertices = 0;
+ _indexData.numIndices = 0;
+ _vertexSyncRequired = true;
+ _indexSyncRequired = true;
+ }
+
+ /** Adds a mesh to the batch by appending its vertices and indices.
+ *
+ * @param mesh the mesh to add to the batch.
+ * @param matrix transform all vertex positions with a certain matrix. If this
+ * parameter is omitted, mesh.transformationMatrix
+ * will be used instead (except if the last parameter is enabled).
+ * @param alpha will be multiplied with each vertex' alpha value.
+ * @param subset the subset of the mesh you want to add, or null for
+ * the complete mesh.
+ * @param ignoreTransformations when enabled, the mesh's vertices will be added
+ * without transforming them in any way (no matter the value of the
+ * matrix parameter).
+ */
+ public function addMesh(mesh:Mesh, matrix:Matrix=null, alpha:Number=1.0,
+ subset:MeshSubset=null, ignoreTransformations:Boolean=false):void
+ {
+ if (ignoreTransformations) matrix = null;
+ else if (matrix == null) matrix = mesh.transformationMatrix;
+ if (subset == null) subset = sFullMeshSubset;
+
+ var targetVertexID:int = _vertexData.numVertices;
+ var targetIndexID:int = _indexData.numIndices;
+ var meshStyle:MeshStyle = mesh._style;
+
+ if (targetVertexID == 0)
+ setupFor(mesh);
+
+ meshStyle.batchVertexData(_style, targetVertexID, matrix, subset.vertexID, subset.numVertices);
+ meshStyle.batchIndexData(_style, targetIndexID, targetVertexID - subset.vertexID,
+ subset.indexID, subset.numIndices);
+
+ if (alpha != 1.0) _vertexData.scaleAlphas("color", alpha, targetVertexID, subset.numVertices);
+ if (_parent) setRequiresRedraw();
+
+ _indexSyncRequired = _vertexSyncRequired = true;
+ }
+
+ /** Adds a mesh to the batch by copying its vertices and indices to the given positions.
+ * Beware that you need to check for yourself if those positions make sense; for example,
+ * you need to make sure that they are aligned within the 3-indices groups making up
+ * the mesh's triangles.
+ *
+ *
It's easiest to only add objects with an identical setup, e.g. only quads.
+ * For the latter, indices are aligned in groups of 6 (one quad requires six indices),
+ * and the vertices in groups of 4 (one vertex for every corner).
+ */
+ public function addMeshAt(mesh:Mesh, indexID:int, vertexID:int):void
+ {
+ var numIndices:int = mesh.numIndices;
+ var numVertices:int = mesh.numVertices;
+ var matrix:Matrix = mesh.transformationMatrix;
+ var meshStyle:MeshStyle = mesh._style;
+
+ if (_vertexData.numVertices == 0)
+ setupFor(mesh);
+
+ meshStyle.batchVertexData(_style, vertexID, matrix, 0, numVertices);
+ meshStyle.batchIndexData(_style, indexID, vertexID, 0, numIndices);
+
+ if (alpha != 1.0) _vertexData.scaleAlphas("color", alpha, vertexID, numVertices);
+ if (_parent) setRequiresRedraw();
+
+ _indexSyncRequired = _vertexSyncRequired = true;
+ }
+
+ private function setupFor(mesh:Mesh):void
+ {
+ var meshStyle:MeshStyle = mesh._style;
+ var meshStyleType:Class = meshStyle.type;
+
+ if (_style.type != meshStyleType)
+ setStyle(new meshStyleType() as MeshStyle, false);
+
+ _style.copyFrom(meshStyle);
+ }
+
+ /** Indicates if the given mesh instance fits to the current state of the batch.
+ * Will always return true for the first added mesh; later calls
+ * will check if the style matches and if the maximum number of vertices is not
+ * exceeded.
+ *
+ * @param mesh the mesh to add to the batch.
+ * @param numVertices if -1, mesh.numVertices will be used
+ */
+ public function canAddMesh(mesh:Mesh, numVertices:int=-1):Boolean
+ {
+ var currentNumVertices:int = _vertexData.numVertices;
+
+ if (currentNumVertices == 0) return true;
+ if (numVertices < 0) numVertices = mesh.numVertices;
+ if (numVertices == 0) return true;
+ if (numVertices + currentNumVertices > MAX_NUM_VERTICES) return false;
+
+ return _style.canBatchWith(mesh._style);
+ }
+
+ /** If the batchable property is enabled, this method will add the batch
+ * to the painter's current batch. Otherwise, this will actually do the drawing. */
+ override public function render(painter:Painter):void
+ {
+ if (_vertexData.numVertices == 0) return;
+ if (_pixelSnapping) MatrixUtil.snapToPixels(
+ painter.state.modelviewMatrix, painter.pixelSize);
+
+ if (_batchable)
+ {
+ painter.batchMesh(this);
+ }
+ else
+ {
+ painter.finishMeshBatch();
+ painter.drawCount += 1;
+ painter.prepareToDraw();
+ painter.excludeFromCache(this);
+
+ if (_vertexSyncRequired) syncVertexBuffer();
+ if (_indexSyncRequired) syncIndexBuffer();
+
+ _style.updateEffect(_effect, painter.state);
+ _effect.render(0, _indexData.numTriangles);
+ }
+ }
+
+ /** @inheritDoc */
+ override public function setStyle(meshStyle:MeshStyle=null,
+ mergeWithPredecessor:Boolean=true):void
+ {
+ super.setStyle(meshStyle, mergeWithPredecessor);
+
+ if (_effect)
+ _effect.dispose();
+
+ _effect = style.createEffect();
+ _effect.onRestore = setVertexAndIndexDataChanged;
+ }
+
+ /** The total number of vertices in the mesh. If you change this to a smaller value,
+ * the surplus will be deleted. Make sure that no indices reference those deleted
+ * vertices! */
+ public function set numVertices(value:int):void
+ {
+ if (_vertexData.numVertices != value)
+ {
+ _vertexData.numVertices = value;
+ _vertexSyncRequired = true;
+ setRequiresRedraw();
+ }
+ }
+
+ /** The total number of indices in the mesh. If you change this to a smaller value,
+ * the surplus will be deleted. Always make sure that the number of indices
+ * is a multiple of three! */
+ public function set numIndices(value:int):void
+ {
+ if (_indexData.numIndices != value)
+ {
+ _indexData.numIndices = value;
+ _indexSyncRequired = true;
+ setRequiresRedraw();
+ }
+ }
+
+ /** Indicates if this object will be added to the painter's batch on rendering,
+ * or if it will draw itself right away.
+ *
+ *
Only batchable meshes can profit from the render cache; but batching large meshes
+ * may take up a lot of CPU time. Activate this property only if the batch contains just
+ * a handful of vertices (say, 20 quads).
+ *
+ * @default false
+ */
+ public function get batchable():Boolean { return _batchable; }
+ public function set batchable(value:Boolean):void
+ {
+ if (_batchable != value)
+ {
+ _batchable = value;
+ setRequiresRedraw();
+ }
+ }
+ }
+}
diff --git a/mobile_version/src/starling/display/MovieClip.as b/mobile_version/src/starling/display/MovieClip.as
new file mode 100644
index 00000000..320a4a2a
--- /dev/null
+++ b/mobile_version/src/starling/display/MovieClip.as
@@ -0,0 +1,479 @@
+// =================================================================================================
+//
+// Starling Framework
+// Copyright Gamua GmbH. All Rights Reserved.
+//
+// This program is free software. You can redistribute and/or modify it
+// in accordance with the terms of the accompanying license agreement.
+//
+// =================================================================================================
+
+package starling.display
+{
+ import flash.errors.IllegalOperationError;
+ import flash.media.Sound;
+ import flash.media.SoundTransform;
+
+ import starling.animation.IAnimatable;
+ import starling.events.Event;
+ import starling.textures.Texture;
+
+ /** Dispatched whenever the movie has displayed its last frame. */
+ [Event(name="complete", type="starling.events.Event")]
+
+ /** A MovieClip is a simple way to display an animation depicted by a list of textures.
+ *
+ *
Pass the frames of the movie in a vector of textures to the constructor. The movie clip
+ * will have the width and height of the first frame. If you group your frames with the help
+ * of a texture atlas (which is recommended), use the getTextures-method of the
+ * atlas to receive the textures in the correct (alphabetic) order.
+ *
+ *
You can specify the desired framerate via the constructor. You can, however, manually
+ * give each frame a custom duration. You can also play a sound whenever a certain frame
+ * appears, or execute a callback (a "frame action").
+ *
+ *
The methods play and pause control playback of the movie. You
+ * will receive an event of type Event.COMPLETE when the movie finished
+ * playback. If the movie is looping, the event is dispatched once per loop.
+ *
+ *
As any animated object, a movie clip has to be added to a juggler (or have its
+ * advanceTime method called regularly) to run. The movie will dispatch
+ * an event of type "Event.COMPLETE" whenever it has displayed its last frame.
+ *
+ * @see starling.textures.TextureAtlas
+ */
+ public class MovieClip extends Image implements IAnimatable
+ {
+ private var _frames:Vector.;
+ private var _defaultFrameDuration:Number;
+ private var _currentTime:Number;
+ private var _currentFrameID:int;
+ private var _loop:Boolean;
+ private var _playing:Boolean;
+ private var _muted:Boolean;
+ private var _wasStopped:Boolean;
+ private var _soundTransform:SoundTransform;
+
+ /** Creates a movie clip from the provided textures and with the specified default framerate.
+ * The movie will have the size of the first frame. */
+ public function MovieClip(textures:Vector., fps:Number=12)
+ {
+ if (textures.length > 0)
+ {
+ super(textures[0]);
+ init(textures, fps);
+ }
+ else
+ {
+ throw new ArgumentError("Empty texture array");
+ }
+ }
+
+ private function init(textures:Vector., fps:Number):void
+ {
+ if (fps <= 0) throw new ArgumentError("Invalid fps: " + fps);
+ var numFrames:int = textures.length;
+
+ _defaultFrameDuration = 1.0 / fps;
+ _loop = true;
+ _playing = true;
+ _currentTime = 0.0;
+ _currentFrameID = 0;
+ _wasStopped = true;
+ _frames = new [];
+
+ for (var i:int=0; i numFrames) throw new ArgumentError("Invalid frame id");
+ if (duration < 0) duration = _defaultFrameDuration;
+
+ var frame:MovieClipFrame = new MovieClipFrame(texture, duration);
+ frame.sound = sound;
+ _frames.insertAt(frameID, frame);
+
+ if (frameID == numFrames)
+ {
+ var prevStartTime:Number = frameID > 0 ? _frames[frameID - 1].startTime : 0.0;
+ var prevDuration:Number = frameID > 0 ? _frames[frameID - 1].duration : 0.0;
+ frame.startTime = prevStartTime + prevDuration;
+ }
+ else
+ updateStartTimes();
+ }
+
+ /** Removes the frame at a certain ID. The successors will move down. */
+ public function removeFrameAt(frameID:int):void
+ {
+ if (frameID < 0 || frameID >= numFrames) throw new ArgumentError("Invalid frame id");
+ if (numFrames == 1) throw new IllegalOperationError("Movie clip must not be empty");
+
+ _frames.removeAt(frameID);
+
+ if (frameID != numFrames)
+ updateStartTimes();
+ }
+
+ /** Returns the texture of a certain frame. */
+ public function getFrameTexture(frameID:int):Texture
+ {
+ if (frameID < 0 || frameID >= numFrames) throw new ArgumentError("Invalid frame id");
+ return _frames[frameID].texture;
+ }
+
+ /** Sets the texture of a certain frame. */
+ public function setFrameTexture(frameID:int, texture:Texture):void
+ {
+ if (frameID < 0 || frameID >= numFrames) throw new ArgumentError("Invalid frame id");
+ _frames[frameID].texture = texture;
+ }
+
+ /** Returns the sound of a certain frame. */
+ public function getFrameSound(frameID:int):Sound
+ {
+ if (frameID < 0 || frameID >= numFrames) throw new ArgumentError("Invalid frame id");
+ return _frames[frameID].sound;
+ }
+
+ /** Sets the sound of a certain frame. The sound will be played whenever the frame
+ * is displayed. */
+ public function setFrameSound(frameID:int, sound:Sound):void
+ {
+ if (frameID < 0 || frameID >= numFrames) throw new ArgumentError("Invalid frame id");
+ _frames[frameID].sound = sound;
+ }
+
+ /** Returns the method that is executed at a certain frame. */
+ public function getFrameAction(frameID:int):Function
+ {
+ if (frameID < 0 || frameID >= numFrames) throw new ArgumentError("Invalid frame id");
+ return _frames[frameID].action;
+ }
+
+ /** Sets an action that will be executed whenever a certain frame is reached. */
+ public function setFrameAction(frameID:int, action:Function):void
+ {
+ if (frameID < 0 || frameID >= numFrames) throw new ArgumentError("Invalid frame id");
+ _frames[frameID].action = action;
+ }
+
+ /** Returns the duration of a certain frame (in seconds). */
+ public function getFrameDuration(frameID:int):Number
+ {
+ if (frameID < 0 || frameID >= numFrames) throw new ArgumentError("Invalid frame id");
+ return _frames[frameID].duration;
+ }
+
+ /** Sets the duration of a certain frame (in seconds). */
+ public function setFrameDuration(frameID:int, duration:Number):void
+ {
+ if (frameID < 0 || frameID >= numFrames) throw new ArgumentError("Invalid frame id");
+ _frames[frameID].duration = duration;
+ updateStartTimes();
+ }
+
+ /** Reverses the order of all frames, making the clip run from end to start.
+ * Makes sure that the currently visible frame stays the same. */
+ public function reverseFrames():void
+ {
+ _frames.reverse();
+ _currentTime = totalTime - _currentTime;
+ _currentFrameID = numFrames - _currentFrameID - 1;
+ updateStartTimes();
+ }
+
+ // playback methods
+
+ /** Starts playback. Beware that the clip has to be added to a juggler, too! */
+ public function play():void
+ {
+ _playing = true;
+ }
+
+ /** Pauses playback. */
+ public function pause():void
+ {
+ _playing = false;
+ }
+
+ /** Stops playback, resetting "currentFrame" to zero. */
+ public function stop():void
+ {
+ _playing = false;
+ _wasStopped = true;
+ currentFrame = 0;
+ }
+
+ // helpers
+
+ private function updateStartTimes():void
+ {
+ var numFrames:int = this.numFrames;
+ var prevFrame:MovieClipFrame = _frames[0];
+ prevFrame.startTime = 0;
+
+ for (var i:int=1; i= restTimeInFrame)
+ {
+ changedFrame = false;
+ passedTime -= restTimeInFrame;
+ _currentTime = frame.startTime + frame.duration;
+
+ if (_currentFrameID == finalFrameID)
+ {
+ if (hasEventListener(Event.COMPLETE))
+ {
+ dispatchCompleteEvent = true;
+ }
+ else if (_loop)
+ {
+ _currentTime = 0;
+ _currentFrameID = 0;
+ changedFrame = true;
+ }
+ else return;
+ }
+ else
+ {
+ _currentFrameID += 1;
+ changedFrame = true;
+ }
+
+ frame = _frames[_currentFrameID];
+ frameAction = frame.action;
+
+ if (changedFrame)
+ frame.playSound(_soundTransform);
+
+ if (dispatchCompleteEvent)
+ {
+ texture = frame.texture;
+ dispatchEventWith(Event.COMPLETE);
+ advanceTime(passedTime);
+ return;
+ }
+ else if (frameAction != null)
+ {
+ texture = frame.texture;
+ frame.executeAction(this, _currentFrameID);
+ advanceTime(passedTime);
+ return;
+ }
+
+ restTimeInFrame = frame.duration;
+
+ // prevent a mean floating point problem (issue #851)
+ if (passedTime + 0.0001 > restTimeInFrame && passedTime - 0.0001 < restTimeInFrame)
+ passedTime = restTimeInFrame;
+ }
+
+ if (previousFrameID != _currentFrameID)
+ texture = _frames[_currentFrameID].texture;
+
+ _currentTime += passedTime;
+ }
+
+ // properties
+
+ /** The total number of frames. */
+ public function get numFrames():int { return _frames.length; }
+
+ /** The total duration of the clip in seconds. */
+ public function get totalTime():Number
+ {
+ var lastFrame:MovieClipFrame = _frames[_frames.length-1];
+ return lastFrame.startTime + lastFrame.duration;
+ }
+
+ /** The time that has passed since the clip was started (each loop starts at zero). */
+ public function get currentTime():Number { return _currentTime; }
+ public function set currentTime(value:Number):void
+ {
+ if (value < 0 || value > totalTime) throw new ArgumentError("Invalid time: " + value);
+
+ var lastFrameID:int = _frames.length - 1;
+ _currentTime = value;
+ _currentFrameID = 0;
+
+ while (_currentFrameID < lastFrameID && _frames[_currentFrameID + 1].startTime <= value)
+ ++_currentFrameID;
+
+ var frame:MovieClipFrame = _frames[_currentFrameID];
+ texture = frame.texture;
+ }
+
+ /** Indicates if the clip should loop. @default true */
+ public function get loop():Boolean { return _loop; }
+ public function set loop(value:Boolean):void { _loop = value; }
+
+ /** If enabled, no new sounds will be started during playback. Sounds that are already
+ * playing are not affected. */
+ public function get muted():Boolean { return _muted; }
+ public function set muted(value:Boolean):void { _muted = value; }
+
+ /** The SoundTransform object used for playback of all frame sounds. @default null */
+ public function get soundTransform():SoundTransform { return _soundTransform; }
+ public function set soundTransform(value:SoundTransform):void { _soundTransform = value; }
+
+ /** The index of the frame that is currently displayed. */
+ public function get currentFrame():int { return _currentFrameID; }
+ public function set currentFrame(value:int):void
+ {
+ if (value < 0 || value >= numFrames) throw new ArgumentError("Invalid frame id");
+ currentTime = _frames[value].startTime;
+ }
+
+ /** The default number of frames per second. Individual frames can have different
+ * durations. If you change the fps, the durations of all frames will be scaled
+ * relatively to the previous value. */
+ public function get fps():Number { return 1.0 / _defaultFrameDuration; }
+ public function set fps(value:Number):void
+ {
+ if (value <= 0) throw new ArgumentError("Invalid fps: " + value);
+
+ var newFrameDuration:Number = 1.0 / value;
+ var acceleration:Number = newFrameDuration / _defaultFrameDuration;
+ _currentTime *= acceleration;
+ _defaultFrameDuration = newFrameDuration;
+
+ for (var i:int=0; ifalse when the end
+ * is reached. */
+ public function get isPlaying():Boolean
+ {
+ if (_playing)
+ return _loop || _currentTime < totalTime;
+ else
+ return false;
+ }
+
+ /** Indicates if a (non-looping) movie has come to its end. */
+ public function get isComplete():Boolean
+ {
+ return !_loop && _currentTime >= totalTime;
+ }
+ }
+}
+
+import flash.media.Sound;
+import flash.media.SoundTransform;
+
+import starling.display.MovieClip;
+import starling.textures.Texture;
+
+class MovieClipFrame
+{
+ public function MovieClipFrame(texture:Texture, duration:Number=0.1, startTime:Number=0)
+ {
+ this.texture = texture;
+ this.duration = duration;
+ this.startTime = startTime;
+ }
+
+ public var texture:Texture;
+ public var sound:Sound;
+ public var duration:Number;
+ public var startTime:Number;
+ public var action:Function;
+
+ public function playSound(transform:SoundTransform):void
+ {
+ if (sound) sound.play(0, 0, transform);
+ }
+
+ public function executeAction(movie:MovieClip, frameID:int):void
+ {
+ if (action != null)
+ {
+ var numArgs:int = action.length;
+
+ if (numArgs == 0) action();
+ else if (numArgs == 1) action(movie);
+ else if (numArgs == 2) action(movie, frameID);
+ else throw new Error("Frame actions support zero, one or two parameters: " +
+ "movie:MovieClip, frameID:int");
+ }
+ }
+}
\ No newline at end of file
diff --git a/mobile_version/src/starling/display/Quad.as b/mobile_version/src/starling/display/Quad.as
new file mode 100644
index 00000000..5c0f1e00
--- /dev/null
+++ b/mobile_version/src/starling/display/Quad.as
@@ -0,0 +1,209 @@
+// =================================================================================================
+//
+// Starling Framework
+// Copyright Gamua GmbH. All Rights Reserved.
+//
+// This program is free software. You can redistribute and/or modify it
+// in accordance with the terms of the accompanying license agreement.
+//
+// =================================================================================================
+
+package starling.display
+{
+ import flash.geom.Matrix;
+ import flash.geom.Matrix3D;
+ import flash.geom.Point;
+ import flash.geom.Rectangle;
+ import flash.geom.Vector3D;
+
+ import starling.rendering.IndexData;
+ import starling.rendering.VertexData;
+ import starling.styles.MeshStyle;
+ import starling.textures.Texture;
+ import starling.utils.RectangleUtil;
+
+ /** A Quad represents a colored and/or textured rectangle.
+ *
+ *
Quads may have a color and a texture. When assigning a texture, the colors of the
+ * vertices will "tint" the texture, i.e. the vertex color will be multiplied with the color
+ * of the texture at the same position. That's why the default color of a quad is pure white:
+ * tinting with white does not change the texture color (that's a multiplication with one).
+ *
+ *
A quad is, by definition, always rectangular. The basic quad class will always contain
+ * exactly four vertices, arranged like this:
+ *
+ *
+ * 0 - 1
+ * | / |
+ * 2 - 3
+ *
+ *
+ *
You can set the color of each vertex individually; and since the colors will smoothly
+ * fade into each other over the area of the quad, you can use this to create simple linear
+ * color gradients (e.g. by assigning one color to vertices 0 and 1 and another to vertices
+ * 2 and 3).
+ *
+ *
However, note that the number of vertices may be different in subclasses.
+ * Check the property numVertices if you are unsure.
+ *
+ * @see starling.textures.Texture
+ * @see Image
+ */
+ public class Quad extends Mesh
+ {
+ private var _bounds:Rectangle;
+
+ // helper objects
+ private static var sPoint3D:Vector3D = new Vector3D();
+ private static var sMatrix:Matrix = new Matrix();
+ private static var sMatrix3D:Matrix3D = new Matrix3D();
+
+ /** Creates a quad with a certain size and color. */
+ public function Quad(width:Number, height:Number, color:uint=0xffffff)
+ {
+ _bounds = new Rectangle(0, 0, width, height);
+
+ var vertexData:VertexData = new VertexData(MeshStyle.VERTEX_FORMAT, 4);
+ var indexData:IndexData = new IndexData(6);
+
+ super(vertexData, indexData);
+
+ if (width == 0.0 || height == 0.0)
+ throw new ArgumentError("Invalid size: width and height must not be zero");
+
+ setupVertices();
+ this.color = color;
+ }
+
+ /** Sets up vertex- and index-data according to the current settings. */
+ protected function setupVertices():void
+ {
+ var posAttr:String = "position";
+ var texAttr:String = "texCoords";
+ var texture:Texture = style.texture;
+ var vertexData:VertexData = this.vertexData;
+ var indexData:IndexData = this.indexData;
+
+ indexData.numIndices = 0;
+ indexData.addQuad(0, 1, 2, 3);
+
+ if (vertexData.numVertices != 4)
+ {
+ vertexData.numVertices = 4;
+ vertexData.trim();
+ }
+
+ if (texture)
+ {
+ texture.setupVertexPositions(vertexData, 0, "position", _bounds);
+ texture.setupTextureCoordinates(vertexData, 0, texAttr);
+ }
+ else
+ {
+ vertexData.setPoint(0, posAttr, _bounds.left, _bounds.top);
+ vertexData.setPoint(1, posAttr, _bounds.right, _bounds.top);
+ vertexData.setPoint(2, posAttr, _bounds.left, _bounds.bottom);
+ vertexData.setPoint(3, posAttr, _bounds.right, _bounds.bottom);
+
+ vertexData.setPoint(0, texAttr, 0.0, 0.0);
+ vertexData.setPoint(1, texAttr, 1.0, 0.0);
+ vertexData.setPoint(2, texAttr, 0.0, 1.0);
+ vertexData.setPoint(3, texAttr, 1.0, 1.0);
+ }
+
+ setRequiresRedraw();
+ }
+
+ /** @inheritDoc */
+ public override function getBounds(targetSpace:DisplayObject, out:Rectangle=null):Rectangle
+ {
+ if (out == null) out = new Rectangle();
+
+ if (targetSpace == this) // optimization
+ {
+ out.copyFrom(_bounds);
+ }
+ else if (targetSpace == parent && !isRotated) // optimization
+ {
+ var scaleX:Number = this.scaleX;
+ var scaleY:Number = this.scaleY;
+
+ out.setTo( x - pivotX * scaleX, y - pivotY * scaleY,
+ _bounds.width * scaleX, _bounds.height * scaleY);
+
+ if (scaleX < 0) { out.width *= -1; out.x -= out.width; }
+ if (scaleY < 0) { out.height *= -1; out.y -= out.height; }
+ }
+ else if (is3D && stage)
+ {
+ stage.getCameraPosition(targetSpace, sPoint3D);
+ getTransformationMatrix3D(targetSpace, sMatrix3D);
+ RectangleUtil.getBoundsProjected(_bounds, sMatrix3D, sPoint3D, out);
+ }
+ else
+ {
+ getTransformationMatrix(targetSpace, sMatrix);
+ RectangleUtil.getBounds(_bounds, sMatrix, out);
+ }
+
+ return out;
+ }
+
+ /** @inheritDoc */
+ override public function hitTest(localPoint:Point):DisplayObject
+ {
+ if (!visible || !touchable || !hitTestMask(localPoint)) return null;
+ else if (_bounds.containsPoint(localPoint)) return this;
+ else return null;
+ }
+
+ /** Readjusts the dimensions of the quad. Use this method without any arguments to
+ * synchronize quad and texture size after assigning a texture with a different size.
+ * You can also force a certain width and height by passing positive, non-zero
+ * values for width and height. */
+ public function readjustSize(width:Number=-1, height:Number=-1):void
+ {
+ if (width <= 0) width = texture ? texture.frameWidth : _bounds.width;
+ if (height <= 0) height = texture ? texture.frameHeight : _bounds.height;
+
+ if (width != _bounds.width || height != _bounds.height)
+ {
+ _bounds.setTo(0, 0, width, height);
+ setupVertices();
+ }
+ }
+
+ /** Creates a quad from the given texture.
+ * The quad will have the same size as the texture. */
+ public static function fromTexture(texture:Texture):Quad
+ {
+ var quad:Quad = new Quad(100, 100);
+ quad.texture = texture;
+ quad.readjustSize();
+ return quad;
+ }
+
+ /** The texture that is mapped to the quad (or null, if there is none).
+ * Per default, it is mapped to the complete quad, i.e. to the complete area between the
+ * top left and bottom right vertices. This can be changed with the
+ * setTexCoords-method.
+ *
+ *
Note that the size of the quad will not change when you assign a texture, which
+ * means that the texture might be distorted at first. Call readjustSize to
+ * synchronize quad and texture size.
+ *
+ *
You could also set the texture via the style.texture property.
+ * That way, however, the texture frame won't be taken into account. Since only rectangular
+ * objects can make use of a texture frame, only a property on the Quad class can do that.
+ *
+ */
+ override public function set texture(value:Texture):void
+ {
+ if (value != texture)
+ {
+ super.texture = value;
+ setupVertices();
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/mobile_version/src/starling/display/Sprite.as b/mobile_version/src/starling/display/Sprite.as
new file mode 100644
index 00000000..2cb45b84
--- /dev/null
+++ b/mobile_version/src/starling/display/Sprite.as
@@ -0,0 +1,27 @@
+// =================================================================================================
+//
+// Starling Framework
+// Copyright Gamua GmbH. All Rights Reserved.
+//
+// This program is free software. You can redistribute and/or modify it
+// in accordance with the terms of the accompanying license agreement.
+//
+// =================================================================================================
+
+package starling.display
+{
+ /** A Sprite is the most lightweight, non-abstract container class.
+ * Use it as a simple means of grouping objects together in one coordinate system.
+ *
+ * @see DisplayObject
+ * @see DisplayObjectContainer
+ */
+ public class Sprite extends DisplayObjectContainer
+ {
+ /** Creates an empty sprite. */
+ public function Sprite()
+ {
+ super();
+ }
+ }
+}
\ No newline at end of file
diff --git a/mobile_version/src/starling/display/Sprite3D.as b/mobile_version/src/starling/display/Sprite3D.as
new file mode 100644
index 00000000..d8951b03
--- /dev/null
+++ b/mobile_version/src/starling/display/Sprite3D.as
@@ -0,0 +1,372 @@
+// =================================================================================================
+//
+// Starling Framework
+// Copyright Gamua GmbH. All Rights Reserved.
+//
+// This program is free software. You can redistribute and/or modify it
+// in accordance with the terms of the accompanying license agreement.
+//
+// =================================================================================================
+
+package starling.display
+{
+ import flash.geom.Matrix;
+ import flash.geom.Matrix3D;
+ import flash.geom.Point;
+ import flash.geom.Vector3D;
+
+ import starling.events.Event;
+ import starling.rendering.Painter;
+ import starling.utils.MathUtil;
+ import starling.utils.MatrixUtil;
+ import starling.utils.rad2deg;
+
+ /** A container that allows you to position objects in three-dimensional space.
+ *
+ *
Starling is, at its heart, a 2D engine. However, sometimes, simple 3D effects are
+ * useful for special effects, e.g. for screen transitions or to turn playing cards
+ * realistically. This class makes it possible to create such 3D effects.
+ *
+ *
Positioning objects in 3D
+ *
+ *
Just like a normal sprite, you can add and remove children to this container, which
+ * allows you to group several display objects together. In addition to that, Sprite3D
+ * adds some interesting properties:
+ *
+ *
+ *
z - Moves the sprite closer to / further away from the camera.
+ *
rotationX — Rotates the sprite around the x-axis.
+ *
rotationY — Rotates the sprite around the y-axis.
+ *
scaleZ - Scales the sprite along the z-axis.
+ *
pivotZ - Moves the pivot point along the z-axis.
+ *
+ *
+ *
With the help of these properties, you can move a sprite and all its children in the
+ * 3D space. By nesting several Sprite3D containers, it's even possible to construct simple
+ * volumetric objects (like a cube).
+ *
+ *
Note that Starling does not make any z-tests: visibility is solely established by the
+ * order of the children, just as with 2D objects.
+ *
+ *
Setting up the camera
+ *
+ *
The camera settings are found directly on the stage. Modify the 'focalLength' or
+ * 'fieldOfView' properties to change the distance between stage and camera; use the
+ * 'projectionOffset' to move it to a different position.
+ *
+ *
Limitations
+ *
+ *
On rendering, each Sprite3D requires its own draw call — except if the object does not
+ * contain any 3D transformations ('z', 'rotationX/Y' and 'pivotZ' are zero). Furthermore,
+ * it interrupts the render cache, i.e. the cache cannot contain objects within different
+ * 3D coordinate systems. Flat contents within the Sprite3D will be cached, though.
+ *
+ */
+ public class Sprite3D extends DisplayObjectContainer
+ {
+ private static const E:Number = 0.00001;
+
+ private var _rotationX:Number;
+ private var _rotationY:Number;
+ private var _scaleZ:Number;
+ private var _pivotZ:Number;
+ private var _z:Number;
+
+ private var _transformationMatrix:Matrix;
+ private var _transformationMatrix3D:Matrix3D;
+ private var _transformationChanged:Boolean;
+ private var _is2D:Boolean;
+
+ /** Helper objects. */
+ private static var sHelperPoint:Vector3D = new Vector3D();
+ private static var sHelperPointAlt:Vector3D = new Vector3D();
+ private static var sHelperMatrix:Matrix3D = new Matrix3D();
+
+ /** Creates an empty Sprite3D. */
+ public function Sprite3D()
+ {
+ _scaleZ = 1.0;
+ _rotationX = _rotationY = _pivotZ = _z = 0.0;
+ _transformationMatrix = new Matrix();
+ _transformationMatrix3D = new Matrix3D();
+ _is2D = true; // meaning: this 3D object contains only 2D content
+ setIs3D(true); // meaning: this display object supports 3D transformations
+
+ addEventListener(Event.ADDED, onAddedChild);
+ addEventListener(Event.REMOVED, onRemovedChild);
+ }
+
+ /** @inheritDoc */
+ override public function render(painter:Painter):void
+ {
+ if (_is2D) super.render(painter);
+ else
+ {
+ painter.finishMeshBatch();
+ painter.pushState();
+ painter.state.transformModelviewMatrix3D(transformationMatrix3D);
+
+ super.render(painter);
+
+ painter.finishMeshBatch();
+ painter.excludeFromCache(this);
+ painter.popState();
+ }
+ }
+
+ /** @inheritDoc */
+ override public function hitTest(localPoint:Point):DisplayObject
+ {
+ if (_is2D) return super.hitTest(localPoint);
+ else
+ {
+ if (!visible || !touchable) return null;
+
+ // We calculate the interception point between the 3D plane that is spawned up
+ // by this sprite3D and the straight line between the camera and the hit point.
+
+ sHelperMatrix.copyFrom(transformationMatrix3D);
+ sHelperMatrix.invert();
+
+ stage.getCameraPosition(this, sHelperPoint);
+ MatrixUtil.transformCoords3D(sHelperMatrix, localPoint.x, localPoint.y, 0, sHelperPointAlt);
+ MathUtil.intersectLineWithXYPlane(sHelperPoint, sHelperPointAlt, localPoint);
+
+ return super.hitTest(localPoint);
+ }
+ }
+
+ /** @private */
+ override public function setRequiresRedraw():void
+ {
+ _is2D = _z > -E && _z < E &&
+ _rotationX > -E && _rotationX < E &&
+ _rotationY > -E && _rotationY < E &&
+ _pivotZ > -E && _pivotZ < E;
+
+ super.setRequiresRedraw();
+ }
+
+ // helpers
+
+ private function onAddedChild(event:Event):void
+ {
+ recursivelySetIs3D(event.target as DisplayObject, true);
+ }
+
+ private function onRemovedChild(event:Event):void
+ {
+ recursivelySetIs3D(event.target as DisplayObject, false);
+ }
+
+ private function recursivelySetIs3D(object:DisplayObject, value:Boolean):void
+ {
+ if (object is Sprite3D)
+ return;
+
+ if (object is DisplayObjectContainer)
+ {
+ var container:DisplayObjectContainer = object as DisplayObjectContainer;
+ var numChildren:int = container.numChildren;
+
+ for (var i:int=0; iThis class represents the Starling version of the stage. Don't confuse it with its
+ * Flash equivalent: while the latter contains objects of the type
+ * flash.display.DisplayObject, the Starling stage contains only objects of the
+ * type starling.display.DisplayObject. Those classes are not compatible, and
+ * you cannot exchange one type with the other.
+ *
+ *
A stage object is created automatically by the Starling class. Don't
+ * create a Stage instance manually.
+ *
+ * Keyboard Events
+ *
+ *
In Starling, keyboard events are only dispatched at the stage. Add an event listener
+ * directly to the stage to be notified of keyboard events.
+ *
+ * Resize Events
+ *
+ *
When the Flash player is resized, the stage dispatches a ResizeEvent. The
+ * event contains properties containing the updated width and height of the Flash player.
+ *
+ * @see starling.events.KeyboardEvent
+ * @see starling.events.ResizeEvent
+ *
+ */
+ public class Stage extends DisplayObjectContainer
+ {
+ private var _width:int;
+ private var _height:int;
+ private var _color:uint;
+ private var _fieldOfView:Number;
+ private var _projectionOffset:Point;
+ private var _cameraPosition:Vector3D;
+ private var _enterFrameEvent:EnterFrameEvent;
+ private var _enterFrameListeners:Vector.;
+
+ // helper objects
+ private static var sMatrix:Matrix = new Matrix();
+ private static var sMatrix3D:Matrix3D = new Matrix3D();
+
+ /** @private */
+ public function Stage(width:int, height:int, color:uint=0)
+ {
+ _width = width;
+ _height = height;
+ _color = color;
+ _fieldOfView = 1.0;
+ _projectionOffset = new Point();
+ _cameraPosition = new Vector3D();
+ _enterFrameEvent = new EnterFrameEvent(Event.ENTER_FRAME, 0.0);
+ _enterFrameListeners = new [];
+ }
+
+ /** @inheritDoc */
+ public function advanceTime(passedTime:Number):void
+ {
+ _enterFrameEvent.reset(Event.ENTER_FRAME, false, passedTime);
+ broadcastEvent(_enterFrameEvent);
+ }
+
+ /** Returns the object that is found topmost beneath a point in stage coordinates, or
+ * the stage itself if nothing else is found. */
+ public override function hitTest(localPoint:Point):DisplayObject
+ {
+ if (!visible || !touchable) return null;
+
+ // locations outside of the stage area shouldn't be accepted
+ if (localPoint.x < 0 || localPoint.x > _width ||
+ localPoint.y < 0 || localPoint.y > _height)
+ return null;
+
+ // if nothing else is hit, the stage returns itself as target
+ var target:DisplayObject = super.hitTest(localPoint);
+ return target ? target : this;
+ }
+
+ /** Draws the complete stage into a BitmapData object.
+ *
+ *
If you encounter problems with transparency, start Starling in BASELINE profile
+ * (or higher). BASELINE_CONSTRAINED might not support transparency on all platforms.
+ *
+ *
+ * @param destination If you pass null, the object will be created for you.
+ * If you pass a BitmapData object, it should have the size of the
+ * back buffer (which is accessible via the respective properties
+ * on the Starling instance).
+ * @param transparent If enabled, empty areas will appear transparent; otherwise, they
+ * will be filled with the stage color.
+ */
+ public function drawToBitmapData(destination:BitmapData=null,
+ transparent:Boolean=true):BitmapData
+ {
+ var painter:Painter = Starling.painter;
+ var state:RenderState = painter.state;
+ var context:Context3D = painter.context;
+
+ if (destination == null)
+ {
+ var width:int = context.backBufferWidth;
+ var height:int = context.backBufferHeight;
+ destination = new BitmapData(width, height, transparent);
+ }
+
+ painter.pushState();
+ state.renderTarget = null;
+ state.setProjectionMatrix(0, 0, _width, _height, _width, _height, cameraPosition);
+
+ if (transparent) painter.clear();
+ else painter.clear(_color, 1);
+
+ render(painter);
+ painter.finishMeshBatch();
+
+ context.drawToBitmapData(destination);
+ context.present(); // required on some platforms to avoid flickering
+
+ painter.popState();
+ return destination;
+ }
+
+ /** Returns the stage bounds (i.e. not the bounds of its contents, but the rectangle
+ * spawned up by 'stageWidth' and 'stageHeight') in another coordinate system. */
+ public function getStageBounds(targetSpace:DisplayObject, out:Rectangle=null):Rectangle
+ {
+ if (out == null) out = new Rectangle();
+
+ out.setTo(0, 0, _width, _height);
+ getTransformationMatrix(targetSpace, sMatrix);
+
+ return RectangleUtil.getBounds(out, sMatrix, out);
+ }
+
+ // camera positioning
+
+ /** Returns the position of the camera within the local coordinate system of a certain
+ * display object. If you do not pass a space, the method returns the global position.
+ * To change the position of the camera, you can modify the properties 'fieldOfView',
+ * 'focalDistance' and 'projectionOffset'.
+ */
+ public function getCameraPosition(space:DisplayObject=null, out:Vector3D=null):Vector3D
+ {
+ getTransformationMatrix3D(space, sMatrix3D);
+
+ return MatrixUtil.transformCoords3D(sMatrix3D,
+ _width / 2 + _projectionOffset.x, _height / 2 + _projectionOffset.y,
+ -focalLength, out);
+ }
+
+ // enter frame event optimization
+
+ /** @private */
+ internal function addEnterFrameListener(listener:DisplayObject):void
+ {
+ var index:int = _enterFrameListeners.indexOf(listener);
+ if (index < 0) _enterFrameListeners[_enterFrameListeners.length] = listener;
+ }
+
+ /** @private */
+ internal function removeEnterFrameListener(listener:DisplayObject):void
+ {
+ var index:int = _enterFrameListeners.indexOf(listener);
+ if (index >= 0) _enterFrameListeners.removeAt(index);
+ }
+
+ /** @private */
+ internal override function getChildEventListeners(object:DisplayObject, eventType:String,
+ listeners:Vector.):void
+ {
+ if (eventType == Event.ENTER_FRAME && object == this)
+ {
+ for (var i:int=0, length:int=_enterFrameListeners.length; iviewPort property of the Starling object. */
+ public function get stageWidth():int { return _width; }
+ public function set stageWidth(value:int):void { _width = value; }
+
+ /** The height of the stage coordinate system. Change it to scale its contents relative
+ * to the viewPort property of the Starling object. */
+ public function get stageHeight():int { return _height; }
+ public function set stageHeight(value:int):void { _height = value; }
+
+ /** The Starling instance this stage belongs to. */
+ public function get starling():Starling
+ {
+ var instances:Vector. = Starling.all;
+ var numInstances:int = instances.length;
+
+ for (var i:int=0; iA value close to zero will look similar to an orthographic projection; a value
+ * close to PI results in a fisheye lens effect. If the field of view is set to 0 or PI,
+ * nothing is seen on the screen.
+ *
+ * @default 1.0
+ */
+ public function get fieldOfView():Number { return _fieldOfView; }
+ public function set fieldOfView(value:Number):void { _fieldOfView = value; }
+
+ /** A vector that moves the camera away from its default position in the center of the
+ * stage. Use this property to change the center of projection, i.e. the vanishing
+ * point for 3D display objects.
CAUTION: not a copy, but the actual object!
+ */
+ public function get projectionOffset():Point { return _projectionOffset; }
+ public function set projectionOffset(value:Point):void
+ {
+ _projectionOffset.setTo(value.x, value.y);
+ }
+
+ /** The global position of the camera. This property can only be used to find out the
+ * current position, but not to modify it. For that, use the 'projectionOffset',
+ * 'fieldOfView' and 'focalLength' properties. If you need the camera position in
+ * a certain coordinate space, use 'getCameraPosition' instead.
+ *
+ *
CAUTION: not a copy, but the actual object!
+ */
+ public function get cameraPosition():Vector3D
+ {
+ return getCameraPosition(null, _cameraPosition);
+ }
+ }
+}
\ No newline at end of file
diff --git a/mobile_version/src/starling/errors/AbstractClassError.as b/mobile_version/src/starling/errors/AbstractClassError.as
new file mode 100644
index 00000000..a9168935
--- /dev/null
+++ b/mobile_version/src/starling/errors/AbstractClassError.as
@@ -0,0 +1,23 @@
+// =================================================================================================
+//
+// Starling Framework
+// Copyright Gamua GmbH. All Rights Reserved.
+//
+// This program is free software. You can redistribute and/or modify it
+// in accordance with the terms of the accompanying license agreement.
+//
+// =================================================================================================
+
+package starling.errors
+{
+ /** An AbstractClassError is thrown when you attempt to create an instance of an abstract
+ * class. */
+ public class AbstractClassError extends Error
+ {
+ /** Creates a new AbstractClassError object. */
+ public function AbstractClassError(message:*="Cannot instantiate abstract class", id:*=0)
+ {
+ super(message, id);
+ }
+ }
+}
\ No newline at end of file
diff --git a/mobile_version/src/starling/errors/AbstractMethodError.as b/mobile_version/src/starling/errors/AbstractMethodError.as
new file mode 100644
index 00000000..3206babe
--- /dev/null
+++ b/mobile_version/src/starling/errors/AbstractMethodError.as
@@ -0,0 +1,22 @@
+// =================================================================================================
+//
+// Starling Framework
+// Copyright Gamua GmbH. All Rights Reserved.
+//
+// This program is free software. You can redistribute and/or modify it
+// in accordance with the terms of the accompanying license agreement.
+//
+// =================================================================================================
+
+package starling.errors
+{
+ /** An AbstractMethodError is thrown when you attempt to call an abstract method. */
+ public class AbstractMethodError extends Error
+ {
+ /** Creates a new AbstractMethodError object. */
+ public function AbstractMethodError(message:*="Method needs to be implemented in subclass", id:*=0)
+ {
+ super(message, id);
+ }
+ }
+}
\ No newline at end of file
diff --git a/mobile_version/src/starling/errors/MissingContextError.as b/mobile_version/src/starling/errors/MissingContextError.as
new file mode 100644
index 00000000..114735ee
--- /dev/null
+++ b/mobile_version/src/starling/errors/MissingContextError.as
@@ -0,0 +1,23 @@
+// =================================================================================================
+//
+// Starling Framework
+// Copyright Gamua GmbH. All Rights Reserved.
+//
+// This program is free software. You can redistribute and/or modify it
+// in accordance with the terms of the accompanying license agreement.
+//
+// =================================================================================================
+
+package starling.errors
+{
+ /** A MissingContextError is thrown when a Context3D object is required but not (yet)
+ * available. */
+ public class MissingContextError extends Error
+ {
+ /** Creates a new MissingContextError object. */
+ public function MissingContextError(message:*="Starling context is missing", id:*=0)
+ {
+ super(message, id);
+ }
+ }
+}
\ No newline at end of file
diff --git a/mobile_version/src/starling/errors/NotSupportedError.as b/mobile_version/src/starling/errors/NotSupportedError.as
new file mode 100644
index 00000000..abfacdf6
--- /dev/null
+++ b/mobile_version/src/starling/errors/NotSupportedError.as
@@ -0,0 +1,23 @@
+// =================================================================================================
+//
+// Starling Framework
+// Copyright Gamua GmbH. All Rights Reserved.
+//
+// This program is free software. You can redistribute and/or modify it
+// in accordance with the terms of the accompanying license agreement.
+//
+// =================================================================================================
+
+package starling.errors
+{
+ /** A NotSupportedError is thrown when you attempt to use a feature that is not supported
+ * on the current platform. */
+ public class NotSupportedError extends Error
+ {
+ /** Creates a new NotSupportedError object. */
+ public function NotSupportedError(message:* = "", id:* = 0)
+ {
+ super(message, id);
+ }
+ }
+}
diff --git a/mobile_version/src/starling/events/EnterFrameEvent.as b/mobile_version/src/starling/events/EnterFrameEvent.as
new file mode 100644
index 00000000..de605a0f
--- /dev/null
+++ b/mobile_version/src/starling/events/EnterFrameEvent.as
@@ -0,0 +1,34 @@
+// =================================================================================================
+//
+// Starling Framework
+// Copyright Gamua GmbH. All Rights Reserved.
+//
+// This program is free software. You can redistribute and/or modify it
+// in accordance with the terms of the accompanying license agreement.
+//
+// =================================================================================================
+
+package starling.events
+{
+ /** An EnterFrameEvent is triggered once per frame and is dispatched to all objects in the
+ * display tree.
+ *
+ * It contains information about the time that has passed since the last frame. That way, you
+ * can easily make animations that are independent of the frame rate, taking the passed time
+ * into account.
+ */
+ public class EnterFrameEvent extends Event
+ {
+ /** Event type for a display object that is entering a new frame. */
+ public static const ENTER_FRAME:String = "enterFrame";
+
+ /** Creates an enter frame event with the passed time. */
+ public function EnterFrameEvent(type:String, passedTime:Number, bubbles:Boolean=false)
+ {
+ super(type, bubbles, passedTime);
+ }
+
+ /** The time that has passed since the last frame (in seconds). */
+ public function get passedTime():Number { return data as Number; }
+ }
+}
\ No newline at end of file
diff --git a/mobile_version/src/starling/events/Event.as b/mobile_version/src/starling/events/Event.as
new file mode 100644
index 00000000..395d22b8
--- /dev/null
+++ b/mobile_version/src/starling/events/Event.as
@@ -0,0 +1,190 @@
+// =================================================================================================
+//
+// Starling Framework
+// Copyright Gamua GmbH. All Rights Reserved.
+//
+// This program is free software. You can redistribute and/or modify it
+// in accordance with the terms of the accompanying license agreement.
+//
+// =================================================================================================
+
+package starling.events
+{
+ import flash.utils.getQualifiedClassName;
+
+ import starling.core.starling_internal;
+ import starling.utils.StringUtil;
+
+ use namespace starling_internal;
+
+ /** Event objects are passed as parameters to event listeners when an event occurs.
+ * This is Starling's version of the Flash Event class.
+ *
+ *
EventDispatchers create instances of this class and send them to registered listeners.
+ * An event object contains information that characterizes an event, most importantly the
+ * event type and if the event bubbles. The target of an event is the object that
+ * dispatched it.
+ *
+ *
For some event types, this information is sufficient; other events may need additional
+ * information to be carried to the listener. In that case, you can subclass "Event" and add
+ * properties with all the information you require. The "EnterFrameEvent" is an example for
+ * this practice; it adds a property about the time that has passed since the last frame.
+ *
+ *
Furthermore, the event class contains methods that can stop the event from being
+ * processed by other listeners - either completely or at the next bubble stage.
+ *
+ * @see EventDispatcher
+ */
+ public class Event
+ {
+ /** Event type for a display object that is added to a parent. */
+ public static const ADDED:String = "added";
+ /** Event type for a display object that is added to the stage */
+ public static const ADDED_TO_STAGE:String = "addedToStage";
+ /** Event type for a display object that is entering a new frame. */
+ public static const ENTER_FRAME:String = "enterFrame";
+ /** Event type for a display object that is removed from its parent. */
+ public static const REMOVED:String = "removed";
+ /** Event type for a display object that is removed from the stage. */
+ public static const REMOVED_FROM_STAGE:String = "removedFromStage";
+ /** Event type for a triggered button. */
+ public static const TRIGGERED:String = "triggered";
+ /** Event type for a resized Flash Player. */
+ public static const RESIZE:String = "resize";
+ /** Event type that may be used whenever something finishes. */
+ public static const COMPLETE:String = "complete";
+ /** Event type for a (re)created stage3D rendering context. */
+ public static const CONTEXT3D_CREATE:String = "context3DCreate";
+ /** Event type that is dispatched by the Starling instance directly before rendering. */
+ public static const RENDER:String = "render";
+ /** Event type that indicates that the root DisplayObject has been created. */
+ public static const ROOT_CREATED:String = "rootCreated";
+ /** Event type for an animated object that requests to be removed from the juggler. */
+ public static const REMOVE_FROM_JUGGLER:String = "removeFromJuggler";
+ /** Event type that is dispatched by the AssetManager after a context loss. */
+ public static const TEXTURES_RESTORED:String = "texturesRestored";
+ /** Event type that is dispatched by the AssetManager when a file/url cannot be loaded. */
+ public static const IO_ERROR:String = "ioError";
+ /** Event type that is dispatched by the AssetManager when a file/url cannot be loaded. */
+ public static const SECURITY_ERROR:String = "securityError";
+ /** Event type that is dispatched by the AssetManager when an xml or json file couldn't
+ * be parsed. */
+ public static const PARSE_ERROR:String = "parseError";
+ /** Event type that is dispatched by the Starling instance when it encounters a problem
+ * from which it cannot recover, e.g. a lost device context. */
+ public static const FATAL_ERROR:String = "fatalError";
+
+ /** An event type to be utilized in custom events. Not used by Starling right now. */
+ public static const CHANGE:String = "change";
+ /** An event type to be utilized in custom events. Not used by Starling right now. */
+ public static const CANCEL:String = "cancel";
+ /** An event type to be utilized in custom events. Not used by Starling right now. */
+ public static const SCROLL:String = "scroll";
+ /** An event type to be utilized in custom events. Not used by Starling right now. */
+ public static const OPEN:String = "open";
+ /** An event type to be utilized in custom events. Not used by Starling right now. */
+ public static const CLOSE:String = "close";
+ /** An event type to be utilized in custom events. Not used by Starling right now. */
+ public static const SELECT:String = "select";
+ /** An event type to be utilized in custom events. Not used by Starling right now. */
+ public static const READY:String = "ready";
+ /** An event type to be utilized in custom events. Not used by Starling right now. */
+ public static const UPDATE:String = "update";
+
+ private static var sEventPool:Vector. = new [];
+
+ private var _target:EventDispatcher;
+ private var _currentTarget:EventDispatcher;
+ private var _type:String;
+ private var _bubbles:Boolean;
+ private var _stopsPropagation:Boolean;
+ private var _stopsImmediatePropagation:Boolean;
+ private var _data:Object;
+
+ /** Creates an event object that can be passed to listeners. */
+ public function Event(type:String, bubbles:Boolean=false, data:Object=null)
+ {
+ _type = type;
+ _bubbles = bubbles;
+ _data = data;
+ }
+
+ /** Prevents listeners at the next bubble stage from receiving the event. */
+ public function stopPropagation():void
+ {
+ _stopsPropagation = true;
+ }
+
+ /** Prevents any other listeners from receiving the event. */
+ public function stopImmediatePropagation():void
+ {
+ _stopsPropagation = _stopsImmediatePropagation = true;
+ }
+
+ /** Returns a description of the event, containing type and bubble information. */
+ public function toString():String
+ {
+ return StringUtil.format("[{0} type=\"{1}\" bubbles={2}]",
+ getQualifiedClassName(this).split("::").pop(), _type, _bubbles);
+ }
+
+ /** Indicates if event will bubble. */
+ public function get bubbles():Boolean { return _bubbles; }
+
+ /** The object that dispatched the event. */
+ public function get target():EventDispatcher { return _target; }
+
+ /** The object the event is currently bubbling at. */
+ public function get currentTarget():EventDispatcher { return _currentTarget; }
+
+ /** A string that identifies the event. */
+ public function get type():String { return _type; }
+
+ /** Arbitrary data that is attached to the event. */
+ public function get data():Object { return _data; }
+
+ // properties for internal use
+
+ /** @private */
+ internal function setTarget(value:EventDispatcher):void { _target = value; }
+
+ /** @private */
+ internal function setCurrentTarget(value:EventDispatcher):void { _currentTarget = value; }
+
+ /** @private */
+ internal function setData(value:Object):void { _data = value; }
+
+ /** @private */
+ internal function get stopsPropagation():Boolean { return _stopsPropagation; }
+
+ /** @private */
+ internal function get stopsImmediatePropagation():Boolean { return _stopsImmediatePropagation; }
+
+ // event pooling
+
+ /** @private */
+ starling_internal static function fromPool(type:String, bubbles:Boolean=false, data:Object=null):Event
+ {
+ if (sEventPool.length) return sEventPool.pop().reset(type, bubbles, data);
+ else return new Event(type, bubbles, data);
+ }
+
+ /** @private */
+ starling_internal static function toPool(event:Event):void
+ {
+ event._data = event._target = event._currentTarget = null;
+ sEventPool[sEventPool.length] = event; // avoiding 'push'
+ }
+
+ /** @private */
+ starling_internal function reset(type:String, bubbles:Boolean=false, data:Object=null):Event
+ {
+ _type = type;
+ _bubbles = bubbles;
+ _data = data;
+ _target = _currentTarget = null;
+ _stopsPropagation = _stopsImmediatePropagation = false;
+ return this;
+ }
+ }
+}
\ No newline at end of file
diff --git a/mobile_version/src/starling/events/EventDispatcher.as b/mobile_version/src/starling/events/EventDispatcher.as
new file mode 100644
index 00000000..fad3f714
--- /dev/null
+++ b/mobile_version/src/starling/events/EventDispatcher.as
@@ -0,0 +1,215 @@
+// =================================================================================================
+//
+// Starling Framework
+// Copyright Gamua GmbH. All Rights Reserved.
+//
+// This program is free software. You can redistribute and/or modify it
+// in accordance with the terms of the accompanying license agreement.
+//
+// =================================================================================================
+
+package starling.events
+{
+ import flash.utils.Dictionary;
+
+ import starling.core.starling_internal;
+ import starling.display.DisplayObject;
+
+ use namespace starling_internal;
+
+ /** The EventDispatcher class is the base class for all classes that dispatch events.
+ * This is the Starling version of the Flash class with the same name.
+ *
+ *
The event mechanism is a key feature of Starling's architecture. Objects can communicate
+ * with each other through events. Compared the the Flash event system, Starling's event system
+ * was simplified. The main difference is that Starling events have no "Capture" phase.
+ * They are simply dispatched at the target and may optionally bubble up. They cannot move
+ * in the opposite direction.
+ *
+ *
As in the conventional Flash classes, display objects inherit from EventDispatcher
+ * and can thus dispatch events. Beware, though, that the Starling event classes are
+ * not compatible with Flash events: Starling display objects dispatch
+ * Starling events, which will bubble along Starling display objects - but they cannot
+ * dispatch Flash events or bubble along Flash display objects.
+ *
+ * @see Event
+ * @see starling.display.DisplayObject DisplayObject
+ */
+ public class EventDispatcher
+ {
+ private var _eventListeners:Dictionary;
+
+ /** Helper object. */
+ private static var sBubbleChains:Array = [];
+
+ /** Creates an EventDispatcher. */
+ public function EventDispatcher()
+ { }
+
+ /** Registers an event listener at a certain object. */
+ public function addEventListener(type:String, listener:Function):void
+ {
+ if (_eventListeners == null)
+ _eventListeners = new Dictionary();
+
+ var listeners:Vector. = _eventListeners[type] as Vector.;
+ if (listeners == null)
+ _eventListeners[type] = new [listener];
+ else if (listeners.indexOf(listener) == -1) // check for duplicates
+ listeners[listeners.length] = listener; // avoid 'push'
+ }
+
+ /** Removes an event listener from the object. */
+ public function removeEventListener(type:String, listener:Function):void
+ {
+ if (_eventListeners)
+ {
+ var listeners:Vector. = _eventListeners[type] as Vector.;
+ var numListeners:int = listeners ? listeners.length : 0;
+
+ if (numListeners > 0)
+ {
+ // we must not modify the original vector, but work on a copy.
+ // (see comment in 'invokeEvent')
+
+ var index:int = listeners.indexOf(listener);
+
+ if (index != -1)
+ {
+ var restListeners:Vector. = listeners.slice(0, index);
+
+ for (var i:int=index+1; i = _eventListeners ?
+ _eventListeners[event.type] as Vector. : null;
+ var numListeners:int = listeners == null ? 0 : listeners.length;
+
+ if (numListeners)
+ {
+ event.setCurrentTarget(this);
+
+ // we can enumerate directly over the vector, because:
+ // when somebody modifies the list while we're looping, "addEventListener" is not
+ // problematic, and "removeEventListener" will create a new Vector, anyway.
+
+ for (var i:int=0; i;
+ var element:DisplayObject = this as DisplayObject;
+ var length:int = 1;
+
+ if (sBubbleChains.length > 0) { chain = sBubbleChains.pop(); chain[0] = element; }
+ else chain = new [element];
+
+ while ((element = element.parent) != null)
+ chain[int(length++)] = element;
+
+ for (var i:int=0; i = _eventListeners ? _eventListeners[type] : null;
+ if (listeners == null) return false;
+ else
+ {
+ if (listener != null) return listeners.indexOf(listener) != -1;
+ else return listeners.length != 0;
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/mobile_version/src/starling/events/KeyboardEvent.as b/mobile_version/src/starling/events/KeyboardEvent.as
new file mode 100644
index 00000000..7c388ce9
--- /dev/null
+++ b/mobile_version/src/starling/events/KeyboardEvent.as
@@ -0,0 +1,88 @@
+// =================================================================================================
+//
+// Starling Framework
+// Copyright Gamua GmbH. All Rights Reserved.
+//
+// This program is free software. You can redistribute and/or modify it
+// in accordance with the terms of the accompanying license agreement.
+//
+// =================================================================================================
+
+package starling.events
+{
+ /** A KeyboardEvent is dispatched in response to user input through a keyboard.
+ *
+ *
This is Starling's version of the Flash KeyboardEvent class. It contains the same
+ * properties as the Flash equivalent.
+ *
+ *
To be notified of keyboard events, add an event listener to any display object that
+ * is part of your display tree. Starling has no concept of a "Focus" like native Flash.
+ *
+ * @see starling.display.Stage
+ */
+ public class KeyboardEvent extends Event
+ {
+ /** Event type for a key that was released. */
+ public static const KEY_UP:String = "keyUp";
+
+ /** Event type for a key that was pressed. */
+ public static const KEY_DOWN:String = "keyDown";
+
+ private var _charCode:uint;
+ private var _keyCode:uint;
+ private var _keyLocation:uint;
+ private var _altKey:Boolean;
+ private var _ctrlKey:Boolean;
+ private var _shiftKey:Boolean;
+ private var _isDefaultPrevented:Boolean;
+
+ /** Creates a new KeyboardEvent. */
+ public function KeyboardEvent(type:String, charCode:uint=0, keyCode:uint=0,
+ keyLocation:uint=0, ctrlKey:Boolean=false,
+ altKey:Boolean=false, shiftKey:Boolean=false)
+ {
+ super(type, false, keyCode);
+ _charCode = charCode;
+ _keyCode = keyCode;
+ _keyLocation = keyLocation;
+ _ctrlKey = ctrlKey;
+ _altKey = altKey;
+ _shiftKey = shiftKey;
+ }
+
+ // prevent default
+
+ /** Cancels the keyboard event's default behavior. This will be forwarded to the native
+ * flash KeyboardEvent. */
+ public function preventDefault():void
+ {
+ _isDefaultPrevented = true;
+ }
+
+ /** Checks whether the preventDefault() method has been called on the event. */
+ public function isDefaultPrevented():Boolean { return _isDefaultPrevented; }
+
+ // properties
+
+ /** Contains the character code of the key. */
+ public function get charCode():uint { return _charCode; }
+
+ /** The key code of the key. */
+ public function get keyCode():uint { return _keyCode; }
+
+ /** Indicates the location of the key on the keyboard. This is useful for differentiating
+ * keys that appear more than once on a keyboard. @see Keylocation */
+ public function get keyLocation():uint { return _keyLocation; }
+
+ /** Indicates whether the Alt key is active on Windows or Linux;
+ * indicates whether the Option key is active on Mac OS. */
+ public function get altKey():Boolean { return _altKey; }
+
+ /** Indicates whether the Ctrl key is active on Windows or Linux;
+ * indicates whether either the Ctrl or the Command key is active on Mac OS. */
+ public function get ctrlKey():Boolean { return _ctrlKey; }
+
+ /** Indicates whether the Shift key modifier is active (true) or inactive (false). */
+ public function get shiftKey():Boolean { return _shiftKey; }
+ }
+}
\ No newline at end of file
diff --git a/mobile_version/src/starling/events/ResizeEvent.as b/mobile_version/src/starling/events/ResizeEvent.as
new file mode 100644
index 00000000..8f4162b7
--- /dev/null
+++ b/mobile_version/src/starling/events/ResizeEvent.as
@@ -0,0 +1,44 @@
+// =================================================================================================
+//
+// Starling Framework
+// Copyright Gamua GmbH. All Rights Reserved.
+//
+// This program is free software. You can redistribute and/or modify it
+// in accordance with the terms of the accompanying license agreement.
+//
+// =================================================================================================
+
+package starling.events
+{
+ import flash.geom.Point;
+
+ /** A ResizeEvent is dispatched by the stage when the size of the Flash container changes.
+ * Use it to update the Starling viewport and the stage size.
+ *
+ *
The event contains properties containing the updated width and height of the Flash
+ * player. If you want to scale the contents of your stage to fill the screen, update the
+ * Starling.current.viewPort rectangle accordingly. If you want to make use of
+ * the additional screen estate, update the values of stage.stageWidth and
+ * stage.stageHeight as well.
+ *
+ * @see starling.display.Stage
+ * @see starling.core.Starling
+ */
+ public class ResizeEvent extends Event
+ {
+ /** Event type for a resized Flash player. */
+ public static const RESIZE:String = "resize";
+
+ /** Creates a new ResizeEvent. */
+ public function ResizeEvent(type:String, width:int, height:int, bubbles:Boolean=false)
+ {
+ super(type, bubbles, new Point(width, height));
+ }
+
+ /** The updated width of the player. */
+ public function get width():int { return (data as Point).x; }
+
+ /** The updated height of the player. */
+ public function get height():int { return (data as Point).y; }
+ }
+}
\ No newline at end of file
diff --git a/mobile_version/src/starling/events/Touch.as b/mobile_version/src/starling/events/Touch.as
new file mode 100644
index 00000000..f8fd139d
--- /dev/null
+++ b/mobile_version/src/starling/events/Touch.as
@@ -0,0 +1,240 @@
+// =================================================================================================
+//
+// Starling Framework
+// Copyright Gamua GmbH. All Rights Reserved.
+//
+// This program is free software. You can redistribute and/or modify it
+// in accordance with the terms of the accompanying license agreement.
+//
+// =================================================================================================
+
+package starling.events
+{
+ import flash.geom.Point;
+
+ import starling.display.DisplayObject;
+ import starling.utils.StringUtil;
+
+ /** A Touch object contains information about the presence or movement of a finger
+ * or the mouse on the screen.
+ *
+ *
You receive objects of this type from a TouchEvent. When such an event is triggered,
+ * you can query it for all touches that are currently present on the screen. One touch
+ * object contains information about a single touch; it always transitions through a series
+ * of TouchPhases. Have a look at the TouchPhase class for more information.
+ *
+ * The position of a touch
+ *
+ *
You can get the current and previous position in stage coordinates with the corresponding
+ * properties. However, you'll want to have the position in a different coordinate system
+ * most of the time. For this reason, there are methods that convert the current and previous
+ * touches into the local coordinate system of any object.
+ *
+ * @see TouchEvent
+ * @see TouchPhase
+ */
+ public class Touch
+ {
+ private var _id:int;
+ private var _globalX:Number;
+ private var _globalY:Number;
+ private var _previousGlobalX:Number;
+ private var _previousGlobalY:Number;
+ private var _tapCount:int;
+ private var _phase:String;
+ private var _target:DisplayObject;
+ private var _timestamp:Number;
+ private var _pressure:Number;
+ private var _width:Number;
+ private var _height:Number;
+ private var _cancelled:Boolean;
+ private var _bubbleChain:Vector.;
+
+ /** Helper object. */
+ private static var sHelperPoint:Point = new Point();
+
+ /** Creates a new Touch object. */
+ public function Touch(id:int)
+ {
+ _id = id;
+ _tapCount = 0;
+ _phase = TouchPhase.HOVER;
+ _pressure = _width = _height = 1.0;
+ _bubbleChain = new [];
+ }
+
+ /** Converts the current location of a touch to the local coordinate system of a display
+ * object. If you pass an out-point, the result will be stored in this point
+ * instead of creating a new object.*/
+ public function getLocation(space:DisplayObject, out:Point=null):Point
+ {
+ sHelperPoint.setTo(_globalX, _globalY);
+ return space.globalToLocal(sHelperPoint, out);
+ }
+
+ /** Converts the previous location of a touch to the local coordinate system of a display
+ * object. If you pass an out-point, the result will be stored in this point
+ * instead of creating a new object.*/
+ public function getPreviousLocation(space:DisplayObject, out:Point=null):Point
+ {
+ sHelperPoint.setTo(_previousGlobalX, _previousGlobalY);
+ return space.globalToLocal(sHelperPoint, out);
+ }
+
+ /** Returns the movement of the touch between the current and previous location.
+ * If you pass an out-point, the result will be stored in this point instead
+ * of creating a new object. */
+ public function getMovement(space:DisplayObject, out:Point=null):Point
+ {
+ if (out == null) out = new Point();
+ getLocation(space, out);
+ var x:Number = out.x;
+ var y:Number = out.y;
+ getPreviousLocation(space, out);
+ out.setTo(x - out.x, y - out.y);
+ return out;
+ }
+
+ /** Indicates if the target or one of its children is touched. */
+ public function isTouching(target:DisplayObject):Boolean
+ {
+ return _bubbleChain.indexOf(target) != -1;
+ }
+
+ /** Returns a description of the object. */
+ public function toString():String
+ {
+ return StringUtil.format("[Touch {0}: globalX={1}, globalY={2}, phase={3}]",
+ _id, _globalX, _globalY, _phase);
+ }
+
+ /** Creates a clone of the Touch object. */
+ public function clone():Touch
+ {
+ var clone:Touch = new Touch(_id);
+ clone._globalX = _globalX;
+ clone._globalY = _globalY;
+ clone._previousGlobalX = _previousGlobalX;
+ clone._previousGlobalY = _previousGlobalY;
+ clone._phase = _phase;
+ clone._tapCount = _tapCount;
+ clone._timestamp = _timestamp;
+ clone._pressure = _pressure;
+ clone._width = _width;
+ clone._height = _height;
+ clone._cancelled = _cancelled;
+ clone.target = _target;
+ return clone;
+ }
+
+ // helper methods
+
+ private function updateBubbleChain():void
+ {
+ if (_target)
+ {
+ var length:int = 1;
+ var element:DisplayObject = _target;
+
+ _bubbleChain.length = 1;
+ _bubbleChain[0] = element;
+
+ while ((element = element.parent) != null)
+ _bubbleChain[int(length++)] = element;
+ }
+ else
+ {
+ _bubbleChain.length = 0;
+ }
+ }
+
+ // properties
+
+ /** The identifier of a touch. '0' for mouse events, an increasing number for touches. */
+ public function get id():int { return _id; }
+
+ /** The previous x-position of the touch in stage coordinates. */
+ public function get previousGlobalX():Number { return _previousGlobalX; }
+
+ /** The previous y-position of the touch in stage coordinates. */
+ public function get previousGlobalY():Number { return _previousGlobalY; }
+
+ /** The x-position of the touch in stage coordinates. If you change this value,
+ * the previous one will be moved to "previousGlobalX". */
+ public function get globalX():Number { return _globalX; }
+ public function set globalX(value:Number):void
+ {
+ _previousGlobalX = _globalX != _globalX ? value : _globalX; // isNaN check
+ _globalX = value;
+ }
+
+ /** The y-position of the touch in stage coordinates. If you change this value,
+ * the previous one will be moved to "previousGlobalY". */
+ public function get globalY():Number { return _globalY; }
+ public function set globalY(value:Number):void
+ {
+ _previousGlobalY = _globalY != _globalY ? value : _globalY; // isNaN check
+ _globalY = value;
+ }
+
+ /** The number of taps the finger made in a short amount of time. Use this to detect
+ * double-taps / double-clicks, etc. */
+ public function get tapCount():int { return _tapCount; }
+ public function set tapCount(value:int):void { _tapCount = value; }
+
+ /** The current phase the touch is in. @see TouchPhase */
+ public function get phase():String { return _phase; }
+ public function set phase(value:String):void { _phase = value; }
+
+ /** The display object at which the touch occurred. */
+ public function get target():DisplayObject { return _target; }
+ public function set target(value:DisplayObject):void
+ {
+ if (_target != value)
+ {
+ _target = value;
+ updateBubbleChain();
+ }
+ }
+
+ /** The moment the touch occurred (in seconds since application start). */
+ public function get timestamp():Number { return _timestamp; }
+ public function set timestamp(value:Number):void { _timestamp = value; }
+
+ /** A value between 0.0 and 1.0 indicating force of the contact with the device.
+ * If the device does not support detecting the pressure, the value is 1.0. */
+ public function get pressure():Number { return _pressure; }
+ public function set pressure(value:Number):void { _pressure = value; }
+
+ /** Width of the contact area.
+ * If the device does not support detecting the pressure, the value is 1.0. */
+ public function get width():Number { return _width; }
+ public function set width(value:Number):void { _width = value; }
+
+ /** Height of the contact area.
+ * If the device does not support detecting the pressure, the value is 1.0. */
+ public function get height():Number { return _height; }
+ public function set height(value:Number):void { _height = value; }
+
+ /** Indicates if the touch has been cancelled, which may happen when the app moves into
+ * the background ('Event.DEACTIVATE'). @default false */
+ public function get cancelled():Boolean { return _cancelled; }
+ public function set cancelled(value:Boolean):void { _cancelled = value; }
+
+ // internal methods
+
+ /** @private
+ * Dispatches a touch event along the current bubble chain (which is updated each time
+ * a target is set). */
+ internal function dispatchEvent(event:TouchEvent):void
+ {
+ if (_target) event.dispatch(_bubbleChain);
+ }
+
+ /** @private */
+ internal function get bubbleChain():Vector.
+ {
+ return _bubbleChain.concat();
+ }
+ }
+}
diff --git a/mobile_version/src/starling/events/TouchEvent.as b/mobile_version/src/starling/events/TouchEvent.as
new file mode 100644
index 00000000..613c4071
--- /dev/null
+++ b/mobile_version/src/starling/events/TouchEvent.as
@@ -0,0 +1,218 @@
+// =================================================================================================
+//
+// Starling Framework
+// Copyright Gamua GmbH. All Rights Reserved.
+//
+// This program is free software. You can redistribute and/or modify it
+// in accordance with the terms of the accompanying license agreement.
+//
+// =================================================================================================
+
+package starling.events
+{
+ import starling.core.starling_internal;
+ import starling.display.DisplayObject;
+
+ use namespace starling_internal;
+
+ /** A TouchEvent is triggered either by touch or mouse input.
+ *
+ *
In Starling, both touch events and mouse events are handled through the same class:
+ * TouchEvent. To process user input from a touch screen or the mouse, you have to register
+ * an event listener for events of the type TouchEvent.TOUCH. This is the only
+ * event type you need to handle; the long list of mouse event types as they are used in
+ * conventional Flash are mapped to so-called "TouchPhases" instead.
+ *
+ *
The difference between mouse input and touch input is that
+ *
+ *
+ *
only one mouse cursor can be present at a given moment and
+ *
only the mouse can "hover" over an object without a pressed button.
In Starling, any display object receives touch events, as long as the
+ * touchable property of the object and its parents is enabled. There
+ * is no "InteractiveObject" class in Starling.
+ *
+ * How to work with individual touches
+ *
+ *
The event contains a list of all touches that are currently present. Each individual
+ * touch is stored in an object of type "Touch". Since you are normally only interested in
+ * the touches that occurred on top of certain objects, you can query the event for touches
+ * with a specific target:
This will return all touches of "this" or one of its children. When you are not using
+ * multitouch, you can also access the touch object directly, like this:
+ *
+ * var touch:Touch = touchEvent.getTouch(this);
+ *
+ * @see Touch
+ * @see TouchPhase
+ */
+ public class TouchEvent extends Event
+ {
+ /** Event type for touch or mouse input. */
+ public static const TOUCH:String = "touch";
+
+ private var _shiftKey:Boolean;
+ private var _ctrlKey:Boolean;
+ private var _timestamp:Number;
+ private var _visitedObjects:Vector.;
+
+ /** Helper object. */
+ private static var sTouches:Vector. = new [];
+
+ /** Creates a new TouchEvent instance. */
+ public function TouchEvent(type:String, touches:Vector.=null, shiftKey:Boolean=false,
+ ctrlKey:Boolean=false, bubbles:Boolean=true)
+ {
+ super(type, bubbles, touches);
+
+ _shiftKey = shiftKey;
+ _ctrlKey = ctrlKey;
+ _visitedObjects = new [];
+
+ updateTimestamp(touches);
+ }
+
+ /** @private */
+ internal function resetTo(type:String, touches:Vector.=null, shiftKey:Boolean=false,
+ ctrlKey:Boolean=false, bubbles:Boolean=true):TouchEvent
+ {
+ super.reset(type, bubbles, touches);
+
+ _shiftKey = shiftKey;
+ _ctrlKey = ctrlKey;
+ _visitedObjects.length = 0;
+ updateTimestamp(touches);
+
+ return this;
+ }
+
+ private function updateTimestamp(touches:Vector.):void
+ {
+ _timestamp = -1.0;
+ var numTouches:int = touches ? touches.length : 0;
+
+ for (var i:int=0; i _timestamp)
+ _timestamp = touches[i].timestamp;
+ }
+
+ /** Returns a list of touches that originated over a certain target. If you pass an
+ * out-vector, the touches will be added to this vector instead of creating
+ * a new object. */
+ public function getTouches(target:DisplayObject, phase:String=null,
+ out:Vector.=null):Vector.
+ {
+ if (out == null) out = new [];
+ var allTouches:Vector. = data as Vector.;
+ var numTouches:int = allTouches.length;
+
+ for (var i:int=0; i 0)
+ {
+ var touch:Touch = null;
+
+ if (id < 0) touch = sTouches[0];
+ else
+ {
+ for (var i:int=0; i=0; --i)
+ {
+ if (sTouches[i].phase != TouchPhase.ENDED)
+ {
+ result = true;
+ break;
+ }
+ }
+
+ sTouches.length = 0;
+ return result;
+ }
+
+ // custom dispatching
+
+ /** @private
+ * Dispatches the event along a custom bubble chain. During the lifetime of the event,
+ * each object is visited only once. */
+ internal function dispatch(chain:Vector.):void
+ {
+ if (chain && chain.length)
+ {
+ var chainLength:int = bubbles ? chain.length : 1;
+ var previousTarget:EventDispatcher = target;
+ setTarget(chain[0] as EventDispatcher);
+
+ for (var i:int=0; i { return (data as Vector.).concat(); }
+
+ /** Indicates if the shift key was pressed when the event occurred. */
+ public function get shiftKey():Boolean { return _shiftKey; }
+
+ /** Indicates if the ctrl key was pressed when the event occurred. (Mac OS: Cmd or Ctrl) */
+ public function get ctrlKey():Boolean { return _ctrlKey; }
+ }
+}
\ No newline at end of file
diff --git a/mobile_version/src/starling/events/TouchMarker.as b/mobile_version/src/starling/events/TouchMarker.as
new file mode 100644
index 00000000..df3ff940
--- /dev/null
+++ b/mobile_version/src/starling/events/TouchMarker.as
@@ -0,0 +1,104 @@
+// =================================================================================================
+//
+// Starling Framework
+// Copyright Gamua GmbH. All Rights Reserved.
+//
+// This program is free software. You can redistribute and/or modify it
+// in accordance with the terms of the accompanying license agreement.
+//
+// =================================================================================================
+
+package starling.events
+{
+ import flash.display.BitmapData;
+ import flash.display.Shape;
+ import flash.geom.Point;
+
+ import starling.core.Starling;
+ import starling.display.Image;
+ import starling.display.Sprite;
+ import starling.textures.Texture;
+
+ /** The TouchMarker is used internally to mark touches created through "simulateMultitouch". */
+ internal class TouchMarker extends Sprite
+ {
+ private var _center:Point;
+ private var _texture:Texture;
+
+ public function TouchMarker()
+ {
+ _center = new Point();
+ _texture = createTexture();
+
+ for (var i:int=0; i<2; ++i)
+ {
+ var marker:Image = new Image(_texture);
+ marker.pivotX = _texture.width / 2;
+ marker.pivotY = _texture.height / 2;
+ marker.touchable = false;
+ addChild(marker);
+ }
+ }
+
+ public override function dispose():void
+ {
+ _texture.dispose();
+ super.dispose();
+ }
+
+ public function moveMarker(x:Number, y:Number, withCenter:Boolean=false):void
+ {
+ if (withCenter)
+ {
+ _center.x += x - realMarker.x;
+ _center.y += y - realMarker.y;
+ }
+
+ realMarker.x = x;
+ realMarker.y = y;
+ mockMarker.x = 2*_center.x - x;
+ mockMarker.y = 2*_center.y - y;
+ }
+
+ public function moveCenter(x:Number, y:Number):void
+ {
+ _center.x = x;
+ _center.y = y;
+ moveMarker(realX, realY); // reset mock position
+ }
+
+ private function createTexture():Texture
+ {
+ var scale:Number = Starling.contentScaleFactor;
+ var radius:Number = 12 * scale;
+ var width:int = 32 * scale;
+ var height:int = 32 * scale;
+ var thickness:Number = 1.5 * scale;
+ var shape:Shape = new Shape();
+
+ // draw dark outline
+ shape.graphics.lineStyle(thickness, 0x0, 0.3);
+ shape.graphics.drawCircle(width/2, height/2, radius + thickness);
+
+ // draw white inner circle
+ shape.graphics.beginFill(0xffffff, 0.4);
+ shape.graphics.lineStyle(thickness, 0xffffff);
+ shape.graphics.drawCircle(width/2, height/2, radius);
+ shape.graphics.endFill();
+
+ var bmpData:BitmapData = new BitmapData(width, height, true, 0x0);
+ bmpData.draw(shape);
+
+ return Texture.fromBitmapData(bmpData, false, false, scale);
+ }
+
+ private function get realMarker():Image { return getChildAt(0) as Image; }
+ private function get mockMarker():Image { return getChildAt(1) as Image; }
+
+ public function get realX():Number { return realMarker.x; }
+ public function get realY():Number { return realMarker.y; }
+
+ public function get mockX():Number { return mockMarker.x; }
+ public function get mockY():Number { return mockMarker.y; }
+ }
+}
\ No newline at end of file
diff --git a/mobile_version/src/starling/events/TouchPhase.as b/mobile_version/src/starling/events/TouchPhase.as
new file mode 100644
index 00000000..2749a8ae
--- /dev/null
+++ b/mobile_version/src/starling/events/TouchPhase.as
@@ -0,0 +1,53 @@
+// =================================================================================================
+//
+// Starling Framework
+// Copyright Gamua GmbH. All Rights Reserved.
+//
+// This program is free software. You can redistribute and/or modify it
+// in accordance with the terms of the accompanying license agreement.
+//
+// =================================================================================================
+
+package starling.events
+{
+ import starling.errors.AbstractClassError;
+
+ /** A class that provides constant values for the phases of a touch object.
+ *
+ *
A touch moves through at least the following phases in its life:
+ *
+ * BEGAN -> MOVED -> ENDED
+ *
+ *
Furthermore, a touch can enter a STATIONARY phase. That phase does not
+ * trigger a touch event itself, and it can only occur in multitouch environments. Picture a
+ * situation where one finger is moving and the other is stationary. A touch event will
+ * be dispatched only to the object under the moving finger. In the list of touches
+ * of that event, you will find the second touch in the stationary phase.
+ *
+ *
Finally, there's the HOVER phase, which is exclusive to mouse input. It is
+ * the equivalent of a MouseOver event in Flash when the mouse button is
+ * not pressed.
+ */
+ public final class TouchPhase
+ {
+ /** @private */
+ public function TouchPhase() { throw new AbstractClassError(); }
+
+ /** Only available for mouse input: the cursor hovers over an object without a
+ * pressed button. */
+ public static const HOVER:String = "hover";
+
+ /** The finger touched the screen just now, or the mouse button was pressed. */
+ public static const BEGAN:String = "began";
+
+ /** The finger moves around on the screen, or the mouse is moved while the button is
+ * pressed. */
+ public static const MOVED:String = "moved";
+
+ /** The finger or mouse (with pressed button) has not moved since the last frame. */
+ public static const STATIONARY:String = "stationary";
+
+ /** The finger was lifted from the screen or from the mouse button. */
+ public static const ENDED:String = "ended";
+ }
+}
\ No newline at end of file
diff --git a/mobile_version/src/starling/events/TouchProcessor.as b/mobile_version/src/starling/events/TouchProcessor.as
new file mode 100644
index 00000000..76ff3751
--- /dev/null
+++ b/mobile_version/src/starling/events/TouchProcessor.as
@@ -0,0 +1,481 @@
+// =================================================================================================
+//
+// Starling Framework
+// Copyright Gamua GmbH. All Rights Reserved.
+//
+// This program is free software. You can redistribute and/or modify it
+// in accordance with the terms of the accompanying license agreement.
+//
+// =================================================================================================
+
+package starling.events
+{
+ import flash.geom.Point;
+ import flash.utils.getDefinitionByName;
+
+ import starling.core.Starling;
+ import starling.display.DisplayObject;
+ import starling.display.Stage;
+
+ /** The TouchProcessor is used to convert mouse and touch events of the conventional
+ * Flash stage to Starling's TouchEvents.
+ *
+ *
The Starling instance listens to mouse and touch events on the native stage. The
+ * attributes of those events are enqueued (right as they are happening) in the
+ * TouchProcessor.
+ *
+ *
Once per frame, the "advanceTime" method is called. It analyzes the touch queue and
+ * figures out which touches are active at that moment; the properties of all touch objects
+ * are updated accordingly.
+ *
+ *
Once the list of touches has been finalized, the "processTouches" method is called
+ * (that might happen several times in one "advanceTime" execution; no information is
+ * discarded). It's responsible for dispatching the actual touch events to the Starling
+ * display tree.
+ *
+ * Subclassing TouchProcessor
+ *
+ *
You can extend the TouchProcessor if you need to have more control over touch and
+ * mouse input. For example, you could filter the touches by overriding the "processTouches"
+ * method, throwing away any touches you're not interested in and passing the rest to the
+ * super implementation.
+ *
+ *
To use your custom TouchProcessor, assign it to the "Starling.touchProcessor"
+ * property.
+ *
+ *
Note that you should not dispatch TouchEvents yourself, since they are
+ * much more complex to handle than conventional events (e.g. it must be made sure that an
+ * object receives a TouchEvent only once, even if it's manipulated with several fingers).
+ * Always use the base implementation of "processTouches" to let them be dispatched. That
+ * said: you can always dispatch your own custom events, of course.
+ */
+ public class TouchProcessor
+ {
+ private var _stage:Stage;
+ private var _root:DisplayObject;
+ private var _elapsedTime:Number;
+ private var _lastTaps:Vector.;
+ private var _shiftDown:Boolean = false;
+ private var _ctrlDown:Boolean = false;
+ private var _multitapTime:Number = 0.3;
+ private var _multitapDistance:Number = 25;
+ private var _touchEvent:TouchEvent;
+
+ private var _touchMarker:TouchMarker;
+ private var _simulateMultitouch:Boolean;
+
+ /** A vector of arrays with the arguments that were passed to the "enqueue"
+ * method (the oldest being at the end of the vector). */
+ protected var _queue:Vector.;
+
+ /** The list of all currently active touches. */
+ protected var _currentTouches:Vector.;
+
+ /** Helper objects. */
+ private static var sUpdatedTouches:Vector. = new [];
+ private static var sHoveringTouchData:Vector.