Starling Display Objects 類別繼承關係圖,顯示 DisplayObject、DisplayObjectContainer、Stage、Sprite、Button、Quad、Image 與 MovieClip 的關係

← INSIGHTS & PERSPECTIVES | 前端開發

Starling Display Objects 介紹:Starling 啟動、物件樹與 Stage

整理 Starling Display Objects 的入門概念,包含 Starling 啟動方式、DisplayObject 類別繼承樹、DisplayObject 與 Stage 的差異,以及原生 Flash 物件在 Starling 場景中的限制。

Starling Display Objects 的核心概念,是先用一個 `Starling` 物件建立整個 Starling 世界,再把畫面內容放進 `starling.display.DisplayObject` 所構成的物件樹。`DisplayObject` 是所有 Starling 畫面物件的基礎,`Stage` 則是整棵顯示樹的根容器;理解這兩個角色,後面看 Quad、Image、Button、Sprite、MovieClip 會清楚很多。

Starling framework 要怎麼啟動?

Starling framework 的啟動點是一個 `starling.core.Starling` 實例。應用程式建立 `Starling` 物件時傳入根場景類別與原生 Flash stage,接著呼叫 `start()` 開始渲染。

所有使用 Starling framework 的應用程式,起始點都是由一個 `Starling` 物件來創建整個 Starling 世界。`Starling` 物件的 API 可以參考官方文件:starling.core.Starling

下面是一個最簡單的啟動範例:

```actionscript

package {

import starling.core.Starling;

import starling.display.Sprite;

[SWF(width="1280", height="752", frameRate="60", backgroundColor="#000000")]

public class Startup extends Sprite

{

private var mStarling:Starling;

public function Startup() {

// 建立 Starling 物件

mStarling = new Starling(Game, stage);

// start it!

mStarling.start();

}

}

}

```

這段程式碼裡的 `Game` 是 Starling 世界的根場景類別,`stage` 則是 Flash 原生舞台。換句話說,Starling 不是直接取代 Flash stage,而是在原生 stage 之上建立自己的 Stage3D 顯示世界。

Starling 世界的物件樹長什麼樣子?

Starling 世界的物件樹以 `DisplayObject` 為共同祖先,往下分成可承載子物件的容器類別,以及負責實際繪製內容的顯示類別。這個分支決定物件能不能 `addChild()`。

官方 Display Objects 說明可以看到,Starling 裡的畫面物件繼承樹長這樣:

Starling Display Objects 類別繼承關係圖

從類別繼承圖可以看出,`starling.display.DisplayObject` 是一切 Starling 畫面物件的祖先,並繼承自 `EventDispatcher`。比較需要先記住的是這兩條路線:

類別分支代表物件重點
`DisplayObjectContainer` 分支`Stage`、`Sprite`、`Button`可以包含其他 `DisplayObject`,因此能使用 `addChild()` 管理子物件
非容器顯示物件分支`Quad`、`Image`、`MovieClip`負責繪製或播放畫面內容,通常不能再承載子物件

這也是 Starling 初學時最容易混淆的地方:`starling.display.MovieClip` 看起來像原生 Flash 的 MovieClip,但在 Starling 世界裡,`MovieClip` 沒有辦法使用 `addChild()`。`MovieClip` 比較像動畫影片,可以播放、控制位置、旋轉或偵測碰撞,但不能在裡面再加入其他 MovieClip。

DisplayObject 在 Starling 裡負責什麼?

`DisplayObject` 是 Starling 顯示物件樹的抽象根類別,不能直接 `new` 出來使用。自訂顯示物件必須繼承 `DisplayObject`,並實作渲染與碰撞範圍計算。

官方手冊可以看這裡:starling.display.DisplayObject

`DisplayObject` 的子孫包含像 `Quad`、`Image`、`MovieClip` 這類負責動畫與畫面繪製的物件;另一邊的 `DisplayObjectContainer` 則是放物件的容器,可以再加入其他 `DisplayObject`。

Starling 裡的 `DisplayObject` 其實是一個 abstract class,沒有辦法被直接建立。若要自己做一個顯示物件,一定要繼承並實作這兩個方法:

```actionscript

// 實作如何利用 Stage3D 產生畫面

function render(support:RenderSupport, parentAlpha:Number):void;

// 實作物件碰撞偵測的方式

function getBounds(targetSpace:DisplayObject, resultRect:Rectangle=null):Rectangle;

```

從繼承樹可以發現,`MovieClip` 與 `DisplayObjectContainer` 採用不一樣的碰撞偵測方法與圖形 render 方式。`DisplayObject` 本身也提供多點觸控偵測、物件座標設定,以及不同層 `DisplayObjectContainer` 之間的座標轉換功能。

Stage 在 Starling 顯示樹裡是什麼角色?

`starling.display.Stage` 是 Starling 顯示樹的根容器,會在建立 `Starling` 物件時自動建立。開發者通常不需要自己 new Stage,只需要把顯示物件加到 Starling 場景裡。

官方手冊可以看這裡:starling.display.Stage

Starling 物件有它自己的主場景物件 `Stage`,也就是 `starling.display.Stage`。`Stage` 和 Flash 裡的 Stage 類似,是放所有 Starling 物件的母容器;官方文件的說法是,Starling stage object 是被 render 的 display tree root。

`starling.display.Stage` 裡面只能包含繼承自 `starling.display.DisplayObject` 的物件,不能包含任何 `flash.display.DisplayObject` 相關物件。這兩種類別完全不能相容,不能把原生 Flash 顯示物件直接當成 Starling 顯示物件使用。

Starling 可以放原生 Flash DisplayObject 嗎?

Starling 場景不能直接混放 `flash.display.DisplayObject`,但可以透過 `Starling.current.nativeOverlay` 把原生 Flash 物件放到 Flash stage 上。nativeOverlay 的內容永遠會蓋在 Starling 畫面最上層。

雖然在 Starling 裡可以用下面這段程式加入原生 Flash 物件:

```actionscript

Starling.current.nativeOverlay.addChild(textInput);

```

但這其實只是取得 `flash.display.Stage` 上方的 overlay,把元件放進去而已。原生 Flash 物件永遠會被放在畫面的最上層,不會真的進入 Starling 的 display tree。

Starling nativeOverlay 與原生 Flash 物件疊放示意

這個限制在做文字輸入框、嵌入原生元件或混合舊有 Flash 內容時特別重要。若畫面需要互相遮罩、排序或碰撞偵測,最好先確認物件是 Starling DisplayObject 還是原生 Flash DisplayObject,否則圖層順序會和直覺不同。

DisplayObject、DisplayObjectContainer、MovieClip 怎麼分辨?

判斷 Starling 顯示物件時,可以先問「這個物件能不能裝子物件」。能裝子物件的通常屬於 `DisplayObjectContainer` 分支;只負責畫圖或播放影格的物件,通常不能當容器用。

用實作角度整理,差異大致如下:

問題優先看哪個類別實務判斷
需要把多個物件組成一個畫面區塊`Sprite` 或其他 `DisplayObjectContainer`使用 `addChild()` 管理子物件
需要顯示單張圖片或矩形色塊`Image`、`Quad`物件本身負責 render,不負責承載子物件
需要播放影格動畫`MovieClip`交給 `Juggler` 控制播放,不能把它當 Flash MovieClip 容器
需要整個 Starling 世界的根節點`Stage`建立 `Starling` 時自動建立,不需要自己 new

我的理解方式是:Starling 的 API 故意接近 Flash display list,但不要把兩者視為同一套模型。Starling DisplayObject 是 Stage3D 世界裡的顯示物件,Flash DisplayObject 是原生 display list 的顯示物件;名稱相近,底層行為不一樣。

延伸閱讀

常見問題

QStarling DisplayObject 是什麼?

Starling DisplayObject 是 Starling 顯示物件樹的基礎類別。`Quad`、`Image`、`MovieClip`、`Sprite`、`Stage` 都是從這個根類別往下延伸出來的顯示物件。

QStarling DisplayObject 可以直接 new 嗎?

Starling DisplayObject 不能直接 `new` 出來使用,因為 `DisplayObject` 是 abstract class。若要自訂顯示物件,需要繼承 `DisplayObject` 並實作 `render()` 與 `getBounds()`。

QStarling MovieClip 可以使用 addChild 嗎?

Starling MovieClip 不能使用 `addChild()`。`starling.display.MovieClip` 是播放影格動畫的顯示物件,不是 `DisplayObjectContainer`,因此不能像原生 Flash MovieClip 一樣當容器使用。

QStarling Stage 需要自己建立嗎?

Starling Stage 不需要自己建立。建立 `Starling` 物件時,Starling framework 會自動建立 `starling.display.Stage`,並把它作為整個 Starling display tree 的根節點。

QStarling 可以直接加入 flash.display.DisplayObject 嗎?

Starling display tree 不能直接加入 `flash.display.DisplayObject`。若真的需要原生 Flash 物件,可以用 `Starling.current.nativeOverlay.addChild()` 疊在 Starling 畫面上方,但該物件仍屬於原生 Flash display list。

參考資料

最後更新

2014-02-07(本文保留 2014 年 Starling Display Objects 學習筆記內容,並補上 GEO 結構。)

關於作者 {#author}

Claire Chang | 企業 AI 導入與流程轉型顧問。專注於 AI Agent 架構設計、ERP 系統整合與企業 AI 治理。

首次發布:2014-02-07