Here’s your license key for TexturePacker:
TP-xxxxxxxxxxxxxxxx
I’ve added a license for PhysicsEditor (see file attached) in case you might want to try it too 😉
Nice blog! I would be happy to get a (short) blog post in return.
In case you do a tutorial post about my tools I can link back to your blog from the tutorials section on my page. That might give you some more visitors on your page!
I sent you a blogger license for TexturePacker some time ago,
and I am curious how you like the program.
Did you get it running successfully? Or do you need some assistance?
I would be happy to get a (short) blog post in return.
package
{
import flash.display.Sprite;
import starling.core.Starling;
[SWF(frameRate="60",Width="800",Height="600")]
public class StarlingTest extends Sprite
{
public function StarlingTest()
{
var star:Starling = new Starling(Main, stage);
star.start();
}
}
}
Main.as
package {
import flash.display.Bitmap;
import starling.core.Starling;
import starling.display.MovieClip;
import starling.display.Sprite;
import starling.events.Touch;
import starling.events.TouchEvent;
import starling.events.TouchPhase;
import starling.textures.Texture;
import starling.textures.TextureAtlas;
public class Main extends Sprite {
[Embed(source = 'test.xml', mimeType = 'application/octet-stream')]
private var AtlasXML:Class;
[Embed(source = 'test.png')]
private var AtlasTexture:Class;
private var mc:AlphaMovieClip ;
public function Main() {
var bitmap:Bitmap = new AtlasTexture();
var texture:Texture = Texture.fromBitmap(bitmap);
var xml:XML = XML(new AtlasXML());
var atlas:TextureAtlas = new TextureAtlas(texture, xml);
mc = new AlphaMovieClip("run",atlas, bitmap.bitmapData,30);
var m2:MovieClip = new MovieClip(atlas.getTextures("run"),30);
m2.loop = false;
m2.x = 200;
mc.addEventListener(TouchEvent.TOUCH, touchEventHandler);
addChild(mc);
addChild(m2);
Starling.juggler.add(mc);
Starling.juggler.add(m2);
}
private function touchEventHandler(event:TouchEvent):void {
var touch:Touch = event.getTouch(this);
if(!touch ) return;
if (touch.phase == TouchPhase.BEGAN){
mc.pause();
}else if(touch.phase == TouchPhase.ENDED){
mc.play();
}
}
}
}
AlphaMovieClip.as
package {
import flash.display.BitmapData;
import flash.geom.Point;
import flash.geom.Rectangle;
import flash.utils.Dictionary;
import starling.display.DisplayObject;
import starling.display.MovieClip;
import starling.textures.SubTexture;
import starling.textures.Texture;
import starling.textures.TextureAtlas;
public class AlphaMovieClip extends MovieClip
{
private var m_TexturePrefix :String = "";
private var m_TextureAtlas :TextureAtlas = null;
private var m_Textures :Vector. = null;
private var m_TextureInfo :Dictionary = null;
private var m_BitmapData :BitmapData = null;
public function AlphaMovieClip(texturePrefix:String, textureAtlas:TextureAtlas, bitmapData:BitmapData, fps:Number = 12)
{
m_TextureInfo = new Dictionary();
var names:Vector. = textureAtlas.getNames(texturePrefix);
for each (var name:String in names)
{
var textureInfo:Object = { };
textureInfo.name = name;
textureInfo.texture = textureAtlas.getTexture(name);
m_TextureInfo[name] = textureInfo;
}
m_TexturePrefix = texturePrefix;
m_TextureAtlas = textureAtlas;
m_Textures = textureAtlas.getTextures(texturePrefix);
m_BitmapData = bitmapData;
super(m_Textures, fps);
}
override public function hitTest(localPoint:Point, forTouch:Boolean = false):DisplayObject
{
if (forTouch && visible && touchable)
{
if (getBounds(this).containsPoint(localPoint))
{
var texture:Texture = getFrameTexture(currentFrame);
var subtexture:SubTexture = texture as SubTexture;
var textureFrame:Rectangle = subtexture.frame;
var clipping:Rectangle = subtexture.clipping;
var frameBound:Rectangle = new Rectangle(
Math.abs(textureFrame.x),
Math.abs(textureFrame.y),
clipping.width * m_TextureAtlas.texture.width,
clipping.height * m_TextureAtlas.texture.height
);
clipping.x *= m_TextureAtlas.texture.width;
clipping.y *= m_TextureAtlas.texture.height;
var final_x:uint = (frameBound.containsPoint(localPoint) ? localPoint.x - frameBound.x : uint.MAX_VALUE);
var final_y:uint = (frameBound.containsPoint(localPoint) ? localPoint.y - frameBound.y : uint.MAX_VALUE);
if (final_x != uint.MAX_VALUE && final_y != uint.MAX_VALUE)
{
var pixel:uint = m_BitmapData.getPixel32(clipping.x + final_x, clipping.y + final_y);
if (uint((pixel >> 24) & 0xFF) == 0)
{
return null;
}
}
else
{
return null;
}
}
}
return super.hitTest(localPoint, forTouch);
}
}
}
public function Game2() {
addEventListener(Event.ADDED_TO_STAGE, onAdded);
}
private function onAdded (e:Event):void {
// create a Bitmap object out of the embedded image
var sausageBitmap:Bitmap = new Sausage();
// create a Texture object to feed the Image object
var texture:Texture = Texture.fromBitmap(sausageBitmap);
for (var i:int = 0; i < NUM_SAUSAGES; i++) {
// create a Image object with our one texture
var image:Image = new Image(texture);
// set a random alpha, position, rotation
image.alpha = Math.random();
// define a random initial position
image.x = Math.random()*stage.stageWidth
image.y = Math.random()*stage.stageHeight
image.rotation = deg2rad(Math.random()*360);
// show it
addChild(image);
// store references for later
sausagesVector[i] = image;
}
}
}
}[/code]
package {
import flash.display.Bitmap;
import starling.display.Button;
import starling.display.Sprite;
import starling.events.Event;
import starling.textures.Texture;
public class Game extends Sprite {
[Embed(source = "../media/textures/button_up.png")]
private static const Button_UP:Class;
[Embed(source = "../media/textures/button_down.png")]
private static const Button_DOWN:Class;
public function Game() {
addEventListener(Event.ADDED_TO_STAGE, onAdded);
}
private function onAdded (e:Event):void {
// create a Bitmap object out of the embedded image
var buttonSkinUp:Bitmap = new Button_UP();
var buttonSkinDown:Bitmap = new Button_DOWN();
// 創建按鈕
var myButton:Button = new Button(Texture.fromBitmap(buttonSkinUp), "這是按鈕", Texture.fromBitmap(buttonSkinDown));
// 創建Menu容器並把按鈕加上去
var menuContainer:Sprite = new Sprite();
menuContainer.addChild(myButton);
// centers the menu
menuContainer.x = stage.stageWidth - menuContainer.width >> 1;
menuContainer.y = stage.stageHeight - menuContainer.height >> 1;
// show the button
addChild(menuContainer);
}
}
}
public override function hitTest( localPoint:Point, forTouch:Boolean=false ) :DisplayObject
{
// on a touch test, invisible or untouchable objects cause the test to fail
if( forTouch && (!visible || !touchable) )
{
return null;
}
// otherwise, check bounding box of hitArea (which is a Rectangle here)
var result:DisplayObject = null;
if( _hitArea.containsPoint( localPoint ) )
{
result = this;
}
return result;
}
package {
import starling.display.Sprite;
import starling.events.Event;
import starling.text.TextField;
public class Game extends Sprite {
public function Game() {
addEventListener(Event.ADDED_TO_STAGE, onAdded);
}
private function onAdded (e:Event):void {
// create the TextField object
var legend:TextField = new TextField(300, 300, "簡單的文字範例", "Verdana", 38, 0xFFFFFF);
// centers the text on stage
legend.x = stage.stageWidth - legend.width >> 1;
legend.y = stage.stageHeight - legend.height >> 1;
// show it
addChild(legend);
}
}
}
Standard TrueType fonts:也就是一般內嵌字型的方式,將.ttf的文字檔案直接用embed的方式嵌入swf裡。
下面是一個簡單的範例:
package {
import flash.text.Font;
import starling.display.Sprite;
import starling.events.Event;
import starling.text.TextField;
public class Game extends Sprite {
[Embed(source='/../media/fonts/Abduction.ttf', embedAsCFF='false', fontName='Abduction')]
public static var Abduction:Class;
public function Game() {
addEventListener(Event.ADDED_TO_STAGE, onAdded);
}
private function onAdded (e:Event):void {
// create the font
var font:Font = new Abduction();
// create the TextField object
var legend:TextField = new TextField(300, 300, "使用內嵌字型的簡單範例!", font.fontName, 38, 0xFFFFFF);
// centers the text on stage
legend.x = stage.stageWidth - legend.width >> 1; legend.y = stage.stageHeight - legend.height >> 1;
// show it
addChild(legend);
}
}
}

Bitmap fonts:If you need speed or fancy font effects, use a bitmap font instead. That is a font that has its glyphs rendered to a texture atlas. To use it, first register the font with the method registerBitmapFont, and then pass the font name to the corresponding property of the text field.
一個使用Bitmap來當作字型檔案的簡單範例如下:
字型檔案下載:fontRegular
package
{
import flash.display.Bitmap;
import starling.display.Sprite;
import starling.events.Event;
import starling.text.BitmapFont;
import starling.text.TextField;
import starling.textures.Texture;
import starling.utils.Color;
public class Game extends Sprite {
[Embed(source = "../media/fonts/fontRegular.png")]
private static const BitmapChars:Class;
[Embed(source="../media/fonts/fontRegular.fnt", mimeType="application/octet-stream")]
private static const BritannicXML:Class;
public function Game() {
addEventListener(Event.ADDED_TO_STAGE, onAdded);
}
private function onAdded (e:Event):void {
// creates the embedded bitmap (spritesheet file)
var bitmap:Bitmap = new BitmapChars();
// creates a texture out of it
var texture:Texture = Texture.fromBitmap(bitmap);
// create the XML file describing the glyphes position on the spritesheet
var xml:XML = XML(new BritannicXML());
// register the bitmap font to make it available to TextField
TextField.registerBitmapFont(new BitmapFont(texture, xml));
// create the TextField object
var bmpFontTF:TextField = new TextField(400, 400, "使用內嵌字型的簡單範例!", "BritannicBold", 10);
// the native bitmap font size, no scaling
bmpFontTF.fontSize = BitmapFont.NATIVE_SIZE;
// use white to use the texture as it is (no tinting)
bmpFontTF.color = Color.WHITE;
// centers the text on stage
bmpFontTF.x = stage.stageWidth - bmpFontTF.width >> 1;
bmpFontTF.y = stage.stageHeight - bmpFontTF.height >> 1;
// show it
addChild(bmpFontTF);
}
}
}
//要實作要如何利用Stage3D來產生畫面的方式
function render(support:RenderSupport, parentAlpha:Number):void;
//實作物件碰撞偵測的方式
function getBounds(targetSpace:DisplayObject, resultRect:Rectangle=null):Rectangle
Starling物件有它主場景物件Stage,也就是上圖的Starling.display.Stage,它和flash裡的Stage一樣,是放所有物件的母容器(The Starling stage object, which is the root of the display tree that is rendered)。
Stage3D會依發佈平台的不同而使用不一樣的GPU運算引擎,例如在mac電腦上所使用的是OpenGL,而在Windows則會視電腦所使用的硬體設備去選擇所使用的基礎技術。值得一提的是,即使遇到不支援的硬體,Stage3D仍然可以使用軟件模式去做3D運算,只是會變得十分的緩慢。這邊有一個簡單的性能比較:Stage3D vs WebGL 性能較量
package
{
import flash.display.Sprite;
import starling.core.Starling;
[SWF(frameRate="60",Width="800",Height="600")]
public class StarlingTest extends Sprite
{
public function StarlingTest()
{
var star:Starling = new Starling(Main, stage);
star.start();
}
}
}
Main.as
package
{
import starling.core.Starling;
import starling.display.MovieClip;
import starling.display.Sprite;
import starling.textures.Texture;
import starling.textures.TextureAtlas;
public class Main extends Sprite
{
[Embed(source = 'test.xml', mimeType = 'application/octet-stream')]
private var AtlasXML:Class;
[Embed(source = 'test.png')]
private var AtlasTexture:Class;
public function Main()
{
var texture:Texture = Texture.fromBitmap(new AtlasTexture());
var xml:XML = XML(new AtlasXML());
var atlas:TextureAtlas = new TextureAtlas(texture, xml);
var mc:MovieClip = new MovieClip(atlas.getTextures("run"),30);
addChild(mc);
Starling.juggler.add(mc);
}
}
}
var textInput:flash.text.TextField = new flash.text.TextField();
textInput.type = TextFieldType.INPUT;
Starling.current.nativeOverlay.addChild(textInput);
因為starling的textField本身是不能直接設定為可打字的,因此如果想要在場景上加一個可輸入文字的文字欄位,這邊有很詳細的方法介紹:Text Input with Starling framework。
不過要注意,使用nativeOverlay所加進場景裡的物件,也是永遠會在最上層。下面是官網對於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. Starling will remove the overlay from the display list when it’s empty.
3D rendering pipeline的作用是將渲染操作轉化為一組基本數據操作。GPU邏輯上由許多功能明確的功能區塊組成,每一塊對應著某種基本數據操作。在一條流水線中,這些區塊設置為一連續的操作,也就是說上一個區塊的輸出結果作為下一個區塊的輸入。最簡單的3D圖形渲染管線被叫做固定功能管線。稱之為固定是有原因的,因為該管線是不可不可編碼的,固定管線所以顯得有些僵化,因為它只是把輸入的形狀數據經過管線(一系列級聯的區塊)處理後成為用來顯示的最終圖像。
固定功能管線以以下參數作為輸入:幾何描述(頂點集合和三角形)、幾何形狀所應用的紋理數據、3D場景的幾何結構位置和方向,攝像機的位置和方向,光線數據(每組光線的顏色、位置、強度等等數據),和一些設置管線如何渲染呈現的額外參數。換句話說,你只要提供頂點集合、三角形、紋理數據,硬件就可以完成渲染。固定功能管線通過一個坐標變換和光照區塊(transform and lighting),把頂點集合從模型(model)本地坐標轉換為屏幕舞台坐標。這個區塊也負責處理頂點照明,緊接著的區塊是視角剪裁區塊(viewport clipping),主要負責對上一個區塊處理後場景數據進行剪裁(關係到是否參與此區塊以後的渲染和是否在可見等)以符合實際顯示視角的需要。