[FlashIDE]ダイナミックテキストへのフォント指定について、CS4とCS5では挙動が変わったみたい

ダイナミックテキストへのフォント指定での挙動について。
CS5から挙動が変わってることに気付いたのでメモ。

◆手順
1.FlashIDEにて、ステージにダイナミックテキストを置く。
2.ダイナミックテキストに何か文字(ここでは”あいうえお”とする)を入力。
3.ダイナミックテキストに任意のフォント(ここではA-OTF 新ゴ Pro Bとする)を指定。
(ここでフォント:A-OTF 新ゴ Pro Bは埋め込まない)
4.パブリッシュ
5.フォント(A-OTF 新ゴ Pro B)が入っていないPCで表示を確認。

◆結果
・CS4でパブリッシュした場合
→文字が、デバイスフォントで表示される。
・CS5でパブリッシュした場合
→文字が、指定フォント(A-OTF 新ゴ Pro B )で表示される。

つまり、CS4ではフォントの埋め込みは行われないが、CS5ではフォントが埋め込まれている。
またここでは、入力した文字(あいうえお)のみが埋め込まれているので、動的にtextを変更しようとしても使える文字は”あいうえお”だけとなる。

というわけで、これをCS4でも同様の挙動をさせるには、

1.ダイナミックテキストを選択
2.プロパティパネルの「文字の埋め込み」をクリック
3.「自動読み込み」ボタンをクリック。
→ダイナミックテキストの文字列(ここでは”あいうえお”)が埋め込み対象文字となる。
4.「OK」をクリック
これでOK。

つまりCS5からは、上記の埋め込み作業を自動でやってくれるようになったようだ。
嬉しいような、こんがらがるような。。。

[AS]mouseEnabled=falseで下の階層にあるボタンを有効にするときの注意。

感覚的に勘違いをしていたのでメモしておく。

言葉で書いてもうまく伝えられないので、まずは以下フレームアクションのスクリプト参照。


import flash.display.Sprite;

//1階層目
//コンテナ的sp(塗り無し)
var container01:Sprite = new Sprite();

//コンテナの背景的なもの(赤塗り)
var bg01:Sprite = new Sprite();
bg01.graphics.beginFill(0xFF0000);
bg01.graphics.drawRect(0,0,300,300);
bg01.graphics.endFill();

//ボタン的なもの
var btn01:Sprite = new Sprite();
btn01.graphics.beginFill(0x660000);
btn01.graphics.drawRect(40,40,40,40);
btn01.graphics.endFill();
btn01.buttonMode = true;

//コンテナ的なものをメインのタイムラインに配置
this.addChild(container01);
//背景的なものをコンテナに配置
container01.addChild(bg01);
//ボタン的なものをコンテナに配置
container01.addChild(btn01);

//////////////////////////////////////

//2階層目
//コンテナ的sp(塗り無し)
var container02:Sprite = new Sprite();
//1階層目が見えるように半透明にして配置をずらす
container02.alpha = .5;
container02.x = container02.y = 20;

//コンテナの背景的なもの(青塗り)
var bg02:Sprite = new Sprite();
bg02.graphics.beginFill(0x0000FF);
bg02.graphics.drawRect(0,0,300,300);
bg02.graphics.endFill();

//ボタン的なもの
var btn02:Sprite = new Sprite();
btn02.graphics.beginFill(0x000066);
btn02.graphics.drawRect(40,40,40,40);
btn02.graphics.endFill();
btn02.buttonMode = true;

//コンテナ的なものをメインのタイムラインに配置
this.addChild(container02);
//背景的なものをコンテナに配置
container02.addChild(bg02);
//ボタン的なものをコンテナに配置
container02.addChild(btn02);

//1階層目のボタンを押せるようにするには、
//2階層目の背景的なものをmouseEnabled = false
bg02.mouseEnabled = false;
//さらに、コンテナ的なspもmouseEnabled = false;
//にしないとだめ
container02.mouseEnabled = false;

はまったポイントは2階層目のコンテナ自身に対してもmouseEnable=falseを設定してあげないといけないということ。
2階層目のコンテナ自身は塗りを持ってないから、(塗りの実体である)背景だけをmouseEnable=falseにすればいいんじゃね、と思い込んでおりましたが、それだと1階層目のボタンに触れません。
コンテナ自身もmouseEnabled=falseにしてやらないとだめだったのです。
感覚的に、コンテナをmouseEnabled=falseにしちゃったら、コンテナが内包しているボタンもmouseEnabled=false扱いとなってしまうかと思ったら、そんなことは無いというオチ。
mouseChildrenってプロパティもあるし、それぞれの機能をちゃんと理解しとかないとマズイです。。

[iPhone]Objective- Cの勉強メモ:xibファイルとはどういうものなのか

・xibファイルとは、
XML Interface Builderの略。
その名の通り、xml形式のファイル。
これをxcodeから開くとInterfaceBuilder(アプリケーション:以下IB)が立ち上がってビジュアル的にxmlの中身を編集できる。
(ということだと思う)

・Flashでいったらxibファイルって何にあたるの?
とTwitterでつぶやいたら、
エライ人から「FLEXでいうところのMXMLみたいなもの」と教えてもらった。
なるほど、FLEXでもMXMLも表示オブジェクトの配置情報を持っているし、MXMLを使わなくてもASで表示オブジェクトの配置することもできる。
(でもMXMLも使い方をよくわかってない)

ちょっと調べてみようと思ったらかなり分かりやすい素敵記事発見。

iPhone:Xib/Nib ファイル(その1):「支出管理」サポート
iPhone:Xib/Nib ファイル(その2) :「支出管理」サポート

xibファイルは、UIApplicationかUIViewControllerのサブクラスによってロードされるものなのね。
どのクラスにも設定できちゃうから、この辺りの仕組みがよくわからなかった。
ありがたやありがたや。

[iPhone] Objective- Cの勉強メモ:Xcodeショートカット:ヘッダーファイルとソースファイルの切り替え

.h/.mファイルの切り替え
cmd + option + 上キー(交互に切り替わる)

[AS]リスナー関数の弱参照について

避けて通ってきたところを理解できた(気がする)のでメモ。

リスナー関数を弱参照にする場合は、addEvenListener()の第5引数をtrueとする。


//例
//第5引数のデフォルト値はfalse
this.addEventListener(Event.ENTER_FRAME, this.enterFrameHandler,false,0,true);

trueを設定することでリスナー関数は弱参照となりガベージコレクション(GC)の対象となる。
※弱参照とGCについては偉い人のサイトがわかりやすいです。
イベントリスナ (AS3) とガーベジコレクション:akihiro kamijo
Tweenのアニメーションが途中で止まる:FumioNonaka.com

はまったのはここで弱参照となるリスナー関数の状態。
どういうことかというと・・・
以下の処理ではリスナー関数が弱参照でGCが発動した際にenterframe処理は停止。
これは認識どおり。


//フレームアクション
//GCが発動するとhogeの出力が止まる。
this.addEventListener(Event.ENTER_FRAME, function(e:Event):void{trace("hoge");},false,0,true);
//※もちろん、第五引数をfalseにした場合はenterframe処理はGCが発動しても動き続ける。

でも以下のように書いた場合は、第五引数をtrueにしてあってもenterframe処理はGCが発動しても動き続ける。


//フレームアクション
//GCが発動してもhogeは出力され続ける。
this.addEventListener(Event.ENTER_FRAME, this.enterFrameHandler,false,0,true);
function enterFrameHandler(e:Event):void{
trace("hoge");
}

なんで???参照きれて破棄されるんじゃないのと思ったら・・・
リスナー関数:enterFrameHandlerの自身の参照がthisに残っているから破棄されないということらしい。

なのでこう書けば破棄される。


//フレームアクション
//GCが発動でhogeの出力は止まる。
function init(){
this.addEventListener(Event.ENTER_FRAME, this.enterFrameHandler,false,0,true);
//関数init内にenterFrameHandlerを定義することでローカル関数となる。
function enterFrameHandler(e:Event):void{
trace("hoge");
}
}
init();

ちなみにこれではだめ。


//フレームアクション
//GCが発動でもhogeの出力が止まらない。
function init(){
this.addEventListener(Event.ENTER_FRAME, this.enterFrameHandler,false,0,true);
}
//関数initの外にenterFrameHandlerを定義することで関数自身の参照が保持される。
function enterFrameHandler(e:Event):void{
trace("hoge");
}
init();

ようするに。。。
第五引数をtrueにしても、弱参照になるのは、addEventLisner()とリスナー関数の関係性、と。
リスナー関数自身の参照が残ってる場合はtrueにしてもそれが残って破棄されない、と。
なんとなく、わかったような。。。
リスナー関数自身の参照も残らないようにしないといけないということらしい。

[iPhone] Objective- Cの勉強メモ:NSNotificationCenterでイベント通知の管理

Objective-CはASと違ってデリゲートとという機能がある。
デリゲートとは別に色んなクラスが通知するイベントを一括で管理してくれるクラスがあるみたい。
それが、NSNotificationCenterクラス。

手順としては、
1.NSNotificationCenterのインスタンスを生成
2.通知の登録(インスタンスに通知先、リスナー関数、通知の種類、通知の送信元)
3.通知の開始
4.(通知の終了)
5:(通知の登録解除)

例)


//playerはMPMusicPlayerControllerのインスタンス

//通知センタのインスタンを取得
NSNotificationCenter* noteCenter = [NSNotificationCenter defaultCenter];
//addObserver:通知先
//selector:リスナー関数
//name:通知してほしい通知の種類?
//object:通知の送信元
[noteCenter
addObserver:self
selector:@selector(hoge:)
name:MPMusicPlayerControllerNowPlayingItemDidChangeNotification
object:player];
//通知開始を指示
[player beginGeneratingPlaybackNotifications];

nameはnilにすると全ての種類のイベントが取得対象になる。
(そもそも通知の送信元がどのようなイベントを発信してるかを把握してる必要あり?)
(ドキュメントみれば書いてあるのかな?)
objectはnilにすると、全ての送信元からイベントを受け取る。

あとNSNotificationCenterはシングルトンになるので、インスタンス変数の保持はしなくてもいいみたい。

[iPhone] Objective- Cの勉強メモ:カテゴリという概念を使って元クラスの拡張(メソッドの追加)できる

Objective-CにはASにはない機能でカテゴリという概念がある。
これはクラスファイルにメソッドを追加することができる機能。

通常クラスを拡張するにはそのクラスを継承したサブクラスを定義すればいいと思う。
でも根本的に弄りたくなった場合、元のクラスを書き換えちゃうということもできる。
(ASだと、Flash8でAS2のときは直接編集できたけど、AS3ではSWCになってるから無理ぽ)
でも書き換えちゃうと何か不具合がおきたときとかバックアップとってないと元に戻すのが大変。

というわけでカテゴリという概念は、元クラスを簡易的に拡張できるという概念。
ただし追加できるのはメソッドだけ。
変数は追加できない。
手順は拡張用のクラス(?)ファイルを作ってそこで定義する。

例)UIViewを拡張する、UIViewExファイルを生成する場合
//ヘッダーファイル


#import <UIKit/UIKit.h>
@interface UIView (AnimationExtension)
//メソッドの定義
//ここに追加したいメソッドを書く
-(void) hoge;
@end

//実行ファイル


#import "UIViewExtention.h"
@implementation UIView(AnimationExtension)
//メソッドの実装
    //ここで定義したメソッドを実装する
 -(void) hoge{
    //処理
}
@end

書き方で注意するのは、ヘッダーファイルでのinterfaceのくだり。
変数は定義できないので、{}は書く必要なし。

これを反映されるには、反映させたいクラスファイルにて


#import "UIViewExtention.h"

を記述すればよい。
これが記述されたクラス内では、UIViewインスタンスにUIViewExで追加したメソッドが普通に使えるようになる。

//例


-(void) init{
//imageViewはUIImageVIewクラスのインスタンス
//(UIImageViewのスーパークラスはUIImageなのでhogeメソッドが使える)
[imageView hoge];
}

[iPhone]Objective- Cの勉強メモ:乱数の取り扱い

まずはObjective-CというかC言語での乱数の発生させる方法。
使える関数は2種類
まず
int rand(void);
という関数でint型の乱数を返すことができる。
このときに返る値は、0~馬鹿でかい数という感じ。
馬鹿でかい数はコンパイラによって変わるらしい。
(ASのMath.random()のように、0~1未満というわけでない)


int i;
i = rand();
printf(%d,i);//0から馬鹿でかい数の間の間

ただ、このままだと乱数は実行するたびに常に同じ値を返すことになるので、初期化処理という行為が必要になる。
そこで使うのがsrand();
void srand(unsigned int 初期値);

使い方としては、rand()関数を実行する前にsrand()関数を実行することで初期化すればよし。
初期値には、絶対にかぶらない値を日付データから取ればよし。


//time(NULL)で現在の時刻が1970年1月1日午前0時0分0秒からの通算秒数で得られる。
srand(time(NULL));
rand();

以上が、C言語での設定方法

Objective-Cではsrandは以下のようにするらしい。


//NSDateインスタンスを作って、本日の日付けを秒数に換算してる
srand([[NSDate date] timeIntervalSinceReferenceDate]);
rand()

※C言語のやり方でも問題なさげ。

[AS]progression4 Index.swfからPreloaderのforeground、backgroundを参照するにはCastDocumentインスタンス経由で可能

便利すぎて自分の実装力がどんどん低下してるprogression4のメモ。

Preloaderにて表示オブジェクトを追加するには、backgroundかforegroundを使うことになります。
で、index.swfにてPreloaderのbackgroundおよびforegroundにアクセスするには、index.swfのドキュメントクラスであるCastDocumentがbackgroundおよびforegroundのプロパティを持っているので簡単に参照できます。

そこで、ちょっとはまったのが、このドキュメントクラスの参照の仕方。
結論だけ書くと、こんな感じ。


trace(manager.current.container.root);//出力:[object:index]
//Indexのプロパティを取得するにはIndexでキャストする。
trace(Index(manager.current.container.root).background.numChildren);

要はSceneObjectが持つcontainerプロパティのrootが、index.swfのドキュメントクラスとなっているみたい。

[AS]BetweenAS3のグループ化は、配列を使っても管理可能。  

BetweenAS3でのグループ化について。
ITween.serial()、ITween.parallel()メソッドを使う場合は


//ステージ上に_mc1と_mc2のMovieClipが配置してあるとしてフレームアクション
import org.libspark.betweenas3.BetweenAS3;
import org.libspark.betweenas3.tweens.ITween;

var iTween1:ITween =  BetweenAS3.to( _mc1 , {x:100},1);
var iTween2:ITween =  BetweenAS3.to( _mc2 , {x:100},1);
var iTween:ITween =  BetweenAS3.parallel(iTween1, iTween2);
iTween.play();

ITweenインスタンスをfor文とかで一括で作りたいときは配列で管理。
その際は、parallelTweens()メソッド、serialTweens()メソッドを使う
これは便利!!!


//ステージ上に_mc0から_mc9の10個MovieClipが配置してあるとしてフレームアクション
import org.libspark.betweenas3.BetweenAS3;
import org.libspark.betweenas3.tweens.ITween;

var iTweens:Array = [];
for(var i:int = 0; i < 10; i++){
var name:String = "_mc" + i;
iTweens.push(BetweenAS3.to( getChildByName(name) , {x:100},1));
}
var iTween:ITween =  BetweenAS3.parallelTweens(iTweens);
iTween.play();