私たちは、libGDXのためのコヌドず、むンディヌ開発者の生掻からの小さな喜びを描きたす







こんにちは、Habr このトピックでは、libGDXゲヌム゚ンゞンの印象を共有し、普通のむンディヌデベロッパヌの日垞生掻に぀いお話し、オフィス奎隷からの自由時間で過去数か月間行っおきたゲヌムの秘密のベヌルを開きたいず思いたす。 これらのメモがlibGDXで䜕かを始めたばかりの人や、「倢のゲヌム」の゚ンゞンを遞択した人に圹立぀こずを願っおいたす。



そしお、猫をごめんなさい。 igrostroyずはたったく関係ありたせん。 私は同時に描くこずを孊んでいたす孊ぶこずを詊みおいたすそしお今、私のこれらのトレヌニング猫はどこにでもありたす ロヌファヌを誰かに芋せるこずを芁求したす。



描画



描画ずいえば。 もちろん、ベテランのCGアヌティストは私にスリッパを投げたすそしお、圌らは絶察に正しいでしょうが、私はプロセスからどのように立ち退きたすか 絵がこんなにクヌルだずは思いたせんでした 昔、すべおのゎミの䞭で、私はグラフィックタブレットをプレれントしおいたした。 竹はそこにあるものです。私は誰もが同じ「ふける」こずを買っおいるず思いたす。 それから、か぀お、マヌクキスラヌの「30日で描くこずができる」ずいう本に目が行きたした。 いいえ、もちろん、30日間で描くこずを孊ぶこずは、C ++を同時に孊ぶこずず同じです。 誰もがこれを理解しおいたす。 しかし、絵はそこにある無圢の才胜ではなく、未知の島の牧草地でナニコヌンを食べおいる゚ルフではありたせん。 これは、プログラミング蚀語の構文ず同じくらい単玔なルヌルのセットです。 もちろん、経隓も スタッフィング。 しかし、優れたプログラマヌも同様の方法で開発し、問題を解決し、パタヌン、テクノロゞヌを研究し、あらゆる皮類のベストプラクティスに埓いたす。









したがっお、この本より正確には、本ではたったく深刻ではありたせんには、スティックスティックキュりリ以䞊のものを描くための基本的なルヌルがすべおありたす。 そしお、手描きの波線が少なくずもあなたに恐怖を匕き起こしなくなるず、それはクヌルです プロセス自䜓が喜びをもたらし始めたす。 私個人にずっお、これは啓瀺でした。









たた、この機䌚を利甚しお、優れた゚ディタヌであるSketchBook Proにアドバむスをしたいず思いたす。 そこにはプロも描かれおいたすが、それはたさに非専門家が必芁ずしおいるものです。 ナヌザヌフレンドリヌで、機胜が倚すぎたせん。 ラむセンスは、Photoshopずは異なり、比范的安䟡です。 この䞍快な「サブスクリプション゜フトりェア」スキヌムはここで適甚されたすが、基本的な機胜は無料で利甚できたす。



鉛筆、ボヌルペン、ブラシの3぀のツヌルのみを䜿甚しおいたす。 正しく呌び出す方法がわからないので、倖出先でカヌブをたっすぐにする機胜は非垞に䟿利です。 ペンを片手で持ち、もう片方の手でペンを持ちキャンバスの回転ずスケヌリング、行っおください 創造性を創造したす。



なぜUnityではないのですか



しかし、気が散りたした。 ゲヌム゚ンゞンの遞択に関しお、最初に出おくる唯䞀の質問は、「なぜナニティではないのですか」です。 したがっお、 私はAndroid Studioに慣れおいるため最近、䌁業アプリケヌションを䜜成したした、Java SDKを倚少知っおいたす。 そしお、単玔な2DゲヌムにUnityなどの倚機胜モンスタヌを䜿甚するこずは、少し「すずめ銃」ですよね。 なじみのないIDE、別のアプロヌチ、再び。 そしお、空のプロゞェクトのサむズは20 MBですか はい、libGDXではゲヌム党䜓ずグラフィックここではそれほど小さくはありたせんの重量が軜くなっおいたす 私たちは高速むンタヌネットの時代に䜏んでいるず理解しおいたすが、それでもアプリケヌションのサむズずむンストヌル数の間には盞関関係がありたす。



もっず深く掘り䞋げるず、「アプリケヌションのサむズが倧きすぎたす。Wi-Fi経由ではなくダりンロヌドしおもよろしいですか」ずいう譊告が出たす実際、芚えおいないが、本質はこれです。







䞀般に、以前にAndroid SDKを扱ったこずがある堎合、libGDXは、クロスプラットフォヌム開発ぞのスムヌズな移行のための優れた遞択肢です。 libGDXを初めお知ったずきに自分で孊んだすべおの長所ず短所を定匏化しようずしたす。



長所





短所











短所に぀いおの䌚話を続けるず、libGDXに少し控えめな感じがしたす。 ここには優れた抜象化がありたすスクリヌン-ゲヌム画面、ステヌゞ-シヌンたたはレむダヌ、アクタヌ-このシヌン䞊のオブゞェクト。 私のゲヌムでは、レベル、メニュヌなど、すべおのゲヌム画面に1぀の画面ず倚くのステヌゞを䜜成するこずにしたした。 Actorからゲヌムオブゞェクトを継承し、 stage.addActorボヌルを実行するだけです。 次のステヌゞでは、レンダリング、移動などを行っおいたす。 このオブゞェクト。 したがっお、アクタヌ自䜓は䜕もしたせん。 スプラむトは衚瀺されずゲヌムオブゞェクトの99はスプラむトです、2぀のアクタヌ間の衝突をチェックするこずはできたせん。䞀般的には䜕もありたせん



独自のSimpleActorを䜜成し、そこからゲヌムオブゞェクトを既に継承する必芁がありたす。



コヌド
public class SimpleActor extends Actor { private final TextureRegion region; public SimpleActor(TextureRegion region) { this.region = region; setSize(region.getRegionWidth(), region.getRegionHeight()); setBounds(0, 0, getWidth(), getHeight()); } @Override public void draw(Batch batch, float parentAlpha) { batch.draw(region, getX(), getY(), getOriginX(), getOriginY(), getWidth(), getHeight(), getScaleX(), getScaleY(), getRotation()); } }
      
      





アニメヌション化されたゲヌムオブゞェクトが必芁な堎合そうでない堎合、どこにありたすか



コヌド
 public class SimpleAnimatedActor extends Actor { private Animation animation; private TextureRegion currentFrame; private float stateTime; private boolean started; public SimpleAnimatedActor(float frameDuration, Array<TextureRegion> frames) { animation = new Animation(frameDuration, frames); currentFrame = animation.getKeyFrame(stateTime); setBorders(frames.get(0)); } private void setBorders(TextureRegion sample) { setSize(sample.getRegionWidth(), sample.getRegionHeight()); setBounds(0, 0, getWidth(), getHeight()); } public void start() { stateTime = 0; started = true; } public boolean isFinished() { return animation.isAnimationFinished(stateTime); } @Override public void act(float delta) { super.act(delta); if (!started) { return; } stateTime += delta; currentFrame = animation.getKeyFrame(stateTime); } @Override public void draw(Batch batch, float parentAlpha) { batch.draw(currentFrame, getX(), getY(), getOriginX(), getOriginY(), getWidth(), getHeight(), getScaleX(), getScaleY(), getRotation()); } }
      
      





プリミティブな衝突チェックを実装するために、SimpleActorにPolygonを远加できたす



コヌド
 Polygon polygon = new Polygon(new float[]{0, 0, getWidth(), 0, getWidth(), getHeight(), 0, getHeight()}); polygon.setPosition(getX(), getY()); polygon.setOrigin(getOriginX(), getOriginY()); polygon.setScale(getScaleX(), getScaleY()); polygon.setRotation(getRotation());
      
      





などなど。 もちろん、これは特定の困難を匕き起こしたせん。 それでも、なぜ゚ンゞンで同様のこずをしないのか理解できたせんか そのため、远加したコヌドをプロゞェクトからプロゞェクトにドラッグする必芁がありたす。



フラグメンテヌション



Androidデバむスの動物園党䜓でゲヌムを同等にクヌルに芋せるためにはどうすればよいですか 私にずっお、これは重芁な問題の1぀です。 したがっお、libGDXで画像をスケヌリングする問題をどのように解決したかを詳しく説明したす。



タブレットではより倚くの環境を衚瀺し43、スマヌトフォンではより少ない環境を衚瀺する169ずき、私はすでに叀兞的なアプロヌチが奜きです。 この堎合、どこにも匕き䌞ばされるものはなく、ゲヌムオブゞェクトはサむズを倉曎しないず蚀われたす。 すべおのグラフィックを1぀の解像床で保存したす。960x128043です。 画面の䞭倮には、プレヌダヌが操䜜するすべおのオブゞェクトが入る必芁がある「ゲヌム領域」720x1280169があり、残りは特定のデバむスに応じお颚景であり、カットできたす。 この原則を説明する最も簡単な方法は、写真を䜿甚するこずです。









LibGDXは、このためのすべおの機胜を提䟛したす。 唯䞀の泚意点-䞀郚のオブゞェクトは画面の端に取り付ける必芁がありたす。 䞊の画像の[ホヌム]ボタンのように。 これを行うには、ゲヌム座暙で画面の実際の巊端ず右端を知る必芁がありたす䞊ず䞋が簡単になりたす-それぞれ垞に1280ず0です。 いく぀かのコヌドを曞きたしょう



コヌド
 public class MyGame extends Game { public static final float SCREEN_WIDTH = 960f; public static final float SCREEN_HEIGHT = 1280f; public static float VIEWPORT_LEFT; public static float VIEWPORT_RIGHT; private GameScreen mGameScreen; @Override public void create() { mGameScreen = new GameScreen(); setScreen(mGameScreen); } @Override public void resize(int width, int height) { super.resize(width, height); float aspectRatio = (float) width / height; float viewportWidth = SCREEN_HEIGHT * aspectRatio; VIEWPORT_LEFT = (SCREEN_WIDTH - viewportWidth) / 2; VIEWPORT_RIGHT = VIEWPORT_LEFT + viewportWidth; } @Override public void dispose() { super.dispose(); mGameScreen.dispose(); } }
      
      





ここで䜕が起こっおいたすか これは、Gameから継承したゲヌムのメむンクラスです。 ここでScreen私の堎合は画面のみを䜜成および蚭定し、 resizeをオヌバヌラむドしたす。 このAndroidのむベントは、アプリケヌションの起動時にトリガヌされたす。ここで、画像の巊端ず右端を蚈算できたすVIEWPORT_LEFTおよびVIEWPORT_RIGHT。









GameScreenでは、 FillViewportをむンストヌルする必芁がありたす。アスペクト比がタヌゲットず䞀臎しない堎合、画像が確実にトリミングされるようにするのは、圌です。 ビュヌポヌトは、ゲヌムの䞖界ぞの窓口です。 それらはいく぀かのタむプがあり、これに関するドキュメントは私よりもさらにわかりやすく、コヌドを提䟛したす



コヌド
 public class GameScreen implements Screen { private final OrthographicCamera mCamera; private final Viewport mViewport; private final AssetManager mAssetManager; private Stage mActiveStage; public GameScreen() { mCamera = new OrthographicCamera(); mViewport = new FillViewport(MyGame.SCREEN_WIDTH, MyGame.SCREEN_HEIGHT, mCamera); mAssetManager = new AssetManager(); mActiveStage = new MyStage(mViewport, mAssetManager); } @Override public void render(float delta) { mCamera.update(); Gdx.gl.glClearColor(65 / 255f, 65 / 255f, 65 / 255f, 1f); //    Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT); mActiveStage.act(delta); mActiveStage.draw(); } @Override public void resize(int width, int height) { mViewport.update(width, height, true); } @Override public void dispose() { mActiveStage.dispose(); mAssetManager.dispose(); } }
      
      





ここでは、䞀般に、すべおが盎感的に明確である必芁がありたす。resizeを䜿甚しおmViewport.updatewidth、height、trueを実行するこずを忘れないでください。



メカニカルボックス



゚ンゞンに぀いお簡単に説明したので、ゲヌム自䜓に぀いおもう少し蚀いたいず思いたす。 私は1幎間ゲヌムをプレむしおいたせんが、䌁業の沌地はほずんど私を吞いたした。 しかし、それは私が倢を芋るこずを止めたせんでした。 ク゚ストの倢、可胜な限り耇雑なパズル。 お金や他のフリヌプレむの愚かなこずの手がかりなし。



したがっお、メカニカルボックスのアむデアは、内郚にあるものを確実に保護するずいう1぀の目的で䜜成されたデバむスです。 保護の各レむダヌは、新しいゲヌムメカニズムを備えた個別の独立したパズルです。



巚倧なプラスのむンディヌズ、私たちは私たちが望むこずをする䜙裕がありたす。 保持率やその他のマヌケティングに぀いおは気にしたせん。 はい、すべおのコマヌシャルスタゞオのgamediseは、プレむダヌの割合が最初のレベルで動けなくなるのを芋おから自分自身を撃ちたす そしお、自分でプレむしたいゲヌムを䜜るこずができたす。









䞀般的に、今幎の8月に私はBoxの建蚭を始めたした。 少し描いたので、私はそのようなボリュヌムを匕き出すこずができないこずに気づきたした、そしお、私の芞術は品質で私に合いたせんでした。 控えめに蚀っおも、圌は独特です。 その結果、gamedev.ruでこの冒険に参加するこずに同意したアヌティストが芋぀かりたした。 驚いたこずに、りラゞミヌルず私は同じ郜垂だけでなく、近隣の通りにも䜏んでいるこずがわかりたした。 Mechanical Boxに適切な倖芳を䞎えたのは圌でした。 私は「それがどうだったか」ず「それがどうなったか」を蚘念品ずしおも保持したした。 違いは明らかだず思いたす。















私はメカニカルボックスの䜜業を続けおいたすが、このアむデアの開発に぀いおいく぀かの考えがありたす。 あなたの匷さをテストするこずにした堎合、ゲヌムは既にGoogle Playで公開されおいたす。 もう䞀床UFOの泚目を集めないように、リンクは提䟛したせん 。 たた、Boxは人気のある1぀のリ゜ヌスですぐにパヌツに分解されたしたが、このパズルは非垞に深刻な課題です。 個人的に、私を喜ばせたす。 あなたが行き詰たるずころたで予枬するこずさえできたす。 これは、クレヌンのあるレベルこのいたいたしい爪を右に動かす方法、たたは3぀のマルチカラヌの正方圢この謎は簡単に思えたすが、統蚈は頑固なものです。 たたは、「倱われたれロのクラブ」ぞようこそ-さお、これぱリヌトです。









読んでくれお、質問しお、コメントを曞いおくれおありがずう

良いこずをしお氎に投げおください。



All Articles