/** @param difficulty Which difficulty level the game model should be on. */
  public GameModel(Difficulty difficulty) {
    bulletManager = new BulletManager();
    enemyManager = new EnemyManager();
    pickupManager = new PickupManager();
    WeaponFactory.initialize(bulletManager);
    enemySpawner = new EnemySpawner(new RandomWaveList(difficulty));
    enemySpawner.addPropertyChangeListener(enemyManager);
    player = new Player(PlayerID.PLAYER1, bulletManager);
    pcs = new PropertyChangeSupport(this);

    // Player listens when enemies are killed
    enemyManager.addPropertyChangeListener(player);
  }
  /**
   * Creates a new ParabolaEnemy
   *
   * @param startPoint where the ParabolaEnemy will appear
   * @param midPoint a point between the startPoint and the endPoint (in x coordinate), specifying
   *     the look of the movement curve
   * @param endPosition where the ParabolaEnemy will move towards
   * @param weaponName what kind of weapon this enemy will wield
   */
  public ParabolaEnemy(
      Position startPoint, Position midPoint, Position endPoint, ObjectName weaponName) {
    super(
        new EnemyShip(startPoint, SHIP_SIZE, SHIP_SIZE, HITPOINTS, ObjectName.PARABOLA_ENEMYSHIP),
        WeaponFactory.getNewWeapon(weaponName));
    if (!midPointIsInMiddle(startPoint.getX(), midPoint.getX(), endPoint.getX())) {
      throw new IllegalArgumentException(
          "MidPoints x-coordinate must lie between startPoints"
              + " x-coordinate and endPoints x-coordinate");
    }
    this.startPoint = startPoint;
    this.midPoint = midPoint;
    this.endPoint = endPoint;

    // negate speed if the curve goes from right to left
    if (endPoint.getX() - startPoint.getX() < 0) {
      speed *= -1;
    }
  }
  private void checkCollisions() {
    final List<IBullet> playerBullets = bulletManager.getBulletsFrom(PlayerID.PLAYER1);
    final List<IBullet> enemyBullets = bulletManager.getBulletsFrom(PlayerID.ENEMY);

    // Check player bullets against enemies
    for (IBullet b : playerBullets) {
      for (IEnemy e : enemyManager.getEnemies()) {
        if (b.collidesWith(e.getShip())) {
          e.getShip().receiveDamage(b.getDamage());
          pcs.firePropertyChange(Constants.EVENT_ENEMY_DAMAGED, null, e.getShip());
          b.markForRemoval();
        }
      }
    }

    // Check enemy bullets against player
    if (!player.isInvincible()) {
      for (IBullet b : enemyBullets) {
        if (b.collidesWith(player.getShip())) {
          player.getShip().receiveDamage(b.getDamage());
          pcs.firePropertyChange(Constants.EVENT_ENTITY_INVINCIBLE, null, player);
          b.markForRemoval();
          break;
        }
      }
    }

    // Check Items against player
    for (int i = 0; i < pickupManager.getPickups().size(); i++) {
      WeaponPickup wp = pickupManager.getPickups().get(i);
      if (wp.collidesWith(player.getShip())) {
        player.giveWeapon(WeaponFactory.getNewWeapon(wp.getObjectName()));
        pickupManager.removePickup(i);
        i--;
      }
    }
  }