2011年8月31日水曜日

ログ出力テストの習慣

cocos2d(0.99.5) で CCSprite を親ノードから削除した時には、CCSprite に余分な retain をしていなければ、自動でメモリが解放されます。

しかし、Objective-C を始めたばかりの時は不安がありますよね。App Storeで売られているアプリでも、メモリ管理が怪しそうなものをちらほら見かけます。
Xcode のパフォーマンスツールの Leaks を使って、メモリリークをチェックするというのもちょっと大袈裟な場合、ログを出力してテストする習慣をつけましょう。

CCSpriteの親クラスである CCNodeクラスのソースコード CCNode.m を開きます。deallocメソッドの頭には以下のように CCLOGINFOマクロが記述されています。
CCLOGINFO はcocos2d で定義されているログ出力マクロで、内容は CCLOG とまったく同じです。しかし、Debugビルドのデフォルトでは CCLOG マクロは有効になりますが、CCLOGINFO の方は無効にされています。
// CCNode.m
- (void) dealloc
{
 CCLOGINFO( @"cocos2d: deallocing %@", self);
  :
 [super dealloc];
}
CCLOGINFO マクロを有効にするためには、COCOS2D_DEBUG という定義を1から2に変更してやる必要があります。具体的には、「ターゲット cocos2d libraries の情報」ウィンドウを開き、Debugビルドの設定を以下のように変更して、ビルドし直します。


あとは自分のアプリケーション側で、以下のように CCSprite を親ノードから削除してみれば、CCLOGINFOからのログが出力されます。されなければ dealloc が呼ばれなかった事になるので、メモリリークの疑いが生まれます。
// 親ノードから削除
[sprite removeFromParentAndCleanup:YES];

ログ出力例
2011-09-01 22:42:12.225 AppName[39527:207] cocos2d: deallocing <CCSprite = 068726F0 | Rect = (326.00,1.00,32.00,122.00) | tag = -1 | atlasIndex = -1>


Box2d 2.2.0 リリース

Box2d 2.2.0 がリリースされたようです。
改造2.0.1をずっと使い続け、最近やっと 2.1.2 に移行しはじめたばかりでしたが、まさかのタイミングでした。

変更内容は以下のとおりなので、メソッドが変更になるような面倒なことはなさそうです。
  • The dynamic tree is now self-balancing, leading to significant speed improvements for large worlds.
  • Added wheel joint, friction joint, and rope joint.
  • Implemented b2ChainShape with smooth collision support.
  • The gear joint no longer requires static bodies to be used.
  • Many bug fixes.

この中では、巨大ワールドでのダイナミックオブジェクトツリーが最適化されたのと、新しいジョイントタイプが追加されたのが気になります。
cocos2d プロジェクトでも、いずれインポートされるかと思われます。

2011年8月30日火曜日

FlashでiPhoneアプリのモックアップ作り

書籍、iPhoneアプリで稼ごうを読んでいます。
この本は iPhoneアプリの設計・デザインから開発まで、さらにプロモーションのノウハウなど、個人開発者や小企業ではなかなか得られなかった情報を提供してくれる良書だと思いました。個人的には、アプリ開発受注時の注意点、見積書の書き方など、大変勉強になりました。

この本の中で、企画段階でアプリのモックアップを作るのに便利なツールが、いくつか紹介されていました。今まであまり気にしていなかったのですが、確かにニーズはあるなという気がします。
そこで、ひとつの方法として Flash CS5.5 + AIR for iOS を使ったモックアップ作りというのを提案してみます。
今回は、現在企画中の「ニンジンゲーム」を例にして、Flash でモックアップを作ってみました。

まず、ステージサイズを320×480にした空のドキュメントを作ります。
それから、タイムラインの1フレームに1画面分の情報を入れていきます。
今回は以下の3画面をタイムライン上に作成しました。
Flashを使う利点として、テキスト、シェイプ、ビットマップ画像などを自由に配置できることが上げられます。

ステージ1:タイトル画面

ステージ2:ゲーム画面

ステージ3:ゲームオーバー画面&広告エリア

全体のタイムラインは以下のようになりました。

ステージ1のタイムラインに、以下の ActionScript を埋め込みます。
stop();

stage.addEventListener(MouseEvent.CLICK,stageClick);

function stageClick(e:MouseEvent):void {
	var no:int = currentFrame;
	++no;  // 次のフレームNOを計算
	if (no>totalFrames) {
		no = 1;  // 最初のフレームへ戻る
	}
	gotoAndStop(no);  // フレーム移動
}
これで、画面をタップする毎に、1画面ずつ遷移していくモックアップアプリケーションができました。
これをパソコン上でプレビューするだけでもいいですが、AIR for iOS アプリとしてパブリッシュして、iPhoneなどのデバイスに転送すれば、プレゼンの際に威力を発揮するのではないかと思われます。




2011年8月29日月曜日

ネコグラス時計 ver.1.1 申請中

先ごろリリースしましたネコグラス時計のバージョン1.1を iTunes Connect へ申請しました。
iPhoneユーザーの方には申し訳ありませんが、iPad用アプリケーションになります。



今回の変更点は以下のようになります。
・マルチタッチ対応。
・セッティング画面でのスライドボタンの操作性向上。

ネコグラス時計は AIR for iOS で開発されています。


2011年8月27日土曜日

Dr.Mandala 遊び方

Dr.Mandala ver.2.0 を iTunes Connect へ申請しました。
変更箇所は多岐にわたり、概ね以下のようになりました。
  • 無料体験時間を10分に延長
  • ビジュアルを変更
  • ユーザーインターフェースを変更
  • アイコンを変更
  • サウンドエフェクトを変更

Dr.Mandala は、リアルタイムにヴィジュアル・エフェクトの変化を楽しむアプリケーションですが、静止画として保存し、なんちゃってアートで遊ぶことも可能です。
過去に僕が作った画像集があります。(Art of iPhone)

例えばこちらは、今回僕が新たに Dr.Mandala で作った素材です。

渋い画像ですが、なんとなく曼荼羅っぽくなっていますね。
これを同じ iPhoneアプリの TiltShift Generator で加工してみますと、こんな感じになります。↓

ヴィヴィッドな感じになりました。なんちゃって曼荼羅の完成〜♪

他にも、ネオン風な感じなのも♪


ぜひ、みなさんもオススメ画像アプリを使って、なんちゃって曼荼羅画像を作ってみてはいかがでしょうか?

2011年8月26日金曜日

Dr. Mandala ver.2.0アップデート作業

ここ数日は、Dr. Mandala の改良を行っていました。
なんと次回アップデートは、前回から約10ヶ月ぶりになってしまいました。
日本のApp Storeでネガティブな書き込みをされてから、国内ではまったく売れなくなってしまい、正しいことを書かれているにしても、モチベーションがかなり減退していたことは否定できません…。

巻き返しができるのか分かりませんが、 これではイカンと、また改良に着手し始めました。
今回のアップデートは、Dr. Mandalaの機能の見直しと、よりシンプルさを追求する方針で行いました。
その結果、「デバイスをシャッフルしてキャンバスの回転速度を変更する」という操作は無しにして、常にAutoで回転速度がコントロールされるようにしました。これによって、操作の煩雑さを一軸減らすことができました。「3本指タップで回転を止める」操作は残してあります。

Dr. Mandala は アドオンを購入することによって、製品版へアップグレードできる仕組みになっていて、それまでは時間制限付き体験プレイという形になっています。その体験時間を1プレイ10分に延長してみました。
さすがに2分では短すぎでした。これによって多くの人が「インストール→なんだこれよく分からん→即削除」という結果になっていたのではないかと推測します。この2分という数字は、実は最初はもうちょっと長かったのですが、知人から「体験時間が長いから買うまでもない」と言われて、それを鵜呑みにして設定したものでした。しかし、何分がペストなのか、まだ僕には分かりません。

開発の話しになりますが、アドオン購入フローのデバッグをしていたところ、SKProductsResponse オブジェクトのプロダクトリストが、空になって返ってくるという現象がおきました。
- (void)productsRequest:(SKProductsRequest *)request didReceiveResponse:(SKProductsResponse *)response
{
	NSArray *myProduct = response.products; // 空のNSArrayが返ってくる!
}
もちろん In App Purchase のプロダクトは、iTunes Connectに登録されていて、今まで正常に動いていました。まったく手がかりが無かったのですが、ふと思って一旦アプリをデバイスから削除して、再インストールしたらリストが取得できるようになりました。
もしかしたら App Storeからダウンロードした Dr. Mandala に、開発中の Dr. Mandala を上書きインストールしたことによって、SKPaymentQueueサービスのデータ引き継ぎがうまくいって無かったのかもしれません。
依然、正しいことは分かっていませんが、もし同様の事でハマっていましたら、試してみてはいかがでしょうか。

2011年8月22日月曜日

CCNodeのdrawメソッドでOpenGL

cocos2dでCCSpriteをテクスチャーに描画する方法を調べていました。
Dr. Mandala のようなキャンバス系お絵かきソフトを cocos2d で作りたいと考えていたためです。

残念ながら、cocos2dのクラスリファレンスやネットを調べても、それらしい便利なメソッドは見つけられませんでした。
どうもそういう特殊用途のメソッドは、自分でOpenGL ESで実装するというのが正解みたいです。また、cocos2dのソースをちょっと見た限りでは、OpenGL ESを知っていればそう難しい事でもなさそうです。

今回調べて分かったことは、CCNodeクラスの -(void)draw メソッドをオーバーライドして、その中でOpenGL ESコマンドが書けるらしいということです。
テクスチャーへの描画はちょっと脇へ置いて、まずは、その辺りを最初に試してみることにしました。

お題は、背景にグラデーションのスプライトを敷くプログラムです。
新たに CCSpriteクラスを継承した、Bg クラスを作成しました。

ヘッダファイル抜粋
// Bg.h
@interface Bg : CCSprite {
}
+ (id)bg;
@end

実装ファイル抜粋
// Bg.m
@implementation Bg

+ (id)bg
{
	return [[[self alloc] init] autorelease];
}

- (void)draw
{
	// デフォルトでは以下のstateはEnableになっているので
	// このメソッドを去る時には、必ずEnableに戻しておかなければいけない。
	// - glEnableClientState(GL_VERTEX_ARRAY);
	// - glEnableClientState(GL_COLOR_ARRAY);
	// - glEnableClientState(GL_TEXTURE_COORD_ARRAY);
	// - glEnable(GL_TEXTURE_2D);
	// また、これ以外のstateはDisableに戻しておくこと。

	CGSize screenSize = [[CCDirector sharedDirector] winSize];	// スクリーンサイズ

	// シートを敷く
	const GLfloat vertices[] = {
		0,0,
		0,screenSize.height,
		screenSize.width,0,
		screenSize.width,screenSize.height,
	};
	const GLfloat colors[] = {
		1.0f,0.0f,0.0f,1.0f,
		0.0f,1.0f,0.0f,1.0f,
		0.0f,0.0f,1.0f,1.0f,
		1.0f,1.0f,0.0f,1.0f,
	};
	
	glDisableClientState(GL_TEXTURE_COORD_ARRAY);
	glDisable(GL_TEXTURE_2D);
	
	glVertexPointer(2, GL_FLOAT, 0, vertices);
	glColorPointer(4, GL_FLOAT, 0, colors);		// α値を含めたRGBAにしなければならないので、最初のパラメータは4
	glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
	
	glEnableClientState(GL_TEXTURE_COORD_ARRAY);
	glEnable(GL_TEXTURE_2D);
}
@end

あとは、Bgクラスをインスタンス化して、適当なシーンに追加するだけです。
Bg *bg = [Bg bg];
bg.position = CGPointZero;	// (0,0) は画面の左下
[myScene addChild:bg z:-1 tag:GameSceneNodeTagBg];

実行結果は下のような感じになります。
前回のテストプログラムから引き継いで、だいぶサイケになったネコ君でした。


2011年8月21日日曜日

@synthesizeの代名記法

cocos2dのObjective-Cのソースを眺めていて、@synthesizeで初めて知った記法がありました。

CCTexture2Dのヘッダファイルでは、こんな感じに定義されております。
@interface CCTexture2D : NSObject
{
	GLuint name_;
	CGSize size_;
	    :
	    :
}
/** texture name */
@property(nonatomic,readonly) GLuint name;

/** returns content size of the texture in pixels */
@property(nonatomic,readonly, nonatomic) CGSize contentSizeInPixels;
おやっ?と思ったのは、変数が name_ で定義されているのに、@property が name で定義されていたからです。

実装の方を見ると、こんな感じになっておりました。
@synthesize contentSizeInPixels = size_, name = name_;
@synthesizeに=を付けて代名させることが出来るとは知りませんでした。
いつから出来たのでしょうか。最初から?

ちなみにヘッダファイルに定義されている、下の2つ目の nonatomic ってなんでしょうか?
何か意味があるのかな? 単なる記述ミス?
@property(nonatomic,readonly, nonatomic) CGSize contentSizeInPixels;

2011年8月20日土曜日

ズッコケGuys バージョン1.1

ズッコケGuys バージョン1.1がリリースされました。


更新内容は以下のようになっています。
  • 画質の向上
  • アニメーション速度の向上
  • ズッコケ君のメガネが外れるアクション追加
  • セルフ広告システムの変更
  • バグの修正
今回は間に合いませんでしたが、次回の更新の時には、マルチタッチに対応したいと思います。



2011年8月19日金曜日

cocos2dで簡単アニメーションプログラム

cocos2dで作る iPhone&iPadゲームプログラミングのサンプルプログラムを動かして勉強してきましたが、そもそもじっとしていられない質なのと、自分の理解度を試すために、簡単なプログラムを作りました。

内容は、ネコグラス時計のネコのアニメーションを表示するだけのものです。
工程としては以下のようになりました。
  1. Flashでネコだけをステージに配置したSWFファイルを作成
  2. SWFSheetでネコのアニメーションを1つのテクスチャファイルに書き出し
  3. 使用するアニメーション画像を画像ソフトで切り出す
  4. TexturePackerProでテクスチャアトラスを作成
  5. アニメーションタイムラインをplistファイルで作成
  6. Xcodeでcocos2dのテンプレートプロジェクトを作成
  7. plistファイルからCCAnimationデータを作成するエクステンションを追加
  8. ネコをCCSpriteで表示

工程1 : Flashでネコだけをステージに配置したSWFファイルを作成

Flash CS5.5で、ネコをステージに配置したSWFファイルを作成します。ステージのサイズもネコに合わせて小さくしましたが、あえて必要な作業ではありません。

工程2 :  SWFSheetでネコのアニメーションを1つのテクスチャファイルに書き出し


工程3 :  使用するアニメーション画像を画像ソフトで切り出す


SWFSheetで書き出した画像ファイルから、上記の3つ画像をそれぞれ切り出しました。切り出す際に、それぞれの中心位置がズレないように注意して下さい。
書き出したファイル名は cat0.png , cat1.png , cat3.png としましたが、ファイル名はそれぞれ好きな名前で良いです。

工程4 : TexturePackerProでテクスチャアトラスを作成


先ほどの3つのpngファイルを TexturePackerPro へ Drag&Drop してテクスチャ アトラスを作成します。pngファイル名はcocos2d上ではフレーム名として扱われ、それぞれのテクスチャを呼び出す際のkeyとなるので覚えておいて下さい。
パブリッシュすると、テクスチャ画像とplistファイルが書き出されます。ファイル名は、それぞれ cat-tex.png , cat-tex.plist とします。

工程5 : アニメーションタイムラインをplistファイルで作成

プロパティエディタなどでタイムライン アニメーションの設定ファイルを作成します。
今回は上記のように設定しました。animations、frames、delayは固定名なので変えないで下さい。
cat_type1 はアニメーション名です。プログラム中からアニメーションを呼び出す際の keyとなります。
framesの中身は、各フレームで呼び出されるフレーム名を設定します。先ほどの pngファイル名になります。
delayは各フレーム間の時間(秒)を設定します。今回は0.06秒にしました。

工程6 : Xcodeでcocos2dのテンプレートプロジェクトを作成

ここはcocos2dアプリを作るときのお決まりの工程なので割愛します。

工程7 : plistファイルからCCAnimationデータを作成するエクステンションを追加

参考にしたのは、Loading Cocos2D Sprite Frame Animations from Plist Filesです。
ここでは、CCAnimationCacheクラスにエクステンション機能をつけて、先ほどのplistファイルを読み込み、CCAnimationデータを生成する方法が解説されています。これを元に、独自の実装を追加していくのが良いのではないかと思いました。

工程8 :  ネコをCCSpriteで表示

まず、適当なシーン作成のイニシャライザで、以下のコードを記述します。ここでは、テクスチャ アトラスとアニメーションファイルを読み込ませておきます。それぞれキャッシュに入れるので、後からkeyを使用して、いつでも呼び出すことが可能になります。
最後にネコ(Catクラス)のインスタンスを作成し、適当なポジションに配置します。
// テクスチャアトラスの読み込み
CCSpriteFrameCache *frameCache = [CCSpriteFrameCache sharedSpriteFrameCache];
[frameCache addSpriteFramesWithFile:@"cat-tex.plist"];

// アニメーションの読み込み
CCAnimationCache *animCache = [CCAnimationCache sharedAnimationCache];
[animCache addAnimationsWithFile:@"cat-anim.plist"];

CGSize screenSize = [[CCDirector sharedDirector] winSize];

Cat *cat = [Cat cat];
cat.position = CGPointMake(screenSize.width/2,screenSize.height/2);
[self addChild:cat z:0 tag:GameSceneNodeTagCat];

Catクラスは、CCSpriteクラスの派生クラスにしてあります。ここでは採用しませんでしたが、NSObjectの派生クラスにして、CCSpriteクラスを保持(Has a)する方法もあります。
Catクラスのイニシャライザでは以下のコードを記述します。この中で、cat_type1 を keyとして、キャッシュから CCAnimation データを呼び出し、そのアニメーションを無限ループさせるアクションを生成し、その後実行しています。
+ (id)cat
{
	return [[[self alloc] initWithImage] autorelease];
}

- (id)initWithImage
{
	if ((self = [super initWithSpriteFrameName:@"cat0.png"])) {
		CCAnimation *animation = [[CCAnimationCache sharedAnimationCache] animationByName:@"cat_type1"];
		if (animation!= nil) {
			CCAction *action = [CCRepeatForever actionWithAction:[CCAnimate actionWithAnimation:animation restoreOriginalFrame:NO]];
			[self runAction:action];
		}
	}
	return self;
}


以上のような工程で、初めてでも案外あっさり完成してしまいました。
うーん、Flashほどでは無いにしても、cocos2dも楽々らくち〜んかも!

レビューステータスにMetadata Rejectedが追加

今朝は一刻、集中豪雨でした。しかも凄い湿度!
早くもエアコンのお世話になってしまいました。

iTunes Connect から New Features for Apps Now Available というタイトルで案内メールが飛び込んできました。
内容は以下のような感じでした。
  • レビューステータスにMetadata Rejectedが追加された
    アイコン、スクリーンショット、アプリ名、キーワード、レーティング、カテゴリーなどのメタデータに問題がある時には、Metadata Rejected状態になる。
    ただしアプリ開発者は、アプリの再提出が必要なく、メタデータを編集して修正することができる。
  • Bundle IDが編集できる
    アプリの提出がされておらず、Game Center及びiAdを使用していないなら、Bundle IDを編集することができる。
Rejectedの文字がアプリ開発者をビビらせますが(笑)、内容としては悪くなさそうですね。

2011年8月18日木曜日

cocos2dで使えるテクスチャツールたち

少し時間が空いたので、cocos2d修行再開しました。



使用しているのはこの本です。
久しぶりにやると前のことをかなり忘れてしまうので(笑)、一章分まるまる読みなおしたりして、やっと第7章まで終わりました。
この本は、原著のすばらしさもさることながら、翻訳者の方たちもcocos2dに精通してるらしいので、補足情報も盛りだくさんでありがたいです。

7章までを要約すると、だいたいCCNode(CCLayer,CCSprite)クラスの使い方に終始していました。そもそもcocos2dがスプライトライブラリコアといった感じなので、これはこの本全体に言えることなのかもしれません。ActionScript3で例えるならば、DisplayObjectとDisplayObjectContainerクラスといったところでしょうか。

僕がこの本を気に入っているのは、たんなるスプライトライブラリのリファレンスに留まらず、2Dゲームをオーサリングする開発環境に配慮された記事が多いところでしょうか。
初心者向けというよりは、何度かゲームプログラムを作った経験のある中級者以上向けの本かと思います。

7章まで紹介されているオーサリングツールとしては、
フォント系
テクスチャ系 (テクスチャ アトラス作成)
があります。こういったツールの紹介だけでも、ゼロから自分で調べるよりはたいへん助かりました。(全て国外のツールだし)
特に、2Dスプライトのテクスチャ ファイル(米ではテクスチャ アトラスというらしい)を作成するツールは、ゲームを作るにおいて、あると無いとじゃ大違いなので助かります。

自分がcocos2dでゲーム開発するとして、一番欲しいと思っているのは、タイムラインに沿ったアニメーションを作成できるアートデザイナー用のエディターです。Flashのようなものです。
cocos2dのフォーラムでも時々、アニメーションエディターに関しては話題になっているようですが、それなりに求められている割りには、これだ!というものが見つけられませんでした。アニメーションエディターなどは、社内ツールとして独自開発されたものが使用されていることが多く、あまり外に出てこないのが要因でしょうか?

用途は限定されますが、簡単なアニメーションデータ作成になら使えそうなツールがありました。
SWFSheetはFlashからパブリッシュされたSWFファイルを読み込んで、ステージに配置されたムービークリップのアニメーションを1つのテクスチャファイルに書きだしてくれるツールです。AIRアプリなのでMac、Windowsで利用できます。
僕もFlashのデータをcocos2dへ持っていけないかなと考えていたので、このツールを見た時はアイデアものだなぁと思いました。すばらしいです。

下の画像はSWFSheetで、ネコグラス時計のネコのムービークリップをテクスチャファイル化しているものです。


このツールの難点を上げてみますと、
  • アニメーションによっては同じ画像が複数登録されてしまうので無駄が出る
  • 隙間が大きい画像だと無駄も大きい
  • 数百フレームの巨大なアニメーションの書き出しには無理がある
といったところでしょうか。
とはいえ、Flashでタイムラインアニメーションを作成する開発スタジオでは、重宝しそうなツールですね。



2011年8月16日火曜日

ネコグラス時計のマルチタッチ対応

ネコグラス時計のマルチタッチ対応を行いました。
AIR でも、マルチタッチイベントを取得できるクラスが追加されています。
なので簡単に実装できると思っていたら、意外な落とし穴が…。

マルチタッチのイベントを扱うクラスは TouchEvent クラスです。
リファレンスを見ると、今まで使用していた MouseEvent クラスを TouchEvent クラスに置き換えるだけでなんとかなりそうです。

んが、この TouchEvent クラスが、Macに対応していないようなのです!!
コードを記述することはできますが、イベントを受け取ることができないのです。デバッグに不便です。

マウスではクリックイベントが同時に起きるという事はないので、Macが TouchEvent クラスに対応していないのも、当たり前なのでしょうか?
マウスクリックもマルチタッチの1回目のタッチと同じとして、TouchEvent クラスでハンドリングできても良かったのではないかと思います。

しかし、Adobeオフィシャル的には、MouseEvent 、TouchEvent を併用するのが、正しい作法であるみたいです。以下は、base_mcというSprite上のマウスイベントと、タッチイベントを受け取るコードです。

var base_mc:Sprite = new Sprite();
base_mc.addEventListener(MouseEvent.MOUSE_DOWN,baseMouseDown);
base_mc.addEventListener(TouchEvent.TOUCH_BEGIN,baseMultiTouchBegin);
addChild(base_mc);

// base_mcマウスダウンイベント
function baseMouseDown(e:MouseEvent):void {
	trace(e.stageX.toString()+","+e.stageY.toString());
}

// base_mcのマルチタッチイベント
function baseMultiTouchBegin(e:TouchEvent):void {
	if (!e.isPrimaryTouchPoint) {
		trace(e.stageX.toString()+","+e.stageY.toString());
	}
}

上記を実行すると、Mac上では、baseMouseDown()関数しか呼ばれません。

iOS上では、baseMouseDown()、baseMultiTouchBegin()の両関数が呼ばれます。
しかし、複数同時タッチした場合に、1つ目のタッチイベントが baseMouseDown()、baseMultiTouchBegin()の両方にやってくることになります。なので、一方をスキップしてやらなければいけません。
TouchEvent.isPrimaryTouchPointプロパティは、このイベントが MouseEvent にマップされているかどうかを表すBoolean値です。これが true であれば MouseEventでマップされているよ、という意味になります。なんて都合の良いプロパティでしょう(笑)
この isPrimaryTouchPoint プロパティこそが、僕が先に「Adobeオフィシャル的」と言った意味なのでした。

何はともあれ、ネコグラス時計でもマルチタッチに対応することができました。タッチした時のエフェクトが重い関係で、2つ同時までしかマルチタッチを許しておりませんが。(笑)
でも、だいぶ良い感じになりました。

2011年8月13日土曜日

ズッコケ君のメガネが…

ズッコケGuysのバージョン1.1を開発中です。
変更点は以下のようになる予定です。
画質の向上に関しては、全体的にビットマップレンダリングのクォリティを上げて対応しました。詳しくはまたいずれ。
フレームレートに関しては、iPadの方が効果大きいですが、iPhone4でも若干ですが向上しました。

そして、なんと言っても目玉はメガネ!


あっ、メガネが外れてる!(笑)
長年の謎だった、ズッコケ君の素顔が、とうとう明かされる時が来たのです!

しかし、そんなに期待するほど、すごい顔だったのか!?
それはご自身の目でお確かめ下さい。

2011年8月12日金曜日

App Store風アイコン制作サービス

iPhone アプリのセルフ広告を出す時、アイコン画像を表示するのが流行ってますが、App Storeに表示されるように画像を加工するのには、それなりに手間がかかります。

Photoshopなどで自分で加工するのも手ですが、もっと手っ取り早くApp Store風アイコンを制作できる Webサービスが iConeです。
アイコンとアイコーン…。(笑)

ネコグラス時計の広告用アイコンを作ってみました。

アイコン画像を読み込む時は、ICON IMAGE の LOADボタンではなく、BASE IMAGE の方なので注意しましょう。

ネコグラス時計 リリースされました!

iPadなごやか置き時計の「ネコグラス時計」がリリースされました。
App Storeから確認することができます。


ネコグラス時計は Adobe Flash CS5.5 の AIR for iOS で作られています。
アプリ開発者の方には、AIR 2.6 + iPadの実力がどれ程のものか、ぜひご自分の目でお確かめ頂ければと思います。



2011年8月11日木曜日

StageWebViewでセルフ広告


ズッコケGuysのタイトル画面から、「AND MORE APP」というボタンを押すと、App Storeが起動します。そして、Dr. Mandalaというアプリケーションを紹介するようになっています。いわゆるセルフ広告です。

この導線は、紹介するアプリがひとつしかない場合は簡潔で良いのですが、紹介したいアプリが増えてくると問題が生じます。
ネコグラス時計がもう直ぐリリースされるはずなので、ズッコケGuys上でのセルフ広告システムをバージョンアップしました。

セルフ広告は、頻繁に変更できるように、広告データ本体は外部サーバに持たせて、3Gもしくは Wifi 回線から取得します。
まわりくどくなってしまいましたが(笑)、ようするにAIRのStageWebViewクラスを使って、HTMLでセルフ広告を表示する方法にしました。
アプリアイコン(リンク)をタップすると、App Storeが起動して、そのアプリのページまで移動するので、機能的にも問題ありません。


以下が全コードです。
var webView:StageWebView = new StageWebView();
var rect:Rectangle = new Rectangle(0,0,STAGE_WIDTH,STAGE_HEIGHT-30);
webView.viewPort = rect;
webView.stage = stage;
webView.addEventListener(ErrorEvent.ERROR, onWebViewError );
webView.addEventListener(LocationChangeEvent.LOCATION_CHANGING, onWebViewLocChanging );
webView.addEventListener(LocationChangeEvent.LOCATION_CHANGE, onWebViewLocChange );

// ロケールによって読み込むURLを変える
var adUrl:String = Locale.loadString("IDS_AD_URL");
try {
	webView.loadURL(adUrl);
} catch (e:Error) {
	trace(e);
}

function onWebViewLocChange( event:LocationChangeEvent ):void {
	trace("Change to "+ event.location);
	if (event.location != adUrl) {   
		navigateToURL( new URLRequest( event.location ) );
		try { 
			webView.loadURL(adUrl);
		} catch (e:Error) { 
			trace(e);
		}
	}
}

function onWebViewLocChanging( event:LocationChangeEvent ):void {
	trace( "Changing " + event.location);
	event.preventDefault();
	navigateToURL( new URLRequest( event.location ));
}

function onWebViewError( error:ErrorEvent ):void {
	trace( error );
}

気を付けなければならないのは、StageWebView は Spriteクラスなどの表示オブジェクトとは違い、コンテナ先は stage しか選べないということです。
表示プライオリティは、全表示オブジェクトよりも上になってしまうようです。
かなりゴリ押しな実装のようですね(笑)

2011年8月10日水曜日

デバイス回転 AIR 2.6と2.7の違い

AIR for iOSで、デバイス回転時のステージの見栄えが、AIR 2.6と2.7で若干変わっています。
AIR 2.6の時は、ガシャ、ガシャンと2段階右折のようにステージが回転していましたが、 2.7になってより自然に回転しているように見えます。

違いが分かるように、ネコグラス時計を使ってデモしてみました。


2011年8月9日火曜日

AIR 2.7で対応言語リストバグの確認


ネコグラス時計アプリをApp Storeへ登録申請しました。
リリースされるまで、今しばらくお待ちください!
先にリリース中のズッコケGuysも、なかなかの好評を頂いております。ありがとうございます。

ネコグラス時計も、Adobe AIRの例のバグで、対応言語リストに沢山の言語が表示されると思いますが、本当に対応している言語は、英語と日本語だけです。
購入者のみなさまには、大変申し訳ありませんが、よろしくお願いいたします。

さてこのバグですが、なんとかならないのかと思い、AIR 2.7 SDK(2.7.0.20020)で再パッケージング化して、そのダミーパッケージを iTunes ConnectへSubmitしてみました。
が! やはり結果は同じでした…。(TT)

こんな感じに Localizations の項に、余計な言語が追加されてしまいます。

このバグがあると、AIR for iOSを利用したアプリの開発に、本格的に移行できないので早く修正して欲しいのですが、今のところ望み薄であります。

2011年8月5日金曜日

バグ対応のプライオリティに負ける

ネコグラス時計、完成しました〜。
いえーい!

 
あとは iTunes Connect へ Submit するのみです。
しかしSubmitする時に、アプリの概要を英語と日本語で記述しなければならず、「分かりやすく、かつ面白く伝える」という命題も含めて、すんなりとは進ませてくれません。
週末中にSubmitできればいいのだけど。

さて、以前から問題にしていた「ズッコケGuysで対応していない言語までApp Storeでリスト表記されてしまう」というAIR for iOSのバグ(#2878252)ですが、Adobe側からのコメントが出ました。
Unfortunately this bug couldn't be fixed for near future release due to low priority and frequency. It is appreciated that anyone affected by this issue could leave vote notes about how the bug fix is important for you and your business.
バグはAdobe側でも再現できたけど、対応プライオリティとしては低く、近い将来にバグフィックスすることはできない。ということだそうです。
プライオリティが低いというのは、問題を抱えているこちらとしては、聞き捨てならない言葉ですが、要はそういう事らしいです。

む、むー。バグフィックスはFlash CS6.0待ち?
なんか1時間ぐらいで修正できそうなバグなんだけどなぁ…。まあ、チェックにはそれなりに時間は要しますが。
お願いします Adobe様!

2011年8月4日木曜日

AIR for iOSで起動時にデバイスの向きを調べる

「ネコライフ時計 for iPad」 改め「ネコグラス時計」は、全てのデバイスの向きに対応しています。



デバイスの向きは、stage.deviceOrientationの値から得ることができます。
デバイスの回転を検出したらイベントを発生させて、そのイベントオブジェクトからデバイスの向きを調べることもできます。

ただしデバイスの回転イベントは、アプリ起動時には補足できないので、ネコグラス時計では、画面の初期化のために最初だけ stage.deviceOrientationの値を調べておりました。
しかし、困ったことにこの stage.deviceOrientationには、以下のような注意書きがついていました。
注意: deviceOrientation は常に取得できるとは限りません。アプリケーションの最初の起動時や、デバイスが水平に置かれている場合などは、デバイスの方向が「unknown」(不明)として報告されます。
アプリケーションの起動時に必ずunknownになるという不思議な仕様に、しばらく悩みました。
デバイスの向きが不明でも、画面(ステージ) は必ずどこかの方向へ向いている訳なので、要はその向きが分かればいいわけです。現在の画面(ステージ)の向きを調べるには、stage.orientationの値から得ることができます。

stage.deviceOrientation と stage.orientation。この2つのプロパティの意味の違いを混同すると、思わぬバグを混入させるハメになるので注意した方が良いでしょう。

参考 : Adobe Help 現在のステージの方向および縦横比の取得

2011年8月3日水曜日

AIR for iOS 多言語対応問題

以前お伝えした、ズッコケGuysで対応していない言語まで App Storeでリスト表示されてしまうという問題ですが、AIR for iOSのバグだという情報をAdobe AIRフォーラムで頂き、Bugリポート(#2878252)にリストされている事を確認しました。

残念ながら今現在、回避策はないようです…。
この問題って、有料ソフトを販売する時に、購入者さんを騙すことになりはしまいか?
はやいところ直して頂きたいです。



2011年8月2日火曜日

AIR 2.7 Timer Problem

ネコライフ時計 for iPad、もうじき完成です。
縦置き、横置き対応!
リビングや仕事机に飾って欲いです!(笑)



今回は結局、AIR 2.7を使用しませんでした。

というのも、AIR 2.7(ver.2.7.0.20020)のTimerクラスにバグらしきものを発見してしまったからです。一応、Adobeにはバグレポート(#2931038)を提出しておきましたが、うまく伝わってるか不安(汗)

バグ症状は2種類みつけました。
  • 60秒間隔でTimerEvent.TIMERが起動するように設定したが、最初の1回目のイベント起動がおよそ1.5〜2倍ぐらいの時間がたってから起動する。
  • 上記のTimerEvent.TIMERイベントが起動して、その数秒以内に timerObj.reset()→timerObj.start()を実行すると、その直後にTimerEvent.TIMERイベントが起動してしまう。(期待する動作は60秒後に起動)
どちらも AIR 2.6では正常に動作することを確認しております。
すべてのプロジェクトで、このように動作するのかは分かりませんが、ネコライフ時計では100%このようになってしまいました。
Related Posts Plugin for WordPress, Blogger...