public void tick() {
    if (GlobalOptions.isGameplayStopped) return;

    timeLeft--;
    if (timeLeft == 0) mario.die("Time out!");
    xCamO = xCam;
    yCamO = yCam;

    if (startTime > 0) {
      startTime++;
    }

    float targetXCam = mario.x - 160;

    xCam = targetXCam;

    if (xCam < 0) xCam = 0;
    if (xCam > level.length * cellSize - GlobalOptions.VISUAL_COMPONENT_WIDTH)
      xCam = level.length * cellSize - GlobalOptions.VISUAL_COMPONENT_WIDTH;

    fireballsOnScreen = 0;

    for (Sprite sprite : sprites) {
      if (sprite != mario) {
        float xd = sprite.x - xCam;
        float yd = sprite.y - yCam;
        if (xd < -64
            || xd > GlobalOptions.VISUAL_COMPONENT_WIDTH + 64
            || yd < -64
            || yd > GlobalOptions.VISUAL_COMPONENT_HEIGHT + 64) {
          removeSprite(sprite);
        } else {
          if (sprite instanceof Fireball) fireballsOnScreen++;
        }
      }
    }

    tickCount++;
    level.tick();

    //            boolean hasShotCannon = false;
    //            int xCannon = 0;

    for (int x = (int) xCam / cellSize - 1; x <= (int) (xCam + this.width) / cellSize + 1; x++)
      for (int y = (int) yCam / cellSize - 1; y <= (int) (yCam + this.height) / cellSize + 1; y++) {
        int dir = 0;

        if (x * cellSize + 8 > mario.x + cellSize) dir = -1;
        if (x * cellSize + 8 < mario.x - cellSize) dir = 1;

        SpriteTemplate st = level.getSpriteTemplate(x, y);

        if (st != null) {
          //                        if (st.getType() == Sprite.KIND_SPIKY)
          //                        {
          //                            System.out.println("here");
          //                        }

          if (st.lastVisibleTick != tickCount - 1) {
            if (st.sprite == null || !sprites.contains(st.sprite)) st.spawn(this, x, y, dir);
          }

          st.lastVisibleTick = tickCount;
        }

        if (dir != 0) {
          byte b = level.getBlock(x, y);
          if (((Level.TILE_BEHAVIORS[b & 0xff]) & Level.BIT_ANIMATED) > 0) {
            if ((b % cellSize) / 4 == 3 && b / cellSize == 0) {
              if ((tickCount - x * 2) % 100 == 0) {
                //                                    xCannon = x;
                for (int i = 0; i < 8; i++) {
                  addSprite(
                      new Sparkle(
                          x * cellSize + 8,
                          y * cellSize + (int) (Math.random() * cellSize),
                          (float) Math.random() * dir,
                          0,
                          0,
                          1,
                          5));
                }
                addSprite(new BulletBill(this, x * cellSize + 8 + dir * 8, y * cellSize + 15, dir));

                //                                    hasShotCannon = true;
              }
            }
          }
        }
      }

    for (Sprite sprite : sprites) sprite.tick();

    byte levelElement = level.getBlock(mario.mapX, mario.mapY);
    if (levelElement == (byte) (13 + 3 * 16) || levelElement == (byte) (13 + 5 * 16)) {
      if (levelElement == (byte) (13 + 5 * 16)) mario.setOnTopOfLadder(true);
      else mario.setInLadderZone(true);
    } else if (mario.isInLadderZone()) {
      mario.setInLadderZone(false);
    }

    for (Sprite sprite : sprites) sprite.collideCheck();

    for (Shell shell : shellsToCheck) {
      for (Sprite sprite : sprites) {
        if (sprite != shell && !shell.dead) {
          if (sprite.shellCollideCheck(shell)) {
            if (mario.carried == shell && !shell.dead) {
              mario.carried = null;
              mario.setRacoon(false);
              // System.out.println("sprite = " + sprite);
              shell.die();
              ++this.killedCreaturesTotal;
            }
          }
        }
      }
    }
    shellsToCheck.clear();

    for (Fireball fireball : fireballsToCheck)
      for (Sprite sprite : sprites)
        if (sprite != fireball && !fireball.dead)
          if (sprite.fireballCollideCheck(fireball)) fireball.die();
    fireballsToCheck.clear();

    sprites.addAll(0, spritesToAdd);
    sprites.removeAll(spritesToRemove);
    spritesToAdd.clear();
    spritesToRemove.clear();
  }