public void addXP(int amount) {
    root.engine.missionHandler.pushEvent(new BasicEvent(EventType.SingleXPGain, amount));

    this.xp += amount;
    xpInRound += amount;

    while (xp >= xpNeed) {
      level++;
      xp -= xpNeed;
      xpNeed = getXPForLevel(level);

      ABoundingBox b = root.render.spriteRenderer.camera.getDisplayBounds();
      // root.engine.gui.setCustomFont( new Font( Font.SANS_SERIF, Font.BOLD, 30 ) );
      root.engine.gui.pushNotification("LEVEL UP", 0xff_ffffff, b.x + b.w / 2, b.y + b.h);
      root.engine.missionHandler.pushEvent(new BasicEvent(EventType.LevelUp, level));

      if (root.input.sound) levelUpSound.play();
    }

    if (this.xp < 0) this.xp = 0;

    view.levelChanged();
  }
public class PowerUpSRElement extends FrameSpriteElement {
  private static ASoundClip pickUpSound =
      ASoundClip.createFromClassPath("de/koller/ld27/resources/sound/puHit.wav");

  private final String mask;
  private final int color;

  private static final int MOUSELESS_FRAME = 0;
  private static final int MOUSEOVER_FRAME = 1;
  private static final int MOUSEDOWN_FRAME = 2;

  private final PowerUp powerUp;

  public PowerUpSRElement(PowerUp powerUp, float x, float y, float z, String mask, int color) {
    super(x, y, z, uniqueTexturesName(mask, color));

    this.mask = mask;
    this.color = color;
    this.powerUp = powerUp;

    this.addBehavior(new DragHandler());
  }

  private static String name(String mask, int color) {
    return mask + Integer.toHexString(color);
  }

  private static String[] uniqueTexturesName(String mask, int color) {
    return new String[] {
      name(mask, color) + AButtons.MOUSELESS_POSTFIX,
      name(mask, color) + AButtons.MOUSEOVER_POSTFIX,
      name(mask, color) + AButtons.MOUSEDOWN_POSTFIX,
    };
  }

  @Override
  public void init(SpriteRenderer renderer) {
    AButtons.createMainButtonTexture(
        name(mask, color), mask, color, renderer.getTextureContainer());
    super.init(renderer);
  }

  @Override
  public void removed() {
    super.removed();
  }

  private class DragHandler extends SRDraggable {
    private boolean isPickedUp = false;

    @Override
    protected void pickedUp() {
      super.pickedUp();

      powerUp.handler.root.engine.missionHandler.pushEvent(
          new BasicEvent(EventType.CardPickedUp, powerUp.timeToDespawn));

      powerUp.putOfAssembly();
      isPickedUp = true;

      PowerUpSRElement.this.setZDepth(PowerUpSRElement.this.getzDepth() + 1);

      if (powerUp.handler.root.input.sound) pickUpSound.play();
    }

    @Override
    protected void layerDown() {
      super.layerDown();
      isPickedUp = false;

      powerUp.layedDown();

      PowerUpSRElement.this.setZDepth(PowerUpSRElement.this.getzDepth() - 1);

      BasicEvent b = new BasicEvent(EventType.CardDrag);
      b.object = powerUp;
      powerUp.handler.root.engine.missionHandler.pushEvent(b);
    }

    @Override
    public void updateInput(InputPlain input, boolean overlapped) {
      super.updateInput(input, overlapped);

      if (isMouseOver()) PowerUpSRElement.this.setFrame(PowerUpSRElement.MOUSEOVER_FRAME);
      else PowerUpSRElement.this.setFrame(PowerUpSRElement.MOUSELESS_FRAME);

      if (isPickedUp) PowerUpSRElement.this.setFrame(PowerUpSRElement.MOUSEDOWN_FRAME);

      if (isPickedUp) powerUp.updatePickedUp();
    }
  }
}
public class LevelManager extends PlainNode<LD27Root> {
  private static ASoundClip levelUpSound =
      ASoundClip.createFromClassPath("de/koller/ld27/resources/sound/levelUp.wav");

  @Child public final LevelView view = new LevelView();

  private int level = 1;

  private int xp = 0;
  private int xpNeed = getXPForLevel(level);

  private int xpInRound = 0;

  public void addXP(int amount) {
    root.engine.missionHandler.pushEvent(new BasicEvent(EventType.SingleXPGain, amount));

    this.xp += amount;
    xpInRound += amount;

    while (xp >= xpNeed) {
      level++;
      xp -= xpNeed;
      xpNeed = getXPForLevel(level);

      ABoundingBox b = root.render.spriteRenderer.camera.getDisplayBounds();
      // root.engine.gui.setCustomFont( new Font( Font.SANS_SERIF, Font.BOLD, 30 ) );
      root.engine.gui.pushNotification("LEVEL UP", 0xff_ffffff, b.x + b.w / 2, b.y + b.h);
      root.engine.missionHandler.pushEvent(new BasicEvent(EventType.LevelUp, level));

      if (root.input.sound) levelUpSound.play();
    }

    if (this.xp < 0) this.xp = 0;

    view.levelChanged();
  }

  @Override
  protected void update(int elapsedTime) {
    super.update(elapsedTime);

    if (xpInRound != 0) {
      root.engine.missionHandler.pushEvent(new BasicEvent(EventType.XPGain, xpInRound));
      xpInRound = 0;
    }
  }

  public int getXPForLevel(int level) {
    return level * level + 20;
  }

  public int getXp() {
    return xp;
  }

  public int getLevel() {
    return level;
  }

  public float getLevelProgress() {
    return (float) xp / (float) xpNeed;
  }
}