package com.yokmama.learn10.chapter09.lesson41; import com.badlogic.gdx.ApplicationAdapter; import com.badlogic.gdx.Gdx; import com.badlogic.gdx.audio.Music; import com.badlogic.gdx.audio.Sound; import com.badlogic.gdx.graphics.GL20; import com.badlogic.gdx.graphics.OrthographicCamera; import com.badlogic.gdx.graphics.Texture; import com.badlogic.gdx.graphics.g2d.BitmapFont; import com.badlogic.gdx.graphics.g2d.SpriteBatch; import com.badlogic.gdx.math.Intersector; import com.badlogic.gdx.math.Rectangle; public class MyGdxGame extends ApplicationAdapter { // 描画範囲 public static final int VIEWPORT_WIDTH = 800; public static final int VIEWPORT_HEIGHT = 480; SpriteBatch batch; // 現在のゲームの状態 public GameState gameState = GameState.Ready; // スコア private int score; // カメラ private OrthographicCamera uiCamera; private OrthographicCamera camera; // テクスチャ private BitmapFont textFont; private Texture heroTexture; private Texture backgroundTexture; private Texture backgroundFarTexture; private Texture backgroundNearTexture; private Texture roadTexture; private Texture chipsTexture; private Texture mineTexture; private Texture finishTexture; private Music music; private Sound collisionSound; private Sound coinSound; private Sound finaleClapsSound; // 各種制御用クラス Text text; private Hero hero; private Background background; private Generator generator; // カメラ左端の位置 float cameraLeftEdge; // ゴール位置 float finishX; @Override public void create() { Gdx.app.log("MyGdxGame", "create()"); batch = new SpriteBatch(); // ゲーム用カメラ camera = new OrthographicCamera(); camera.setToOrtho(false, VIEWPORT_WIDTH, VIEWPORT_HEIGHT); camera.position.set(camera.viewportWidth / 2, camera.viewportHeight / 2, 0); // UI用カメラ uiCamera = new OrthographicCamera(); uiCamera.setToOrtho(false, VIEWPORT_WIDTH, VIEWPORT_HEIGHT); initResources(); // ゴール地点の決定 finishX = (background.stageWidth - VIEWPORT_WIDTH) / Background.SPEED + Hero.HERO_LEFT_X; // 音楽の再生 music.setLooping(true); music.setVolume(0.6f); music.play(); resetWorld(); } private void initResources() { // 各種リソースの読込み textFont = new BitmapFont(Gdx.files.internal("verdana39.fnt")); heroTexture = new Texture("UnityChan.png"); finishTexture = new Texture("flag.png"); backgroundTexture = new Texture("bg.png"); backgroundFarTexture = new Texture("bg_far.png"); backgroundNearTexture = new Texture("bg_near.png"); roadTexture = new Texture("road.png"); chipsTexture = new Texture("coins.png"); mineTexture = new Texture("fire.png"); music = Gdx.audio.newMusic(Gdx.files.internal("music.mp3")); collisionSound = Gdx.audio.newSound(Gdx.files.internal("laser3.mp3")); coinSound = Gdx.audio.newSound(Gdx.files.internal("coin05.mp3")); finaleClapsSound = Gdx.audio.newSound(Gdx.files.internal("clapping.mp3")); // 各種制御用クラス初期化 text = new Text(textFont); hero = new Hero(heroTexture); background = new Background(backgroundTexture, backgroundFarTexture, backgroundNearTexture, roadTexture); background.setViewport(VIEWPORT_WIDTH, VIEWPORT_HEIGHT); generator = new Generator(chipsTexture, mineTexture); } @Override public void dispose() { Gdx.app.log("MyGdxGame", "dispose()"); textFont.dispose(); heroTexture.dispose(); backgroundTexture.dispose(); backgroundFarTexture.dispose(); backgroundNearTexture.dispose(); roadTexture.dispose(); finishTexture.dispose(); chipsTexture.dispose(); mineTexture.dispose(); music.dispose(); collisionSound.dispose(); coinSound.dispose(); finaleClapsSound.dispose(); } @Override public void resize(int width, int height) { uiCamera.update(); } // ゲームを最初の状態に戻す private void resetWorld() { score = 0; // キャラクターの位置と状態の初期化 hero.init(); // カメラの位置を開始点へ設定 camera.position.x = VIEWPORT_WIDTH / 2 - Hero.HERO_LEFT_X; cameraLeftEdge = camera.position.x - VIEWPORT_WIDTH / 2; generator.init(VIEWPORT_WIDTH); generator.clear(); } @Override public void render() { Gdx.gl.glClearColor(0, 153.0f / 255.0f, 204.0f / 255.0f, 1); // #0099CC Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT); updateWorld(); drawWorld(); } // 各種状態を変更する private void updateWorld() { float deltaTime = Gdx.graphics.getDeltaTime(); // 入力制御 if (Gdx.input.justTouched()) { if (gameState == GameState.Ready) { gameState = GameState.Running; hero.startRunning(); } else if (gameState == GameState.GameOver) { gameState = GameState.Ready; resetWorld(); } else if (gameState == GameState.GameCleared) { gameState = GameState.Ready; resetWorld(); } else if (gameState == GameState.Running) { hero.jump(); } Gdx.app.log("MyGdxGame", "gameState=" + gameState); } // オブジェクトの新規生成 if (generator.chipGenerationLine < cameraLeftEdge + VIEWPORT_WIDTH && generator.chipGenerationLine + 5 * 50.0f < finishX) { generator.generate(this); } // オブジェクトの更新 generator.update(this, deltaTime); // キャラクターの状態を更新 hero.update(deltaTime); // カメラの位置をキャラクターに合わせて移動させる if (gameState != GameState.GameCleared) { camera.position.x = VIEWPORT_WIDTH / 2 + hero.position.x - Hero.HERO_LEFT_X; cameraLeftEdge = camera.position.x - VIEWPORT_WIDTH / 2; } // ゲームクリアチェック if (gameState != GameState.GameCleared) { float heroX = hero.position.x; if (finishX < heroX) { finaleClapsSound.play(); gameState = GameState.GameCleared; hero.win(); // クリアしたことを通知 } } // ゲームオーバーまたはゲームクリア後は衝突判定を行わない if (gameState == GameState.GameOver || gameState == GameState.GameCleared) { return; } // 衝突判定 Rectangle heroCollision = hero.collisionRect; for (Chip chip : generator.chips) { if (!chip.isCollected && Intersector.overlaps(chip.collisionCircle, heroCollision)) { chip.collect(); coinSound.play(); score += chip.getScore(); } } for (Mine mine : generator.mines) { if (!mine.hasCollided && Intersector.overlaps(mine.collisionCircle, heroCollision)) { mine.collide(); collisionSound.play(); hero.die(); gameState = GameState.GameOver; } } } // 描画 private void drawWorld() { camera.update(); batch.setProjectionMatrix(camera.combined); batch.begin(); // ゲーム描画 background.draw(batch, cameraLeftEdge); generator.draw(this); hero.draw(this); batch.draw(finishTexture, finishX, 0, finishTexture.getWidth() * 0.35f, finishTexture.getHeight() * 0.35f); batch.end(); batch.setProjectionMatrix(uiCamera.combined); batch.begin(); // UI描画 // 文字列描画 if (gameState == GameState.Ready) { text.drawTextTop(batch, "START"); } else if (gameState == GameState.GameCleared) { text.drawTextTop(batch, "SCORE: " + score); text.drawTextCenter(batch, "LEVEL CLEAR"); } else if (gameState == GameState.GameOver) { text.drawTextTop(batch, "SCORE: " + score); text.drawTextCenter(batch, "GAME OVER"); } else if (gameState == GameState.Running) { text.drawTextTop(batch, "SCORE: " + score); } batch.end(); } }