/** 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; }
/** * Returns a polygon framing the specified scene footprint. * * @param x the x tile coordinate of the "upper-left" of the footprint. * @param y the y tile coordinate of the "upper-left" of the footprint. * @param width the width in tiles of the footprint. * @param height the height in tiles of the footprint. */ public static Polygon getFootprintPolygon( MisoSceneMetrics metrics, int x, int y, int width, int height) { SmartPolygon footprint = new SmartPolygon(); Point tpos = MisoUtil.tileToScreen(metrics, x, y, new Point()); // start with top-center point int rx = tpos.x + metrics.tilehwid, ry = tpos.y; footprint.addPoint(rx, ry); // right point rx += width * metrics.tilehwid; ry += width * metrics.tilehhei; footprint.addPoint(rx, ry); // bottom-center point rx -= height * metrics.tilehwid; ry += height * metrics.tilehhei; footprint.addPoint(rx, ry); // left point rx -= width * metrics.tilehwid; ry -= width * metrics.tilehhei; footprint.addPoint(rx, ry); // end with top-center point rx += height * metrics.tilehwid; ry -= height * metrics.tilehhei; footprint.addPoint(rx, ry); return footprint; }
/** * Does the necessary jiggery pokery to figure out where the specified object's associated * location is. * * @param tilemgr a tile manager that can be used to look up the tile information. * @param tileId the fully qualified tile id of the object tile. * @param tx the object's x tile coordinate. * @param ty the object's y tile coordinate. * @param orient - the orientation to use in the returned location, or {@link #OBJECT_ORIENTATION} * if the tile's orientation should be used */ public static StageLocation locationForObject( TileManager tilemgr, int tileId, int tx, int ty, int orient) { try { int tsid = TileUtil.getTileSetId(tileId); int tidx = TileUtil.getTileIndex(tileId); TrimmedObjectTileSet tset = (TrimmedObjectTileSet) tilemgr.getTileSet(tsid); if (tset == null || (orient == OBJECT_ORIENTATION && tset.getSpotOrient(tidx) < 0)) { return null; } if (orient == OBJECT_ORIENTATION) { orient = tset.getSpotOrient(tidx); } Point opos = MisoUtil.tilePlusFineToFull( _metrics, tx, ty, tset.getXSpot(tidx), tset.getYSpot(tidx), new Point()); // Log.info("Computed location [set=" + tset.getName() + // ", tidx=" + tidx + ", tx=" + tx + ", ty=" + ty + // ", sx=" + tset.getXSpot(tidx) + // ", sy=" + tset.getYSpot(tidx) + // ", lx=" + opos.x + ", ly=" + opos.y + // ", fg=" + _metrics.finegran + "]."); return new StageLocation(opos.x, opos.y, (byte) orient); } catch (Exception e) { log.warning("Unable to look up object tile for scene object", "tileId", tileId, e); } return null; }
public BlockGlyph(MisoSceneMetrics metrics, int bx, int by) { _bpoly = MisoUtil.getTilePolygon(metrics, bx, by); }
/** * 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; }
/** 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); }
/** Converts full coordinates to Cartesian coordinates. */ public static void locationToCoords(int lx, int ly, Point coords) { int tx = MisoUtil.fullToTile(lx), fx = MisoUtil.fullToFine(lx); int ty = MisoUtil.fullToTile(ly), fy = MisoUtil.fullToFine(ly); coords.x = tx * _metrics.finegran + fx; coords.y = ty * _metrics.finegran + fy; }