2017-09-20 1 views
0

기본 게임을 배우기 위해 간단한 게임을 개발하고 있습니다. 모든 것이 잘 돌아가는 것처럼 보이지만, 잠시 후 나는 부서지기 시작할 것입니다. 무슨 일이 일어나고 있는지 생각해 봅니다. 너무 많은 객체를 만들고 메모리가 부족한 것 같지만, 이것을 막을 방법이 확실하지 않습니다. 누군가가 조언을했는지 또는 내가 실수를하는 곳을 볼 수 있었는지 궁금해서 조언을 듣게되어 기뻤습니다.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() 방법에 넣고 화면을 재사용하지 않으므로 hide() 방법에서 화면의 dispose() 방법을 호출 할 수 있습니다.

텍스처, SpriteBatches 및 스테이지는 모두 Disposables입니다.

하지만 같은 화면의 모든 인스턴스를 다시로드하기 때문에 화면을 버리고 같은 화면의 다른 인스턴스를로드하는 것은 낭비입니다. 게임 플레이와 관련된 물건의 상태를 재설정하고 새 화면을 만들고 설정하는 대신 사용하는 방법을 만드는 것이 더 합리적입니다.

그런데 stage.act()은 자체 내부 SpriteBatch에서 begin()end()을 호출합니다. 자체 SpriteBatch를 사용하는 것은 낭비이기 때문에 esixitng 인스턴스를 Stage 생성자로 전달해야합니다.

+0

게임 플레이/화면 상태를 재설정 할 수있는 곳이 있습니까? 나는이 프로젝트에서 꽤 오랜 시간 동안 떨어져 있었지만 최근에 자유 시간을 가졌습니다. 메모리 모니터를 사용하여 분석을 한 결과, 화면을 다시로드 할 때 가비지 콜렉터를 호출하는 중이었고 결국 프로그램이 계속 유지할 수 없을 정도로 자주 발생하고있었습니다. 그래서 모든 것을 다시로드하는 대신에 자산을 재설정하는 것이 핵심입니다. 감사합니다 .1 – Tyler

+0

상태를 재설정하는 것은 전적으로 귀하의 구체적인 경우에 달려 있습니다. 일반적으로 적용 가능한 모든 매개 변수를 원하는 값으로 설정하는 메서드를 작성합니다. 가비지 컬렉터가 자주 호출되는 경우 게임 루프의 어딘가에 많은 새로운 객체를 만드는 것과 같은 별도의 문제입니다. – Tenfour04

+0

자바에서 메모리를 돌보는 가비지 수집기에 대해 읽은 많은 내용은 게임에 적용되지 않습니다. OpenGL은 GC 제어 밖에있는 많은 메모리 할당이 필요하기 때문입니다. 따라서 메소드를 처리해야 할 필요가 생기고, 처리가 끝난 후 처리 할 때 메모리 누수가 발생합니다. – Tenfour04

관련 문제