c-geru のすべての投稿

Xcode 4 と Xcode 3 との併用

Xcode 4 をインストールしてみたらなんと英語版。「なんだー」と思っていたら、Xcode 3 との併用も可能らしいので、Xcode 3 を再びインストール。手順については下記を参考にさせていただきました。感謝。

で、インストールしてXcode 3 で以前作ったモノを開いてみたら、プロジェクトに含まれるコードのほとんどが赤字(存在しない)状態で、かつ左上はBase SDK Missingに…。

調べてみたら、プロジェクト>プロジェクト設定の編集で「一般」を選択して「パス」欄を見ると、Xcodeのルートディレクトリが起点になっているようです。なので・・・
  1. プロジェクトファイル一式をXcode3のルートディレクトリに移動。
  2. プロジェクト>プロジェクト設定の編集で「一般」を選択して、「すべての構成のベースSDK」を「Latest iOS (iOS 4.3)」に変更。
  3. プロジェクト>プロジェクト設定の編集で「ビルド」を選択して、「iOS Deployment Target」など必要な項目を設定する。
  4. プロジェクト>アクティブSDKを設定>Simulator に切替。
と設定し、やっとiOSシミュレータで起動するようになりました。やれやれ。
インストールばかりやってないで、いい加減まともなアプリを1本つくらないと…(^^;。
Base SDK Missingについては、過去の記事「XcodeのBase SDK Missing」もご参照下さい。

外接円を描いてみた

ここのところ必要に迫られて、いろいろ図形の描画をしました。で、前回のカスタム線に続いて、今度は外接円を描きました。サンプルはこちら
円の公式(r*r = (x – a)* (x – a)+(x -b)*(x -b))と3点の座標から連立方程式を作って、解いただけです。…と書くと簡単そうですけど、ASの式にするのに結構手間がかかりました。数学苦手だし(笑)。スクリプトはこんな感じです。
//3点から円を描く
function drawCircleFromPoint()
{
//任意の3点から円の半径、中心点を求める
//(3点の座標と円の公式の連立方程式)
var A:Number = Math.pow(point1.x,2) – Math.pow(point0.x,2) + Math.pow(point1.y,2) – Math.pow(point0.y,2);
var B:Number = point1.y – point0.y;
var C:Number = Math.pow(point2.x,2) – Math.pow(point0.x,2) + Math.pow(point2.y,2) – Math.pow(point0.y,2);
var D:Number = point2.y – point0.y;
var E:Number = point1.x – point0.x;
var F:Number = point2.x – point0.x;
var b:Number = (F*A – E*C)/(B*F – D*E)/2;
var a:Number = (C – 2*b*D)/(2*F);
var r:Number = Math.sqrt(Math.pow(point0.x – a,2) + Math.pow(point0.y – b,2));
//求めた円を描画
var sp_gr:Graphics = sp.graphics;
sp_gr.clear();
//円;
sp_gr.lineStyle(1,0x00FF00,1);
sp_gr.drawCircle(a,b,r);
//中心点;
sp_gr.moveTo(a-3,b-3);
sp_gr.lineTo(a+3,b+3);
sp_gr.moveTo(a-3,b+3);
sp_gr.lineTo(a+3,b-3);
}

※point0,point1,point2はそれぞれ円のmcを指します(サンプル参照)。

いざ書こうとすると意外と面倒なのでメモとして。あんまり用途がないかもしれませんけど…。

Arrayの落とし穴(2) – ゼロの配列

普段あまり使わないのだけれど、Arrayは・・・

var array:Array = new Array(0,2)

とやっても生成できます。で、たまたま横着してこの方式で・・・

array = new Array(0)

とやって、array[0] == 0 になると思ったら、要素ゼロの配列になってしまい、しばらく「何でだろうな??」とはまってしまいました。ヘルプ通りの仕様なんですけどね。

var array:Array = new Array(0,2)
trace(array,array.length) >> 0,2 2
array = new Array(0)
trace(array,array.length) >>  0

まあこんなコトで躓くこともないと思いますが、自分ではまたやりかねないのでメモ。

素直にこうすれば、何の問題も起きないんですけどねw。
array = [0]
trace(array,array.length) >> 0 1

[追記]2011.5.11
野中さんから情報いただきました。初期化は[]を使う方が速いらしいです。

いろんな線を描くクラスを作ってみた

GraphicsでmoveTo,lineToで線を描く時に、Flash上でできる破線、点線などの描画が出来ない。みんなどうしてるのか・・・と調べると、結局自作するしかないようなので、CustomLine用のクラスを書いてみました。点線、破線、波線、二重線に対応してます。サンプルはこちら
こういうのって汎用ライブラリはないのかな〜。役に立つようならwonderflにでも投稿してみようかしらん。でももうあるかな?
この手のいいライブラリがあったら教えて下さい。

XcodeのBase SDK Missing

久しぶりにXcodeをいじったら、iOS3.1.3用につくったプロジェクトが軒並みエラーで書き出せず。ベースSDKとか4.2かLatest iOSしかないし…(T_T)。Xcodeを3.2.5に上げたのが原因か?
いろいろ調べて対処法を発見。
  1. プロジェクト>プロジェクト設定を編集を選択。
  2. ビルドを選択して、アーキテクチャ>ベースSDKをLatest iOSに変更。
  3. 同じくビルドで、Deployment>iOS Deployment TargetをiOS3.1.3に変更。
  4. 同じくビルドで、Code Singning>コード署名ID>Any iOSを現在有効なIDに変更。
  5. プロジェクト設定を閉じる。
  6. これでもまだ「Base SDK Missing」と出ているので、プロジェクトファイルを閉じて、再び開く。
これで右上に「4.2 | Dbug | XXX | XXX | armv6」などと表示され、「Base SDK Missing」
は消えているので、これでビルドして実機(iPhone3G)に書きだしできました。ふう。
この辺はなんかうまいこと自動で変換する仕組みとかないのかな〜。ちゃんと下位互換を作って欲しいよ、まったく…。
ちなみにiPhoneの勉強始めに手に取った「iPhone SDKの教科書」のサイト見たら、iOSのバージョンに合わせてサンプルファイルが更新されていました。細かいサポートが素晴らしいです!今回の問題解決の糸口にもなりました。改めてオススメです。

[補足]

  • 上記6.は実行しなくても、ビルドがうまくいく時もあるみたいです。違いはいまいちわからない…。
  • Resource>xxx.plistにある「Bundle Identifier」も要チェック。私の場合は「com.yourcompany」になってしまってました。

AACオーディオをNetStreamで再生する際の問題点

ちょっとはまったのでメモ。
AACファイルをNetStreamを使って再生する場合、FLVと同様に・・・
rcv_ns.play(url_flv);
rcv_ns.seek(0);
rcv_ns.pause();

みたいな感じで、先頭に位置づけておいて、NetStream.resume()とNetStream.puase()を切り替えて、再生・一時停止を実装しています。例えば、こんな感じ。
if (isNowPlaying) {
//終了の場合は、巻き戻して再生
if (flg_finish) {
flg_finish = false;
rcv_ns.seek(0);
}
rcv_ns.resume();
} else {
rcv_ns.pause();
}
この状態で、NetStream.seek(0)で一時停止(NetStream.pause())した状態で放置しておくと、NetStream.resume()してもAACが再生されなくなってしまいます。つまり初期状態や先頭まで巻き戻した状態でそのままにしておくと、再生ボタンが効かなくなるということです。
FLVでテストしても問題は発生せず、どうもAACに固有の問題のようです。結局、NetStream.resume()の前には、強制的にNetStream.timeで位置合わせしてやることで解決しました。
if (isNowPlaying) {
//終了の場合は、巻き戻して再生
if (flg_finish) {
flg_finish = false;
rcv_ns.seek(0);
} else {
rcv_ns.seek(rcv_ns.time);
}
rcv_ns.resume();
} else {
rcv_ns.pause();
}
う〜ん、なんか釈然としないけど、バグなんだろうか?
直接は関係ないですが、AdobeのサイトにAAC関連の記事を見つけたので貼っておきます。NetStreamで読み込むAACにSoundTransformを使う方法なんて事も書いてあります。

東京ひよこの会(第1回勉強会)みんなで共有ファイルのDL

3/5に東京ひよこの第一回勉強会を開催しました。
初めての幹事でよくわからぬままの見切り発車でしたが、各自制作のファイルを元にそれぞれ有意義な発表だったと思います。各参加者、会場提供のビバマンボさんに感謝です。ちょっと時間を見誤り、予定を1時間もオーバーしてしまいましたが(笑)。
持ち寄ったファイルはみんなで共有ということで、ここからDLできます。参加者は勿論、惜しくも参加できなかった方もご覧になって「どんな会だったのか」を感じていただけるといいかもです。
みなさん続々とブログ等に感想、解説など書いて下さってます。是非、Twitterでハッシュタグ#tokyopiyoをチェック!
これを機会に第二回、第三回と続くといいなと思います。

外部swfからフォントをロードする際の注意点

これまたハマったのでメモ。

ライブラリで「新規フォント…」を選択、リンケージ設定して単独のswfとして書きだし、本体のswfと分離して、外部swfからフォントを埋め込むテクニックがありますが、この時、本体側のテキストフィールドに同じフォントが指定されていると、フォントの適用ができません。
例えば、フォントを適用しようとするtextFieldに同じフォントが指定されていると、文字が表示されません(textFieldはフォント埋め込みせず、テキストは空の状態)。
またムービークリップがmc1,mc2とタイムライン上に時系列に並んでいる(例:1-5フレームにmc1、6-10フレームにmc2)場合で・・・
  • mc1には、外部swfからASでフォント適用するtextFieldがある。
  • mc2には、外部swfのフォントが指定されたtextFieldがある。
のようになっていると、最初にmc1を表示したときには文字が表示されているが、mc2を表示した後に再度mc1を表示すると、文字が見えないという現象が起きます(mc2のtextFieldはテキストの有無は問わず)。
正確な理由はわかりませんが、本体swfと外部swfで同じ名前のフォントを使おうとしてコンフリクトしているとか、既に本体側にフォントがあると見なされてスルーされるか..でしょうか。
わざわざ外部swfにするフォントを本体側に指定すること自体が無意味なわけですが、レイアウト確認用に文字を入れておいて、後から外部フォント化するなど、指定が残ってしまう場合もあるので、要注意だと思います(実際、ハマりましたし)。
外部swfからフォントをロードする方法については、下記サイトを参考にしました。感謝。

IE7でwindow.openする際の注意点

ExternalInterface.call()で”window.open”を使って、別ウィンドウを開こうとしてマハったのでメモ。

IE7で”window.open”を使う場合は、swfのEMBEDで「wmode=”transparent”」にしないといけないらしい。最近の仕事は分業が多くて、自分でHTML書く機会も少ないので、全然知らなかったです。というか、やったけど忘れているのか?
下記のサイトを参考にしました。感謝。

外部swfからクラスを呼び出す

画像が固定(更新なし)のスライドショー的なものを作っていて、外部swfにひとまとめにして、そこから画像を取り出そうと考えてみた。

画像はphoto.swfに入れて、そのライブラリのプロパティでリンケージを設定して「photo0」のようにクラス名をつけておく。それで書き出すだけ。
で、取り出しはSWFをロードするクラスに書きます。
package {
import flash.events.EventDispatcher;
import flash.display.Loader;
import flash.display.LoaderInfo;
import flash.display.MovieClip;
import flash.net.URLRequest;
import flash.events.Event;
import flash.system.LoaderContext;
import flash.system.ApplicationDomain;
import flash.events.ProgressEvent;
public class SwfLoader extends Loader {
var flg_play:Boolean;
var func_complete:Function;
private var cont:LoaderContext;
//コンストラクタ
function SwfLoader(url:String,isPlay:Boolean,func_comp:Function = null) {
flg_play = isPlay;
func_complete = func_comp;
//各種イベント定義
this.contentLoaderInfo.addEventListener(Event.INIT,onInit_swf);
this.contentLoaderInfo.addEventListener(Event.COMPLETE,onLoaded_swf);
this.contentLoaderInfo.addEventListener(ProgressEvent.PROGRESS, onLoadProgress_swf);
//for URL
var urlReq:URLRequest = new URLRequest(url);
cont = new LoaderContext();
cont.applicationDomain = ApplicationDomain.currentDomain;
this.load( urlReq, cont);
}
//—–Event.INIT
function onInit_swf(evt:Event):void {
//ロード中は再生しないよう停止
var info:LoaderInfo = LoaderInfo(evt.target);
var mc:MovieClip = info.content as MovieClip;
mc.stop();
}
//swf:ロード継続
private function onLoadProgress_swf(e:ProgressEvent):void {
//継続イベント:送信(ProgressEvent.PROGRESSを引き継ぐ)
dispatchEvent(e);
}
//—–Event.COMPLETE
function onLoaded_swf(evt:Event):void {
try {
//指定関数の呼び出し(LoaderInfo.contentを渡す)
var info:LoaderInfo = LoaderInfo(evt.target);
var mc:MovieClip = info.content as MovieClip;
//再生の有無
if (flg_play) {
mc.play();
} else {
mc.stop();
}
if (func_complete != null) {
func_complete(mc);
}
} catch (err:TypeError) {
trace(err.message);
}
}
public function getImage():Loader {
return this;
}
public function checkClass(ClassName:String):Class {
var cl:Class;
//アプリケーションドメインに指定したクラスがあるか
if (cont.applicationDomain.hasDefinition(ClassName)) {
//取得したクラスをClass型変数に代入
cl = cont.applicationDomain.getDefinition(ClassName) as Class;
trace(“外部SWFファイルから”+ClassName+”クラスをインポートしました”);
} else {
trace(“外部SWFファイルには”+ClassName+”クラスは存在しません”);
}
return cl;
}
}
}

本体側では、こんな感じにswfをロードして・・・

import SwfLoader;
var swf_content:SwfLoader;
//画像用swf:ロード
function loadContent_img():void {
var url:String = “photo.swf”;
var flg_play:Boolean = false;
swf_content = new SwfLoader(url,flg_play);
swf_content.addEventListener(ProgressEvent.PROGRESS, checkLoad_font);
this.addChildAt(swf_content,1);
}
SwfLoaderのcheckClass()という関数を使って、外部swfからBitmapDataを取得します。
//ビットマップ取得
function getBitmap_img(no:int):Bitmap {
var name_bmp:String = “photo” + String(no);
var imgClass:Class = swf_content.checkClass(name_bmp);
if (imgClass != null) {
var img:BitmapData = new imgClass(stage.stageWidth,stage.stageHeight);
var bmp:Bitmap = new Bitmap(img);
}
return bmp;
}

納品先での画像差し替えが不要で、定期的に一括更新かけるような場合は便利かも。作例はこちら

下記のサイトを参考にさせていただきました。