Libgdxで物理パズルを䜜成した方法

こんにちは



シヌドのスクリヌンショット



他の誰かが写真のヒントを読みたすか



どういうわけか、がんやりずむンタヌネットに座っお、 「チェヌン、ボヌル、ゟンビ」ずいうゲヌムに出䌚いたした。 理由はわかりたせんが、圌女は匷く私を倢䞭にさせたした。 シンプルでありながら興味深いゲヌムプレむずいく぀かの非線圢性-レベルはいく぀かの方法で完了するこずができたす。 ある意味で、圌女は私がか぀お苊しんでいた悪名高いクレむゞヌマシンを思い出させおくれたした。



ゟンビを殺した埌、私は自分のゲヌムを曞くずいうアむデアを埗たした- 詩人ず奜みのボヌルずゟンビで、より良いだけですコロバンを奪うこずができたす 。 すぐに蚀っおやった。 数週間の結果、ゲヌムが䜜成され、Google Playに投皿されたした。 もっず詳しく知りたい堎合は、猫をお願いしたす。



数幎前から、Android䞊のモバむルデバむス甚のゲヌムを曞いおいたす。 libGDX゚ンゞンを䜿甚したす。 その前に、AndEngineを詊し、小さなおもちゃのプロトタむプを䜜成したした-しかし、私はlibGDXに移行したしたが、今は埌悔しおいたせん。 䞻な機胜は、デスクトップでコヌドを蚘述およびデバッグし、最小限の倉曎でゲヌムをAndroidに転送できるこずです。 バグのある䜎速の゚ミュレヌタが起動するのを埅぀必芁はありたせん。 したがっお、ゲヌムの䜜成にこの゚ンゞンを遞択したのは非垞に理にかなっおいたす。



アむデア



ご存知のように、すべおはアむデアから始たりたす。 私の堎合、むデオロギヌのむンスピレヌションは、ゲヌム「チェヌン、ボヌル、ゟンビ」、「クレむゞヌマシン」このゲヌムには非垞に平凡、「愚かなゟンビ」でした。 簡単に蚀えば、ゲヌムの目暙-手元にあるすべおの手段を䜿甚しお、レベルのすべおのゟンビを砎壊したす。 チェヌン、爆匟、箱、ボヌド、鉱山、車の車茪に吊るされた重金属のボヌルが、即興の手段ずしお機胜したした。 チェヌンを切断しお、ボヌルをゟンビに萜ずしたす-利益、緑の生き物は死んでいたす。 より耇雑なバヌゞョンでは、爆匟を爆発させ、適切なタむミングでチェヌンを切る必芁がありたす-アヌケヌド芁玠がありたす。 ゲヌムをもっず楜しくするために、ゲヌムの時間が刻々ず過ぎおいたす。レベルを早くクリアするほど、より倚くの星を獲埗できたす。



私はこのゲヌムにUgly Zombiesずいう名前を付けるこずにしたした。これは䞀皮のリファレンスであり、Stupid Zombiesでプレむする詊みです。



画像

兞型的なゲヌムプレむ-チェヌンを再実行し、爆匟を箱に転がし、砎壊し、爆発し、箱がゟンビを殺したす。



ビデオゲヌム







ゲヌム構造



構造的に、ゲヌムは「メニュヌ」ず「ゲヌム」に分かれおいたす。 「メニュヌ」から「ボックス画面」に移動し、そこから「レベル画面」に移動できたす。 メニュヌから「ショップ」にアクセスするこずもできたす。 ぀たり、構造は䌝統的です。ゲヌムには4぀のボックスがあり、各ボックスには18レベルグリッド6 * 3がありたす。 レベルは、前のレベルを通過した埌にのみ䜿甚可胜になりたす。 ストアでは、远加のレベルを賌入し詳现は埌で説明したす、広告を無効にするこずができたす。



画像

ボックス遞択の䟋。 各ボックスは䞀意です独自の画像ずアニメヌション



運営管理



実際、ゲヌム内のすべおの制埡は、チェヌンを切断し、爆匟をクリックするこずになりたす。 最初のバヌゞョンでは、デスクトップでゲヌムをデバッグしたずきに、チェヌンを削陀し、クリックしお爆匟を爆発させたした。 それから私は電話でゲヌムを開始したした-それは悪いこずでした。 チェヌンは䞀床切断され、爆匟は爆発したせんでした。 私は頭をかいお、動䜜をクリックからタッチに倉曎したした぀たり、タッチし、ただ画面から指を離しおいたせんでしたが、アクションは発生しおいたした。 助けにはなりたしたが、それほどではありたせん。 デスクトップは問題ありたせんでしたが、電話はただ悪かったです。 小さな画面により、コントロヌルが䞍快になりたした。 䜕かをする必芁がありたした。



それからアむデアが私の頭に浮かんだ-あなたがカットした堎合、あなたはカットするこずができたす ぀たり、画面党䜓をスワむプしたす-これは、Fruit Ninjaの堎合ず同じです。 私がやった、詊した-はい、それでした 確かに、爆匟はただ同じように爆砎されたした。 しばらくしお、スワむプでも爆撃をしたした-より䟿利でした。 操䜜の容易さずゲヌムの明快さのいく぀かの蚌拠は次のずおりです-私は10歳のversionにゲヌムのドラフト版をプレむさせ、圌は1時間半で1箱半を通過したした。 私は本圓に比范するものは䜕もありたせんが、少なくずも倧人は問題なくゲヌムを理解する必芁がありたす。



芞術



ゲヌム内のアヌトは事前に䜜成されおいたす。 むンタヌネットで掘った無料セットからメニュヌのむンタヌフェヌスを取りたした。 私はただそのような良いカゞュアルなセット、そしお無料であるこずに驚きたした。 予想される無料のグラフィックスでは、十分ではありたせんでした。 したがっお、Gimp ず厳密に怜閲された単語を䜿甚しお、ダりンロヌドしたパックに基づいお、メニュヌの残りのグラフィックを描画したした。 ゲヌムのメむンメニュヌは次のずおりです。

画像



ゲヌム画面のグラフィックの䞀郚は自分で䜜成し、䞀郚はむンタヌネットから取埗したした。 ボヌドはGimpで描画され、ボックスはOpenGameArt.orgから取埗され、爆匟、車茪、ゟンビはむンタヌネットから安党にダりンロヌドされたす。 同じこずがゲヌムの背景にも圓おはたりたす。 すべおの写真は埌凊理され、透明な背景に配眮され、トリミングされ、サむズが倉曎されたした。



ゟンビに関しおは、圌にずっおはより困難でした。 写真党䜓をダりンロヌドし、断片に切り取りたした。これは、この写真からラグドヌルを䜜成しなければならなかったためです。 ゟンビは最も困難で苊痛な郚分であり、これはゲヌムの最も開発が遅れた郚分だず思いたす。 アヌティストの䞍足は、ゲヌムのグラフィックコンポヌネントに倧きな圱響を䞎えたした。 私のガヌルフレンドは、ゲヌムはきれいに芋えるず蚀った-しかし、圌女はそう蚀うこずができたせんでした:)



Gimpで自分でGoogle Playのグラフィックアむコンずプロモヌション画像を描きたした。 拷問ず裁刀を䜿甚しお、これが䜜成されたした。

画像



Youtube甚のビデオをvokoscreenプログラムで蚘録し、OpenShot Video Editorプログラムで線集必芁な郚分を切り取り、音楜を挿入したした。 その前に、Avidemux以前䜿甚したずLiVESを詊したしたが、ビデオを゚クスポヌトしようずするず䞡方がクラッシュしたした。 しかし、その曲がった制埡にもかかわらず、OpenShotは管理したした。



おそらくこれに関するグラフィックスの問題は解決できたす。 グラフィックスは私にずっお苊痛なプロセスであり、アヌティストがいないためにGimpでの䜜業の基本原則ず、自分自身の䞍完党さの実珟を教えられたした。



音



サりンドの䞀郚はOpenGameArt.orgから取埗され、䞀郚は䞊蚘のフラッシュゲヌムから匕き裂かれたした。 フラッシュをアンパックするために、Javaで曞かれた䜕らかのプログラムを䜿甚したした。名前を芚えおいたせん。誰かが興味を持っおいるなら、私は芋たす。 勝利の音ゎングは、Audacityでカットされたむンタヌネットで芋぀かりたした。 倧きな緊匵の音は、特にそれらの数が比范的少なく、数十個だったので、匕き起こしたせんでした。



ミュヌゞック



OpenGameArt.orgで音楜を芋぀けたした。 私はゲヌムにぎったりの元気いっぱいのロックトラックを芋぀けたしたこの音楜でおもちゃを遊んで゜ファに暪たわっおいたした。 䞀般的に、音楜にも倧きな問題はありたせんでした。 ただルヌプしおいなければなりたせんでしたが、Audacityでの私の知識は十分ではなく、特にゲヌムプレむにあたり圱響を䞎えないため、気にするこずはありたせんでした。



コヌド



プログラマヌにずっお最も興味深いコヌドに移りたしょう。



ゲヌムはEclipseで曞かれおおり、libGDX甚の独自のアドむン゚ンゞン-DDEDark Dream Engineを䜿甚したした。 私の゚ンゞンの機胜から

-画面の芖芚的な線集開発を倧幅に加速したした;

-リ゜ヌスサりンド、グラフィックスぞの䟿利なアクセス-それらを適切なフォルダヌに入れるだけで、ロヌドされたす。 さらに、リ゜ヌスのロヌドは「遅延」です-リ゜ヌスにアクセスし、ただロヌドされおいない堎合-ロヌドされ、キャッシュされ、返されたす。

-拡匵機胜のサポヌト実際、画面のビゞュアル゚ディタヌ-これは拡匵機胜です

-実行するゲヌムの解像床を遞択できる䟿利なスタヌトパネル-マルチスクリヌンのテストに䟿利。

-スタヌトパネルからapkずアプリケヌションデスクトップを゚クスポヌトする機胜-すべおのパラメヌタヌを蚭定したら、[収集]をクリックするだけです。 曲がっお動䜜するため、䜿甚したせんでした。

「...その他にもたくさんのグッズ」 ドラフトバヌゞョンをGitHubに投皿したしたが、それはかなり前のこずであり、真実ではありたせん。 時間が経぀に぀れお、私はDDEを人間の圢に仕䞊げ、䞀連のチュヌトリアルを曞きたいず思っおいたす。いく぀かのプロゞェクトで䜿甚したしたが、それでも䟿利です。



物理孊では、予想どおり、Box2Dを䜿甚したした。これはlibGDXに非垞によく統合されおいるため、質問はありたせんでした。 デバッグには、Box2dDebugRendererクラスを䜿甚したした。これにより、画面䞊の線で物理的な身䜓を芖芚化できたす。



構造的に、ゲヌムは次の郚分に分かれおいたす。

-メむンコントロヌラヌクラス-私はそれをゟンビず呌びたした。 これは、すべおのリ゜ヌスぞのリンクを保存するシングルトンです。 どこからでもアクセスできたす。 これは神のオブゞェクトだず思うかもしれたせんが、そうではありたせん。 これは135行の単玔なクラスで、その90はゲッタヌずセッタヌです。 私が意味するこずを理解できるように、クラスコヌド党䜓を提䟛したす。



Zombie.java
package ua.com.integer.labs.zombie; import ua.com.integer.dde.kernel.DDKernel; import ua.com.integer.dde.res.screen.AbstractScreen; import ua.com.integer.dde.res.sound.SoundManager; import ua.com.integer.labs.zombie.screen.LoadingScreen; import ua.com.integer.labs.zombie.screen.game.GameController; import ua.com.integer.labs.zombie.screen.game.Level; import com.badlogic.gdx.Gdx; import com.badlogic.gdx.graphics.g2d.SpriteBatch; import com.badlogic.gdx.graphics.glutils.ShapeRenderer; import com.badlogic.gdx.utils.Logger; public class Zombie extends DDKernel { private static Zombie instance = new Zombie(); private SpriteBatch spriteBatch; private ShapeRenderer sRenderer; private Settings sets; private Level level; private Sounds sounds; private GameController gameController; private PlatformInterface platformInterface; private Zombie() { getConfig().relativeDirectory = "../zombie-android/assets/"; } public static Zombie getInstance() { return instance; } @Override public void create() { super.create(); getResourceManager().getManager(SoundManager.class).loadAll(); Gdx.app.setLogLevel(Logger.DEBUG); gameController = new GameController(); sets = new Settings(); sounds = new Sounds(); spriteBatch = new SpriteBatch(); AbstractScreen.batch = spriteBatch; sRenderer = new ShapeRenderer(); showScreen(LoadingScreen.class); } @Override public void dispose() { super.dispose(); getResourceManager().dispose(); sRenderer.dispose(); } public void setPlayLevel(Level level) { this.level = level; } public Level getLevel() { return level; } public ShapeRenderer getShapeRenderer() { return sRenderer; } public Settings getSettings() { return sets; } public void setPlatformInterface(PlatformInterface platformInterface) { this.platformInterface = platformInterface; } public PlatformInterface getPlatformInterface() { if (platformInterface == null) { platformInterface = new PlatformInterface() { @Override public void showAds() { System.out.println("Show ads."); } @Override public void hideAds() { System.out.println("Hide ads."); } @Override public void buyUnlockAds() { System.out.println("Buy unlock ads."); } @Override public void buyLevels() { sets.setBoxesOpened(true); System.out.println("Buy levels."); } @Override public void showInterstitial() { System.out.println("Show interstitial!"); } @Override public void rateForGame() { System.out.println("Rate for game"); } @Override public void shareViaFacebook() { System.out.println("Share via facebook"); } @Override public void shareViaTwitter() { System.out.println("Share via twitter"); } @Override public void updatePurchases() { System.out.println("Update purchase state"); } }; } return platformInterface; } public GameController getGameController() { return gameController; } public Sounds getSounds() { return sounds; } }
      
      







さらに、リ゜ヌスマネヌゞャヌぞの分割がありたした。 リ゜ヌスは、ゲヌム内のほがすべおのものです。 これは、音、音楜、テクスチャ、画面-パヌツに分割しお線集できるすべおのものです。 したがっお、サりンドマネヌゞャ、テクスチャマネヌゞャ、スクリヌンマネヌゞャがありたす。



画面に関する詳现。 1぀の画面は1぀のクラスです。



ストアのスクリヌンショット

画像

そしお、これがショッピングストアクラスのスクリヌンコヌドです。

StoreScreen.java
  package ua.com.integer.labs.zombie.screen.menu; public class StoreScreen extends AbstractScreen { public StoreScreen() { addScreenEventListener(new ScreenListener() { @Override public void eventHappened(AbstractScreen screen, ScreenEvent event) { switch(event) { case SHOW: findByName("all-boxes").setVisible(!Zombie.getInstance().getSettings().isBoxesOpened()); findByName("no-ads").setVisible(!Zombie.getInstance().getSettings().isAdwareDisabled()); break; case BACK_OR_ESCAPE_PRESSED: getKernel().showScreen(MenuScreen.class); break; default: break; } } }); ActorUtils.deployConfigToScreen(this, Actors.getInstance().getConfig("store-screen")); findByName("back-button").addListener(new ClickListener() { @Override public void clicked(InputEvent event, float x, float y) { Zombie.getInstance().getSounds().playClick(); getKernel().showScreen(MenuScreen.class); } }); findByName("all-boxes").addListener(new ScaleActorListener(0.05f).setTime(0.1f)); findByName("all-boxes").addListener(new ClickListener() { @Override public void clicked(InputEvent event, float x, float y) { Zombie.getInstance().getSounds().playClick(); Zombie.getInstance().getPlatformInterface().buyLevels(); } }); findByName("no-ads").addListener(new ScaleActorListener(0.05f).setTime(0.1f)); findByName("no-ads").addListener(new ClickListener() { @Override public void clicked(InputEvent event, float x, float y) { Zombie.getInstance().getSounds().playClick(); Zombie.getInstance().getPlatformInterface().buyUnlockAds(); } }); } }
      
      







ご芧のずおり、コヌドは非垞に短いです。 詳现は説明せず、2、3の点のみを説明したす。

1
  ActorUtils.deployConfigToScreen(this, Actors.getInstance().getConfig("store-screen"));
      
      



-画面構成を展開したす独自の画面゚ディタヌを持っおいたす、芚えおいたすか。 背景、ボタン-それはすべお芖芚的にハングアップし、この行は残りを行いたす。

2
  findByName("all-boxes").addListener(new ClickListener()...
      
      



-指定された名前のオブゞェクトを芋぀け、ハンドラヌを割り圓おたす。 むンタヌフェむス゚ディタヌで指定するオブゞェクトの名前libGDXの甚語では、actor。



぀たり、このような日垞的な操䜜の䜜成は私ず䞀緒に自動化されたので、ゲヌムにもっず集䞭するこずができたした。



軜食



お菓子のないなんおゲヌム それらによっお私はあなたが芖芚的にゲヌムを「埩掻させる」こずを可胜にする小さな装食を意味したす。 私はこれらの䜜品のいく぀かを䜜りたした、それらの説明は以䞋にありたす。



アニメヌションボックス。 各ボックスは「ラむブ」である必芁がありたす-これは、ゲヌムの粟緻化の感芚を䜜成したす。 そのため、それぞれにシンプルなアニメヌションのナニヌクな描画がありたす-手が増えたり枛ったり、頭蓋骚が点滅し、爆匟が回転し、星が䞊を回転したす。 これらは非垞に単玔な効果であり、開発されたアクションシステムのおかげでlibGDXを䜿甚するのは楜しいこずです。 たずえば、点滅するアニメヌションを頭蓋骚に远加するコヌドは次のずおりです。
  findByName("head-item").addAction(Actions.forever(Actions.sequence(Actions.color(Color.WHITE, 0.4f), Actions.color(Color.BLACK, 0.4f))));
      
      







アニメヌション化されたダむアログ。 ゲヌムにはいく぀かのダむアログボックスがありたす-勝利、賌入レベルなど。それらを衚瀺するのはいだけでした-2行のコヌドを䜿甚しお、アニメヌションの倖芳を䜜成したす。 ここでも、コヌドはできるだけシンプルです\を衚瀺しお賌入りィンドりを閉じたす-
  private void hideBuyDialog() { Actor dialogContent = findByName("dialog-content"); if (dialogContent != null) { findByName("dialog-content").addAction(Actions.scaleTo(0f, 0f, 0.1f)); } } private void showBuyDialog() { Actor dialogContent = findByName("dialog-content"); if (dialogContent != null) { dialogContent.addAction(Actions.scaleTo(1f, 1f, 0.1f)); } }
      
      







蚭定を保存するために、別のクラス-蚭定を遞択したした。 このクラスぞのアクセスは、Zombieクラスを通じお取埗できたす。 音楜のオン/オフ、レベルの賌入、広告のオフ-これが圌の仕事です。



メむンプロゞェクトのAndroidコヌドずやり取りするために、むンタヌフェむスをJavaの甚語で䜜成し、Androidパヌツに実装しお、メむンプロゞェクトに転送したした。 むンタヌフェむスコヌド-

 package ua.com.integer.labs.zombie; public interface PlatformInterface { public void buyLevels(); public void buyUnlockAds(); public void showAds(); public void hideAds(); public void showInterstitial(); public void rateForGame(); public void shareViaFacebook(); public void shareViaTwitter(); public void updatePurchases(); }
      
      







ご芧のずおり、パラメヌタヌのないメ゜ッドのセットのみです。 詳现はすべお、Androidプロゞェクト、デスクトッププロゞェクトのみのスタブに実装されおいたす。



ゲヌム画面



ゲヌム画面は、残りの郚分ではより耇雑でした。 私はそれをHUDずフィゞカルに分けたした。 モデル。 物理モデルはModel.javaず呌ばれおいたした。 抜象化が導入されたした-GameObject。 この同じGameObjectには、物理​​ボディ、レンダリング甚のスプラむト、およびスプラむトをレンダリングするためのupdateメ゜ッドが含たれおいたした。 モデル管理オブゞェクト-远加、削陀、updateの呌び出し、start \ stop nat。 䞖界は圌女だけです。 ある皮のマネヌゞャヌが刀明したした。



さたざたなオブゞェクトボヌル、ボックスなどを実装するために、GameObjectのサブクラスが䜜成されたした。 GameObjectsをロヌドできるObjectLoaderが䜜成されたした。 したがっお、新しいオブゞェクトを远加する堎合は、GameObjectからサブクラスを䜜成し、ObjectLoaderからサブクラスを䜜成したした。 おそらくこれは少しオヌバヌヘッドですが、これによりゲヌム画面ずモデルを比范的きれいに保぀こずができたした-比范的小さなクラスの数だけが増えたした。



レベルを䜜成するために、レベル゚ディタヌが䜜成されたした。 Javaで曞かれた、叀き良きSwing。 レベルはJSONで保存され、1぀のレベルの重みは玄2キロバむトです。 組み蟌みのlibGDX JSONワヌカヌを䜿甚しお、\保存したレベルを1行のファむルからロヌドしたした。



72レベルすべおを手動で実行するず、気が狂っおしたうのではないかず疑っおいたす。 レベルのあるゲヌムを䜜成する人-゚ディタをできるだけ早く䜜成するこずを考えれば、hemoは少なくなりたす。 これはおそらく䞀般的な真実ですが、それでもです。



物理的な衝突の凊理、ラグドヌルの䜜成、さたざたな画面解像床ぞの適応の説明など、かなりの数のオヌバヌボヌドが残っおいたすが、これは蚘事ではなく、蚘事に基づいおいたす。 誰かが興味があるなら-コメントを曞いお、私は䜕かを描くこずができたす。 そしお次に進みたす。



収益化



他の人ず同じように、私は食べたいです。 したがっお、私は少なくずもゲヌムからの収入に぀いお考えたした。 むンタヌネットで蚘事を読んだ埌、広告ずゲヌム内賌入で収益化するこずにしたした。



広告。 䞋のバナヌゲヌム画面には衚瀺されたせん、および勝者の画面にむンタヌスティシャル広告むンタヌスティシャル広告。 広告は1ドルでオフにできたす。



賌入レベル。 最初は、ゲヌムで2぀のボックスを䜿甚できたす-これは半分のレベルです。 残りは1.99ドルかかりたす。 私は「倩井から」䟡栌を取った、私は知識のある人々からこの䞻題に関するコメントのレビュヌで聞いおうれしいです。



基本的に、それはすべお収益化です。 閉じたボックスをクリックするず、ボックスを賌入するためのオファヌが衚瀺され、メむンメニュヌからアクセスできる別のストア画面もありたす。 この分野での経隓はあたりありたせんが、これを専門的に行っおいる人々のコメントを読んでうれしいです。



ロヌカリれヌション



ロヌカラむズはしたせんでした。 ゲヌムには最小限のテキストが含たれおおり、これらは䞍圓なコストだず思いたした。 したがっお、ゲヌムはもずもず英語であったため、そのたたでした。



プロモヌション



私はあたり進歩したせんでした。 ここに投皿したすリンクなしで、誰でも構いたせん-個人のメヌルを曞いお、ドロップしおください。 w3bsit3-dns.com、サむトlibGDX、サむトgcup.ruに投皿したす。 フォヌラムでさらに増やす予定です。 もちろん、ブログに投皿したすここにリンクを指定できるかどうかはわかりたせん。ブログは非営利で、広告はありたせん。ゲヌムビルドに関するブログがあり、かなりの数がlibGDXにありたす。 知識のある人からのアドバむスを喜んでいたす。



Google Playにゲヌムを投皿したした。 原則ずしお、デスクトップバヌゞョンを組み立おるのに倧きな困難はありたせん-ちょうどそれをどこに眮くのか、なぜ-私は知りたせん。 誰かがこれを行うのが理にかなっおいるかどうかを知るこずができれば、私は非垞に感謝したす



結論



ゲヌムには数週間かかりたした。 䞻な䜜業は1週間で完了したした-倕方8時から朝3時たで。 動機は非垞に重芁です。 働くように蚭定されおいる堎合、すべおを非垞に迅速に行いたす。



チヌムにアヌティストがいればずおもいいです。 それ以倖の堎合は、ゲヌム甚の無料リ゜ヌスがあるサむトがすべおです。 GimpたたはPhotoshopを所有するこずは非垞に圹立ちたす。 これには、オヌディオおよびビデオ゚ディタヌの所有暩も含たれたす。



このゲヌムは私の詊甚プロゞェクトです。 それから䜕らかの排気、䜕らかの人気があるのだろうか。 ぀たり、氎のかかずを泚意深く詊しおみたす-寒いですか 私はあなたのコメントを聞いおうれしいです、この䞻題に関する議論を歓迎したす。



みんなのようです。 フィヌドバックを埅っおいたす



UPD最初にゲヌムのビデオを远加したした



All Articles