I have this libgdx side scrolling game and the music file(mp3) keeps on playing over itself instead of being disposed and playing a single time.It sounds like multiple music files are playing at the same time and the game gets slow and crashes.
The game goes from MenuState(the menu)>>PlayState(the actual playing area)>>GameOverState(the gameover class)>>PlayState>>GameOverState and so on...
The music in the playstate keeps on playing without disposing itself and the game crashes.
Here's my PlayState
package com.mygdx.game.States;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.audio.Music;
import com.badlogic.gdx.graphics.Color;
import com.badlogic.gdx.graphics.Texture;
import com.badlogic.gdx.graphics.g2d.BitmapFont;
import com.badlogic.gdx.graphics.g2d.SpriteBatch;
import com.badlogic.gdx.graphics.g2d.freetype.FreeTypeFontGenerator;
import com.badlogic.gdx.math.Vector2;
import com.badlogic.gdx.utils.Array;
import com.badlogic.gdx.utils.TimeUtils;
import com.mygdx.game.GrumpyDemo;
import com.mygdx.game.Sprites.Bird;
import com.mygdx.game.Sprites.Tube;
/**
* Created by Kronos on 28-01-2017.
*/
public class PlayState extends State {
private static final int TUBE_SPACING = 75;
private static final int TUBE_COUNT = 4;
private Bird bird;
private Texture actualGamebg;
private Tube tube ;
private Texture ground;
private Vector2 groundPos1,groundPos2;
private static final int HIGHEST_GROUND_LIMIT = -30;
private Array<Tube> tubes;
private int k;
long startTime=0;
private Music mainMusic;
private Music scoreIncrease;
private Music wingFlap;
public BitmapFont font24;
public String SCORE;
public int l;
public PlayState(GameStateManager gsm) {
super(gsm);
bird = new Bird(0,300);
actualGamebg = new Texture("bg.png");
cam.setToOrtho(false, GrumpyDemo.WIDTH/2,GrumpyDemo.HEIGHT/2);
tubes =new Array<Tube>();
ground = new Texture("ground.png");
mainMusic = Gdx.audio.newMusic(Gdx.files.internal("mainmusic.mp3"));
scoreIncrease = Gdx.audio.newMusic(Gdx.files.internal("smw_coin.ogg"));
wingFlap = Gdx.audio.newMusic(Gdx.files.internal("sfx_wing.ogg"));
font24= new BitmapFont();
SCORE = new String();
fontGenerator();
groundPos1 = new Vector2(cam.position.x -cam.viewportWidth/2, HIGHEST_GROUND_LIMIT);
groundPos2 = new Vector2((cam.position.x - cam.viewportWidth/2) + ground.getWidth(),HIGHEST_GROUND_LIMIT);
startTime = TimeUtils.nanoTime();
for(int i=1 ; i<=TUBE_COUNT; i++){
tubes.add(new Tube(i* (TUBE_SPACING + Tube.TUBE_WIDTH)));
}
mainMusic.play();
mainMusic.setVolume(0.8f);
mainMusic.setLooping(true);
}
@Override
protected void handleInput() {
if (Gdx.input.justTouched())
bird.jump();
wingFlap.setLooping(false);
wingFlap.play();
wingFlap.setVolume(0.1f);
}
@Override
public void update(float dt) {
handleInput();
updateGround();
bird.update(dt);
if (TimeUtils.timeSinceNanos(startTime) > 1400000000)
{
Score();
startTime = TimeUtils.nanoTime();
}
SCORE = String.valueOf(k);
for(int i =0 ; i< tubes.size;i++)
{
Tube tube= tubes.get(i);
if (cam.position.x - (cam.viewportWidth/2) > tube.getPosTopTube().x + tube.getTopTube().getWidth())
{
tube.reposition(tube.getPosTopTube().x + ((Tube.TUBE_WIDTH + TUBE_SPACING) *TUBE_COUNT));
}
if(tube.collides(bird.getBounds()))
{
cam.position.x = bird.getPosition().x;
mainMusic.stop();
gsm.set(new GameOverState(gsm));
l=k;
}
else
cam.position.x = bird.getPosition().x +80;
}
if (bird.getPosition().y <= ground.getHeight()){
gsm.set(new GameOverState(gsm));
l = k;
}
cam.update();
}
@Override
public void render(SpriteBatch sb) {
sb.setProjectionMatrix(cam.combined);
sb.begin();
sb.draw(actualGamebg, cam.position.x - (cam.viewportWidth/2), 0);
sb.draw(bird.getTexture(), bird.getPosition().x , bird.getPosition().y);
for(Tube tube: tubes) {
sb.draw(tube.getTopTube(), tube.getPosTopTube().x, tube.getPosTopTube().y);
sb.draw(tube.getBottomTube(), tube.getPosBottomTube().x, tube.getPosBottomTube().y);
}
sb.draw(ground,groundPos1.x,groundPos1.y);
sb.draw(ground,groundPos2.x,groundPos2.y);
font24.draw(sb,SCORE,cam.position.x -2,cam.position.y + 15);
sb.end();
}
/**
* spritebatches must be drawn in order .The one at the bottommost acts as the top layer.
*/
@Override
public void dispose() {
actualGamebg.dispose();
bird.dispose();
font24.dispose();
for(Tube tube: tubes)
{
tube.dispose();
}
ground.dispose();
System.out.println("Play State Disposed");
}
private void updateGround()
{
if (cam.position.x-(cam.viewportWidth/2) > groundPos1.x + ground.getWidth())
{
groundPos1.add(ground.getWidth()*2,0);
}
if (cam.position.x-(cam.viewportWidth/2) > groundPos2.x + ground.getWidth())
{
groundPos2.add(ground.getWidth()*2,0);
}
}
public void Score()
{
k++;
scoreIncrease.play();
scoreIncrease.setVolume(0.3f);
}
public int getL(){
return l;
}
public void fontGenerator(){
FreeTypeFontGenerator generator = new FreeTypeFontGenerator(Gdx.files.internal("bitmapfont/PressStart2P.ttf"));
FreeTypeFontGenerator.FreeTypeFontParameter parameter= new FreeTypeFontGenerator.FreeTypeFontParameter();
parameter.size=12;
parameter.color= Color.GOLD;
parameter.borderColor= Color.GOLDENROD;
font24= generator.generateFont(parameter);
font24.setUseIntegerPositions(false);
}
}
It then transitions into GameOverState which is:
package com.mygdx.game.States;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.audio.Music;
import com.badlogic.gdx.graphics.Color;
import com.badlogic.gdx.graphics.Texture;
import com.badlogic.gdx.graphics.g2d.BitmapFont;
import com.badlogic.gdx.graphics.g2d.SpriteBatch;
import com.badlogic.gdx.graphics.g2d.freetype.FreeTypeFontGenerator;
import com.badlogic.gdx.math.Vector2;
import com.mygdx.game.GrumpyDemo;
import com.mygdx.game.States.PlayState;
/**
* Created by Kronos on 28-01-2017.
*/
public class GameOverState extends State {
private Texture gameOver;
private Texture gameOverBg;
private Texture playAgainBtn;
private Texture ground;
private Vector2 groundPos1;
private Music gameOverMusic;
private BitmapFont totalScore;
private String STRING;
public PlayState playState;
public Boolean AdStart = true;
public GameOverState(GameStateManager gsm) {
super(gsm);
cam.setToOrtho(false, GrumpyDemo.WIDTH/2,GrumpyDemo.HEIGHT/2);
gameOver = new Texture("gameover.png");
gameOverBg = new Texture ("bg.png");
playAgainBtn = new Texture("playbtn.png");
ground = new Texture("ground.png");
AdStart = new Boolean(true);
gameOverMusic = Gdx.audio.newMusic(Gdx.files.internal("gameoversfx.ogg"));
groundPos1 = new Vector2(cam.position.x -cam.viewportWidth/2, -30);
totalScore = new BitmapFont();
STRING = new String();
playState = new PlayState(gsm);
gameOverMusic.play();
gameOverMusic.setVolume(1.0f);
}
@Override
public void handleInput() {
if (Gdx.input.justTouched())
{
gsm.set(new PlayState(gsm));
gameOverMusic.stop();
AdStart = false;
}
}
@Override
public void update(float dt) {
handleInput();
STRING = "SCORE: " + playState.getL();
fontGenerator();
}
@Override
public void render(SpriteBatch sb) {
sb.setProjectionMatrix(cam.combined);
sb.begin();
sb.draw(gameOverBg,0,0);
sb.draw(gameOver, cam.position.x-gameOver.getWidth()/2 , 5*(cam.position.y/3));
sb.draw(ground,groundPos1.x,groundPos1.y);
sb.draw(playAgainBtn,cam.position.x-playAgainBtn.getWidth()/2,2*(cam.position.y/3));
totalScore.draw(sb,STRING,cam.position.x - gameOver.getWidth()/4 ,5*(cam.position.y/4));
sb.end();
}
@Override
public void dispose() {
gameOver.dispose();
gameOverBg.dispose();
playAgainBtn.dispose();
ground.dispose();
totalScore.dispose();
playState.dispose();
System.out.println("Game Over State Disposed");
}
public void fontGenerator(){
FreeTypeFontGenerator generator = new FreeTypeFontGenerator(Gdx.files.internal("bitmapfont/PressStart2P.ttf"));
FreeTypeFontGenerator.FreeTypeFontParameter parameter= new FreeTypeFontGenerator.FreeTypeFontParameter();
parameter.size=12;
parameter.color= Color.GOLD;
parameter.borderColor= Color.GOLDENROD;
totalScore= generator.generateFont(parameter);
totalScore.setUseIntegerPositions(false);
}
public Boolean getAdStart(){
return AdStart;
}
}
I'm still new to this so forgive me if the question is asked inappropriately. Any help is highly appreciated thanks.
You need to stop music of PlayState when you're moving to GameOverState.
As i check you forget to stop music of PlayState when bird position is less than ground height.
if (bird.getPosition().y <= ground.getHeight()){
gsm.set(new GameOverState(gsm));
l = k;
}
No need to create music instance each time when PlayState or/and GameOverState called. Make it at once and use it until you play your game. Dispose your assets like music and all when you exit game.
In some big/heavy game when Assets are very large then need to dispose some Assets when we move from one scene to another scene.