Libgdxのカジュアルゲーム、開発の微妙な瞬間

この記事は、初心者と経験豊富な開発者の両方に役立ちます。 それはゲーム開発の基本的なポイントをカバーしており、解決しなければならなかった問題は重要です。 興味があるなら、猫の下でお願いします。 また、libdgxの開発者は、記事の最後にあるリンクが役立つと思うでしょう。



開発がほぼ1年間続いた複雑なゲームにうんざりして、野心的ではなく、シンプルで、ベータ版を超えるものを書くことにしました。 リリース、タッチマーケティング、さらにはもちろん、タイムキラーのビジョンでユーザーを喜ばせることを超えたものを見たかったのです。



彼らは、ブレインストーミングを配置することでゲームのコンセプトを発明し、約20のアイデアを生成し、最良のアイデアを選択し、許容可能なオプションに開発しました。



ゲームデザインについて少し説明しますが、開発の微妙なポイントを理解しやすくなります。



ユーザーに負担をかけず、ゲームを少しリラックスさせるのに役立つ面白い設定のタイムキラーを作成したかったのです。 ゲームの最初のバージョンでは、それはビームの間を飛んだ単なるボールであり、加速度計によって制御されていました。 ゲームの特徴の1つは、ゲームの複雑さが1分に増加することであり、それはすべて器用さに依存します。



光を見た最初のバージョン








その結果、ユーザーと話し、複数のベータテストを実施した後、さまざまなヒーロー、ゲームボーナス、実績、および記録をゲームに追加しました。



人としてのヒーローはかなり興味深いステップであり、紫色のボールの代わりにヘルメットの不機嫌なモンスターが飛び始め、魂のようなものが現れたとき、ゲームに対する人々の態度も大きく変わりました。



今日のゲームの様子








Gradleおよびlibgdx。



libgdxのプロジェクトのビルドシステムは非常にうれしい驚きでした。 バージョン1.0から、uiユーティリティを使用してプロジェクトを作成するときに、必要なプラットフォームのプロジェクトを収集するgradleスクリプトも作成されます。 これは初心者の開発者にとって非常に便利です。 誰もがIdeaからiOSプロジェクトをビルドし、エミュレーターまたはデバイスで実行する方法をゼロから学びたいとは思わないでしょう。 標準ツールを使用して、これはワンクリックで行われます。



gradleがあなたのためにすることの小さな例。 このメソッドは、ライブラリをnatives-ios.jarから* .aに解凍し、build / libs / iosに配置します。



task copyNatives << { file("build/libs/ios/").mkdirs(); configurations.natives.files.each { jar -> def outputDir = null if (jar.name.endsWith("natives-ios.jar")) outputDir = file("build/libs/ios") if (outputDir != null) { copy { from zipTree(jar) into outputDir include "*.a" } } } }
      
      







アトラスを使用する



これは、グラフィックスの最適化に関しては、ゲーム開発に関するすべての本に書かれています。



テクスチャアトラスを使用する利点。



私たち自身のために、 GUI拡張gdx-texturepacker-guiを見つけました。 原則として、苦情はありませんが、私が知る限り、それのサポートと開発は2012年末に終了しました。



シーンのシングルトン



すべてのチュートリアルで説明されているlibgdxを使用する場合の標準的なアプローチは、新しい画面用に新しい画面を作成することです。

habrahabr.ru/post/224175

github.com/libgdx/libgdx/wiki/Extending-the-simple-game



  game.setScreen(new GameScreen(game));
      
      





すべてがうまくいき、新しいゲームは以前のゲーム、新しい人生、新しい画面に依存しません。

しかし、死後の再生の機能と「やり直し」の論理を実現したとき、すべてがそれほど楽しいわけではないことに気付きました。 プロセスは次のようになります。新しいゲーム->再生->再生->やり直し->再生->やり直し。



ここでメモリの問題が始まり、GCがオンになりました。時には、一部のオブジェクトが既に終了した画面を参照しているという事実に遭遇しました。



問題を解決する必要がありました。



ここでは、 シングルトーンが助けになります。各画面のオブジェクトは1つだけ必要です。ゲームとゲーマーの複数の画面を作成する必要はありません。それらの状態を簡単に制御できます。



他のスクリーンショットと同様に、入力するたびに新しいストア画面を作成する必要はなく、一度だけ実行します。



同一のオブジェクトのプール



知っている人はこのセクションを飛ばしてもかまいませんが、ゲームの開発を始めたばかりのとき、プールについて以前に話されていたらとてもうれしかったです。 詳細はこちら

私たちの旧友GCが、うらやましい頻度で0.2〜0.4秒間ゲームをハングさせると誰が思ったでしょう。



ゲームを作成するための主なルールの1つは、アーキテクチャを構築し、すべてのオブジェクトが再利用可能で、GCが呼び出されないようにコードを記述することです(できれば決してしない)



たとえば、私たちの場合、これらは再利用可能なブロック、コイン、パーティクルを少量で一度だけ作成し、ブロックの場合は25個で、キューに入れ、必要に応じてオブジェクトが消えた/崩壊したときに使用し、次の使用までキューに戻します。



プールの実装
  public class MultiPool<T> { private final List<Pool<T>> mPools = new ArrayList<>(); public void registerPool(final int pID, final Pool<T> pPool) { this.mPools.add(pID, pPool); } public T obtainPoolItem(final int pID, float x, float y, int type) { final Pool<T> pool = this.mPools.get(pID); if (pool == null) { return null; } else { return pool.newObject(x, y, type); } } public void recyclePoolItem(final int pID, final T pItem) { final Pool<T> pool = this.mPools.get(pID); if (pool != null) { pool.free(pItem); } } } public class Pool<T> { public interface PoolObjectFactory<T> { public T createObject(float x, float y, int type); } private final Array<T> freeObjects; private final PoolObjectFactory<T> factory; private final int maxSize; public Pool(PoolObjectFactory<T> factory, int maxSize) { this.factory = factory; this.maxSize = maxSize; this.freeObjects = new Array<T>(false, maxSize); } public T newObject(float x, float y, int type) { T object = null; if (freeObjects.size == 0) { object = factory.createObject(x, y, type); } else { object = freeObjects.pop(); } return object; } public void free(T object) { if (freeObjects.size < maxSize) { freeObjects.add(object); } } }
      
      







プールを使用したオブジェクトの最適化は、ゲームで実行できる最も重要なものの1つです。 さまざまな変更で、これはアプリケーションでも使用されますが、そこでは少し簡単です。 アプリケーションが多かれ少なかれパッシブモードで使用されている場合、ユーザーはGCの動作に気付かないことさえあります。



PS 1nt3g3rからの有用なコメント



LibGDXにはプール(プール)用の独自の便利なクラスがあり、プールのプール(プール)があります。 最終的に、作業は次のように要約されます。



モンスターm = Pools.obtain(Monster.class); //プールからオブジェクトを取得します。 必要なオブジェクトのクラスを示すだけです。

... //オブジェクトを使用しました

Pools.free(m); //オブジェクトをプールに返しました



ストリーム:難易度の高いプレイ



この種のゲームを開発する際の主なポイントの1つは、誤用に対する保護です。このケースでは、携帯電話を揺るがすことでした。 この問題は、X軸に沿って最大速度を制限することで解決しました;ユーザーがどれだけ電話を振っても、速く飛ぶことはありません。



ゲームの速度自体を設定するには、非常に多くのテストが必要でした。なぜなら、 カメラの加速、xのヒーローの加速、yのヒーローの加速の3つのインジケーターのバランスをとる必要がありました。 数学的に、境界条件を計算しました-それらの速度は、その後ゲームが非現実的で無意味になり、すべてのデータが実験的に選択されました。 ヒーローの加速ロジックを何度か書き直しました。 多くの人がゲームの複雑さと進行状況のグラフを見たと思います。



進行状況からのゲームの複雑さのグラフ








一般的に、彼はゲームの複雑さがどのように成長する必要があるかを説明します。 「レベルはありません。これを行う必要はありません。速度を滑らかに上げながら線形関係を作ります。」 完了したら、次の質問はどのように速度を迅速に上げるかであることに気付きました。



ゲームが最初の数秒から難しい場合、人々は快適になる時間を持っていません。 最初のバージョンでは、何をすべきかをすぐに理解していなければ、人は開始後10秒以内に死亡する可能性がありました。



バーを上げて、ゲームは10秒まで非常に落ち着き、再びペースが上がりました。 プレイするのが難しすぎて非現実的であるというレビューをまだ聞きましたが、ハードコアのレベルを約20%下げることをお勧めしました。



繰り返しますが、彼らは複雑に遊び、別の実験を行いました。 最初の20〜30秒間、人々は幸せでしたが、驚いたことに、誰もが同じことについて言いました。 ゆっくり加速します。 すでに死んでいたはずです。」

最終的に、古典的な複雑さの図に到達しました。このバージョンでは、複雑さが無限に大きくなることはないため、少し変更されました。



ゲームの複雑さの進行への依存








適切なプラットフォーム配置アルゴリズムを選択することも非常に重要でした。 この場合、アルゴリズムは次のとおりです。 合計で、5つのプラットフォームが1行に収まり、最初のプラットフォームが作成され、次のプラットフォームごとにこの割合が減少する確率は80%になります。 行全体がプラットフォームで構築されないように、生成されたプラットフォームの数をカウントする必要があります。4がすでにインストールされている場合は、5番目を設定しないでください。 また、前の行の通路の位置を保存します。これは、プレイヤーが収集しなければならないコインのトラックを構築するために必要です。



Libgdxおよび2Dグラフィックス。



Libgdx開発者は、インターフェースを作成するための非常に便利なシステムがあると書いています。 libgdxで作業したことがある人の多くは、それがどれほど難しいか、長いことを知っていると思います。

github.com/libgdx/libgdx/wiki/Scene2d.ui

はい、彼らは作業を容易にするためのクラスのセットを持っています、レイアウトがあり、ウィジェットがありますが、画面上のそれらの簡単な配置です-それは膨大な作業でした。



私が間違っている場合、正しいことを学びますが、すぐに便利なプロトタイピングとGUIを作成する手段が見つかりませんでした。 最近、彼らが再びデザインの変更、ボタンの移動、画面間のトランジションの描画を始めたとき、私はもうこれができないことに気付きました。 ビルダーのインターフェースの検索が開始されました。記事までさかのぼると、GUIを作成するためにJavaでデスクトップアプリケーションを作成する人がいるという事実に出くわしました。



その結果、githubで非常に興味深いソリューションを見つけました。 Cocos2d-xフレームワークには、インターフェイスを作成するための独自のスタジオがあり、しかも奇跡だということがわかりました。 -以前のバージョンは、エクスポート形式としてjsonを使用します。

中国のある職人がすでにこのスタジオのパーサーを書いています。 作業の本質は非常に簡単です。jsonを取得し、オブジェクトにシリアル化し、Scene2dを使用してこれらのオブジェクトを使用してGUIを作成します。



このバージョンは、OSXバージョンだけでなく、後のバージョンのcocostudioとの互換性を保つために、少し名前を付けました。



現在サポートされているCocostudioバージョン:



v1.0.0.0 Beta for Mac

Windows用v1.5.0.1ベータ



私は貢献者に喜んでいます。ライブラリにはたくさんの開発が必要です(ココナッツはすでにバージョン2+に切り替えています)。これらのツールの良好な互換性を達成したいと思っています。



彼らはこのプラットフォームで実行することを決めたので、アンドロイドですべてを収集したことに注意したいと思います。 iOSでは、ビルドもうまくいきます。 幸いなことに、gradleビルドはすでに作成されています。 iOSの唯一の問題は、ゲームに近いすべてのサービスをrobovmに書き換える必要があることです。



最後まで読んでくれた人に感謝します。 コメントでご質問にお答えできることを嬉しく思います。 約束どおり、リソースへのリンク。



Coco-libgdx-gui: github.com/xPutnikx/cocostudio-ui-libgdx/tree/kotlin

テクスチャパッカー: code.google.com/p/libgdx-texturepacker-gui



All Articles