iOSゲームの開発は、個人的な面と個人的な面の両方の点で豊かな体験になる可能性があります 金融 成長。今年の初めに、Cocos2Dベースのゲームを展開しました。 ビーレース 、AppStoreへ。そのゲームプレイはシンプルです。プレイヤー(この場合はミツバチ)がポイントを集めて障害物を回避する無限のランナーです。見る ここに デモ用。
このチュートリアルでは、Cocos2Dから公開まで、iOS向けのゲーム開発の背後にあるプロセスについて説明します。参考までに、短い目次を次に示します。
ざらざらした詳細に入る前に、両者の違いを理解しておくと役に立ちます。 スプライト と物理的なオブジェクト。
エンドレスランナーゲームの画面に表示される特定のエンティティの場合、そのエンティティのグラフィック表現は、 スプライト 、物理エンジンでのそのエンティティのポリゴン表現は、 物理的なオブジェクト 。
そのため、スプライトは画面上に描画され、対応する物理オブジェクトに支えられて、物理エンジンによって処理されます。その設定はここで視覚化できます。ここでは、スプライトが画面に表示され、物理的なポリゴンの対応物が緑色で囲まれています。
デフォルトでは、物理オブジェクトはそれぞれのスプライトに接続されていません。つまり、 iOS開発者 使用する物理エンジンと、スプライトとボディの接続方法を選択できます。最も一般的な方法は、デフォルトのスプライトをサブクラス化し、それに具体的な物理ボディを追加することです。
それを念頭に置いて…
Cocos2D-iphone はiOS用のオープンソースフレームワークであり、ハードウェアグラフィックスアクセラレーションにOpenGLを使用し、 シマリス そして Box2D 物理エンジン。
まず第一に、なぜそのようなフレームワークが必要なのですか?まず、フレームワークは、ゲーム開発でよく使用されるコンポーネントを実装します。たとえば、Cocos2Dはスプライトをロードできます(特に、 スプライトシート (( どうして? ))、物理エンジンを起動または停止し、タイミングとアニメーションを適切に処理します。そして、これはすべて、広範囲にわたってレビューおよびテストされたコードで行われます。なぜ、劣る可能性のあるコードの書き直しに時間を費やすのでしょうか。
しかし、おそらく最も重要なのは— Cocos2Dゲーム開発はグラフィックハードウェアアクセラレーションを使用しています 。このような加速がないと、スプライトの数が中程度のiOS無限ランナーゲームは、パフォーマンスが著しく低下します。より複雑なアプリケーションを作成しようとすると、画面に「バレットタイム」効果が表示されるようになります。つまり、アニメーション化しようとするときに、各スプライトの複数のコピーが表示されます。
近接性のゲシュタルト原理は傾向です
最後に、Cocos2Dはそれ以来メモリ使用量を最適化します スプライトをキャッシュします 。したがって、複製されたスプライトは最小限の追加メモリを必要とし、これは明らかにゲームに役立ちます。
私がCocos2Dでラップしたすべての賞賛の後、それは非論理的に見えるかもしれません ストーリーボードの使用を提案する 。 Cocos2Dなどでオブジェクトを操作してみませんか?正直なところ、静的ウィンドウの場合、XcodeのInterfaceBuilderとそのストーリーボードメカニズムを使用する方が便利なことがよくあります。
まず、マウスを使用して、エンドレスランナーゲームのすべてのグラフィック要素をドラッグして配置できます。次に、StoryboardAPIは非常に便利です。 (そして、はい、私は知っています ココスビルダー )。
これが私のストーリーボードの概要です。
ゲームのメインビューコントローラーには、いくつかのHUD要素が上にあるCocos2Dシーンが含まれています。
白い背景に注意してください。これはCocos2Dシーンであり、実行時に必要なすべてのグラフィック要素をロードします。その他のビュー(ライブインジケーター、タンポポ、ボタンなど)はすべて標準のCocoaビューであり、InterfaceBuilderを使用して画面に追加されます。
詳細については詳しく説明しません。興味がある場合は、GitHubで例を見つけることができます。
(もう少しモチベーションを高めるために、私のエンドレスランナーゲームについてもう少し詳しく説明したいと思います。技術的な議論に進みたい場合は、このセクションをスキップしてください。)
ライブゲームプレイ中、ミツバチは動かず、フィールド自体が実際に駆け寄り、さまざまな危険(クモと有毒な花)と特典(タンポポとその種子)をもたらします。
Cocos2Dには、キャラクターを追跡するように設計されたカメラオブジェクトがあります。実際には、ゲームの世界を含むCCLayerを操作することはそれほど複雑ではありませんでした。
コントロールはシンプルです。画面をタップすると蜂が上に移動し、もう一度タップすると蜂が下に移動します。
ワールドレイヤー自体には、実際には2つのサブレイヤーがあります。ゲームが開始されると、最初のサブレイヤーが0からBUF_LENまで入力され、最初に表示されます。 2番目のサブレイヤーは、BUF_LENから2 * BUF_LENに事前に入力されています。ミツバチがBUF_LENに到達すると、最初のサブレイヤーがクリーンアップされ、2 * BUF_LENから3 * BUF_LENに即座に再入力され、2番目のサブレイヤーが表示されます。このようにして、メモリリークを回避するための重要な部分である、廃止されたオブジェクトを保持せずに、レイヤーを交互に切り替えます。
物理エンジンに関しては、2つの理由でChipmunkを使用しました。
物理エンジンは、実際には衝突検出にのみ使用されていました。時々、「なぜあなたはあなた自身の衝突検出を書かなかったのですか?」と尋ねられます。実際には、それはあまり意味がありません。物理エンジンはまさにその目的のために設計されました。複雑な形状の物体間の衝突を検出し、そのプロセスを最適化することができます。たとえば、物理エンジンは多くの場合、世界をセルに分割し、同じセルまたは隣接するセル内のボディに対してのみ衝突チェックを実行します。
インディーズインフィニットランナーゲーム開発の重要な要素は、小さな問題に遭遇しないようにすることです。時間はアプリを開発する際の重要なリソースであり、自動化は信じられないほど時間を節約できます。
しかし、場合によっては、自動化が完璧主義と期限の遵守の間の妥協点になることもあります。この意味で、完璧主義はアングリーバードのキラーになる可能性があります。
たとえば、現在開発中の別のiOSゲームでは、特別なツールを使用してレイアウトを作成するためのフレームワークを構築しました( GitHub )。このフレームワークには制限があります(たとえば、シーン間の適切な遷移がありません)が、これを使用すると、10分の1の時間でシーンを作成できます。
したがって、特別なスーパーツールを使用して独自のスーパーフレームワークを構築することはできませんが、これらの小さなタスクをできるだけ多く自動化することはできますし、そうする必要があります。
完璧主義はアングリーバードのキラーになる可能性があります。時間はiOSゲーム開発の重要なリソースです。 つぶやきこの無限のランナーを構築する上で、自動化が再び重要でした。たとえば、私のアーティストは、特別なDropboxフォルダーを介して高解像度のグラフィックを送ってくれます。時間を節約するために、App Storeで必要なさまざまなターゲット解像度のファイルセットを自動的にビルドするスクリプトをいくつか作成し、-hdまたは@ 2xも追加しました(上記のスクリプトは ImageMagick )。
追加のツールに関して、私は見つけました TexturePacker 非常に便利です。スプライトをスプライトシートにパックできるため、すべてのスプライトが1つのファイルから読み取られるため、アプリのメモリ消費量が少なくなり、読み込みが速くなります。また、ほぼすべての可能なフレームワーク形式でテクスチャをエクスポートできます。 (TexturePackerは無料のツールではありませんが、価格に見合う価値があると思います。次のような無料の代替ツールを確認することもできます。 ShoeBox 。)
ゲームの物理学に関連する主な問題は、各スプライトに適したポリゴンを作成することです。言い換えれば、不明瞭な形の蜂や花の多角形の表現を作成します。手作業でこれを実行しようとしないでください。常に多くの特殊なアプリケーションを使用してください。 Inkspaceでベクターマスクを作成し、それをゲームにインポートするなど、非常にエキゾチックなものもあります。
私自身の無限のランナーゲーム開発のために、このプロセスを自動化するツールを作成しました(を参照) ここに 適切な使用法のために)、私はこれを呼び出します AndengineVertexヘルパー 。名前が示すように、それは当初のために設計されました Andengineフレームワーク 、最近では多くのフォーマットで適切に機能しますが。
この場合、plistパターンを使用する必要があります。
%.5f%.5f
次に、オブジェクトの説明を含むplistファイルを作成します。
jet_ant vertices -0.182620.08277 -0.14786-0.22326 0.20242-0.55282 0.470470.41234 0.038230.41234
そしてオブジェクトローダー:
- (void)createBodyAtLocation:(CGPoint)location{ float mass = 1.0; body = cpBodyNew(mass, cpMomentForBox(mass, self.sprite.contentSize.width*self.sprite.scale, self.sprite.contentSize.height*self.sprite.scale)); body->p = location; cpSpaceAddBody(space, body); NSString *path =[[NSBundle mainBundle] pathForResource:@'obj _descriptions' ofType:@'plist']; // e = 0.7; shape->u = 1.0; shape->collision_type = OBJ_COLLISION_TYPE; cpSpaceAddShape(space, shape); }
スプライトが物理的なボディにどのように対応するかをテストするには、を参照してください。 ここに 。
はるかに良いですよね?
要約すると、可能な場合は常に自動化します。単純なスクリプトでも、時間を大幅に節約できます。そして重要なことに、その時間はマウスクリックの代わりにプログラミングに使用できます。 (さらなる動機付けのために、ここに トークンXKCD 。)
ゲームで収集されたブローボールはアプリ内通貨として機能し、ユーザーが蜂の新しいスキンを購入できるようにします。ただし、この通貨はリアルマネーで購入することもできます。アプリ内課金に関して注意すべき重要な点は、購入の有効性についてサーバー側のチェックを実行する必要があるかどうかです。購入可能な商品はすべて、ゲームプレイの点で基本的に同じであるため(蜂の外観を変更するだけ)、購入の有効性についてサーバーチェックを実行する必要はありません。ただし、多くの場合、必ずそうする必要があります。
詳細については、レイ・ヴェンダーリッヒは完璧です アプリ内課金チュートリアル 。
cまたはs法人の違い
モバイルゲームでは、 付き合い Facebookの「いいね」ボタンを追加したり、リーダーボードを設定したりするだけではありません。ゲームをよりエキサイティングにするために、マルチプレイヤーバージョンを実装しました。
それはどのように機能しますか?まず、iOS GameCenterのリアルタイムのマッチメイキングを使用して2人のプレーヤーが接続されます。プレイヤーは実際に同じ無限ランナーゲームをプレイしているので、ゲームオブジェクトのセットは1つだけで十分です。つまり、1人のプレーヤーのインスタンスがオブジェクトを生成している必要があり、他のプレイのインスタンスがそれらを読み取ります。つまり、両方のプレーヤーのデバイスがゲームオブジェクトを生成している場合、エクスペリエンスを同期させるのは困難です。
そのことを念頭に置いて、接続が確立された後、両方のプレーヤーはお互いに乱数を送信します。数字の大きいプレイヤーが「サーバー」として機能し、ゲームオブジェクトを作成します。
分割された世界世代の議論を覚えていますか? 2つのサブレイヤーがありました。1つは0からBUF_LENまで、もう1つはBUF_LENから2 * BUF_LENまでですか?このアーキテクチャは偶然に使用されたものではありません。遅延したネットワーク上でスムーズなグラフィックスを提供する必要がありました。オブジェクトの一部が生成されると、それはplistにパックされ、他のプレーヤーに送信されます。バッファは、ネットワークの遅延があっても2番目のプレーヤーがプレイできるように十分な大きさです。両方のプレーヤーは、0.5秒の間隔でお互いに現在の位置を送信し、またすぐに上下の動きを送信します。エクスペリエンスをスムーズにするために、位置と速度はスムーズなアニメーションで0.5秒ごとに修正されるため、実際には、他のプレーヤーが徐々に動いたり加速したりしているように見えます。
マルチプレイヤーのエンドレスランニングゲームプレイに関しては、確かにさらに多くの考慮事項がありますが、これにより、関連する課題の種類を理解できるようになることを願っています。
ゲームは決して終わらない。確かに、私が自分自身を改善したいいくつかの分野があります。
ワールドレイヤーは、CCMoveByアクションを使用して移動されます。 CCMoveByアクションがCCRepeatForeverで循環されたため、ワールドレイヤーの速度が一定の場合、これは問題ありませんでした。
-(void) infiniteMove{ id actionBy = [CCMoveBy actionWithDuration: BUFFER_DURATION position: ccp(-BUFFER_LENGTH, 0)]; id actionCallFunc = [CCCallFunc actionWithTarget:self selector:@selector(requestFillingNextBuffer)]; id actionSequence = [CCSequence actions: actionBy, actionCallFunc, nil]; id repeateForever = [CCRepeatForever actionWithAction:actionSequence]; [self.bufferContainer runAction:repeateForever]; }
しかし後で、ゲームが進むにつれてゲームを難しくするために、ワールド速度の増加を追加しました。
-(void) infiniteMoveWithAccel { float duration = BUFFER_DURATION-BUFFER_ACCEL*self.lastBufferNumber; duration = max(duration, MIN_BUFFER_DURATION); id actionBy = [CCMoveBy actionWithDuration: duration position: ccp(-BUFFER_LENGTH, 0)]; id restartMove = [CCCallFunc actionWithTarget:self selector:@selector(infiniteMoveWithAccel)]; id fillBuffer = [CCCallFunc actionWithTarget:self selector:@selector(requestFillingNextBuffer)]; id actionSequence = [CCSequence actions: actionBy, restartMove, fillBuffer, nil]; [self.bufferContainer runAction:actionSequence]; }
この変更により、アクションを再開するたびにアニメーションがボロボロになりました。私は問題を修正しようとしましたが、役に立ちませんでした。ただし、ベータテスターは動作に気づかなかったため、修正を延期しました。
独自のインディー無限ランナーゲームを作成することは素晴らしい経験になる可能性があります。そして、プロセスの公開ステップに到達すると、自分の作品を公開するのは素晴らしい気分になります。
レビュープロセスは、数日から数週間の範囲である可能性があります。詳細については、役立つサイトがあります ここに クラウドソーシングされたデータを使用して、現在のレビュー時間を推定します。
さらに、私は使用することをお勧めします AppAnnie App Store内のすべてのアプリケーションに関するさまざまな情報を調べたり、次のような分析サービスに登録したりします。 Flurry Analytics 役立つこともあります。
そして、このゲームがあなたに興味をそそられたなら、必ずチェックしてください ビーレース お店で。