@Override
  public void dispose() {
    // call methods to dispose of bird and tubes as they pass off screen
    bg.dispose();
    bird.dispose();

    ground.dispose();
    for (Tube tube : tubes) tube.dispose();
  }
  @Override
  public void render(SpriteBatch sb) {

    Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);

    sb.setProjectionMatrix(cam.combined);
    sb.begin();

    // Determine what to render based on score
    {
      if (score <= 3) {
        sb.draw(bg2, cam.position.x - (cam.viewportWidth / 2), 0);
        sb.draw(bird.getTexture(score), bird.getPosition().x, bird.getPosition().y);

      } else if (score <= 6) {
        sb.draw(bg, cam.position.x - (cam.viewportWidth / 2), 0);
        sb.draw(bird.getTexture(score), bird.getPosition().x, bird.getPosition().y);

      } else if (score <= 9) {
        sb.draw(android_bg, cam.position.x - (cam.viewportWidth / 2), 0);
        sb.draw(bird.getTexture(score), bird.getPosition().x, bird.getPosition().y);

      } else if (score > 9) {
        sb.draw(cob_bg, cam.position.x - (cam.viewportWidth / 2), 0);
        sb.draw(bird.getTexture(score), bird.getPosition().x, bird.getPosition().y);
      }

      // pass score to tube to determine what to render
      for (Tube tube : tubes) {

        sb.draw(tube.getTopTube(score), tube.getPosTopTube().x, tube.getPosTopTube().y);
        sb.draw(tube.getBottomTube(score), tube.getPosBotTube().x, tube.getPosBotTube().y);
      }

      // determine what ground to render based on current score
      if (score <= 3) {
        sb.draw(ground, groundPos1.x, groundPos1.y);
        sb.draw(ground, groundPos2.x, groundPos2.y);
      } else if (score <= 6) {
        sb.draw(ground2, groundPos1.x, groundPos1.y);
        sb.draw(ground2, groundPos2.x, groundPos2.y);
      } else if (score <= 9) {
        sb.draw(ground3, groundPos1.x, groundPos1.y);
        sb.draw(ground3, groundPos2.x, groundPos2.y);
      } else if (score > 9) {
        sb.draw(ground4, groundPos1.x, groundPos1.y);
        sb.draw(ground4, groundPos2.x, groundPos2.y);
      }
    }

    sb.end();

    sb.begin();

    // Write score to screen
    font.setColor(Color.WHITE);
    font.draw(sb, String.format("%.0f", score), scoreX, scoreY);

    sb.end();
  }
  @Override
  public void update(float dt) {
    handleInput();
    updateGround();
    updateScoreLocation();
    bird.update(dt);
    cam.position.x = bird.getPosition().x + 80;

    if (bird.getBounds().x >= 156) score = (bird.getBounds().x / 176) - 0.6f;

    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(score).getWidth()) {
        tube.reposition(
            tube.getPosTopTube().x + ((Tube.TUBE_WIDTH + TUBE_SPACING) * TUBE_COUNT), score);
      }

      // Check for tube collision
      if (tube.collides(bird.getBounds())) gsm.set(new GameOver(gsm, score));
    }
    // Check for ground collision
    if (bird.getPosition().y <= ground.getHeight() + GROUND_Y_OFFSET)
      gsm.set(new GameOver(gsm, score));

    // update camera
    cam.update();
  }