2017-09-20 1 views
0

私は基本的な量のJavaを学ぶための簡単なゲームを開発しようとしています。すべてがうまくいくようですが、しばらくするとクラッシュするようになります。私は何が起こっていると思います、私はあまりにも多くのオブジェクトを作成し、メモリが不足しているが、私はこれを防ぐ方法がわかりません。誰かがヒントを持っているのか、どこで私が間違いをしているのか分かり、アドバイスを聞いてうれしいです。Android Studio/LibGDXゲームでメモリ不足が発生する

package com.colordash.game; 

import com.badlogic.gdx.Gdx; 
import com.badlogic.gdx.Screen; 
import com.badlogic.gdx.graphics.GL20; 
import com.badlogic.gdx.graphics.OrthographicCamera; 
import com.badlogic.gdx.graphics.Texture; 
import com.badlogic.gdx.graphics.g2d.TextureRegion; 
import com.badlogic.gdx.scenes.scene2d.InputEvent; 
import com.badlogic.gdx.scenes.scene2d.InputListener; 
import com.badlogic.gdx.scenes.scene2d.Stage; 
import com.badlogic.gdx.scenes.scene2d.ui.Button; 
import com.badlogic.gdx.scenes.scene2d.utils.TextureRegionDrawable; 
import com.badlogic.gdx.utils.viewport.ScreenViewport; 

import java.util.Random; 

class GameScreen implements Screen { 
    private final ColorDash game; 
    private Texture backgroundTexture; 

    private OrthographicCamera camera; 

    // rby ryb yrb ybr bry byr 

    private float screenWidth; 
    private float screenHeight; 
    private int leftPressedValue; 
    private int rightPressedValue; 
    private int measuredValue; 
    private int neededValue; 

    private float redHeight; 
    private float blueHeight; 
    private float yellowHeight; 

    private Stage stage; 

    private Texture centerDisplayTexture; 
    Texture buttonLRed; 

    private float time; 

    int randomNum; 

    public GameScreen(final ColorDash gam) { 
     this.game = gam; 
     time = 0; 

     backgroundTexture = new Texture(Gdx.files.internal("background2.png")); 
     backgroundTexture.setWrap(Texture.TextureWrap.Repeat, Texture.TextureWrap.Repeat); 

     // create the camera and the SpriteBatch 

     stage = new Stage(new ScreenViewport()); //Set up a stage for the ui 
     screenWidth = stage.getWidth(); 
     screenHeight = stage.getHeight(); 

     float buttonWidth = 3 * (screenWidth/12); 
     float buttonHeight = 4 * (screenHeight/12); 

     float buttonLower = 1 * (screenHeight/3) - buttonHeight; 
     float buttonMid = 2 * (screenHeight/3) - buttonHeight; 
     float buttonHigher = 3 * (screenHeight/3) - buttonHeight; 

     float col1 = screenWidth - 23 * (screenWidth/24); 
     float col2 = screenWidth - 1 * (screenWidth/24) - buttonWidth; 

     Random randomButtons = new Random(); 
     int buttonLocations = randomButtons.nextInt(6); 
     if (buttonLocations == 0) { 
      redHeight = buttonLower; 
      blueHeight = buttonMid; 
      yellowHeight = buttonHigher; 
     } else if (buttonLocations == 1) { 
      redHeight = buttonLower; 
      blueHeight = buttonHigher; 
      yellowHeight = buttonMid; 
     } else if (buttonLocations == 2) { 
      redHeight = buttonMid; 
      blueHeight = buttonLower; 
      yellowHeight = buttonHigher; 
     } else if (buttonLocations == 3) { 
      redHeight = buttonHigher; 
      blueHeight = buttonLower; 
      yellowHeight = buttonMid; 
     } else if (buttonLocations == 4) { 
      redHeight = buttonHigher; 
      blueHeight = buttonMid; 
      yellowHeight = buttonLower; 
     } else if (buttonLocations == 5) { 
      redHeight = buttonMid; 
      blueHeight = buttonHigher; 
      yellowHeight = buttonLower; 
     } 

     // red 1 
     // blue 2 
     // yellow 4 

     int[] combinations = new int[6]; 
     combinations[0] = 2; // red red 
     combinations[1] = 3; // red blue 
     combinations[2] = 4; // blue blue 
     combinations[3] = 5; // yellow red 
     combinations[4] = 6; // yellow blue 
     combinations[5] = 8; // yellow yellow 

     leftPressedValue = 0; 
     rightPressedValue = 0; 
     measuredValue = 0; 

     Random rn = new Random(); 
     int randomNum = rn.nextInt(6); 
     if (ColorDash.lastRandomNumber == randomNum) { 
      randomNum = rn.nextInt(6); 

     } 
     neededValue = combinations[randomNum]; 

     if (neededValue == 2) { 
      centerDisplayTexture = new Texture(Gdx.files.internal("redBig.png")); 
     } else if (neededValue == 3) { 
      centerDisplayTexture = new Texture(Gdx.files.internal("purple.png")); 
     } else if (neededValue == 4) { 
      centerDisplayTexture = new Texture(Gdx.files.internal("blueBig.png")); 
     } else if (neededValue == 5) { 
      centerDisplayTexture = new Texture(Gdx.files.internal("orange.png")); 
     } else if (neededValue == 6) { 
      centerDisplayTexture = new Texture(Gdx.files.internal("green.png")); 
     } else if (neededValue == 8) { 
      centerDisplayTexture = new Texture(Gdx.files.internal("bigyellow.png")); 
     } 

     // center display 
     TextureRegion centerDisplayTextureRegion = new TextureRegion(centerDisplayTexture); 
     TextureRegionDrawable centerDisplayTexRegionDrawable = new TextureRegionDrawable(centerDisplayTextureRegion); 

     Button centerDisplay = new Button(centerDisplayTexRegionDrawable); 
     centerDisplay.setSize(screenHeight/2, screenHeight/2); 
     centerDisplay.setPosition(screenWidth/2 - (screenHeight/2)/2, screenHeight/2 - (screenHeight/2)/2); 
     stage.addActor(centerDisplay); 

     // red buttons 
     Texture redButtonTexture = new Texture(Gdx.files.internal("redright.png")); 
     TextureRegion redButtonTextureRegion = new TextureRegion(redButtonTexture); 
     TextureRegionDrawable redButtonTexRegionDrawable = new TextureRegionDrawable(redButtonTextureRegion); 

     Button buttonLRed = new Button(redButtonTexRegionDrawable); 
     buttonLRed.setSize(buttonWidth, buttonHeight); 
     buttonLRed.getStyle().up = new TextureRegionDrawable(new TextureRegion(new Texture(Gdx.files.internal("redleft.png")))); 
     //buttonLRed.getStyle().down = new TextureRegionDrawable(new TextureRegion(new Texture(Gdx.files.internal("redleft.png")))); 
     buttonLRed.setPosition(col1, redHeight); 

     Button buttonRRed = new Button(redButtonTexRegionDrawable); 
     buttonRRed.setSize(buttonWidth, buttonHeight); 
     buttonRRed.getStyle().up = new TextureRegionDrawable(new TextureRegion(new Texture(Gdx.files.internal("redright.png")))); 
     //buttonRRed.getStyle().down = new TextureRegionDrawable(new TextureRegion(new Texture(Gdx.files.internal("redright.png")))); 
     buttonRRed.setPosition(col2, redHeight); 

     buttonLRed.addListener(new InputListener() {@Override 
     public void touchUp(InputEvent event, float x, float y, int pointer, int button) { 
      leftPressedValue = 1; 
     }@Override 
     public boolean touchDown(InputEvent event, float x, float y, int pointer, int button) { 
      leftPressedValue = 1; 
      return true; 
     } 
     }); 
     buttonRRed.addListener(new InputListener() {@Override 
     public void touchUp(InputEvent event, float x, float y, int pointer, int button) { 
      rightPressedValue = 1; 
     }@Override 
     public boolean touchDown(InputEvent event, float x, float y, int pointer, int button) { 
      rightPressedValue = 1; 
      return true; 
     } 
     }); 

     stage.addActor(buttonLRed); 
     stage.addActor(buttonRRed); //Add the button to the stage to perform rendering and take input. 

     // blue buttons 
     Texture blueButtonTexture = new Texture(Gdx.files.internal("blue.png")); 
     TextureRegion blueButtonTextureRegion = new TextureRegion(blueButtonTexture); 
     TextureRegionDrawable blueButtonTexRegionDrawable = new TextureRegionDrawable(blueButtonTextureRegion); 

     Button buttonLBlue = new Button(blueButtonTexRegionDrawable); 
     buttonLBlue.setSize(buttonWidth, buttonHeight); 
     buttonLBlue.getStyle().up = new TextureRegionDrawable(new TextureRegion(new Texture(Gdx.files.internal("blueleft.png")))); 
     //buttonLBlue.getStyle().down = new TextureRegionDrawable(new TextureRegion(new Texture(Gdx.files.internal("blueleft.png")))); 
     buttonLBlue.setPosition(col1, blueHeight); 

     Button buttonRBlue = new Button(blueButtonTexRegionDrawable); 
     buttonRBlue.setSize(buttonWidth, buttonHeight); 
     buttonRBlue.getStyle().up = new TextureRegionDrawable(new TextureRegion(new Texture(Gdx.files.internal("blueright.png")))); 
     //buttonRBlue.getStyle().down = new TextureRegionDrawable(new TextureRegion(new Texture(Gdx.files.internal("right.png")))); 
     buttonRBlue.setPosition(col2, blueHeight); 

     buttonLBlue.addListener(new InputListener() {@Override 
     public void touchUp(InputEvent event, float x, float y, int pointer, int button) { 
      leftPressedValue = 2; 
     }@Override 
     public boolean touchDown(InputEvent event, float x, float y, int pointer, int button) { 
      leftPressedValue = 2; 
      return true; 
     } 
     }); 
     buttonRBlue.addListener(new InputListener() {@Override 
     public void touchUp(InputEvent event, float x, float y, int pointer, int button) { 
      rightPressedValue = 2; 
     }@Override 
     public boolean touchDown(InputEvent event, float x, float y, int pointer, int button) { 
      rightPressedValue = 2; 
      return true; 
     } 

     }); 

     stage.addActor(buttonLBlue); 
     stage.addActor(buttonRBlue); //Add the button to the stage to perform rendering and take input. 

     // yellow buttons 
     Texture yellowButtonTexture = new Texture(Gdx.files.internal("yellow.png")); 
     TextureRegion yellowButtonTextureRegion = new TextureRegion(yellowButtonTexture); 
     TextureRegionDrawable yellowButtonTexRegionDrawable = new TextureRegionDrawable(yellowButtonTextureRegion); 

     Button buttonLYellow = new Button(yellowButtonTexRegionDrawable); 
     buttonLYellow.setSize(buttonWidth, buttonHeight); 
     buttonLYellow.getStyle().up = new TextureRegionDrawable(new TextureRegion(new Texture(Gdx.files.internal("yellowleft.png")))); 
     //buttonLYellow.getStyle().down = new TextureRegionDrawable(new TextureRegion(new Texture(Gdx.files.internal("yellowleft.png")))); 
     buttonLYellow.setPosition(col1, yellowHeight); 

     Button buttonRYellow = new Button(redButtonTexRegionDrawable); 
     buttonRYellow.setSize(buttonWidth, buttonHeight); 
     buttonRYellow.getStyle().up = new TextureRegionDrawable(new TextureRegion(new Texture(Gdx.files.internal("yellowright.png")))); 
     //buttonRYellow.getStyle().down = new TextureRegionDrawable(new TextureRegion(new Texture(Gdx.files.internal("yellowright.png")))); 
     buttonRYellow.setPosition(col2, yellowHeight); 

     buttonLYellow.addListener(new InputListener() {@Override 
     public void touchUp(InputEvent event, float x, float y, int pointer, int button) { 
      leftPressedValue = 4; 
     }@Override 
     public boolean touchDown(InputEvent event, float x, float y, int pointer, int button) { 
      leftPressedValue = 4; 
      return true; 
     } 
     }); 
     buttonRYellow.addListener(new InputListener() {@Override 
     public void touchUp(InputEvent event, float x, float y, int pointer, int button) { 
      rightPressedValue = 4; 
     }@Override 
     public boolean touchDown(InputEvent event, float x, float y, int pointer, int button) { 
      rightPressedValue = 4; 
      return true; 
     } 
     }); 

     stage.addActor(buttonLYellow); 
     stage.addActor(buttonRYellow); //Add the button to the stage to perform rendering and take input. 

     Gdx.input.setInputProcessor(stage); 

     //Start taking input from the ui 
     camera = new OrthographicCamera(); 
     camera.setToOrtho(false, stage.getWidth(), stage.getHeight()); 
     ColorDash.lastRandomNumber = randomNum; 

    } 

    @Override 
    public void render(float delta) { 

     Gdx.gl.glClearColor(0, 0, 0, 1); 
     Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT); 

     game.batch.begin(); 
     game.batch.draw(backgroundTexture, 0, 0, 0, 0, Math.round(screenWidth), Math.round(screenHeight)); 
     //game.font.draw(game.batch,toString().valueOf(randomNum),400,350); 
     //game.font.draw(game.batch,toString().valueOf(ColorDash.lastRandomNumber),400,400); 
     game.batch.end(); 

     // tell the camera to update its matrices. 
     camera.update(); 

     float deltaTime = Gdx.graphics.getDeltaTime(); 
     time += deltaTime; 

     double timeSpeeedMultiplier = ColorDash.counter * 0.005; 

     // tell the SpriteBatch to render in the 
     // coordinate system specified by the camera. 
     game.batch.setProjectionMatrix(camera.combined); 

     game.batch.begin(); 
     stage.act(Gdx.graphics.getDeltaTime()); //Perform ui logic 
     stage.draw(); //Draw the ui 
     game.batch.end(); 

     measuredValue = leftPressedValue + rightPressedValue; 
     if (measuredValue > 20) { 
      measuredValue = 0; 
     } 

     if (time > (2 - 2 * timeSpeeedMultiplier)) { 
      game.setScreen(new GameOverScreen(game)); 
      ColorDash.scoreFinal = ColorDash.counter; 

     } 

     if (Gdx.input.isTouched()) { 
      if (leftPressedValue > 0 && rightPressedValue > 0 && measuredValue != neededValue) { 
       game.setScreen(new GameOverScreen(game)); 
       ColorDash.scoreFinal = ColorDash.counter; 
      } 
      if ((leftPressedValue > 0 && rightPressedValue > 0 && measuredValue == neededValue)) { 
       ColorDash.counter++; 
       if (ColorDash.counter == 15) { 
        game.setScreen(new GameScreenLevel2(game)); 
       } else { 
        game.setScreen(new GameScreen(game)); 
       } 
       leftPressedValue = 0; 
       rightPressedValue = 0; 
       measuredValue = 0; 
       ColorDash.scoreFinal = +((2 - 2 * timeSpeeedMultiplier) - deltaTime); 

      } 
     } else { 
      leftPressedValue = 0; 
      rightPressedValue = 0; 
      measuredValue = 0; 
     } 

    } 

    @Override 
    public void resize(int width, int height) {} 

    @Override 
    public void show() { 
     // start the playback of the background music 
     // when the screen is shown 
    } 

    @Override 
    public void hide() {} 

    @Override 
    public void pause() {} 

    @Override 
    public void resume() {} 

    @Override 
    public void dispose() { 
     backgroundTexture.dispose(); 
     Gdx.input.setInputProcessor(null); 
    } 
} 
+0

ガベージコレクションする必要のあるオブジェクトが別の長い生きたオブジェクト(静的オブジェクトなど)によって参照されている場合、メモリリークが発生しています。この長い生きたオブジェクトはGCルートと呼ばれます。私はimmediatlyあなたのコードに問題を見ているわけではない、別のクラスでメモリリークがある可能性がありますか?また、画像が大きすぎて、それを縮小する必要がある可能性があります – PrisonMike

答えて

1

この画面への参照が失われる前に、コンストラクタまたはcreate()に初期化するすべての使い捨てオブジェクトが配置されている必要があります。 dispose()のすべての呼び出しを画面のdispose()メソッドに置き、画面を再利用していないため、画面のdispose()メソッドをhide()メソッドから呼び出すことができます。

テクスチャ、スプライトバッチ、ステージはすべてディスポーザブルです。

しかし、すべての同じアセットが再びロードされているため、同じ画面の別のインスタンスを読み込んで画面を破棄するのは無駄です。新しいスクリーンを作成して設定するのではなく、ゲームプレイ関連のものの状態をリセットして使用する方法を作る方が理にかなっています。

ちなみにstage.act()は、begin()end()を独自の内部スプライトバッチで呼び出します。独自のSpriteBatchを持つことも無駄です。したがって、esixitngインスタンスをStageコンストラクタに渡す必要があります。

+0

ゲームプレイ/スクリーンの状態をリセットするために私をどこに向けることができますか?私はこのプロジェクトからかなり離れていましたが、最近私は自由な時間を過ごしました。 メモリモニタを使って分析しましたが、何が起きているのかは、画面を読み込んでガベージコレクタを呼び出していたことが分かりました。だから私はすべてを再ロードするのではなく資産をリセットすることがここの鍵です。 ありがとうございます1 – Tyler

+0

リセット状態は、あなたの特定のケースに完全に依存します。通常は、適用可能なすべてのパラメータを必要な値に設定するメソッドを記述します。ガベージコレクタが頻繁に呼び出される場合、それはゲームループのどこかに新しいオブジェクトをたくさん作成するような別の問題です。 – Tenfour04

+0

OpenGLはGCの制御外にあるメモリの割り当てを多く必要とするため、ガベージコレクタについて、Javaでメモリの世話をすることについて多くのことをゲームには適用しません。そのため、メソッドを処理する必要があり、処理が完了したときに何かを処理しなければ、メモリリークが発生します。 – Tenfour04

関連する問題