Category Archives: Flash

ExternalInterface.callが重い

Flashから毎フレームExternalInterface.callでJSの関数を呼び出したりしている時に、そのJSの関数内でなにかしらのObjectをreturnしてるとその処理に手間がかかるのか、Flashのフレームレートがすごい落ちる。

CoffeeScriptで関数の最後に@を入れてるとこの現象が起こりやすいので、ExternalInterface.callで直接呼び出される関数の最後はreturn falseして回避しておく。

さらにそのJSの関数内でDOMの操作みたいなちょっと重めの処理(width, height変えたり、left, top変えたり)をしてたりしても同様の現象が起こる。この場合はJSの関数内でやっている処理をsetTimeout(Function, 0)でくるんで非同期で処理してあげると回避できた。

なんだろこれ?ExternalInterface.callで呼び出した処理が終わるのをFlashが待っちゃうからかな?

追記1:
こういうことらしい

追記2:
CoffeeScriptで行末returnしないようにするには「return」だけ書いとけばいいっぽい。

算数メモ

毎度公式をググるのはいい加減めんどいのでここにまとめてく。
(これらを覚えられるほどの知能はない)

距離と角度からx、y方向の距離を求める

var dx:Number = Math.cos(degree * Math.PI / 180 ) * distance;
var dy:Number = Math.sin(degree * Math.PI / 180 ) * distance;

03bc502b-41cb-426a-8cea-d28c2a500107

2点間の角度

var radian:Number = Math.atan2(targetY - currentY, targetX - currentX);
var degree:Number = radian * 180 / Math.PI;

8fc882bd-ba74-4651-b7c0-2edf61e9d023

2点間の距離

var dx:Number = targetX - currentX;
var dy:Number = targetY - currentY;
var distance:Number = Math.sqrt(dx * dx + dy * dy);

bcaf9577-e04f-46bd-ae87-3b5cb82087c1

角度からラジアン

var radian:Number =  degree * Math.PI / 180;

ラジアンから角度

var degree:Number = radian * 180 / Math.PI;

バネ運動

var vx:Number = ( currentX + ((targetX - currentX) * spring) * friction;
var vy:Number = ( currentY + ((targetY - currentY) * spring) * friction;
currentX += vx;
currentY += vy;

Ustream Flash APIの使い方

UstreamのFlash Client APIのドキュメントがこんな状態でかなり不親切でして、色々と苦心したので今後の為にメモ。

Ustream Client APIを使う時は、まずAPIを操作するClassの定義が詰まったswfを直接Ustream(http://www.ustream.tv/flash/viewer.rsl.swf)から読み込む。そしてこのswfの中のClassを使ってゴニョゴニョする。
ローカルで実行する時はあらかじめ「viewer.rsl.swf」をローカルにダウンロードしておき、これを読み込んで使う。
※読み込む配信チャンネルが有料のアドフリーアカウントでない場合、www.ustream.tvからviewer.rsl.swfを読み込むと、ビデオ内広告用のデータが読み込まれる。このビデオ内広告がエラーを吐いており、Flashが停止してしまう(2012.12.07時点)。無料アカウントでテストする時は注意。

viewer.rsl.swf、viewer.rsl.swc等はここから一式ダウンロードできる。

自分がこのAPIを使った時は、API(Logicクラス)を叩く処理をUstreamPlayerクラス(仮)というクラスに封じ込めておいた。このUstreamPlayerクラスを直にnewしてしまうとUstreamPlayer内で参照しているローカルのswcを呼んでしまうため、getDefinitionByNameを使ってインスタンス化する。こうすればviewer.rsl.swcを外部ライブラリ(swfには含めない)として参照することができるので、オンラインのviewer.rsl.swfと、ローカルのviewer.rsl.swfの内部の挙動が違っていてもエラーは出なくなる(ハズ)。

Continue reading

ビックロベーダー

お仕事でソーシャルシューティングゲーム、ビックロベーダー(PC版)を作りました。
FacebookやTwitterにログインしてプレイすると友達がアイテムとして登場して楽しーっていうゲームです。
Stage3Dをガリガリ使って作ってるのでハイスペックめな環境でプレイしてみて下さーい。

クレジット:
Art Direction: Yugo Nakamura (tha ltd.)
Design + Flash: Naoki Nishimura (tha ltd.)
Engineering: Keiji Hokamura (tha ltd.)
Logo Design: Taro Yumiba (tha ltd.)
Music: FPM
SE: 株式会社フルメタル・モンキーズ

というわけで上でも書いた通り今回はStage3D(Away3D)を使って作ってます。

なにぶん商業案件なので、FlashPlayer11以上で、Stage3Dが動かない、もしくは、ソフトウェアレンダリングで動いてしまった時にごめんなさいアラートを出してます。
そん時に使ったStage3D環境判定用のクラスがこれ。
Stage3Dが使えるかどうかと、ソフトウェアレンダリングになってるかどうかを判定するクラスです。

↓使い方

で、ログによるとこのアラートが表示されたのは全体のアクセスの中で1.2%とのこと(2012/9/27現在)。
なのでFlashPlayer11以上が入ってて、サイトが表示できた人はだいたいStage3Dが動くみたい。

そんな感じ。

Away3Dの座標系

CIDから対応する文字を取得する

わけあってCIDをもとに対応する文字を取得したい。
ざっと調べてみたら、CIDと文字が対になった一覧表はこのへんにあるんだけどプログラムからは使いにくい。

プログラムから使いやすそうな資料を探してみたところ、どうもAcrobat内部ではCIDをUnicodeに変換するようなことをしてるらしいことがわかった。その変換に関する資料がこれ

すかさずこの資料の後半のMapping Fileを拝借。
CIDを投げたらCID→Unicode→String.fromCharCode()で文字を取得ってクラスを作ったんだけど、どうも取得したUnicodeが期待した文字に変換できてない。

この「Unicode」はString.fromCharCodeで変換できる「Unicode」じゃないのかなぁ?

うーん…

と思ったら、FontForgeで使ってるcidmapっていうCIDのマッピングファイルに「Adobe-Japan1-6.cidmap」ってのがあった。これをコンバートして使ってみたらうまく変換できた。ワーイ。
どうも上記のデータはAdobe-Japan2のマッピングデータらしい。なるほろ。

package
{
  
  public class CharCodeUtil 
  {
    static private var list:Array;
    
    public function CharCodeUtil() 
    {
      
    }
    
    static public function getCharFromCID(cid:uint):String
    {
      var char:String = "";
      
      init();
      
      for each (var obj:Object in list) 
      {
        if (cid == uint(obj.c[0]))
        {
          char = String.fromCharCode(uint(obj.u));
          break;
        }
      }
      
      return char;
    }
    
    static private function init():void
    {
      if (list) return;
      
      list = [
        //ここに.cidmapをArray化したデータを
      ];
    }
  }
}

FlashPlayer 11.1.102.55で静止テキストフィールドのサイズがバグる

こんな感じに膨らむ。

Away3DのWhiteShadingBitmapMaterialでメモリリーク

Away3DのWhiteShadingBitmapMaterialを普通に使ってるとBitmapDataをガンガンキャッシュしてメモリリーク起こすのでclearCache()してね、とのこと。

Issue 95 – away3d – Feature to clear bitmap cache in WhiteShadingBitmapMaterial (or texture setter) – Realtime 3D engine for Flash – Google Project Hosting

取り急ぎ5秒おきにキャッシュクリアして回避。

package wimax.away3d.material 
{
    import away3d.materials.WhiteShadingBitmapMaterial;
    import flash.display.BitmapData;
    import flash.events.TimerEvent;
    import flash.utils.Timer;
    
    public class ImprovedWhiteShadingBitmapMaterial extends WhiteShadingBitmapMaterial 
    {
        public var clearCacheInterval:int = 5000;
        
        public function ImprovedWhiteShadingBitmapMaterial(bitmap:BitmapData, init:Object=null) 
        {
            super(bitmap, init);
            
            var t:Timer = new Timer(clearCacheInterval);
            t.addEventListener(TimerEvent.TIMER, function(e:TimerEvent):void
            {
                clearCache();
            });
            t.start();
        }
    }
}

ActionScript 3 SDK for Facebook Platform API ハマリどころメモ

ActionScript 3 SDK for Facebook Platform APIを使う時に、attributes.nameを指定せずattributes.idだけを指定してswfobject.embedSWFすると、SDK内のExternalInterface.objectIDを参照している箇所でnullが返ってjsの方でエラーが出るブラウザがある。

このままだとjsの処理が止まってFB.loginとかFB.apiでコールバックが呼ばれなくなってしまうので、attributes.idと同じ名前をattributes.nameで指定してExternalInterface.objectIDを参照できるようにする。

var flashvars = {
};
 
var params = {
    base:'.',
    menu:'false',
    wmode: 'window',
    allowFullScreen:'true',
    allowscriptaccess:'always'
};
 
var attributes = {
    id:"hoge", //←これと
    name:"hoge" //←これを指定する
};
 
swfobject.embedSWF('main.swf', 'flashcontent', '100%', '100%', '10.0.0', '', flashvars, params, attributes);

Objective-C を強引に AS3 で例えるメモ

全部雰囲気で理解してるので間違ってる可能性大です。

変数宣言

プリミティブ型
int num → var num:int

クラス型
MyClass *myClass → var myClass:MyClass

※プリミティブ型以外の型は変数宣言で*付ける

ディスプレイオブジェクト的な概念

UIView → DisplayObject
UIResponder → InteractiveObject
addSubView → addChild
CGContextRef → Graphics
UIImage → BitmapData
UIImageView → Bitmap

座標指定
view.center = CGPointMake(100, 200)

view.x = 100;
view.y = 200;

リサイズ
view.size = CGSizeMake(100, 200)

view.width = 100;
view.height = 200;

メソッド

[instance method] → instance.method()
method:は:までがメソッド名

イベントハンドラ

[obj addTarget:self action:@selector(nullEventHandler:) forControlEvents:NullEventNull]

obj.addEventListener(NullEvent.NULL, nullEventHandler)

ヌル

nil → null

タイマー

NSTimer → Timer

文字列

@”This is text” → “This is text”

関数の定義

– (void)func: (NSString)arg1 argument2:(NSString)arg2 argument3:(NSString)arg3
{
}
※argument2とargument3は引数名(ラベル)で省略可。

private function func(arg1:String, arg2:String, arg3:String):void
{
}

関数の呼び出し

[obj func:@”引数1″ argument2:@”引数2″ argument3:@”引数3″];

obj.func(“引数1″, “引数2″, “引数3″);

コンストラクタ呼び出し

[[Class alloc] init] → new Class()

用語

プロトコル → インターフェイス

デリゲート

//インターフェイス(プロトコル)で通知用の関数定義
interface IHoge
{
function onHoge():void;
}

//デリゲートされるクラス
class Hoge implements IHoge
{
public function onHoge():void
{
trace(“called Hoge”);
}
}

/*
イベント(この場合は初期化)が起こったらインターフェイス(プロトコル)に対して通知関数を呼ぶ

デリゲート?
*/
class Main()
{
public Main(hoge:IHoge)
{
hoge.onHoge();
}
}

実行順序

アプリ起動

main()実行

UIApplicationMain()実行

アプリケーションデリゲートオブジェクトを呼び出し
– アプリケーションデリゲートオブジェクト = UIApplicationDelegateプロトコルを採用(継承)したオブジェクト
– didFinishLaunchingWithOptions:

イベントループ
– ユーザーの操作等々
– アプリケーションデリゲートオブジェクト経由で各メソッドを呼び出す

アプリ終了準備 → applicationWillResignActive:

アプリ終了 → applicationDidEnterBackground:

参照:
http://developer.apple.com/jp/devcenter/ios/library/documentation/iPhoneAppProgrammingGuide.pdf