Jigar Pandya
Jigar Pandya

Reputation: 2147

Pause/Resume a Simple Libgdx Game for android

Presently I'm trying to implement simple game using libgdx for Android Platform. I have implemented the game but don't know how to pause and resume game based on user input.Kindly suggest idea as well as some practical code to implement the same.I am using simple game code demonstrated in libgdx library. Thank you.

Here is the code :

public class Drop implements ApplicationListener {
   Texture dropImage;
   Texture bucketImage;
   Sound dropSound;
   Music rainMusic;
   SpriteBatch batch;
   OrthographicCamera camera;
   Rectangle bucket;
   Array<Rectangle> raindrops;
   long lastDropTime;

   @Override
   public void create() {
      // load the images for the droplet and the bucket, 64x64 pixels each
      dropImage = new Texture(Gdx.files.internal("droplet.png"));
      bucketImage = new Texture(Gdx.files.internal("bucket.png"));

      // load the drop sound effect and the rain background "music"
      dropSound = Gdx.audio.newSound(Gdx.files.internal("drop.wav"));
      rainMusic = Gdx.audio.newMusic(Gdx.files.internal("rain.mp3"));

      // start the playback of the background music immediately
      rainMusic.setLooping(true);
      rainMusic.play();

      // create the camera and the SpriteBatch
      camera = new OrthographicCamera();
      camera.setToOrtho(false, 800, 480);
      batch = new SpriteBatch();

      // create a Rectangle to logically represent the bucket
      bucket = new Rectangle();
      bucket.x = 800 / 2 - 64 / 2; // center the bucket horizontally
      bucket.y = 20; // bottom left corner of the bucket is 20 pixels above the bottom screen edge
      bucket.width = 64;
      bucket.height = 64;

      // create the raindrops array and spawn the first raindrop
      raindrops = new Array<Rectangle>();
      spawnRaindrop();
   }

   private void spawnRaindrop() {
      Rectangle raindrop = new Rectangle();
      raindrop.x = MathUtils.random(0, 800-64);
      raindrop.y = 480;
      raindrop.width = 64;
      raindrop.height = 64;
      raindrops.add(raindrop);
      lastDropTime = TimeUtils.nanoTime();
   }

   @Override
   public void render() {
      // clear the screen with a dark blue color. The
      // arguments to glClearColor are the red, green
      // blue and alpha component in the range [0,1]
      // of the color to be used to clear the screen.
      Gdx.gl.glClearColor(0, 0, 0.2f, 1);
      Gdx.gl.glClear(GL10.GL_COLOR_BUFFER_BIT);

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

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

      // begin a new batch and draw the bucket and
      // all drops
      batch.begin();
      batch.draw(bucketImage, bucket.x, bucket.y);
      for(Rectangle raindrop: raindrops) {
         batch.draw(dropImage, raindrop.x, raindrop.y);
      }
      batch.end();

      // process user input
      if(Gdx.input.isTouched()) {
         Vector3 touchPos = new Vector3();
         touchPos.set(Gdx.input.getX(), Gdx.input.getY(), 0);
         camera.unproject(touchPos);
         bucket.x = touchPos.x - 64 / 2;
      }
      if(Gdx.input.isKeyPressed(Keys.LEFT)) bucket.x -= 200 * Gdx.graphics.getDeltaTime();
      if(Gdx.input.isKeyPressed(Keys.RIGHT)) bucket.x += 200 * Gdx.graphics.getDeltaTime();

      // make sure the bucket stays within the screen bounds
      if(bucket.x < 0) bucket.x = 0;
      if(bucket.x > 800 - 64) bucket.x = 800 - 64;

      // check if we need to create a new raindrop
      if(TimeUtils.nanoTime() - lastDropTime > 1000000000) spawnRaindrop();

      // move the raindrops, remove any that are beneath the bottom edge of
      // the screen or that hit the bucket. In the later case we play back
      // a sound effect as well.
      Iterator<Rectangle> iter = raindrops.iterator();
      while(iter.hasNext()) {
         Rectangle raindrop = iter.next();
         raindrop.y -= 200 * Gdx.graphics.getDeltaTime();
         if(raindrop.y + 64 < 0) iter.remove();
         if(raindrop.overlaps(bucket)) {
            dropSound.play();
            iter.remove();
         }
      }
   }

   @Override
   public void dispose() {
      // dispose of all the native resources
      dropImage.dispose();
      bucketImage.dispose();
      dropSound.dispose();
      rainMusic.dispose();
      batch.dispose();
   }

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

   @Override
   public void pause() {
   }

   @Override
   public void resume() {
   }
}

Upvotes: 6

Views: 21495

Answers (5)

Steve Marcus
Steve Marcus

Reputation: 229

Even more simple, see here: https://github.com/libgdx/libgdx/wiki/Continuous-&-non-continuous-rendering

In your ApplicationListener's create method, just put

Gdx.graphics.setContinuousRendering(false);
Gdx.graphics.requestRendering(); 

Set up a boolean

public boolean paused = false;

Then for example a button listener to pause/resume on a button press

 buttonPause.addListener(new ChangeListener() {
            public void changed (ChangeEvent event, Actor actor) {

            // set paused true or false here

            }
        });

Then right at the end of your render method, just add:

if (!paused) {
            Gdx.graphics.requestRendering();
        }

The render method is now paused/resumed.

Upvotes: 2

CatchTheThunder
CatchTheThunder

Reputation: 57

I tried using this approach: I made GAME_PAUSED a boolean , If it is true don't update your screen or camera . Otherwise update Camera .

boolean GAME_PAUSED = false;


    if (GAME_PAUSED) {
    //Do not update camera
        batch.begin();
        resumeButton.draw(batch);
        batch.end();
    } else {
    //Update Camera
    Gdx.gl.glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
    Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
    world.step(1/60f, 8, 3);
    camera.update();
    debugRenderer.render(world, camera.combined);
    //Do your game running
    }

Upvotes: -1

witnessmenow
witnessmenow

Reputation: 308

I don't have the rep to reply to comments, but the flickering of items is something I ran into before.

You are no longer clearing the screen and redrawing the sprites in your render when its paused right? If I am not mistaken if you glClear and redraw the srpites in every render i think it will stop

Upvotes: 1

bemeyer
bemeyer

Reputation: 6231

The most simple thing is, that you add an Enum:

public enum State
{
    PAUSE,
    RUN,
    RESUME,
    STOPPED
}

And modify your rendermethod

private State state = State.RUN;

@Override
public void render()
{
    switch (state)
    {
    case RUN:
//do suff here
        break;
    case PAUSE:
//do stuff here

        break;
    case RESUME:

        break;

    default:
        break;
    }
}

Use the callback from android too. For example use the callbacks from libgdx to change the state:

@Override
public void pause()
{
    this.state = State.PAUSE;
}

@Override
public void resume()
{
    this.state = State.RESUME;
}

Also add something like a setMethod for the state so you can change it on userevent.

public void setGameState(State s){
    this.state = s;
}

Upvotes: 12

Daahrien
Daahrien

Reputation: 10320

You can use states, with enums or constants. and only update in the Running state. Something like this:

public enum State{
    Running, Paused
}

State state = State.Running;

@Override
public void render(){
    switch(state){
        case Running:
            update();
            break;
        case Paused:
            //don't update
            break;
    }
    draw();
}

public void update(){
    //your update code
}
public void draw(){
    //your render code
}

Upvotes: 6

Related Questions