2012年10月17日 星期三

Adobe AIR 與Push Notifications

為大家介紹Adobe AIR 原生支援的Push Notifications 功能, 配合apns-php 伺服器發出訊息給iOS 裝置.

簡單測試需要的準備:
  • Adobe AIR 3.4 或以上SDK (安裝SDK 於Flash Builder 請參考)
  • 一個iOS 裝置 (不能以XCode Simulator 來取代)
  • 需要.p12, .mobileprovision 與.pem 檔 (製作包含Push Notifications 功能請參考)
  • 一個執行Push Notification Provider 的伺服器, 我們可以使用apns-php


Push Notifications 的運作原理:

  • 使用Adobe AIR 提供的介面(RemoteNotifier) 並執行訂閱(subscribe), 取得一個Device Token (這是每個iOS 裝置獨一無異的記號)
  • 把Device Token 提交給伺服器記下
  • 利用Push Notification Provider 發放訊息給這些Device Token
  • 這個iOS 裝置會收到Push Notification
Push Notifications 基本工作流程


Adobe AIR 提供以下三種Push Notification 提示:
  • NotificationStyle.ALERT - 在收到通知時顯示警告方塊的通知
  • NotificationStyle.BADGE - 收到通知時會以數字/影像更新應用程式圖示的通知
  • NotificationStyle.SOUND - 在收到通知時播放聲音的通知
Adobe AIR 在iOS 接收Push Notifications

在Adobe AIR 程式編寫, 提供一個按鈕給用戶按下(clickHandler), 取得iOS 裝置的Device Token:
private function clickHandler(event:MouseEvent):void{
  trace("clickHandler: " + RemoteNotifier.supportedNotificationStyles.length);
  myTxt.appendText("clickHandler: " + RemoteNotifier.supportedNotificationStyles.length+"\n");
  
  if ( RemoteNotifier.supportedNotificationStyles.length > 0)
  {
    var preferredNotificationStyles:Vector.<string> = new Vector.<string>;
    
    preferredNotificationStyles.push(NotificationStyle.ALERT);
    preferredNotificationStyles.push(NotificationStyle.SOUND);
    preferredNotificationStyles.push(NotificationStyle.BADGE);
    
    var subscribeOptions:RemoteNotifierSubscribeOptions = new RemoteNotifierSubscribeOptions();
    subscribeOptions.notificationStyles = preferredNotificationStyles;
    
    rn = new RemoteNotifier();
    
    rn.addEventListener(RemoteNotificationEvent.TOKEN, sendDeviceTokenToServer);
    rn.addEventListener(StatusEvent.STATUS, subscriptionFailureCallback);
    
    rn.subscribe(subscribeOptions);
  }
}
protected function subscriptionFailureCallback(event:StatusEvent):void
{
  trace("Received Status event for registrationFailure with code:" + event.code + " and level:" + event.level + "\n");
  myTxt.appendText("Received Status event for registrationFailure with code:" + event.code + " and level:" + event.level + "\n");
}
protected function sendDeviceTokenToServer(event:RemoteNotificationEvent):void
{
  trace("Received " + event.type + " with tokenString:" + event.tokenId + "\n");
  myTxt.appendText("Received " + event.type + " with tokenString:" + event.tokenId + "\n");
}

在Adobe AIR 程式發佈設定:
  • Certificate 和Provisioning file 需要使用包含Push Notifications 功能的.p12 和 .mobileprovision 檔
  • 在XML 設定檔加入Entitlements 設定:
    <iPhone>
      <Entitlements><![CDATA[
        <key>get-task-allow</key>
        <true/>
        <key>aps-environment</key>
        <string>development</string>
        <key>keychain-access-groups</key>
        <array>
          <string>KEYCHAIN_ACCESS_GROUP</string>
        </array>
      ]]></Entitlements>
    </iPhone>
  • 在Flex Compiler > Additional compilder arguments: 更改成:
    -locale en_US -swf-version=17

架設apns-php 伺服器後, 我們更改sample_push.php 的內容作為發訊測試:
  • 更改.pem 檔名稱, 並把.pem 檔案複製至與sample_push.php 同一資料夾內
  • 加入iOS 裝置的Device Token
更改sample_push.php 內容

當執行sample_push.php 後, 測試對像的iOS 裝置會接收到Push Notification. 大家可以 [下載] 範例試試看.

參考資料: http://blogs.adobe.com/airodynamics/2012/05/29/push-notifications-support-in-ios/

2012年10月16日 星期二

製作p12, mobileprovision 與pem

製作p12 :  認證檔 iOS Certificate (包含Push Notifications 功能)
  1. 進入iOS Provisioning Portal, 在App IDsNew App ID

  2. 輸入新增程式的名稱 (NameApp ID)

  3. 找尋新增的程式, 按下Configure

  4. 啟動Enable for Apple Push Notification service, 並在Development Push SSL Certificate 按下Configure

  5. 然後按指示, 在MAC OS X 的Utilities 開啟Keychain Access, 選擇:
    Keychain > Certificate > Assistant > Request a Certificate from a Certificate Authority

  6. 產生一個csr 檔, 並儲存於桌面上

  7. 把桌面上的csr 檔上載給iOS Provisioning Portal 處理

  8. 處理完成後, 會產生一個cer 檔, 把它下載至桌面

  9. 在桌面執行cer 檔後, 在Keychain Access 會新增一個Certificate

  10. 在新增的Certificate 右按Export 產生p12 檔


製作mobileprovision :  描述檔 Provisioning Profile
  1. ProvisioningDistribution 選擇New Profile

  2. 輸入Profile Name 等資料

  3. 手動更新iOS Provisioning Portal 網頁(數秒時間便可), 直至新增的項目提供mobileprovision 檔下載按鈕


製作pem :  數位憑證 Push Certificate
  1. 開啟MAC OS X 的Terminal, 移至儲存p12 檔的桌面位置: (請更改為正確路徑)
    cd /Users/YOUR_USER_NAME/Desktop/
  2. 然後輸入以下指令產生pem 檔:
    openssl pkcs12 -in Certificates.p12 -out server_certificates_bundle_sandbox.pem -nodes -clcerts

若大家沒有開發者帳號, 可考慮暫時使用假認證檔(p12) 和描述檔(mobileprovision) 作測試. 待日後正式發佈時, 才購買開發者帳號.

2012年10月10日 星期三

as3dpad 操控桿介紹

as3dpad 是作者製作的一個類別庫, 目的在Adobe AIR mobile 提供一個虛擬操控桿, 於iOS 和Android 等流動裝置運作, 為遊戲提供一個輸入方法.

配合Starling 的 [範例] (請以鍵盤WASDm, 操控)

as3dpad 渲染部分參考SpriteSheetClip 的手法, 所以在stage3d 之上有效運作, 與Starling 等框架相容.
另外, 類別庫提供以鍵盤代替螢幕輸入(WASDm,), 給開發人員在電腦直接測試遊戲.

弧度(radians) 表示操控桿位置

以下是編寫的簡單步驟:
  1. 建立DPad 物件
    var dPad:DPad = new DPad();
    this.addChild(dPad);
    
  2. 接收X 軸與Y 軸回傳的數據
    dPad.leftPad.addEventListener(DPadEvent.TOUCH_PRESS, touchPressHandler);
    dPad.leftPad.addEventListener(DPadEvent.TOUCH_RELEASE, touchReleaseHandler);
    
    private function touchPressHandler(event:DPadEvent):void{
      var axisPad:AxisPad = event.target as AxisPad;
      trace("radians: " + axisPad.radians);
      trace("distance: " + axisPad.distance + "/" + axisPad.maxDistance);
      trace("press left:  " + (axisPad.value & AxisPad.LEFT));
      trace("press right: " + (axisPad.value & AxisPad.RIGHT));
      trace("press up:    " + (axisPad.value & AxisPad.UP));
      trace("press down:  " + (axisPad.value & AxisPad.DOWN));
    }
    private function touchReleaseHandler(event:DPadEvent):void{
      ...
    }
    
  3. 接收A 和B 按鈕回傳的數據
    dPad.rightPad.addEventListener(DPadEvent.TOUCH_PRESS_A, touchPressAHandler);
    dPad.rightPad.addEventListener(DPadEvent.TOUCH_PRESS_B, touchPressBHandler);
    dPad.rightPad.addEventListener(DPadEvent.TOUCH_RELEASE_A, touchReleaseAHandler);
    dPad.rightPad.addEventListener(DPadEvent.TOUCH_RELEASE_B, touchReleaseBHandler);
    
    private function touchPressAHandler(event:DPadEvent):void{
      var groupPad:GroupPad = event.target as GroupPad;
      trace("press A: " + (groupPad.value & GroupPad.A_BUTTON));
      trace("press B: " + (groupPad.value & GroupPad.B_BUTTON));
    }
    private function touchPressBHandler(event:DPadEvent):void{
        ...
    }
    private function touchReleaseAHandler(event:DPadEvent):void{
        ...
    }
    private function touchReleaseBHandler(event:DPadEvent):void{
        ...
    }

類別庫提供以下範例參考:
  • example01_basic - 基本用法 [demo]
  • example02_custom_UI - 自定介面 [demo]
  • example03_double_AxisPad - 雙操控桿 [demo]
  • example04_touch9Grid - 螢幕九格觸控 [demo]
  • example05_starling - 配合Starling [demo]

Launch Examples Launch Examples Launch Examples Launch Examples Launch Examples

大家可以 [下載] 範例試試看.

2012年9月26日 星期三

[教學] Panorama 全景圖實作

日本的Spark project 為Action Script 開發人員提供大量程式庫. 其中AlternativaTemplate 編寫的Camera 操作控制, 能簡單實作全景圖, 並透過Alternativa3D 運行Stage3D 硬體加速顯示.

請按 [觀看] 範例

以下是編寫的步驟:

  1. 建立一個新類別並繼承AlternativaTemplate 類別
  2. 設定CameraCameraType.PANORAMA 模式
  3. 設定紋理材料(TextureMaterial) 為內嵌的全景圖像(assets/test1.jpg)
  4. 建立一個幾何球體(GeoSphere) 並貼上紋理材料
package
{
  import alternativa.engine3d.materials.TextureMaterial;
  import alternativa.engine3d.primitives.GeoSphere;
  import alternativa.engine3d.resources.BitmapTextureResource;
  
  import org.libspark.alternativa3d.camera.CameraType;
  import org.libspark.alternativa3d.view.AlternativaTemplate;
  
  [SWF(backgroundColor="#000000", frameRate="60", quality="LOW", width="800", height="480")]
  public class Alternativa_Panorama extends AlternativaTemplate
  {
    [Embed(source = "assets/test1.jpg")]
    private static var ImageCls:Class;
    
    public function Alternativa_Panorama():void{
      super({
        cameraType:CameraType.PANORAMA,
        useDiagram : true
      });
    }
    override protected function atInit():void{
      var material:TextureMaterial = new TextureMaterial(new BitmapTextureResource(new ImageCls().bitmapData));
      var shpere:GeoSphere = new GeoSphere(100, 32, true, material);
      scene.addChild(shpere);
    }
  }
} 
在Android 和iOS 運作正常, 大家可以 [下載] 範例試試看.

參考資料: http://clockmaker.jp/blog-en/2011/11/alternativa3d-panorama/

2012年9月24日 星期一

SpriteSheetClip 的高效能渲染

關於2D 渲染部分, 我們大多選擇以Stage3D 為基礎的Starling 圖像引擎, 其效能必然是最好. 若大家希望簡單製作, 又要求達到一個理想的渲染效果, SpriteSheetClip 相信是個好選擇, 它比傳統MovieClip 效能高很多.


SpriteSheetClip 運作原理十分簡單, 它是繼承Bitmap 類別, 建立時記錄Sprite Sheet 的內容. 當播放時更換相對的BitmapData 內容, 達到連續播放效果.

請按 [觀看] 範例
以下是使用方法:
  1. 準備一份Sprite Sheet 格式檔案的PNG 與JSON:
    [Embed("assets/Animation.png")]
    public var AnimationImage:Class;
     
    [Embed("assets/Animation.json", mimeType="application/octet-stream")]
    public var AnimationData:Class;
    

  2. 透過SpriteSheetClip 產生實體:
    var mc:SpriteSheetClip = new SpriteSheetClip(AnimationImage, AnimationData);
    mc.gotoAndPlay("someLabel");
    this.addChild(mc);
    

  3. 設定實體位置(x, y), 縮放(scaleX, scaleY), 旋轉(rotation) 或透明度(alpha):
    mc.x = 10;
    mc.y = 10;
    mc.scaleX = 0.5;
    mc.scaleY = 0.5;
    mc.rotation = 90;
    mc.alpha = 0.8;
    

  4. Event.ENTER_FRAME 呼叫step() 功能, 手動觸發播放:
    this.addEventListener(Event.ENTER_FRAME, onEnterFrame);
    ...
    function onEnterFrame(event:Event):void {
          mc.step();
    }

在沒有Stage3D 硬體加速幫助下, 純粹更換BitmapData 能給出高效能渲染, 這個既簡單又實用的手法, 確實令人驚訝喔.

參考資料: http://blog.domlib.com/articles/291

後記:
由於SpriteSheetClip 依賴Zoe 產生相關的PNG 與JSON. 若Zoe 產生內容有所更改, SpriteSheetClip 需要作出相應的改動, 它們之間沒有統一的標準.

2012年9月21日 星期五

[教學] AIRKinect 的魔法帽子

Kinect 與Flash 的連接, 我們透過AIRKinect (安裝參考)簡單地完成. 以下為大家介紹魔法帽子範例, 當一個人走進Kinect 範圍, 在螢幕為她蓋上一個魔法帽子.


  1. 在程序啟動時, 對AIRKinect 物件加入三個事件監聽器:
      CameraImageEvent.RGB_IMAGE_UPDATE - 影像每次更新產生的事件
      UserEvent.USERS_WITH_SKELETON_ADDED - 發現一個新骨架時事件
      UserEvent.USERS_WITH_SKELETON_ADDED - 骨架離開Kinect 事件
    if (Kinect.isSupported()) {
      // <----- get Kinect instance
      _device = Kinect.getDevice();
      
      // <----- add listener for Kinect
      _device.addEventListener(CameraImageEvent.RGB_IMAGE_UPDATE, rgbImageUpdateHandler, false, 0, true);
      _device.addEventListener(UserEvent.USERS_WITH_SKELETON_ADDED, skeletonsAddedHandler, false, 0, true);
      _device.addEventListener(UserEvent.USERS_WITH_SKELETON_REMOVED, skeletonsRemovedHandler, false, 0, true);
      
      ...
      
      // <----- start the Kinect
      _device.start(settings);
    }
    

  2. 當發現一個新骨架, 我們建立一個帽子MovieClip, 產生魔法效果:

    帽子(_Hat1) 魔法效果是由Flash IDE 的時間軸製作
    ...
    [Embed(source="assets/hat1.swf")]
    private var _Hat1:Class;
    ...
    private function skeletonsAddedHandler(event:UserEvent):void{
      for each(var addedUser:User in event.users){
        var sprite:Sprite = new Sprite();
        var head:SkeletonJoint = addedUser.getJointByName("head");
        var headRGB:Point = head.position.rgb;
        sprite.name = addedUser.trackingID.toString();
        sprite.x = headRGB.x;
        sprite.y = headRGB.y;
        
        // <----- add the MovieClip to stage
        sprite.addChild(new _Hat1() as MovieClip);
        _sprites.push(sprite);
        this.addChild(sprite);
      }
    }
    

  3. 若骨架離開Kinect, 把相對於這個骨架的帽子刪除:
    private function skeletonsRemovedHandler(event:UserEvent):void{
      for each(var removedUser:User in event.users){
        for(var i:int=0; i<_sprites.length; i++){
          var id:String = removedUser.trackingID.toString();
          if(_sprites[i].name==id){
            this.removeChild(_sprites[i]);
            _sprites.splice(i, 1);
          }
        }
      }
    }
    

  4. 影像每次更新時, 追蹤每個骨架頭部(head) 和頸部(neck) 關節位置, 計算兩者距離來決定帽子大小, 並利用TweenLite 把帽子移至頭部:

    Kinect 關節名稱
    private function rgbImageUpdateHandler(event:CameraImageEvent):void{
      // <----- get Kinect RGB Camera image to display
      _bitmapData.draw(event.imageData);
      
      for each(var user:User in _device.users) {
        if (user.hasSkeleton) {
          var head:SkeletonJoint = user.getJointByName("head");
          var neck:SkeletonJoint = user.getJointByName("neck");
          var headRGB:Point = head.position.rgb;
          var neckRGB:Point = neck.position.rgb;
          var diff:Number = Math.abs(neckRGB.y - headRGB.y);
          var diffBase:Number = 50;
          var scale:Number = diff/diffBase;
          var id:String = user.trackingID.toString();
          
          // <----- find the MovieClip
          for(var i:int=0; i<_sprites.length; i++){
            if(_sprites[i].name==id){
              // <----- change the MovieClip position
              TweenLite.to(_sprites[i], 0.1, {x:headRGB.x, y:headRGB.y, scaleX:scale, scaleY:scale});
              break;
            }
          }
        }
      }
    }
    
大家可以 [下載] 範例試試看.

後記:
微軟推出的Kinect 硬體在不同的版本, 是有不同的支援上限:
Kinect for Xbox 360 是由2009 年6 月份推出, 支援追蹤兩組骨架, 解像度640x480 @30Hz.
Kinect for Windows 是由2012 年2 月份推出, 支援追蹤四組骨架, 解像度1280x960 @30Hz.

2012年9月12日 星期三

[教學] 原生OpenCV 編譯C++ 成SWC 庫

研究Augmented Reality 的朋友, 相信對OpenCV (Open Source Computer Vision Library) 有一定認識. 她是由英特爾(Intel) 公司發起並參與開發, 以BSD 許可證授權發行, 可以在商業和研究領域中免費使用. 我們可用於開發實時的圖像處理, 計算機視覺以及模式識別程序.

wouter 編譯的OpenCV SWC 庫, 能透過讀取Cascade XML檔案辨認不同物件

現在為大家介紹如何在MAC OS X 中, 透過Adobe Alchemy (安裝參考) 編譯原生OpenCV:
  1. 我們到bonext 下載已整理的OpenCV 包. (OpenCV2.2.0 版本)
  2. 把bonext 解壓並存於/Library/bonext/ 路徑上.
  3. 在Terminal 中, 分別進入以下五個路徑:
    cd /Library/bonext/src/opencv/calib3d/
    cd /Library/bonext/src/opencv/contrib/
    cd /Library/bonext/src/opencv/core/
    cd /Library/bonext/src/opencv/imgproc/
    cd /Library/bonext/src/opencv/objdetect/

    並在每個路徑請輸入以下指命進行編譯:
    repo_root=/Library/bonext/;
    alc-on; rm -rdf log ; rm -f *.o; mkdir log ; for src in *.cpp ; do g++ -I$repo_root/include -DOSX -c -Wall -O3 -o ${PWD##*/}_`basename $src .cpp`.o $src 2> `basename $src .cpp`.log ; done ; mv -v *.log ./log ; alc-off; for f in ./log/*.log ; do grep 'error' $f ; done | cat | sort -u > ./log/errors.log ; less ./log/errors.log
  4. 若編譯正確, 會在每一個路徑找到多個.o 檔案. 把它們移至/Library/bonext/flash/ 路徑上.
  5. 根據bonext 者作提示, 我們需要刪除core_system.o 檔案.
  6. 最後, 在/Library/bonext/flash/ 路徑, 輸入以下指命編譯成.swc 檔案:
    rm *achacks* *.swc ; alc-on; g++ -swc -Wall -O3 -DOSX -I../include -o camlib.swc *.o camlib.cpp ; alc-off;
我們透過Adobe Alchermy 成功產生swc 元件, 在Flash Builder 設定swc 路徑後, 便可以使用:
package
{
  import flash.display.Sprite;
  import cmodule.camlib.CLibInit;
  
  public class Bonext_WebCam extends Sprite
  {
    private var lib:Object;
    ...
    public function setupCLib():void
    {
      ...
      // <----- create a library instance from swc
      var loader:CLibInit = new CLibInit;
      lib = loader.init();
      ...
    }
    ...
    public function enterFrameHandler(event:Event):void
    {
      ...
      // <----- call a method from swc
      var outPixels:ByteArray = lib.setFramePtr(pixels,pixels.length);
      ...
    }
    ...
  }
}

在bonext 的作者純粹示範呼叫OpenCV 使影像變成灰色. 當然我們可以修改camlib.cpp 檔案, 加入相對的函數給Action Script 調用, 發揮OpenCV 的強大功能. 大家可以 [下載] 範例試試看.

2012年9月7日 星期五

AIRKinect 怪獸

AIRKinect 配合Away3D 可以製作很多有趣事, 我們把Away3D 當中的怪獸, 配合AIRKinect 的骨架移動3D 模型, 怪獸起動來喔~~~



只要修改AIRKinect 內建範例, 把關節名稱對應為Away3D 怪獸範例的模型:
var jointMapping:Vector.<Number> = Vector.<Number>([
  (mesh.animationState.animation as SkeletonAnimation).skeleton.jointIndexFromName("head"),
  (mesh.animationState.animation as SkeletonAnimation).skeleton.jointIndexFromName("neck"),
  (mesh.animationState.animation as SkeletonAnimation).skeleton.jointIndexFromName("waist"),
  
  (mesh.animationState.animation as SkeletonAnimation).skeleton.jointIndexFromName("luparm"),
  (mesh.animationState.animation as SkeletonAnimation).skeleton.jointIndexFromName("lloarm"),
  (mesh.animationState.animation as SkeletonAnimation).skeleton.jointIndexFromName("lhand"),
  
  (mesh.animationState.animation as SkeletonAnimation).skeleton.jointIndexFromName("ruparm"),
  (mesh.animationState.animation as SkeletonAnimation).skeleton.jointIndexFromName("rloarm"),
  (mesh.animationState.animation as SkeletonAnimation).skeleton.jointIndexFromName("rhand"),
  
  (mesh.animationState.animation as SkeletonAnimation).skeleton.jointIndexFromName("lupleg"),
  (mesh.animationState.animation as SkeletonAnimation).skeleton.jointIndexFromName("lloleg"),
  (mesh.animationState.animation as SkeletonAnimation).skeleton.jointIndexFromName("lfoot"),
  
  (mesh.animationState.animation as SkeletonAnimation).skeleton.jointIndexFromName("rupleg"),
  (mesh.animationState.animation as SkeletonAnimation).skeleton.jointIndexFromName("rloleg"),
  (mesh.animationState.animation as SkeletonAnimation).skeleton.jointIndexFromName("rfoot")
]);

大家可以 [下載] 範例試試看.

2012年9月4日 星期二

Beyond Reality Face 臉部偵測引擊

Beyond Reality Face 是一個臉部偵測引擊, 能夠實時偵測臉部輪廓. 她們提供SDK 免費下載和測試, 若開發人員於商業用途, 需要購買許可證. 雖然不是完全免費, 但作為Augmented Reality 引擊, 她是一個不錯的參考.

請按 [觀看] 範例 (需要Web Camera)

識別臉部的位置

者作把Beyond Reality Face 範例整理, 發現十分有趣, 大家可以 [下載] 範例試試看.

2012年9月2日 星期日

foxhole 元件

foxhole 是一個以Starling Framework 為基礎的元件庫, 與MadComponents 性質十分相似, 它們都是以Stage3D 技術, 在iOS 或Android 中流暢操作的UI 框架.

請按 [觀看] Layout Explorer 範例

請按 [觀看] Gallery 範例

請按 [觀看] Tile List 範例

foxhole 主要透過程式編寫來決定元件的位置與關係. 與MadComponents 的XML 設定有所不同.

API 參考: http://flashtoolbox.com/foxhole-starling/documentation/

2012年8月30日 星期四

[教學] 安裝Adobe Alchemy 在MAC OS X

Adobe 在2009 年的研究項目中, 曾經被喻為劃時代的Adobe Alchemy, 開發者以C/C++ 編寫核心, 給ActionScript 調用, 達至加速效果. 回到今天運作平台分裂嚴重, 對我們現在Windows, MAC, Android 及iOS 同樣可以分享, 當年這個技術實在意義重大.

Adobe Alchemy 基於LLVM 技術運行

現在為大家說明如何在MAC OS X 環境中, 運用Adobe Alchemy 編譯C/C++ 語言, 包裝給ActionScript 調用.

必須有以下的準備:

安裝步聚:
  1. 把Flash Builder 內的SDK bin 目錄設定為MAC OS X 的PATH 環境變數(PATH Environment Variables)
     - 打開.bash_profile 檔案, 在Terminal 輸入:
          touch ~/.bash_profile; open ~/.bash_profile
     - 在TextEdit 中, 把空白的.bash_profile 檔案更改成:
         (請把Adobe Flash Builder 4.6/4.6.0_AIR3.4 更改成正確路徑)
          PATH="$PATH:/Applications/Adobe Flash Builder 4.6/sdks/4.6.0_AIR3.4/bin"
          export PATH

     - 在TextEdit 中把.bash_profile 檔案儲存(Command+S)
     - 然後在Terminal 輸入:
          source ~/.bash_profile
    - 關閉Terminal (Command+Q)
  2. 測試是否設定正確, 重新開啟Terminal, 然後輸入:
      adt -version
    若步聚正確, 會顯示SDK 版本代號"3.4.0.3010"
  3. 把下載的Alchemy Toolkit Package 解壓存放於/Library/alchemy/
  4. 把游漂移至alchemy 目錄內, 在Terminal 輸入:
      cd /Library/alchemy
  5. 執行alchemy 目錄內的config, 在Terminal 輸入:
      ./config
  6. 在PATH 環境變數加入alchemy 相關資料:
     - 再次打開.bash_profile 檔案, 在Terminal 輸入:
          touch ~/.bash_profile; open ~/.bash_profile
     - 在TextEdit 中, 把.bash_profile 檔案更改成:
         source "/Library/alchemy/alchemy-setup"
         PATH="$PATH:/Applications/Adobe Flash Builder 4.6/sdks/4.6.0_AIR3.4/bin"
         PATH="$PATH:/Library/alchemy/achacks"
         export PATH

     - 在TextEdit 中把.bash_profile 檔案儲存(Command+S)
     - 然後在Terminal 輸入:
          source ~/.bash_profile
     - 關閉Terminal (Command+Q)
  7. 重新開啟Terminal, 分別輸入:
      alc-on

      gcc
    以上兩個指令, 不會出現"command not found" 錯誤訊息, 代表設定完成

範例編譯:

  1. 把游漂移至alchemy/samples/stringecho/ 目錄內, 在Terminal 輸入:
      cd /Library/alchemy/samples/stringecho/
  2. 在Terminal 輸入:
      alc-on; which gcc
    以上指令會顯示出gcc 路徑"/Library/alchemy/achacks/gcc"
  3. 把c 語言編譯成swc 元件, 在Terminal 輸入:
      gcc stringecho.c -O3 -Wall -swc -o stringecho.swc
  4. 若元件正確產生, 在Terminal 會顯示以下訊息: (若發生錯誤, 請看編譯錯誤修正)
    1911.achacks.swf, 259831 bytes written
    frame rate: 60
    frame count: 1
    69 : 4
    72 : 259761
    76 : 33
    1 : 0
    0 : 0
    frame rate: 24
    frame count: 1
    69 : 4
    77 : 506
    64 : 31
    63 : 16
    65 : 4
    9 : 3
    41 : 26
    82 : 471
    1 : 0
    0 : 0
      adding: catalog.xml (deflated 75%)
      adding: library.swf (deflated 70%)

編譯錯誤修正:

修正一
  • 若在編譯時, 出現以下錯誤:
    Array @ARGV missing the @ in argument 1 of shift() at /Library/alchemy/achacks/gcc line 218.
    我們需以在/Library/alchemy/achacks 的gcc 檔案的218 行, 加入"@"字元, 請更改成:
    { $path = shift(@ARGV) }

修正二
  • 若在編譯時, 出現以下錯誤:
    dyld: Library not loaded: /usr/lib/libltdl.3.dylib
      Referenced from: /Library/alchemy/bin/llvm-gcc
      Reason: image not found

    我們需要把游漂移至/usr/lib/ 目錄內, 在Terminal 輸入:
      cd /usr/lib/
    然後再在Terminal 輸入:
      sudo ln -s libltdl.7.dylib libltdl.3.dylib

使用swc 元件:

我們透過Adobe Alchermy 成功產生swc 元件, 在Flash Builder 設定swc 路徑後, 便可以使用:
package
{
  import flash.display.Sprite;
  import cmodule.stringecho.CLibInit;
  
  public class stringecho_mobile extends Sprite
  {
    public function stringecho_mobile()
    {
      var loader:CLibInit = new CLibInit;
      var lib:Object = loader.init();
      trace(lib.echo("foo"));
    }
  }
}

大家若在Windows 環境下安裝Alchemy, 請參考這個連結, 安裝原理與MAC 很相近.

Alchermy 安裝參考:
http://labs.adobe.com/wiki/index.php/Alchemy:Documentation:Getting_Started
更改PATH 環境變數參考:
http://hathaway.cc/2008/06/how-to-edit-your-path-environment-variables-on-mac-os-x/
編譯錯誤修正參考:
http://forums.adobe.com/message/3892045

2012年8月29日 星期三

Flash Builder 4.7 beta

Adobe Lab, 我們可以免費下載最新Flash Builder 4.7 beta 版. 這版本支援Adobe AIR 3.4 以下兩個功能:
  • 以USB 連接iOS 裝置部署(deployment) 和除錯(debugging)
  • 或發佈於Xcode 中的iOS simulator 運作 (只限MAC OS X)



由於Flash Builder 4.7 beta 版不是內置Adobe AIR 3.4, 我們需要作以下設定:
  1. 下載Flash Builder 4.7 beta 版和完成安裝
  2. 下載Adobe AIR 3.4 SDK
  3. 對MAC OS X 使用者, 請參考這個SDK 設定. (若Windows 使用者請參考這個)
  4. 最後, 我們在Run -> Run Configurations -> Mobile Application 找到新的設定介面, 在<Choose launch method> 可以選擇三個方式發佈:
     - On AIR Simulator
     - On iOS Simulator
     - On device

Flash Builder 4.7 在發佈上的優化, 對開發者帶來方便, 實在是一件好事.
關於認證檔(Certificate) 和描述檔(Provisioning file) 設定大家可以參考這個.

2012年8月27日 星期一

MadComponents 元件

在Stage3D 技術發展下, 我們會找到很多相關應用, 在UI 元件也分享到硬體加速的成果. MadComponents 是其中一個在免費的框架, 目的是在iOS 或Android 以同一個UI 操作介面, 透過Stage3D 技術流暢運作.

請按 [觀看] 範例一
請按 [觀看] 範例二

開發人員主要透過XML 作介面設定, 我們來個簡單的Hello World 示範: [下載]

package
{
  import com.danielfreeman.madcomponents.UI;
  
  import flash.display.Sprite;
  import flash.display.StageAlign;
  import flash.display.StageScaleMode;
  
  [SWF(backgroundColor="#ffffff", frameRate="60", quality="LOW")]
  public class madcomponents_test01 extends Sprite
  {
    protected static const HOME_VIEW:XML = <vertical>
                        <label>Hello, World!</label>
                        <button>Continue</button>
                         </vertical>;  
    
    public function madcomponents_test01()
    {
      super();
      
      stage.align = StageAlign.TOP_LEFT;
      stage.scaleMode = StageScaleMode.NO_SCALE;
      
      UI.create(this, HOME_VIEW);
    }
  }
}

MadComponents 還有很多實用元件, 在官方的文件教程(Tutorial) 中有詳細說明:


以下是官方提供己利用MadComponents 框架製作, 並發佈於App Store 和Google Play 中的程式:
대전맞고 온라인 고스톱
The Etiquette App
Actionary
SimsUShare Mobile Lite

在Adobe AIR 發展領域, 跨平台的高效能元件, 相信會是其中的一個優勢.
除了Appcelerator Titanium 以javascript 作編寫語言, 然後編譯成源生元件. 我們還可以選擇MadComponents.

API 參考: http://e2easy.byethost9.com/madcomponents/