2012年4月30日 星期一

StageWebView 與Web App 混合使用

Adobe AIR 目的是給開發者一個跨平台發佈, 我們可以好好利用這個優勢. 當中StageWebView 是一個值得關注的功能, 能混合於HTML 和Javascript 開發成Web App. 作者製作一個Web App, 包含以下三個HTML 功能:

PhotoSwipe
Video.js
krpano Panorama Viewer


在這個範例中, 我們會把這三個功能包裝於Adobe AIR 內, 並分別儲存於:
  • PhotoSwipe -  所有檔案儲存於html 資料夾中, 與安裝檔一同發佈給用戶
      (完全本地儲存) href="PhotoSwipe/index.html"
  • Video.js - 播放功能儲存於html 資料夾中, 播放時載入網上的影片
      (部分本地儲存) href="videojs/demo.html"
  • krpano - 直接跳到網上的範例
      (完全網上儲存) href="http://krpano.com/krpano.html?pano=panos/rom/marktplatz/marktplatz.xml"
發佈html 資料夾設定 (Included files)

資料夾index.html 的內容, 純粹以傳統HTML 方式運作, 可以超連結本地內容或外部網頁.
資料夾index.html 的內容

作者編寫一個名為AirView 類別, 作為StageWebView 與介面控制部分的連繫. 主要功能:
  • 當屏幕大小改變, 自動調整介面控制部分位置
    private function stageResizeHander(event:Event):void {
      var menuHeight:Number = 0;
      ...
      _webView.viewPort = new Rectangle(0, menuHeight, _stage.stageWidth, _stage.stageHeight - menuHeight);
    }
    
  • 載入HTML 的標題<title>
    private function webViewCompleteHandler(event:Event):void {
      ...
      _titleTxt.text = _webView.title;
      ...
    }
    
  • 處理返回事件
    private function backMouseDownHandler(event:MouseEvent):void {
      if(_backBtn.enabled)
        if (_webView.isHistoryBackEnabled)
          _webView.historyBack();
    }
    
  • 複製html 資料夾至用戶設備中  (作本地儲存)
    public static function copyFile(folderName:String, indexName:String, once:Boolean = true):String {
     var source:File = File.applicationDirectory.resolvePath(folderName);
     var destination:File = File.applicationStorageDirectory;
     if (!destination.resolvePath(indexName).exists || !once)
        source.copyTo(destination, true);
     return "file://" + destination.resolvePath(indexName).nativePath;
    }

介面分為兩部分:
  • 內容以StageWebView 顯示HTML.
  • 控制元件由Flash 負責, 因應個人喜好設計, 自由度十分高.


作者認為, 關於Adobe AIR 的StageWebView, 是一個製作Web Apps 的一個理想方式. 若我們配合Stage3D, 更可提升畫面上的特效 (例: 兩個HTML 之間的轉換效果).

對比jQuery Mobile, Sencha Touch 等框架更為彈性, 因為每一個html 獨立運作, 開發簡單方便. 設計師自由製作介面, 如同網頁製作一樣.

對比TitaniumPhone Gap 等框架, 包裝成Web Apps 不需安裝SDK, 沒有複雜的安裝與設定. 同時支援Web Apps 與高效能的遊戲開發.

若大家有興趣, 可以改良一下, 加入Stage3D 特效, 在iOS 及Andoird 發佈給用戶.
大家可以 [下載] 範例試試看.

小記: 若StageWebView 與HTML 產生互動, 可參考以下連結.
注意事項: 若發佈Android 版本, 請確定發佈設定給予INTERNET Permisssion, 以免外部連結失敗喔.


2012年4月17日 星期二

[教學] 物理盒子遊戲製作 (Physical Box)

這個遊戲製作教學, 目標完成一個物理盒子遊戲, 在iOS 和Android 運作.
我們使用Adobe AIR, 結合Starling 圖像引擎Nape 物理引擎, 製作一個簡單小遊戲.

遊戲說明:
  • 按藍色盒子, 會使它消失
  • 按黑色和紅色盒子, 不會消失
  • 把紅色盒子安全地降落在啡色盒子之上
請按 [觀看] 範例

在設計上, 我們分成以下兩個層面說明:
  • 介面部分 (physical_box.mxml 檔)
       處理遊戲流程 (包括: 載入, 開始和重玩功能)
  • 遊戲部分  (MyGame.as 檔)
       處理遊戲內容 (包括:  盒子定位, 消失藍色盒子和完成遊戲功能)
圖層分佈 (介面部分)

介面部分 (physical_box.mxml 檔)
  1. 初次化Starling 和MyGame 物件
    private function init():void{
      _starling = new Starling(MyGame, this.stage);
      _starling.start();
      _starling.stage.addEventListener(starling.events.Event.ADDED, addedHandler);
    }
  2. 當MyGame 物件被加入至介面部分時, 把 MyGame 物件記下, 然後顯示開始按鈕 (startImg)
    private function addedHandler(event:starling.events.Event):void{
      if(_starling.stage.numChildren>0){
        // <----- remove listener
        _starling.stage.removeEventListener(starling.events.Event.ADDED,addedHandler);
        
        // <----- cache variable
        _myGame = _starling.stage.getChildAt(0) as MyGame;
          
        // <----- add listener
        _myGame.addEventListener(starling.events.Event.COMPLETE,completeHandler);
        
        // <----- invisible busyIndicator
        this.removeElement(busyIndicator);
        
        // <----- visible startImg
        myFade2.play();
      }
    }
    
  3. 當用戶按下開始按鈕, 等待按鈕消失 (Fade Out), 然後呼叫MyGame 物件重新開始
    private function clickStartImgHandler(event:MouseEvent):void{
      restartBtn.visible = true;
      myFade3.play();
    }
    private function effect3Stop():void{
      _myGame.reset();
      this.removeElement(startImg);
    }
    
  4. 最後, 當介面接收MyGame 回傳完成事件 (Event.Complete), 顯示完成圖案 (winImg)
    private function completeHandler(event:starling.events.Event):void{
      myFade1.play();
    }
    


遊戲部分 (MyGame.as 檔)
  1. 當MyGame 物件被產生後, 等待MyGame 物件被加入至介面部分
    public function MyGame(){
      addEventListener(Event.ADDED_TO_STAGE, addedToStageHandler);
    }
    
  2. MyGame 物件進入介面後, 我們設定遊戲空間, 加入遊戲背景圖案, 和定設兩個遊戲事件
    private function addedToStageHandler(event:Event):void{
      // <----- cache variable
      _ns = Starling.current.nativeStage;
      _space = new Space(new Vec2(0, 3000));
      
      // <----- add listener
      addEventListener(Event.ENTER_FRAME, enterFrameHandler);
      _ns.addEventListener(MouseEvent.MOUSE_DOWN, downHandler);
      
      // <----- add background
      addChild(Image.fromBitmap(new _bgClass()));
    }
    
  3. 遊戲事件一: 若用戶按下藍色盒子, 它便會消失
    private function downHandler(event:MouseEvent):void{
      var mp:Vec2 = new Vec2(event.stageX, event.stageY);
      var bodies:BodyList = _space.bodiesUnderPoint(mp);
      if(bodies.length > 0){
        var b:Body = bodies.shift();
        if(b.graphic as Box!=null){
          removeChild(b.graphic);
          b.shapes.clear();
        }
      }
    }
    
  4. 遊戲事件二: 若紅色盒子進入有效區域 (winRect), 便發出完成事件 (Event.Complete)
    private function enterFrameHandler(event:Event):void{
      _space.step(1/60);
      if(_winRect!=null)
        if(_winRect.contains(_star.position.x, _star.position.y)){
          // <----- clear condition
          _winRect= null;
          
          // <----- dispatch event
          this.dispatchEvent(new Event(Event.COMPLETE));
        }
    }
    
  5. 當介面呼叫MyGame 物件重新開始, 我們刪除舊有內容, 然後設定新內容
    public function reset():void{
      // <----- remove all objectes
      var bodies:BodyList = _space.bodies;
      for(var i:int=0; i<bodies.length; i++){
        var b:Body = bodies.at(i);
        this.removeChild(b.graphic);
        b.shapes.clear();
      }
      
      // <----- add objectes
      defineObject();
    }
    
  6. 新內容包括: 盒子可移動範圍, 新盒子, 和紅色盒子有效區域 (winRect)
    private function defineObject():void{
      ......
      addBox(halfW+10, stageH-600);
      
      _base = addBase(halfW, stageH-100);
      _star = addStar(halfW, stageH-610);
      
      _winRect = new Rectangle(halfW-Base.WIDTH/2, stageH-100-Star.HEIGHT, Base.WIDTH, Star.HEIGHT);
    }
    

若大家有興趣, 可以改良一下, 加入更多關卡玩玩喔.
大家可以 [下載] 範例試試看.

注意事項:

  • 若在發佈iOS 版本時, 出現錯誤訊息 (Exception in thread "main" java.lang.OutOfMemoryError: Java heap space),  請選擇執行"Export Release Build" , 它可以避免產生這個錯誤.

錯誤訊息 Java heap space
Export Release Build

2012年4月16日 星期一

於iOS 及Andoird 嵌入式發佈 (Embedded AIR Runtime)

關於Adobe AIR 嵌入式發佈, 把AIR Runtime 包裝於安裝檔案內, 一同發佈給用戶. 這個方法好處在於用戶不需另外安裝Adobe AIR, 減少用戶的混亂. 用戶亦不會知道是由Adobe AIR 所製成.
  1. Project 選擇Export Release Build
  2. 選擇發佈的Target Platforms, 然後按Next
  3. 在選擇Google AndroidDeployment 中, 我們可以選擇:
     - Export application with captive runtime (嵌入式發佈)
     - Export application that uses a shared AIR runtime (共享式發佈)
  4. 完成後的IPA 及APK 檔(分別為iOS 及Android 的安裝檔案格式) 的大小約為:
     - Android 嵌入式: 8973KB
     - Android共享式:   522KB
     - iOS 嵌入式: 6341KB
對於發佈Andoird, 作者較為建議隱藏AIR Runtime 於安裝檔內, 選擇嵌入式發佈, 減少用戶在安裝過程產生混亂. 而發佈iOS 大家只可選擇嵌入式喔.

參考資料:
http://help.adobe.com/en_US/flex/mobileapps/WSc5cd04c102ae3e97-67096d2612dea547bfa-8000.html

注意事項: 這個給Andoird 嵌入式發佈功能, 只限於Adobe Flash Builder 4.6 或以上版本.

2012年4月15日 星期日

Away3D 的地球

國外的高手, 利用美國NASA 拍下地球的照片. 製作一個立體地球, 以Away3D 引擎展示.
大家值得留意, 當中水平光線, 山脊的立體感, 城鎮上的人造光線, 地軸改變等... 都是叫人讚歎.

 請按 [ 觀看 ] 示範 (需要安裝Flash Player 11)
參考來源:
http://www.infiniteturtles.co.uk/blog/away3d-with-flash-11-2-mouse-locking-all-over-the-world

2012年4月12日 星期四

高級功能許可證 (Premium Features License)

Adobe 宣布Flash Player11.2的遊戲高級功能(Premium features), 若遊戲或應用程序同時使用以下兩個功能, 會收取使用費用,費用為淨營收超出5萬美元部分的9%分成:
  • Stage3D硬件加速技術 (Stage3D - Stage3D.request3DContext)
  • 域內存操作 (Domain memory - ApplicationDomain.domainMemory)



對於大多使用Adobe Flash Builder 或Adobe Flash 開發者來說, 是不會進行域內存操作. Adobe 這次目的明顯針對AlchemyUnityUnreal 等C/ C++ 交叉編譯器. 它們編譯後生成SWF 檔案, 透過Flash Player 或Adobe AIR 技術作為最終發佈對象.

作者認為, Adobe 這個動作有利亦有弊.
  • 可以保護為Adobe 專門所開發的3D 引擎
  • 開發者若跨過Adobe 生成SWF 檔案, Adobe 仍然獲得開發回報
  • 但減少使用SWF 的開發數量

不論如何, 這個動作對大部分開發者, 是沒有影響. 大家仍然可以放心使用Adobe Flash Builder 或Adobe Flash 發佈跨平台遊戲或應用程序.

參考資料: http://www.adobe.com/devnet/flashplayer/articles/premium-features.html

後記:
事實上, 作者十分認同Unity 和Unreal 的能力, 在iOS 及Android 產生不少精彩遊戲. 相信大家也玩過的.