/**
   * draw the screen.
   *
   * @param c
   * @param v
   */
  @Override
  public void draw(Canvas c, View v) {
    try {
      // actually draw the screen
      scaledDst.set(0, 0, width, height);
      c.drawBitmap(wallbtm, null, scaledDst, p);

      // draw wall's bounds, for debugging
      // p.setColor(Color.RED);
      // c.drawRect(wallbounds_at_screen_z, p);

      // draw fruits
      for (Fruit f : fruitsSplatted) {
        drawFruit3Dcoords(c, f, f.getSplatBitmap(), wallxcenter, wallycenter);
      }
      synchronized (fruitsFlying) {
        for (Fruit f : fruitsFlying) {
          drawFruit3Dcoords(c, f, f.getBitmap(System.nanoTime()), wallxcenter, wallycenter);
        }
      }
      synchronized (fruitsSelectable) {
        for (Fruit f : fruitsSelectable) {
          // selectable fruit is on z=0, so we can just display normally:
          c.drawBitmap(f.getBitmap(), f.x - f.seed.halfWidth, f.y - f.seed.halfHeight, p);
        }
      }

      // draw combo hits
      for (Combo combo : hitCombos.keySet()) {
        ComboHit ch = hitCombos.get(combo);
        // p.setColor(Color.YELLOW);
        p.setARGB(
            ch.alpha,
            190 + (int) (Math.random() * 60),
            190 + (int) (Math.random() * 60),
            (int) (Math.random() * 60));
        p.setTypeface(act.getGameFont());
        p.setTextSize(act.TS_NORMAL);
        c.drawText(combo.name, ch.x, ch.y, p);
      }

      //            c.drawText("fps: "+fps
      //                    +" w:"+width + " h:" +height
      //                        +"x:"+touchx+" y:"+touchy+"
      // tvx:"+(int)touchvx+"\ttvy:"+(int)touchvy+
      //                    "\tflying:" + fruitsFlying.size()
      //                            + "\nff vz:" + (fruitsFlying.size() > 0 ? fruitsFlying.get(0).vz
      // : -1)
      //                            + "\nff vy:" + (fruitsFlying.size() > 0 ? fruitsFlying.get(0).vy
      // : -1)
      //                            + " ffvz:" + (fruitsFlying.size() > 0 ? fruitsFlying.get(0).vz :
      // -1),
      //                    , 0, 200, p);
      p.setColor(Color.WHITE);
      p.setTextSize(act.TS_NORMAL);
      p.setTypeface(act.getGameFont());
      p.setFakeBoldText(true);
      // drawtext draws bottom-aligned?
      c.drawText("ROUND: " + round, width - rhstextoffset, statstextheight, p);
      c.drawText("LIVES: " + lives, width - rhstextoffset, statstextheight2, p);
      c.drawText("SCORE: " + score, 10, statstextheight, p);
      if (score >= hiscore) {
        hiscore = score;
        hilev = round;
      }
      c.drawText("HIGH: " + hiscore + ", r" + hilev, 10, statstextheight2, p);

      // game programming!  pure and constant state manipulation!
      // this is like fingernails on a chalkboard for the functional programming crowd
      if (gamestate == State.ROUNDSUMMARY
          || gamestate == State.STARTGAME
          || gamestate == State.PLAYERDIED
          || gamestate == State.GAMEOVER) {
        if (gamestate != State.STARTGAME) {
          // round ended, by completion or player death, display stats
          int splatPct = (int) (nWallSplats * 100 / nTotFruit);

          drawCenteredText(
              c, splatPct + "% sPLAttaGe! (" + minRoundPassPct + "% required)", height / 3, p, 0);
          if (gamestate == State.ROUNDSUMMARY) {
            if (splatPct < 80) drawCenteredText(c, "not too bad.", (int) (height / 2.5), p, 0);
            else if (splatPct < 85) drawCenteredText(c, "nice!", (int) (height / 2.5), p, 0);
            else if (splatPct <= 95) {
              drawCenteredText(c, "cRudE!", (int) (height / 2.5), p, 0);
            } else if (round > 10) {
              c.drawText("Dude, really?!", width / 4, (int) (height / 2.5), p);
              c.drawText("Awesome.", width / 3, (int) (height / 2.2), p);
            } else {
              drawCenteredText(c, "eEEeEeeEh!! sPAzMiC!", (int) (height / 2.5), p, 0);
            }
          } else if (gamestate == State.PLAYERDIED || gamestate == State.GAMEOVER)
            c.drawText("...Ooops.", width / 3, (int) (height / 2.5), p);
        }

        if (gamestate != State.PLAYERDIED && gamestate != State.GAMEOVER) {
          String msg = levelmsgMap.get(Integer.valueOf(round));
          if (msg != null) {
            if (msg.contains(LINE_SPLIT_MARKER)) {
              drawCenteredText(
                  c, msg.substring(0, msg.indexOf(LINE_SPLIT_MARKER)), height * 3 / 5, p, 0);
              drawCenteredText(
                  c, msg.substring(msg.indexOf(LINE_SPLIT_MARKER) + 1), height * 2 / 3, p, 0);
            } else drawCenteredText(c, msg, height * 3 / 5, p, 0);
          }
        }

        if (gamestate != State.GAMEOVER) {
          p.setTextSize(act.TS_BIG);
          p.setColor(Color.RED);
          drawCenteredText(c, "Touch to continue", height * 4 / 5, p, -2);
          p.setColor(Color.WHITE);
          drawCenteredText(c, "Touch to continue", height * 4 / 5, p, 0);
        }
      }
      if (gamestate == State.GAMEOVER) {
        p.setTextSize(act.TS_BIG);
        p.setColor(Color.RED);
        drawCenteredText(c, "GamE oVeR!", height / 2, p, -2);
        drawCenteredText(c, "Touch to end game", height * 4 / 5, p, -2);
        p.setColor(Color.WHITE);
        drawCenteredText(c, "GamE oVeR!", height / 2, p, 0);
        drawCenteredText(c, "Touch to end game", height * 4 / 5, p, 0);
      }

    } catch (Exception e) {
      Log.e(MainActivity.LOG_ID, "draw", e);
      e.printStackTrace();
    }
  }