Пример #1
0
  /** Computes a list of the valid locations in this cluster. */
  public static List<SceneLocation> getClusterLocs(Cluster cluster) {
    List<SceneLocation> list = Lists.newArrayList();

    // convert our tile coordinates into a cartesian coordinate system
    // with units equal to one fine coordinate in size
    int fx = cluster.x * _metrics.finegran + 1, fy = cluster.y * _metrics.finegran + 1;
    int fwid = cluster.width * _metrics.finegran - 2, fhei = cluster.height * _metrics.finegran - 2;
    int cx = fx + fwid / 2, cy = fy + fhei / 2;

    // if it's a 1x1 cluster, return one location in the center of the
    // cluster
    if (cluster.width == 1) {
      StageLocation loc =
          new StageLocation(
              MisoUtil.toFull(cluster.x, 2),
              MisoUtil.toFull(cluster.y, 2),
              (byte) DirectionCodes.SOUTHWEST);
      list.add(new SceneLocation(loc, 0));
      return list;
    }

    double radius = (double) fwid / 2;
    int clidx = cluster.width - 2;
    if (clidx >= CLUSTER_METRICS.length / 2 || clidx < 0) {
      log.warning("Requested locs from invalid cluster " + cluster + ".", new Exception());
      return list;
    }

    for (double angle = CLUSTER_METRICS[clidx * 2];
        angle < Math.PI * 2;
        angle += CLUSTER_METRICS[clidx * 2 + 1]) {
      int sx = cx + (int) Math.round(Math.cos(angle) * radius);
      int sy = cy + (int) Math.round(Math.sin(angle) * radius);

      // obtain the orientation facing toward the center
      int orient = 2 * (int) (Math.round(angle / (Math.PI / 4)) % 8);
      orient = DirectionUtil.rotateCW(DirectionCodes.SOUTH, orient);
      orient = DirectionUtil.getOpposite(orient);

      // convert them back to full coordinates for the location
      int tx = MathUtil.floorDiv(sx, _metrics.finegran);
      sx = MisoUtil.toFull(tx, sx - (tx * _metrics.finegran));
      int ty = MathUtil.floorDiv(sy, _metrics.finegran);
      sy = MisoUtil.toFull(ty, sy - (ty * _metrics.finegran));
      StageLocation loc = new StageLocation(sx, sy, (byte) orient);
      list.add(new SceneLocation(loc, 0));
    }

    return list;
  }
Пример #2
0
  /**
   * Locates a spot to stand near the supplied rectangular footprint. First a spot will be sought in
   * a tile immediately next to the footprint, then one tile removed, then two, up to the maximum
   * distance specified by <code>dist</code>.
   *
   * @param foot the tile coordinate footprint around which we are attempting to stand.
   * @param dist the maximum number of tiles away from the footprint to search before giving up.
   * @param pred a predicate that will be used to determine whether a particular spot can be stood
   *     upon (we're hijacking the meaning of "traverse" in this case, but the interface is
   *     otherwise so nice).
   * @param traverser the object that will be passed to the traversal predicate.
   * @param nearto a point (in tile coordinates) which will be used to select from among the valid
   *     standing spots, the one nearest to the supplied point will be returned.
   * @param orient if not {@link DirectionCodes#NONE} this orientation will be used to override the
   *     "natural" orientation of the spot which is facing toward the footprint.
   * @return the closest spot to the
   */
  public static StageLocation findStandingSpot(
      Rectangle foot,
      int dist,
      AStarPathUtil.TraversalPred pred,
      Object traverser,
      final Point nearto,
      int orient) {
    // generate a list of the tile coordinates of all squares around
    // this footprint
    SortableArrayList<StageLocation> spots = new SortableArrayList<StageLocation>();

    for (int dd = 1; dd <= dist; dd++) {
      int yy1 = foot.y - dd, yy2 = foot.y + foot.height + dd - 1;
      int xx1 = foot.x - dd, xx2 = foot.x + foot.width + dd - 1;

      // get the corners
      spots.add(new StageLocation(xx1, yy1, (byte) DirectionCodes.SOUTHWEST));
      spots.add(new StageLocation(xx1, yy2, (byte) DirectionCodes.SOUTHEAST));
      spots.add(new StageLocation(xx2, yy1, (byte) DirectionCodes.NORTHWEST));
      spots.add(new StageLocation(xx2, yy2, (byte) DirectionCodes.NORTHEAST));

      // then the sides
      for (int xx = xx1 + 1; xx < xx2; xx++) {
        spots.add(new StageLocation(xx, yy1, (byte) DirectionCodes.WEST));
        spots.add(new StageLocation(xx, yy2, (byte) DirectionCodes.EAST));
      }
      for (int yy = yy1 + 1; yy < yy2; yy++) {
        spots.add(new StageLocation(xx1, yy, (byte) DirectionCodes.SOUTH));
        spots.add(new StageLocation(xx2, yy, (byte) DirectionCodes.NORTH));
      }

      // sort them in order of closeness to the players current
      // coordinate
      spots.sort(
          new Comparator<StageLocation>() {
            public int compare(StageLocation o1, StageLocation o2) {
              return dist(o1) - dist(o2);
            }

            private final int dist(StageLocation l) {
              return Math.round(100 * MathUtil.distance(l.x, l.y, nearto.x, nearto.y));
            }
          });

      // return the first spot that can be "traversed" which we're
      // taking to mean "stood upon"
      for (int ii = 0, ll = spots.size(); ii < ll; ii++) {
        StageLocation loc = spots.get(ii);
        if (pred.canTraverse(traverser, loc.x, loc.y)) {
          // convert to full coordinates
          loc.x = MisoUtil.toFull(loc.x, 2);
          loc.y = MisoUtil.toFull(loc.y, 2);

          // see if we need to override the orientation
          if (DirectionCodes.NONE != orient) {
            loc.orient = (byte) orient;
          }
          return loc;
        }
      }

      // clear this list and try one further out
      spots.clear();
    }

    return null;
  }
Пример #3
0
 /** Converts Cartesian coordinates back to full coordinates. */
 public static void coordsToLocation(int cx, int cy, Point loc) {
   loc.x = MisoUtil.toFull(cx / _metrics.finegran, cx % _metrics.finegran);
   loc.y = MisoUtil.toFull(cy / _metrics.finegran, cy % _metrics.finegran);
 }