// Applies filter to ALL fixtures that have been added so far
 public void setFilter(short category, short mask) {
   for (Fixture f : scene.getFixtures()) {
     Filter filter = f.getFilterData();
     filter.categoryBits = category;
     filter.maskBits = mask;
     f.setFilterData(filter);
   }
 }
  /**
   * Method is called on end of every collision between two Box2D bodies. Behaviour of the end of
   * certain body collisions are defined in this method. Collisions between bodies are defined and
   * accessed by means of bitwise or-ing their category bits.
   */
  @Override
  public void endContact(Contact c) {
    Fixture fa = c.getFixtureA();
    Fixture fb = c.getFixtureB();

    int collisionDefinition = fa.getFilterData().categoryBits | fb.getFilterData().categoryBits;

    switch (collisionDefinition) {
        // foot sensor breaks from floor
      case B2DVars.BIT_PLAYER_FOOT | B2DVars.BIT_BLOCKS:
        numJumps--;
        break;
        // player breaks from end level region
      case B2DVars.BIT_PLAYER | B2DVars.BIT_END:
        break;
    }
  }
  private static boolean contactFilter(Fixture fixture, Filter filterA) {
    if (filterA == null) return true;
    Filter filterB = fixture.getFilterData();
    if (filterA.groupIndex != 0 && filterA.groupIndex == filterB.groupIndex)
      return filterA.groupIndex > 0;

    return (filterA.maskBits & filterB.categoryBits) != 0
        && (filterA.categoryBits & filterB.maskBits) != 0;
  }
  /**
   * Method is called on every collision between two Box2D bodies. Behaviour of certain body
   * collisions are defined in this method. Collisions between bodies are defined and accessed by
   * means of bitwise or-ing their category bits.
   */
  @Override
  public void beginContact(Contact c) {
    Fixture fa = c.getFixtureA();
    Fixture fb = c.getFixtureB();

    int collisionDefinition = fa.getFilterData().categoryBits | fb.getFilterData().categoryBits;

    switch (collisionDefinition) {
        // foot collides with floor
      case B2DVars.BIT_PLAYER_FOOT | B2DVars.BIT_BLOCKS:
        numJumps++;
        break;

        // Player collides with student, deal damage to player or kill enemy
      case B2DVars.BIT_PLAYER | B2DVars.BIT_STUDENT:
        System.out.println("hit!");
        playerStudentCollisionCount++;

        Vector2 playerPosition, playerVelocity, studentPosition;
        Body player, student;

        if (fa.getUserData().equals("player")) {
          player = fa.getBody();
          playerPosition = fa.getBody().getPosition();
          playerVelocity = fa.getBody().getLinearVelocity();
          student = fb.getBody();
          studentPosition = fb.getBody().getPosition();
        } else {
          player = fb.getBody();
          playerPosition = fb.getBody().getPosition();
          playerVelocity = fb.getBody().getLinearVelocity();
          student = fa.getBody();
          studentPosition = fa.getBody().getPosition();
        }

        // Player hits enemy from above, 0.1 offset is to ensure player is significantly above enemy
        if (playerPosition.y - 0.1 > studentPosition.y && playerVelocity.y <= 0) {
          Game.ass.getAudio("kill").play(1.0f);
          bodiesToKill.add(student);
          player.setLinearVelocity(player.getLinearVelocity().x, 2f);
        } else {
          ((Player) player.getUserData()).damagePlayer();
          Game.ass.getAudio("hit").play(1.0f);
          Vector2 point = new Vector2(playerPosition.x, playerPosition.y);

          if (playerPosition.x < studentPosition.x) {
            player.applyLinearImpulse(new Vector2(-30f, 0), point, true);
          } else {
            player.applyLinearImpulse(new Vector2(30f, 0), point, true);
          }
        }
        break;

        // player collides with coin
      case B2DVars.BIT_PLAYER | B2DVars.BIT_COINS:
        if (fa.getUserData().equals("coin")) {
          // delete coin
          bodiesToKill.add(fa.getBody());
          Game.ass.getAudio("coin").play(1.0f);
        } else {
          bodiesToKill.add(fb.getBody());
          Game.ass.getAudio("coin").play(1.0f);
        }
        break;

        // player collides with end of level region
      case B2DVars.BIT_PLAYER | B2DVars.BIT_END:
        if (fa.getUserData().equals("end")) {
          Player playerB = (Player) fb.getBody().getUserData();
          if (playerB.getNumCoins() == playerB.getNumCoinsToCollect()) {
            playerB.setLevelCompleteBool(true);
            break;
          }
          playerB.setLevelCompleteBool(false);
          break;
        } else {
          Player playerA = (Player) fa.getBody().getUserData();
          if (playerA.getNumCoins() == playerA.getNumCoinsToCollect()) {
            playerA.setLevelCompleteBool(true);
            break;
          }
          playerA.setLevelCompleteBool(false);
          break;
        }
    }
  }