Equinox

MeshPath.java

Sep 30th, 2011
138
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Java 11.89 KB | None | 0 0
  1. /**
  2. *Creates a Mesh-based path, rounds it using Bezier curves, then subdivides the generated *path
  3. *@author Equinox-
  4. */
  5. public class MeshPath {
  6.     public static final Color BLOCK_PATH_COLOR = new Color(0f, 1f, 0f, 1f);
  7.     public static final Color MESH_BORDER = new Color(0.75f, 0.75f, 0.75f,
  8.         0.75f);
  9.     public static final Color MESH_FILL = new Color(0.5f, 0.5f, 0.5f, 0.75f);
  10.     public static final Color SMOOTH_PATH_COLOR = new Color(0f, 0f, 1f, 1f);
  11.     private List<RSTile> blockPath = new ArrayList<RSTile>();
  12.     private final Calculations calc;
  13.     private boolean end;
  14.     private List<RSTile[]> mesh = new ArrayList<RSTile[]>();
  15.     private final Players players;
  16.     private List<RSTile> smoothPath = new ArrayList<RSTile>();
  17.     private final Walking walking;
  18.     private final Range walkingDistance;
  19.  
  20.     public MeshPath(Walking walking, Calculations calc, Players players) {
  21.         this(walking, calc, players, new Range(7, 9));
  22.     }
  23.  
  24.     public MeshPath(Walking walking, Calculations calc, Players players,
  25.         Range walkingDistance) {
  26.         this.walking = walking;
  27.         this.calc = calc;
  28.         this.players = players;
  29.         this.walkingDistance = walkingDistance;
  30.     }
  31.  
  32.     public MeshPath(Walking walking, Calculations calc, Players players,
  33.         RSTile[][] mesh) {
  34.         this(walking, calc, players);
  35.         setMesh(mesh);
  36.     }
  37.  
  38.     public MeshPath(Walking walking, Calculations calc, Players players,
  39.         RSTile[][] mesh, Range walkingDistance) {
  40.         this(walking, calc, players, walkingDistance);
  41.         setMesh(mesh);
  42.     }
  43.  
  44.     public void addLine(RSTile... tiles) {
  45.         if (mesh.size() == 0) {
  46.         mesh.add(tiles);
  47.         return;
  48.         }
  49.         RSTile first = tiles[0];
  50.         RSTile last = tiles[tiles.length - 1];
  51.         RSTile[] oLine = mesh.get(mesh.size() - 1);
  52.         RSTile oFirst = oLine[0];
  53.         RSTile oLast = oLine[oLine.length - 1];
  54.         double straight = calc.distanceBetween(first, oFirst)
  55.             + calc.distanceBetween(last, oLast);
  56.         double crossed = calc.distanceBetween(first, oLast)
  57.             + calc.distanceBetween(last, oFirst);
  58.         if (straight > crossed) {
  59.         mesh.add(tiles);
  60.         return;
  61.         } else {
  62.         RSTile[] reversed = new RSTile[tiles.length];
  63.         for (int i = 0; i < tiles.length; i++)
  64.             reversed[i] = tiles[tiles.length - 1 - i];
  65.         mesh.add(reversed);
  66.         return;
  67.         }
  68.     }
  69.  
  70.     public void addMesh(RSTile[][] mesh) {
  71.         for (RSTile[] line : mesh)
  72.         addLine(line);
  73.     }
  74.  
  75.     public void clearPath() {
  76.         blockPath.clear();
  77.         smoothPath.clear();
  78.     }
  79.  
  80.     public void findPath() {
  81.         findPath(MeshPathType.WEIGHT_CENTER);
  82.     }
  83.  
  84.     public void findPath(MeshPathType placement) {
  85.         findPath(placement, 0, mesh.size() - 1);
  86.     }
  87.  
  88.     public void findPath(MeshPathType placement, int start, int end) {
  89.         blockPath.clear();
  90.         for (int i = start; i <= end; i++)
  91.         blockPath.add(getTileOnLine(placement, mesh.get(i)));
  92.         smoothPath = smoothPath(blockPath);
  93.     }
  94.  
  95.     public RSTile getEnd() {
  96.         if (smoothPath.size() > 0)
  97.         return smoothPath.get(smoothPath.size() - 1);
  98.         else
  99.         return null;
  100.     }
  101.  
  102.     public RSTile getNext() {
  103.         if (smoothPath.size() > 0) {
  104.         for (int i = smoothPath.size() - 1; i >= 0; i--)
  105.             if (calc.tileOnMap(smoothPath.get(i)))
  106.             return smoothPath.get(i);
  107.         return getTileOnMap(smoothPath.get(0));
  108.         }
  109.         return null;
  110.     }
  111.  
  112.     public RSTile getTileOnMap(RSTile base) {
  113.         if (calc.tileOnMap(base))
  114.         return base;
  115.         RSTile me = players.getMyPlayer().getLocation();
  116.         int deltaX = base.getX() - me.getX();
  117.         int deltaY = base.getY() - me.getY();
  118.         double dist = calc.distanceBetween(base, me);
  119.         double eX = deltaX / dist, eY = deltaY / dist;
  120.         return new RSTile(me.getX() + (int) (eX * 15), me.getY()
  121.             + (int) (eY * 15));
  122.     }
  123.  
  124.     public RSTile getStart() {
  125.         if (smoothPath.size() > 0)
  126.         return smoothPath.get(0);
  127.         else
  128.         return null;
  129.     }
  130.  
  131.     public RSTile getTileInMesh(RSTile tile) {
  132.         if (inMesh(tile))
  133.         return tile;
  134.         double bestDist = Double.MAX_VALUE;
  135.         RSTile nearest = null;
  136.         if (mesh.size() > 1) {
  137.         for (int i = 1; i < mesh.size(); i++) {
  138.             RSTile[] lineA = mesh.get(i - 1);
  139.             RSTile[] lineB = mesh.get(i);
  140.             if (lineA != null)
  141.             for (RSTile t : lineA) {
  142.                 double dist = calc.distanceBetween(t, tile);
  143.                 if (dist < bestDist) {
  144.                 nearest = new RSTile(t.getX(), t.getY());
  145.                 bestDist = Double.valueOf(dist);
  146.                 }
  147.             }
  148.             if (lineB != null)
  149.             for (RSTile t : lineB) {
  150.                 double dist = calc.distanceBetween(t, tile);
  151.                 if (dist < bestDist) {
  152.                 nearest = new RSTile(t.getX(), t.getY());
  153.                 bestDist = Double.valueOf(dist);
  154.                 }
  155.             }
  156.         }
  157.         }
  158.         return nearest;
  159.     }
  160.  
  161.     public RSTile getTileOnLine(MeshPathType placement, RSTile... line) {
  162.         List<RSTile> tiles = getTilesOnLines(line);
  163.         int index = 0;
  164.         switch (placement) {
  165.         case ALL_CENTER:
  166.         index = new Range((int) (tiles.size() * .25d),
  167.             (int) (tiles.size() * 0.75d)).random();
  168.         break;
  169.         case FULL:
  170.         index = new Range(0, tiles.size()).random();
  171.         break;
  172.         case WEIGHT_CENTER:
  173.         index = new Range(0, tiles.size()).random();
  174.         break;
  175.         }
  176.  
  177.         if (index < 0)
  178.         index = 0;
  179.         if (index >= tiles.size())
  180.         index = tiles.size() - 1;
  181.  
  182.         if (tiles.size() > 0)
  183.         return tiles.get(index);
  184.         else
  185.         return null;
  186.     }
  187.  
  188.     public RSTile getTileOnLine(RSTile... line) {
  189.         return getTileOnLine(MeshPathType.WEIGHT_CENTER, line);
  190.     }
  191.  
  192.     public RSTile[] getTilePath() {
  193.         RSTile[] tiles = new RSTile[smoothPath.size()];
  194.         for (int i = 0; i < tiles.length; i++)
  195.         tiles[i] = new RSTile(smoothPath.get(i).getX(), smoothPath.get(
  196.             i).getY());
  197.         return tiles;
  198.     }
  199.  
  200.     public List<RSTile> getTilesOnLine(RSTile a, RSTile b) {
  201.         List<RSTile> sublineTiles = new ArrayList<RSTile>();
  202.         int deltaX = b.getX() - a.getX();
  203.         int deltaY = b.getY() - a.getY();
  204.         double dist = calc.distanceBetween(a, b);
  205.         if (dist == 0)
  206.         dist = 1;
  207.         double eX = deltaX / dist, eY = deltaY / dist;
  208.         for (int i = 0; i <= dist; i++)
  209.         sublineTiles.add(new RSTile(a.getX() + (int) (eX * i), a.getY()
  210.             + (int) (eY * i)));
  211.         return sublineTiles;
  212.     }
  213.  
  214.     public List<RSTile> getTilesOnLines(RSTile... line) {
  215.         List<RSTile> sublineTiles = new ArrayList<RSTile>();
  216.         if (line.length == 1)
  217.         sublineTiles.add(line[0]);
  218.         else
  219.         for (int i = 1; i < line.length; i++) {
  220.             RSTile a = line[i - 1];
  221.             RSTile b = line[i];
  222.             sublineTiles.addAll(getTilesOnLine(a, b));
  223.         }
  224.         return sublineTiles;
  225.     }
  226.  
  227.     public boolean hasPath() {
  228.         return smoothPath.size() > 0;
  229.     }
  230.  
  231.     public boolean inMesh(RSTile tile) {
  232.         if (mesh.size() > 1) {
  233.         for (int i = 1; i < mesh.size(); i++) {
  234.             RSTile[] lineA = mesh.get(i - 1);
  235.             RSTile[] lineB = mesh.get(i);
  236.             Polygon poly = new Polygon();
  237.             if (lineA != null)
  238.             for (RSTile t : lineA)
  239.                 poly.addPoint(t.getX(), t.getY());
  240.             if (lineB != null)
  241.             for (RSTile t : lineB)
  242.                 poly.addPoint(t.getX(), t.getY());
  243.  
  244.             if (poly.npoints >= 2)
  245.             if (poly.contains(new Point(tile.getX(), tile.getY())))
  246.                 return true;
  247.         }
  248.         }
  249.         return false;
  250.     }
  251.  
  252.     public boolean isValid() {
  253.         return smoothPath.size() > 0 && getNext() != null
  254.             && !players.getMyPlayer().getLocation().equals(getEnd());
  255.     }
  256.  
  257.     public int meshSize() {
  258.         return mesh.size();
  259.     }
  260.  
  261.     public void paintAll(Graphics2D g) {
  262.         paintMesh(g);
  263.         paintBlockPath(g);
  264.         paintSmoothPath(g);
  265.     }
  266.  
  267.     public void paintBlockPath(Graphics2D g) {
  268.         if (blockPath.size() > 1) {
  269.         g.setColor(BLOCK_PATH_COLOR);
  270.         Point a = null;
  271.         for (RSTile t : blockPath) {
  272.             Point b = calc.tileToMinimap(t);
  273.             if (b.x > 0 && b.y > 0)
  274.             g.fillOval(b.x - 2, b.y - 2, 5, 5);
  275.             if (a != null && a.x > 0 && a.y > 0 && b.x > 0 && b.y > 0)
  276.             g.drawLine(a.x, a.y, b.x, b.y);
  277.             a = b;
  278.         }
  279.         }
  280.     }
  281.  
  282.     public void paintMesh(Graphics2D g) {
  283.         if (mesh.size() > 1) {
  284.         Point[] oldLine = null;
  285.         for (int i = 0; i < mesh.size(); i++) {
  286.             RSTile[] lineB = mesh.get(i);
  287.             Point[] thisLine = new Point[lineB.length];
  288.             Polygon poly = new Polygon();
  289.             boolean onMap = true;
  290.             for (int tile = 0; tile < thisLine.length; tile++) {
  291.             Point p = calc.tileToMinimap(lineB[tile]);
  292.             thisLine[tile] = p;
  293.             poly.addPoint(p.x, p.y);
  294.             if (p.x == -1 || p.y == -1)
  295.                 onMap = false;
  296.             }
  297.             if (oldLine != null) {
  298.             for (Point p : oldLine) {
  299.                 poly.addPoint(p.x, p.y);
  300.                 if (p.x == -1 || p.y == -1)
  301.                 onMap = false;
  302.             }
  303.             if (poly.npoints >= 2 && onMap) {
  304.                 g.setColor(MESH_BORDER);
  305.                 g.draw(poly);
  306.                 g.setColor(MESH_FILL);
  307.                 g.fill(poly);
  308.             }
  309.             }
  310.             oldLine = thisLine;
  311.         }
  312.         }
  313.     }
  314.  
  315.     public void paintSmoothPath(Graphics2D g) {
  316.         if (smoothPath.size() > 1) {
  317.         g.setColor(SMOOTH_PATH_COLOR);
  318.         Point a = null;
  319.         for (RSTile t : smoothPath) {
  320.             Point b = calc.tileToMinimap(t);
  321.             if (b.x > 0 && b.y > 0)
  322.             g.fillOval(b.x - 2, b.y - 2, 5, 5);
  323.             if (a != null && a.x > 0 && a.y > 0 && b.x > 0 && b.y > 0)
  324.             g.drawLine(a.x, a.y, b.x, b.y);
  325.             a = b;
  326.         }
  327.         }
  328.     }
  329.  
  330.     public MeshPath reverse() {
  331.         MeshPath m = new MeshPath(walking, calc, players);
  332.         for (int i = mesh.size() - 1; i >= 0; i--) {
  333.         m.addLine(blockPath.get(i));
  334.         }
  335.         return m;
  336.     }
  337.  
  338.     public void setMesh(RSTile[][] mesh) {
  339.         this.mesh.clear();
  340.         addMesh(mesh);
  341.     }
  342.  
  343.     public List<RSTile> smoothPath(List<RSTile> path) {
  344.         List<RSTile> smoothed = new ArrayList<RSTile>();
  345.         if (path.size() >= 3) {
  346.         for (int i = 0; i < path.size(); i++) {
  347.             if (i + 2 < path.size()) {
  348.             RSTile tile1 = path.get(i);
  349.             RSTile tile2 = path.get(i + 1);
  350.             RSTile tile3 = path.get(i + 2);
  351.             if (i == 0)
  352.                 smoothed.add(tile1);
  353.             double x2, y2;
  354.             double t = 0.5d;
  355.             x2 = (tile1.getX() + t
  356.                 * (-tile1.getX() * 3 + t
  357.                     * (3 * tile1.getX() - tile1.getX() * t)))
  358.                 + t
  359.                 * (3 * tile2.getX() + t
  360.                     * (-6 * tile2.getX() + tile2.getX() * 3
  361.                         * t))
  362.                 + t
  363.                 * t
  364.                 * (tile2.getX() * 3 - tile2.getX() * 3 * t)
  365.                 + tile3.getX() * t * t * t;
  366.             y2 = (tile1.getY() + t
  367.                 * (-tile1.getY() * 3 + t
  368.                     * (3 * tile1.getY() - tile1.getY() * t)))
  369.                 + t
  370.                 * (3 * tile2.getY() + t
  371.                     * (-6 * tile2.getY() + tile2.getY() * 3
  372.                         * t))
  373.                 + t
  374.                 * t
  375.                 * (tile2.getY() * 3 - tile2.getY() * 3 * t)
  376.                 + tile3.getY() * t * t * t;
  377.             smoothed.add(getTileInMesh(new RSTile((int) x2,
  378.                 (int) y2)));
  379.             } else {
  380.             smoothed.add(path.get(i));
  381.             }
  382.         }
  383.         }
  384.         return smoothed;
  385.     }
  386.  
  387.     public boolean traverse() {
  388.         return this.traverse(EnumSet.of(TraversalOption.HANDLE_RUN,
  389.             TraversalOption.SPACE_ACTIONS));
  390.     }
  391.  
  392.     public boolean traverse(EnumSet<TraversalOption> options) {
  393.         RSTile next = getNext();
  394.         if (next == null) {
  395.         return false;
  396.         }
  397.         if (next.equals(getEnd())) {
  398.         if (calc.distanceTo(next) <= 1
  399.             || (end && players.getMyPlayer().isMoving())
  400.             || next.equals(walking.getDestination())) {
  401.             return false;
  402.         }
  403.         end = true;
  404.         } else {
  405.         end = false;
  406.         }
  407.         if (options.contains(TraversalOption.HANDLE_RUN)
  408.             && !walking.isRunEnabled() && walking.getEnergy() > 50) {
  409.         walking.setRun(true);
  410.         }
  411.         if (options.contains(TraversalOption.SPACE_ACTIONS)) {
  412.         RSTile dest = walking.getDestination();
  413.         if (dest != null
  414.             && players.getMyPlayer().isMoving()
  415.             && calc.distanceTo(dest) > 5
  416.             && calc.distanceBetween(next, dest) < walkingDistance
  417.                 .random()) {
  418.             return true;
  419.         }
  420.         }
  421.         return walking.walkTileMM(next, 0, 0);
  422.     }
  423.  
  424.     public int getNearestIndexTo(RSTile t) {
  425.         int len = Integer.MAX_VALUE;
  426.         int bestIndex = -1;
  427.         if (hasPath())
  428.         for (int i = 0; i < smoothPath.size(); i++)
  429.             if (calc.distanceBetween(t, smoothPath.get(i)) < len) {
  430.             bestIndex = i;
  431.             len = calc.distanceTo(t);
  432.             }
  433.         return bestIndex;
  434.     }
  435.  
  436.     public enum MeshPathType {
  437.         ALL_CENTER, FULL, WEIGHT_CENTER
  438.     }
  439.     }
  440.  
Advertisement
Add Comment
Please, Sign In to add comment