だいたい47度

スポンサーサイト

上記の広告は1ヶ月以上更新のないブログに表示されています。
新しい記事を書く事で広告が消せます。

PageTop

エキスパートObjective-Cプログラミングがすごい

エキスパートObjective-Cプログラミングは上級者向けのObjective-C本だ。正直ボクは全部は理解できてない。が、とても勉強になったし今後もなりそうだ。

内容としては、ARC、Blocks、GCDについてそれぞれ扱って200ページ程度。ARC(Automatic Reference Counting)は、retainやreleaseをコンパイラ側で実装してもらう仕組み。BlocksはObjective-Cの関数ポインタのようなもの。GCD(Grand Central Dispatch)はマルチスレッド。

それぞれ概念からきちんと説明してくれるが、気がつくとドップリと深いところに話が進んでいる。たとえば、ARCの説明をするとき、最初にObjective-Cのメモリ管理について説明してくれるが、この説明はどこで読んだものよりもわかりやすい。なるほどなぁと思って読み進めると、retainで何をやっているかからretainの実装はどうやっているか、という話に進んでいく。しまいには公開されていないNSObjectのretainの実装をデバッガを使って予想するところまで話が進む。そこからARCの説明に戻ってくるとまた非常に親切で読みやすい……といった感じだ。

ARCについては、使っていなかったことを公開するくらい便利そう。そもそもcocos2dばかり使っていたから、どうもARCを入れるのが面倒だった。cocos2dのライブラリがARC対応していないから、一々ARCを指定しなくてはならないのだ。ただ、いまはARC対応したcocos2dもあるみたいだし、次は是非使おうと思った(「DiegoTristanと黒白猫の開発日記 」さん参照)。
追記:office-ashipさんを参照してやったら、現行のアプリをARC対応するのは20分もあれば終わりました。概ね自分のアプリのautoreleaseなどを外していく作業。

Blocksについては、cocos2dで使いまくっているので難なく。やはり実装に話が及ぶと難しいが、いままでおまじないと思っていた__BLOCKの実装などがわかるとなるほどなぁと感心する。

GCDについては、難しそうなので避けていたが読んでみると非常にスッキリと頭に入ってきた。いままでのアプリでも使うべきところが幾つかあって、直さなきゃと思った。GCDの後半は個別の話に進んでいくので、実装しながら読んだほうがよさそう。

わかりやすい概念図と、深い実装のところが並んでいるので、開発でちょっと迷った時に参照できるよう横に置いておきたい本。

エキスパートObjective-Cプログラミング -iOS/OS Xのメモリ管理とマルチスレッド-エキスパートObjective-Cプログラミング -iOS/OS Xのメモリ管理とマルチスレッド-
(2011/11/18)
坂本 一樹

商品詳細を見る

スポンサーサイト

PageTop

[Free iPhone Game Apps] Animal Bricks

iPhone app "Animal Bricks" is free brock break (breakout) game with animal blocks!
Enjoy interesting and cute game!


Hit various animal blocks with flower balls. To prevent balls from falling into the bottom, control the flower cart (paddle). As stage progresses, many animals are appeared. All animals have each cute animations.

screenshot4.png

screenshot1.png


If lucky, items comes from brocks. it will help you so.
If you have broken all blocks, you clear the stage. You can play the next stage.

screenshot2.png

screenshot3.png


Sometimes you should use some coins to unlock next stages. You can get coins during game. Don't miss it.
screenshot5.png

All 48 stages! I'll update Animal Bricks to increase stages and types of animal.
-> add more 12 stages in the beginning of this March!

Please enjoy!

PageTop

無料iPhoneアプリゲーム どうぶつブロックくずし

動物ブロック崩しは、無料で遊べるiPhoneアプリゲーム!
かわいい動物たちがいっぱいのゲームを楽しんでね。


動物ブロックくずしは、いろんな動物のブロックに花をあてていくゲームだよ。花が画面から落ちないようにカートを操作してね。ステージが進んでいくといろんな動物が出てくるよ。動物はみんなちょこちょこ動くから、たまに観察してみてね。

screenshot4.png

screenshot1.png


ブロックをこわすとお助けアイテムが出ることがあるよ。がんばって全部のブロックをこわせばステージクリア!次のステージに進めるよ。

screenshot2.png

screenshot3.png


一定のステージまで進むと、先に進むのにコインが必要になるよ。コインはブロックをこわすと出てくるから、取りそこねないようにね!
screenshot5.png

ステージは全部で48個!アップデートでもっと動物もステージも増やしていくよ。お楽しみにね!
→3月初旬に60ステージになる予定だよ!

紹介してくれたレビューサイトさん
2013/02/25 あぷまがどっとねっとさん
2013/02/26 キッズアプリ.comさん
2013/02/28リンゴノコトさん
2013/03/01 Appon!さん
2013/03/12 ゲームセイバーさん
2013/03/17 applivさん
Appliv(アプリヴ) -iPhoneアプリが探せる、見つかる

PageTop

囲碁のアルゴリズム [レビュー]コンピュータ囲碁 モンテカルロ法の理論と実践

ボードゲームにおいてコンピュータの強さは年々上がっている。チェスでは1997年にDeep Blueが世界チャンピオンを破っているし、将棋においてもほぼプロ同等の強さにまでなっている。

その中で、囲碁に関してはコンピュータの成長が遅かった。2005年まではアマ初段以下と言われていた。理由としては、囲碁というゲームの性質がコンピュータで扱うのに向いていなかったことが大きい。詳しくは後述する。

しかし2006年、モンテカルロ木探索というアルゴリズムが発明されたことで囲碁プログラムの強さは一変する。このブレークスルーは、成長が止まっていた囲碁プログラムを一気にアマ5段程度の強さまで引き上げた。

ここでは、コンピュータがボードゲームをするときの考え方から始めて、囲碁が難しい理由、モンテカルロ木探索の取っ掛かりまで書こうと思う。というのもコンピュータ囲碁 ―モンテカルロ法の理論と実践―というコンピュータ囲碁の本として面白い本を見つけたからで、この本へのリードとしてこのブログを書きたいと思う。本については最後に触れる。

コンピュータにとってのボードゲーム
ボードゲームをするとき、人は、言語化されない感覚を大いに使う。人は「概ねこの辺に打つ」ということがわかっているので、幾つかの候補手を考え、相手が対応するだろう手を幾つか考え、それに対して……といった形で考える。最初から経験・感覚で候補手を絞っているのだ。もっと言うと、この手は数手先にやばそうという事さえ、感覚でわかってしまう。

一方で、コンピュータは計算をフルに使う。コンピュータには感覚というものがない。すべては数で表される。「だいたいこのへんに打つ」という感覚ではなく「A地点には確率◯%で打つ」というデジタルな形式で処理される。そのため、手を考える場合も、どうしてその手になるのかを明示的に示せなくてはならない。その代わり、コンピュータの計算処理能は人間とは比べ物にならない速度である。よって、膨大な計算を行うことで「感覚」をデジタルに作り出すことがコンピュータの考え方になる。

例えば、数独の解法を比較すると面白い(ボードゲームではないが)。数独を解くとき、人であれば数値がある程度集まっている怪しそうな領域を調べてみて、数値を一つ一つ書き込んでいくという解法になる。一方のコンピュータの解法はすごい。開いているマス全てにランダムに数字をいれていき、膨大な盤面を生成、たまたまどれかで整合性が取れたらその盤面を正解とする。一々候補を考える手間を取らずに、計算力だけで押し切ってしまうのだ(もちろんもっと効率的にうめていく方法もある)。

コンピュータにとって、全ての手を計算しきれるかどうかで戦略が大きく変わる。コンピュータの計算速度は非常に速いとはいえ、有限である以上、全てのパターンを現実的な時間では試せないこともある。つまりゲームによっては、全部の手を検証できる場合と、全部の手を検証することが時間的に許されない場合があるのだ。3x3の◯×ゲームのような人間でも全パターン読めるような問題は前者にあたるが、多くのボードゲームは後者にあたる。前者であれば全件計算した後で最善手を打てばいい(というか計算し終えた時点で勝敗も決してしまう)のに対し、後者は何かしらの方法で計算を打ち切り、かつその途中までの計算が有用である必要がある。

全ての手を検証できない場合、限られた計算でどれだけ有用な結果を返せるかは、アルゴリズムにかかっている。アルゴリズムとは何を計算するかを規定したものだ。状況に応じて限られたリソースを最大限にいかせるようなルールをアルゴリズムが実現しているかどうかによって、コンピュータの強さは大きく変わってくる。

多くのボードゲームは計算しきれないだけの局面が存在するため、アルゴリズム如何で強さが大きく左右されることになる。よって、ボードゲームに強いコンピュータを作るということは、よりよいアルゴリズムを探索していくことに近い。

囲碁の難しさ
数あるボードゲームの中でも囲碁はコンピュータに向いていない。

まず局面の数が多い。囲碁は19x19であらゆるところに着手できる。8x8かつ相手をひっくり返す部分にしか着することができないオセロとは比べ物にならないくらい局面がありうるだろう。後述する本によれば、オセロは局面数10^28、将棋でも10^69であるのに対し、囲碁は10^170である。

更に途中で勝敗を規定するのが難しい。勝敗が決する最後になるまで、黒白どっちが勝っているかをコンピュータでは判断しにくいのだ。例えば将棋であれば、駒の優劣などがあるので、それらを指標にどちらが優勢かを計算できる。しかし、囲碁では多くの陣地が完全に決定するのが最終盤である上、一時的に損することが将来的な得につながることも多い。よって完全に計算し切らない限り、優勢劣勢の判断をコンピュータが間違えやすい。

つまり、ゲームが最後まで行かないと優劣を決めるのがコンピュータには難しいにも関わらず、ゲームの局面を計算し切るには局面の数が多すぎるというのが囲碁の難しさにつながっている。

モンテカルロ木探索概略
アルゴリズムの一つにモンテカルロ法というものがある。完全な答えを導き出すリソースが膨大になってしまう場合に、乱数を用いて正解に近い値を求める方法だ。よくある例が、円周率を求めるもの。四角の中に内接するような円を描き、四角の中にランダムに点を打ち、円の中に含まれた点の数を数えることで、円周率の近似値を求める。

囲碁においてモンテカルロ法を使うとすると、ある手Aを打ったあとに、ランダムに盤面を埋めていって勝敗を求めることで、Aの勝率を出していくことになる。現在着手可能な手すべてに関して、ランダム盤面埋め処理を複数回ずつ行うことで、各手の勝率を出し、次の手を決めることになる。

このランダムに盤面を埋めていく処理をプレイアウトという。プレイアウトはランダムに埋めていくものではあるが、そのランダムな選択がより人に近いほど(人が選ぶべき手が選択される可能性を高くしてランダム処理するほど)、プレイアウトによって得られる勝率の正確性は上がり、結果的にプログラムが強くなる。よってプレイアウトは囲碁プログラムにおいて大事な位置を占める。

しかし、ただプレイアウトを繰り返していっても、囲碁のプログラムは強くならない。なぜなら、プレイアウトはランダムな手だけで成立するため、相手がミスすると得する手を打ちやすくなるからだ。相手が万一ミスすると大きく儲かるが、きちんと応じると自分が損したりする手があったとすると、期待値的にコンピュータはこの手を打ちたくなってしまう。

つまり、良さげな手があったとしても、その先を読まなくてはいけないのだ。相手が次にどう対応するか、また更に自分がどう対応するか。先を読んで一手目を打つ確率を補正し無くてはならない。

これを実現したのがモンテカルロ木探索である。モンテカルロ木探索は、最初は上述のモンテカルロ法と同様にプレイアウトを繰り返すが、ある程度有望な手が見つかると、その手に関しては打ったものとして相手の手番のプレイアウトを行い始める。普通の手は1段階目のプレイアウトを行いつつ、有望な手に関してはより深くまで調べていくのだ。この探索がnodeをたどっていく木探索の形式をしているので、モンテカルロ木探索と呼ばれる。

本の紹介
ここまでの話に加えて、モンテカルロ木探索を詳しく説明してくれるのが、コンピュータ囲碁 ―モンテカルロ法の理論と実践―である。あまり詳しくない僕でもスラスラと理解できる良著だ。

この本は理論編と実践編で別れており、それぞれ著者も異なる。理論編でコンピュータ囲碁の理論を頭に入れた後、実装をしながらもう一度理論を辿っていけるので、理解がしやすい。

著者はもちろん両者とも第一線の方々であるが、特に実践編の山下さんはコンピュータ将棋の世界大会で優勝していたり、コンピュータ囲碁の大会で3位になっていたりする方だ。実践編ではその実装の詳細をパラメータの数値まで絡めて記述してあって圧巻である。ここまで必要なのかというレベルで書いてある。

理論編を読んでいると、いとも簡単にコンピュータ囲碁が作れる気がしてくる。実際に僕は作ってみようと思った。その後、実践編を読んでいると、ちゃんと強いプログラムにするためには夥しい数の状況に対応を考え、実装して行かないといけないことを痛感して挫折できる。理論と実装の違いを改めて味わえて、そういう意味でも面白い本だった。

囲碁はなかなか難しそうだけど、同じような考え方を使って、何かボードゲームのAIを作ってみようかと思った。もちろん理論以外に機械学習などの知識も必要になってくるので、ハードルは高そうだけど(この本でも機械学習について一定のページは割いてくれているが主題ではない)。

最後に付記しておくが、この本を読む場合は、囲碁のコウやセキという単語はわかるレベルでないとキツい。理論編はついてこれるかもしれないが、実践編は囲碁の知識があることが前提で書かれている。とはいえ、定石を知っている必要などはないので、ちょっと勉強すればすぐ読める本ではあると思う。

コンピュータ囲碁 ―モンテカルロ法の理論と実践―コンピュータ囲碁 ―モンテカルロ法の理論と実践―
(2012/11/10)
美添 一樹、山下 宏 他

商品詳細を見る

PageTop

Box2dの衝突可否制御 categoryBitsとgroupIndex

物理エンジンbox2dにおいて、物体同士の衝突可否を制御したい時があります。物体Aは壁にはぶつかって欲しいけど物体Bにはぶつかってほしくない、のような。

その実装方法として、カテゴリビットによる方法とグループインデックスによる方法(およびその組み合わせ)が選べます。僕は、基本的にはカテゴリビットによる制御を行い、必要な時はgroupIndexを使うのがよいように思います。

カテゴリビット
カテゴリビットは、それぞれのfixtureに設定できる衝突種類のカテゴリのことです。そのカテゴリの物体にぶつかるかどうかはマスクビットで制御できます。

ややこしいので例を使って説明します。

物体A、B、Cについて、それぞれにカテゴリビットを振ってあげます。

typedef enum{
  kCategoryBitTypeA = 0x0001,
  kCategoryBitTypeB = 0x0002,
  kCategoryBitTypeC = 0x0004,
}CategoryBits;

...
//物体Aのfixturedef (B、Cも同様に設定)
fixtureDef.filter.categoryBits = kCategoryBitTypeA;

カテゴリビットは16種類まで設定出来ます。具体的には、0x0001, 0x0002, 0x0004, 0x0008, 0x0010, 0x0020, 0x0040, 0x0080, 0x0100, 0x0200, 0x0400, 0x0800, 0x1000, 0x2000, 0x4000, 0x8000の16種類です。0と1の表記にするとわかりやすいですが、これらは1を一つだけ含むような数値です(0x0040 = 0000|0000|0100|0000)。

上記では、A、B、Cそれぞれのカテゴリビットを0x0001, 0x0002, 0x0004としました。enumで共通ファイルに記述しておき、それぞれのfixturedef.filter.categoryBitsに登録してあげています。

次にマスクビットの登録をします。物体Aは、他の物体A、物体Bとはぶつかりますが、物体Cとはぶつからないとしましょう。

//物体Aのfixturedef
fixtureDef.filter.maskBits = kCategoryBitTypeA + kCategoryBitTypeB;

マスクビットには、衝突対象のカテゴリビットの総和を登録することで、どのカテゴリビットの物体と衝突するかを指定します。

上記の例で言うと、値的には0x0001 + 0x0002 = 0x0003がmaskBitsに登録されています。これは01で表記すれば、0000|0000|0000|0011となり、AとBにふられたフラグが立っていることが分かります。そのため、AおよびBと衝突するfixtureと扱われます。0x0004のフラグは立っていないのでCとはぶつかりません。

maskBitsの値は、fixtureDef.filter.maskBits=0x0003と最初から指定することもできますが、上記のように足し算で記述しておくと修正が入った時にも簡単にできます(ベタ書きしていた場合、フラグのビットを修正したりしたら悲惨な目に遭いますね)。

なお、b2EdgeShapeを使っている場合は以下のように書きます。特に変わったところはないですが、b2EdgeShapeを使用する際はfixture設定を無視することが多いので、一瞬どこに書くのか迷うかもしれません。

//fixturedefを使わない場合
b2EdgeShape groundBox;
groundBox.Set(......);
groundBody->CreateFixture(&groundBox, 0);

//fixturedefを使う場合
b2EdgeShape groundBox;
b2FixtureDef fixtureDef;
fixtureDef.filter.categoryBits = kCategoryBitGround;
fixtureDef.filter.maskBits = ......;
fixtureDef.shape = &groundBox;
groundBox.Set(......);
groundBody->CreateFixture(&fixtureDef);

デフォルトの値としては、categoryBits = 0x0001が振られ、maskBits = 0xFFFFが振られています。maskBits = 0xFFFF = 1111|1111|1111|1111のため、あらゆるものと衝突するのですね。

グループインデックス
グループインデックスもカテゴリビット同様、fixturedefのfilterに設定して使います。

fixtureDef.filter.groupIndex = -1;

groupIndexに負の値を与えると、同じgroupIndexがふられた物体とは衝突しなくなります。またgroupIndexが正の物体は必ず衝突するようになります。

グループインデックスの初期値は0に設定されています。

比較
グループインデックスは、カテゴリビットより単純に実装できそうですが、実装できない状況があります。たとえば、「物体Aは物体B、Cとぶつからないようにしたいが、BとC同士はぶつかるようにしたい」という状況はgroupIndexだけでは実装できません。AとBとCに同じgroupIndexを振っては、BとCが衝突しなくなるからです。一方、カテゴリビットなら、maskBitを調整してあげるだけでOKです。

なお、グループインデックスはカテゴリビットよりも優先されます。カテゴリビットとマスクビットを使って衝突するように指定した物体同士でも、おなじgroupIndexを振られると衝突しなくなります。グループインデックスが初期値である0以外の値の場合は、常にグループインデックスがカテゴリビットより優先されるので注意する必要があります。

以上のことから、僕は、基本的にはカテゴリビットによる制御を行い、必要な時はgroupIndexを使うのがよいように考えています。衝突可否制御がほとんどない場合にも、将来の拡張性を考えるとカテゴリビットを使っておくのが安心な気もします。

Learning Cocos2D: A Hands-On Guide to Building iOS Games with Cocos2D, Box2D, and ChipmunkLearning Cocos2D: A Hands-On Guide to Building iOS Games with Cocos2D, Box2D, and Chipmunk
(2011/07/07)
Rod Wenderlich, Ray Strougo

商品詳細を見る

PageTop

In App Purchase開発前に知っておきたかったこと

アプリ内課金を実装すべくIn App Purchaseを実装していたのですが、コードよりも機能理解のところで引っかかりました。例えば、どの段階で開発に入れるのか、どんな情報はアプリ側で用意しどんな情報はStore側で持つべきか、シミュレータと実機テストの違いは何か、などです。どうせ忘れるのでメモします。

今回作成した課金アイテムは、消費型(Consumable)と非消費型(Non-Consumable)をそれぞれ1つずつです。両方共アプリ内に最初から入れておき、フラグ管理する形にしています。

In App Purchase開発に必要な準備
まず、Appleに開発者登録してあることが必要です。Xcodeを落としただけでなく、すでに年会費も払ってアプリを挙げる権利を持っていることが必要です。

また、Appleと金銭授受契約を結んでいることが必要です。無料アプリ+課金だとしても、有料アプリを売るときに必要な契約を結ぶ必要があります。事前に他アプリで契約していれば特に問題ないです。

アプリ自体は完成している必要はありません。課金アイテムを登録するためには、該当アプリがiTunes Connectに登録されている必要がありますが、バイナリファイルを置く必要もなく、説明やスクリーンショットもとりあえず適当で構いません。それらはあとで修正しましょう。bundleIdは変えられないのできちんとしたものを書いておきましょう。アプリがPrepare for Upload状態になっていればよいです。

基本的には以上ですので、アプリの開発は全然進んでなくても問題ないわけですね。

課金アイテム自体の登録は難しくないです。iTunes ConnectのManage Your Applicationから該当アプリを選択し、Manage In-App Purchasesを選択すればOK。スクリーンショットをあげろと言われますが、あげなくてもテスト環境ではテストできます。

課金アイテムの値段はいつ取得するか
課金アイテムの値段情報はStoreから受け取って使うほうがよいです。課金アイテムはAppleの指定した値段のいずれかで売るわけですが、この値段はレートによって変わりますので、勝手にアプリ側に「85円」とか書いてしまうと後で困ります。逆にStoreから値段を受け取って表示していれば、Storeの値段を低くするだけで勝手に反映されるようになるので楽になります。

幾つかアプリを見てみたのですが、値段を購入処理の最終確認まで表示しないアプリが多いようです。購入ボタンを押す前から画面に値段を表示しているアプリも有るには有りましたが、オフラインで表示をみても値段が変わらないので、おそらくベタ書きしているのだと思います。

購入処理の最終確認は、プログラミングしなくても勝手に表示されます。「◯◯をXX円で購入しますか?」というポップアップが自動的に作成されるのです。ここは金銭単位も含めた言語対応をしてくれるので便利です(課金アイテムの名称(◯◯)だけは自分で登録しておく必要があります)。

結局、課金アイテムの値段はStoreに登録するだけで、アプリ側では使用しないことが多いようです。僕も値段表示は全て最終確認ダイアログだけにしてしまい、アプリ側では特になにもしていません(Storeから帰ってきたデータの中身を標準出力して確認するときだけSKProductのpriceを呼んでいます)。

同じ議論で、課金アイテム名称も特にアプリ側では使っていません。そのため、Storeへの問い合わせは購入ボタンをタップしてから初めて行うように実装しています。

シミュレータと実機テストの違い
いくつかの記事ではシミュレータではIn App Purchaseはテストできないとありましたが、普通にできます。iTunes Connectでテストユーザを登録した後、シミュレータで購入処理を走らせ、テストユーザのIDを打ち込むと普通に買えます。Restoreのテストもできます。

では、何がシミュレータでできないかというと、テストユーザの切り替えができないです。なんでできないんだろう……。面倒くさいです。

追記:シミュレータでもテストユーザ切り替えができました。「iOSシミュレータ>コンテンツと設定をリセット」でユーザ情報が消えるので再度別ユーザでログインできます。ただ、セーブデータも消えるので相変わらず面倒くさいと言えば面倒くさいです。

処理待ちを実装する
考慮から抜けがちなのですが、InAppPurchaseの処理は結構時間がかかります。その間にボタンをタップされまくると多重に処理が走って非常に面倒です。

そのため、一時的に画面を処理待ち状態にする必要があります。同時に、処理が終わったらそれを解除する必要があります。僕はInAppPurchaseの処理はSingletonにまとめているので、そのSingletonにdelegateを渡して、購入処理終了後(もしくは失敗後)に解除処理を呼び出すようにしています。

ややこしいことに画面の処理待ち解除が走らない可能性があります。処理待ち中に画面遷移できないように実装していても、アプリ自体を止められてしまった場合、アプリを再起動直後に処理が走るかもしれないのです。その場合、処理待ち解除の対象はnilかもしれません。

よって、処理待ち解除にはnil対応をいれることと、購入処理自体は処理待ち状態のクラスには持たせないことが重要です。

何をテストすべきか
この項目は意外と難しいです。In App Purchaseはアプリ内に留まらない処理になるため、テスト範囲が広くなります。たとえば、購入処理中に接続を切った場合にどう復旧させるかなどがテストに入ってきます。

困っていたのですが、Tech-GymさんのApp Storeのアプリ内課金のテストパターンが良い感じです。

僕は「ネットワークがないとき」の検出を忘れていました。これに関してはAppleのサンプルクラスのひとつReachabilityがいけています。バージョンが古いとretValがエラーになったりします。

Reachability *internetReach = [Reachability reachabilityForInternetConnection];
NetworkStatus netStatus = [internetReach currentReachabilityStatus];
if (netStatus == NotReachable) {
//接続できてない
} else {
//接続できてる
}

あとはリストア処理がないとリジェクトされるよ、ってのも大事ですね。リストアは非消費型を作ったので必要でした。リストア処理ボタンが必要なので、最初から考えてデザインしないといけないですね。

iPhone&Androidアプリ内課金プログラミング完全ガイド (Smart Mobile Developer)iPhone&Androidアプリ内課金プログラミング完全ガイド (Smart Mobile Developer)
(2012/11/16)
佐藤 航陽、加藤 勝也 他

商品詳細を見る

PageTop

意外と簡単だったiAdとAdmob設定(2) cocos2dで広告付きアプリ

前回はiAdをアプリに組み込みました。ただ、iAdは表示率が悪いという話も聞くので、iAdが表示されなかった場合にGoogleのやっているAdmobが表示されるようにします。

Admobの登録
公式サイトから「Admobに登録する」ボタンを押して、登録開始です。Googleアカウントでログインし、順次登録していきます。関係ないですが、公式サイトの動画カッコイイですね。

登録で引っかかるところは、必須項目に「州」があるところかと思いますが、ここは都道府県を追加すればOKです。表記の順番がちょっと変ですが、とりあえず他はあまり困らないかと。登録が終わるとメールが届きます。

続いて金銭授受方法を登録します。これはアプリを登録しようとしたりするとでてくる画面で行います。具体的には「サイト及びアプリケーション」タブで「サイト/アプリケーションの追加」ボタンを押すなどすると画面が現れます。授受方法としては、銀行取引とPaypalが選べます。

ここでPaypalを選びたいです。というのも銀行取引は取引手数料が2500円程度とられるからです。全然儲けにならない……。よってどんどん話が脇道にそれていきますが、paypalの登録をします。

Paypalは個人の場合プレミアで登録する必要があるのですが、最初パーソナルとビジネスの2つしか選択肢がありません(以前は最初からプレミアが選べたみたいですけど)。そこでパーソナルで登録してからプレミアにアップグレードする形になります。プレミアへのアップグレードには写真付き身分証明書をアップロードし、数日待つ必要があります。待っている間にAdmobにPaypalアカウントを登録しておきましょう。

admobにアプリの情報を適当に書き込んで登録します。サイト及びアプリケーションにアプリが表示されるようになるので、「設定を管理」を押して画面に出てくるパブリッシャーIDを見ておきます。

Admobの準備
Google Developersのサイトを元にSDKの準備をします。ここでは英語サイトを使います。現在日本語サイトの方法で行うとエラーが出ます。

Downloadsから最新のファイルをダウンロードしてきて、readmeとAdd-onsフォルダ以外をプロジェクトにaddします。Add-onsフォルダを追加すると、フォルダ内のGoogle Analyticsサンプルプロジェクトによってo-linker errorが出ます。

次に、前回と同様にSDKフレームワークを6つ追加します。日本語サイトだと4つになっている罠があるので注意して下さい。4つしかいれないと、ここでもo-linker errorが出ちゃいます。

Admobの実装
ビルドが通ったら実装開始です。といっても、前回同様、広告用のレイヤにおいてviewをaddしていくだけです。

まずはiAdを一度無視して、admobが表示できるようにしましょう。iAdとほぼ同じです。以下で.hと.m全文になります。読み込み部分だけをloadAdmobViewRequestという関数で切り出しました。loadAdmobViewRequest内ではテスト広告を表示する端末を指定出来ます。

//AdLayer.h
#import <Foundation/Foundation.h>
#import "cocos2d.h"
#import "GADBannerView.h"

@interface AdLayer : CCLayer<GADBannerViewDelegate>
+ (id)layer;
@end

//AdLayer.m
@implementation AdLayer{
    GADBannerView* _admobView;
}

+ (id)layer{
    return [[[self alloc] initLayer] autorelease];
}

- (id)initLayer {
    if (self = [super init]) {
        _admobView = [[GADBannerView alloc] initWithAdSize:kGADAdSizeBanner];
        _admobView.adUnitID = @"ここに上述したパブリッシャーID";
        _admobView.rootViewController = [[[UIApplication sharedApplication] keyWindow] rootViewController];
        [[[CCDirector sharedDirector] view] addSubview:_admobView];
        _admobView.delegate = self;
        [self loadAdmobViewRequest];
    }
    return self;
}

- (void)dealloc{
    _admobView.delegate = nil;
    [_admobView removeFromSuperview];
    [_admobView release];
    [super dealloc];
}

- (void)loadAdmobViewRequest {
    GADRequest *request = [GADRequest request];
    //以下の端末ではテスト広告をリクエスト
    request.testDevices = [NSArray arrayWithObjects:
                            GAD_SIMULATOR_ID,// シミュレータ
                            nil];
    [_admobView loadRequest:request];
}

これだけで広告が表示されています。簡単。もっと色々やりたければ、顧客情報を取得して適した広告を表示するようにすることもできるみたいです。

iAdとAdmobを組み合わせる
最後にiAdが取得できなかったときにadmobを表示するようにしましょう。といっても単純で、loadAdmobViewRequestをinitから外して、前回作成したbannerView:(ADBannerView *)banner didFailToReceiveAdWithError:(NSError *)errorに入れるだけです。

//iAd広告取得失敗時の処理
- (void)bannerView:(ADBannerView *)banner didFailToReceiveAdWithError:(NSError *)error{
    CCLOG(@"iAd load is failed and try to get Admob ads");
    [self loadAdmobViewRequest];
}

どうやってiAdのロード失敗をテストしようかな、と思っていたのですが、やってみると結構失敗するので、普通に何回かみているときちんと動作していることがわかります。

更にadmobもコケた時用に、自社広告を表示するようにしようと思っています。オフラインのときとかね。GADBannerViewDelegateの- (void)adView:(GADBannerView *)bannerView didFailToReceiveAdWithError:(GADRequestError *)error を上記の呼び出しと同様に使えばOKでしょう。

PageTop

意外と簡単だったiAdとAdmob設定 cocos2dで広告付きアプリ

cocos2dで作った二個目のiPhoneアプリも出来上がってきたので、広告をいれてみようと思います。

色々と検討した結果、iAdとAdmobの併用というよくありそうな結論に至りました。当アプリは海外向けも視野にいれてやってみたいのと、柔らかい雰囲気のアプリなのでアダルトが入る可能性は極力排除したいと考えたのが大きな理由です。SSPも幾つか見てみたのですが、あまり惹かれませんでした……。

なお、最初に迷ったので一応書いておきますが、広告部分の開発はアプリのレビュー申請前でも問題なく出来ます。

初広告 iAdの導入
まずSDKを入れます。Xcode4.5.2だと、プロジェクト名が書いてある部分(target)をクリックして、Summaryタブを選択、iPhoneの向き設定などの下にあるLinked Frameworks and Librariesで追加します。+を押して、iAd Frameworkを追加。

次に広告レイヤを作成します。シーンによって広告の出現可否や位置を変えたいため、レイヤとして作ってしまいます。AdLayerをCCLayerを継承して作成。

AdLayerのinitにiAdの呼び出しを記述します。ADBannerViewを作って、viewにaddするのみです。下のように作ったlayerをsceneにaddしてみると、もう動きます。おぉ、意外と簡単だ!

//AdLayer.h
#import
#import "cocos2d.h"
#import "iAd/iAd.h"

@interface AdLayer : CCLayer
+ (id)layer;
@end

//AdLayer.m
#import "AdLayer.h"
@implementation AdLayer{
  ADBannerView* _adView;
}

+ (id)layer{
  return [[[self alloc] initLayer] autorelease];
}

- (id)initLayer {
 if (self = [super init]) {
  _adView = [[ADBannerView alloc] initWithFrame:CGRectZero];
  _adView.currentContentSizeIdentifier = ADBannerContentSizeIdentifierPortrait;
  [[[CCDirector sharedDirector] view] addSubview:_adView];
 }
 return self;
}

- (void)dealloc{
 [_adView removeFromSuperview];
 [_adView release];
 [super dealloc];
}
@end


追記:iOS4.2以降からADBannerContentSizeIdentifier320x50は非推奨なようです。ADBannerContentSizeIdentifierPortraitに修正しました。armv6関係でiOS4.3以降に絞る人も多いと思うので。

とりあえず上ので動きますが、広告取れなかったときの処理なども追加してみましょう。具体的には、adViewのdelegateをAdLayerにしてやって、AdLayerに処理を書いてやることになります。そのため、AdLayerにADBannerViewDelegateプロトコルを設定します。

//AdLayer.h
@interface AdLayer : CCLayer

//AdLayer.m
- (id)initLayer{
 ......
 _adView.delegate = self;
 _adView.alpha = 0;//loadされるまで消しておく
}

//広告取得成功時の処理
- (void)bannerViewDidLoadAd:(ADBannerView *)banner{
 _adView.alpha = 1;
}

//広告取得失敗時の処理
- (void)bannerView:(ADBannerView *)banner didFailToReceiveAdWithError:(NSError *)error{

}

ロードまで遅いのが気になります。最初は画面外に出しておいて、bannerViewDidLoadAdで画面内に移動するように書くことも多いみたいですね。

あとはレビュー申請したときに、広告の設定を忘れないように。

iAdが動かなかった時用、Admobの登録
iAd取得失敗時にはAdmobの広告を呼び出すようにします。Admobは開発時でも広告が流れるとかで楽しみ。iAdはAppleの作ったバナーが流れるだけなので。

まずSDK。と思ったら、その前にアプリの説明を登録しなきゃいけないのね。

長くなってきたのでまた次回。

PageTop
上記広告は1ヶ月以上更新のないブログに表示されています。新しい記事を書くことで広告を消せます。