Browse Source

Initial version of pathfinding

cognitivegears 5 years ago
parent
commit
a8e68af6db

+ 35
- 64
src/com/droidquest/avatars/GameCursor.java View File

@@ -3,6 +3,7 @@ package com.droidquest.avatars;
3 3
 import com.droidquest.Room;
4 4
 import com.droidquest.RoomDisplay;
5 5
 import com.droidquest.items.*;
6
+import com.droidquest.pathfinder.Node;
6 7
 
7 8
 import javax.swing.*;
8 9
 import java.awt.*;
@@ -324,81 +325,51 @@ public class GameCursor extends Player {
324 325
         return level.cheatmode;
325 326
     }
326 327
 
327
-    public void Animate() {
328
-        if (automove == 1 && room == null) {
329
-            automove = 0;
330
-        }
331
-        if (automove == 1) {
332
-            int dx = autoX - x;
333
-            int dy = autoY - y;
334
-            if (dx == 0 && dy == 0) {
335
-                automove = 0;
336
-                return;
337
-            }
338
-            if (dx < -28) {
339
-                dx = -28;
340
-            }
341
-            if (dx > 28) {
342
-                dx = 28;
343
-            }
344
-            if (dy < -32) {
345
-                dy = -32;
346
-            }
347
-            if (dy > 32) {
348
-                dy = 32;
349
-            }
350
-            walk = 1 - walk;
351
-            if (dx == 0) {
352
-                if (dy < 0) {
353
-                    currentIcon = icons[0 + walk].getImage();
354
-                }
355
-                else {
356
-                    currentIcon = icons[2 + walk].getImage();
357
-                }
328
+
329
+    @Override
330
+    protected void animateCharacter(int dx, int dy) {
331
+        walk = 1 - walk;
332
+        if (dx == 0) {
333
+            if (dy < 0) {
334
+                currentIcon = icons[0 + walk].getImage();
358 335
             }
359 336
             else {
360
-                if (dx < 0) {
361
-                    currentIcon = icons[4 + walk].getImage();
362
-                }
363
-                else {
364
-                    currentIcon = icons[6 + walk].getImage();
365
-                }
366
-            }
367
-            if (dx > 0) {
368
-                moveRight(dx);
337
+                currentIcon = icons[2 + walk].getImage();
369 338
             }
339
+        }
340
+        else {
370 341
             if (dx < 0) {
371
-                moveLeft(-dx);
372
-            }
373
-            if (dy > 0) {
374
-                moveDown(dy);
375
-            }
376
-            if (dy < 0) {
377
-                moveUp(-dy);
342
+                currentIcon = icons[4 + walk].getImage();
378 343
             }
379
-        }
380
-        if (automove == 2) {
381
-            walk = 1 - walk;
382
-            if (autoX > 0) {
344
+            else {
383 345
                 currentIcon = icons[6 + walk].getImage();
384
-                moveRight(autoX);
385 346
             }
347
+        }
348
+    }
386 349
 
387
-            if (autoX < 0) {
388
-                currentIcon = icons[4 + walk].getImage();
389
-                moveLeft(-autoX);
390
-            }
350
+    @Override
351
+    protected void autoMoveFull() {
352
+        walk = 1 - walk;
353
+        if (autoX > 0) {
354
+            currentIcon = icons[6 + walk].getImage();
355
+            moveRight(autoX);
356
+        }
391 357
 
392
-            if (autoY > 0) {
393
-                currentIcon = icons[2 + walk].getImage();
394
-                moveDown(autoY);
395
-            }
358
+        if (autoX < 0) {
359
+            currentIcon = icons[4 + walk].getImage();
360
+            moveLeft(-autoX);
361
+        }
396 362
 
397
-            if (autoY < 0) {
398
-                currentIcon = icons[0 + walk].getImage();
399
-                moveUp(-autoY);
400
-            }
363
+        if (autoY > 0) {
364
+            currentIcon = icons[2 + walk].getImage();
365
+            moveDown(autoY);
401 366
         }
367
+
368
+        if (autoY < 0) {
369
+            currentIcon = icons[0 + walk].getImage();
370
+            moveUp(-autoY);
371
+        }
372
+
402 373
     }
403 374
 
404 375
     public GenericRobot PlayerInRobot(GenericRobot robot) {

+ 23
- 6
src/com/droidquest/avatars/PaintBrush.java View File

@@ -93,8 +93,8 @@ public class PaintBrush extends Player {
93 93
         paintMats[1] = Material.FindSimiliar(new Material(Color.green, false, false));
94 94
         Item robot = null;
95 95
 
96
-        for(Item item : level.items) {
97
-            if(item instanceof OrangeRobot) {
96
+        for (Item item : level.items) {
97
+            if (item instanceof OrangeRobot) {
98 98
                 robot = item;
99 99
             }
100 100
         }
@@ -104,14 +104,14 @@ public class PaintBrush extends Player {
104 104
         paintMats[2] = Material.FindSimiliar(new RobotBlocker(robot, new Color(255, 128, 0)));
105 105
 
106 106
         for (Item item : level.items) {
107
-            if(item instanceof WhiteRobot) {
107
+            if (item instanceof WhiteRobot) {
108 108
                 robot = item;
109 109
             }
110 110
         }
111 111
         paintMats[3] = Material.FindSimiliar(new RobotBlocker(robot, Color.white));
112 112
 
113
-        for(Item item : level.items) {
114
-            if(item instanceof BlueRobot) {
113
+        for (Item item : level.items) {
114
+            if (item instanceof BlueRobot) {
115 115
                 robot = item;
116 116
             }
117 117
         }
@@ -210,9 +210,10 @@ public class PaintBrush extends Player {
210 210
 
211 211
     @Override
212 212
     protected boolean handleRepeatSpace() {
213
-         return false;
213
+        return false;
214 214
     }
215 215
 
216
+    @Override
216 217
     public void moveUp(boolean nudge) {
217 218
         int dist = 32;
218 219
         if (nudge) {
@@ -231,6 +232,7 @@ public class PaintBrush extends Player {
231 232
         }
232 233
     }
233 234
 
235
+    @Override
234 236
     public void moveDown(boolean nudge) {
235 237
         int dist = 32;
236 238
         if (nudge) {
@@ -249,6 +251,20 @@ public class PaintBrush extends Player {
249 251
         }
250 252
     }
251 253
 
254
+//    @Override
255
+//    protected void findPath(int startX, int startY, int endX, int endY) {
256
+//        // The paintbrush can go anywhere
257
+////        autoPath = new ArrayList<Node>();
258
+////        autoPath.add(new Node(endX * 28, endY * 32));
259
+//        autoX = endX * 28;
260
+//        autoY = endY * 28;
261
+//        autoX -= autoX % 2; // Even numbered pixel only!
262
+//        autoY -= autoY % 2;
263
+//        automove = 1;
264
+//
265
+//    }
266
+
267
+    @Override
252 268
     public void moveLeft(boolean nudge) {
253 269
         int dist = 28;
254 270
         if (nudge) {
@@ -267,6 +283,7 @@ public class PaintBrush extends Player {
267 283
         }
268 284
     }
269 285
 
286
+    @Override
270 287
     public void moveRight(boolean nudge) {
271 288
         int dist = 28;
272 289
         if (nudge) {

+ 34
- 33
src/com/droidquest/avatars/SolderingPen.java View File

@@ -225,6 +225,7 @@ public class SolderingPen extends Device implements Avatar {
225 225
         CheckPort();
226 226
     }
227 227
 
228
+    @Override
228 229
     public void Animate() {
229 230
         Room tempRoom = room;
230 231
         super.Animate();
@@ -297,16 +298,16 @@ public class SolderingPen extends Device implements Avatar {
297 298
 
298 299
     public boolean KeyUp(KeyEvent e) {
299 300
         if (e.getKeyCode() == KeyEvent.VK_C && handleGameCursor()) {
300
-                return false;
301
+            return false;
301 302
         }
302 303
         else if (e.getKeyCode() == KeyEvent.VK_R && handleRadio()) {
303
-                return false;
304
+            return false;
304 305
         }
305 306
         else if (e.getKeyCode() == KeyEvent.VK_P && handlePaintbrush()) {
306
-                return false;
307
+            return false;
307 308
         }
308 309
         else if (e.getKeyCode() == KeyEvent.VK_SLASH && handleHelp()) {
309
-                return false;
310
+            return false;
310 311
         }
311 312
         else if (e.getKeyCode() == KeyEvent.VK_RIGHT) {
312 313
             if (carriedBy == null) {
@@ -340,13 +341,13 @@ public class SolderingPen extends Device implements Avatar {
340 341
             WirePort();
341 342
         }
342 343
         else if (e.getKeyCode() == KeyEvent.VK_F && handleFlipDevice()) {
343
-                return false;
344
+            return false;
344 345
         }
345 346
         else if (e.getKeyCode() == KeyEvent.VK_E && handleEnterRoom()) {
346
-                return false;
347
+            return false;
347 348
         }
348 349
         else if (e.getKeyCode() == KeyEvent.VK_X && handleExitRoom()) {
349
-                return false;
350
+            return false;
350 351
         }
351 352
         return false;
352 353
     }
@@ -592,32 +593,32 @@ public class SolderingPen extends Device implements Avatar {
592 593
     @Override
593 594
     public boolean handleFlipDevice() {
594 595
         if (hot) {
595
-             if (ports[0].myWire != null) // If SP is wired
596
-             {
597
-                 // Flip wire attached to SP
598
-                 Port tempPort = ports[0].myWire.fromPort;
599
-                 ports[0].myWire.fromPort = ports[0].myWire.toPort;
600
-                 ports[0].myWire.toPort = tempPort;
601
-             }
602
-             else if (ports[0].myWire == null) // If SP is not wired
603
-             {
604
-                 // Flip wire attached to CurrentPort
605
-                 if (currentPort.myWire != null) {
606
-                     Port tempPort = currentPort.myWire.fromPort;
607
-                     currentPort.myWire.fromPort = currentPort.myWire.toPort;
608
-                     currentPort.myWire.toPort = tempPort;
609
-                 }
610
-             }
611
-         }
612
-         else {
613
-             if (ports[0].myWire != null) // If SP is wired
614
-             {
615
-                 // Flip wire attached to SP
616
-                 Port tempPort = ports[0].myWire.fromPort;
617
-                 ports[0].myWire.fromPort = ports[0].myWire.toPort;
618
-                 ports[0].myWire.toPort = tempPort;
619
-             }
620
-         }
596
+            if (ports[0].myWire != null) // If SP is wired
597
+            {
598
+                // Flip wire attached to SP
599
+                Port tempPort = ports[0].myWire.fromPort;
600
+                ports[0].myWire.fromPort = ports[0].myWire.toPort;
601
+                ports[0].myWire.toPort = tempPort;
602
+            }
603
+            else if (ports[0].myWire == null) // If SP is not wired
604
+            {
605
+                // Flip wire attached to CurrentPort
606
+                if (currentPort.myWire != null) {
607
+                    Port tempPort = currentPort.myWire.fromPort;
608
+                    currentPort.myWire.fromPort = currentPort.myWire.toPort;
609
+                    currentPort.myWire.toPort = tempPort;
610
+                }
611
+            }
612
+        }
613
+        else {
614
+            if (ports[0].myWire != null) // If SP is wired
615
+            {
616
+                // Flip wire attached to SP
617
+                Port tempPort = ports[0].myWire.fromPort;
618
+                ports[0].myWire.fromPort = ports[0].myWire.toPort;
619
+                ports[0].myWire.toPort = tempPort;
620
+            }
621
+        }
621 622
         return true;
622 623
     }
623 624
 }

+ 63
- 18
src/com/droidquest/items/Item.java View File

@@ -5,6 +5,8 @@ import com.droidquest.Wire;
5 5
 import com.droidquest.devices.Device;
6 6
 import com.droidquest.levels.Level;
7 7
 import com.droidquest.materials.ChipTrash;
8
+import com.droidquest.pathfinder.Node;
9
+import com.droidquest.pathfinder.Pathfinder;
8 10
 
9 11
 import javax.swing.*;
10 12
 import java.awt.*;
@@ -15,6 +17,7 @@ import java.io.IOException;
15 17
 import java.io.ObjectInputStream;
16 18
 import java.io.ObjectOutputStream;
17 19
 import java.io.Serializable;
20
+import java.util.ArrayList;
18 21
 
19 22
 public class Item implements Serializable, Cloneable {
20 23
     public transient static Level level;
@@ -28,6 +31,7 @@ public class Item implements Serializable, Cloneable {
28 31
     public transient int autoX; // Destination of automovement
29 32
     public transient int autoY; // Destination of automovement
30 33
     public Room InternalRoom = null; // Room inside this item, if any.
34
+    public transient ArrayList<Node> autoPath = new ArrayList<Node>();
31 35
 
32 36
     protected int repeating = 0; // Keyboard repeat.
33 37
     public int charge = 0; // Battery Charge of this item, if any.
@@ -225,6 +229,11 @@ public class Item implements Serializable, Cloneable {
225 229
         return false;
226 230
     }
227 231
 
232
+    protected void findPath(int startX, int startY, int endX, int endY) {
233
+        Pathfinder pf = new Pathfinder(room);
234
+        autoPath = pf.search(startX, startY, endX, endY, this);
235
+    }
236
+
228 237
     public void MouseClick(MouseEvent e) {
229 238
         int button = 0;
230 239
         if ((e.getModifiers() & InputEvent.BUTTON1_MASK) == InputEvent.BUTTON1_MASK) {
@@ -236,11 +245,23 @@ public class Item implements Serializable, Cloneable {
236 245
 
237 246
         if (button == 1) {
238 247
             if (e.getClickCount() == 1) {
239
-                autoX = e.getX() - width / 2;
240
-                autoY = e.getY() - height / 2;
241
-                autoX -= autoX % 2; // Even numbered pixel only!
242
-                autoY -= autoY % 2;
243
-                automove = 1;
248
+                int endX = e.getX() / 28;
249
+                int endY = e.getY() / 32;
250
+
251
+                int startX = x / 28;
252
+                int startY = y / 32;
253
+
254
+                findPath(startX, startY, endX, endY);
255
+
256
+                if(autoPath != null && autoPath.size() > 0) {
257
+                    Node next = autoPath.remove(0);
258
+
259
+                    autoX = next.getX();
260
+                    autoY = next.getY();
261
+                    autoX -= autoX % 2; // Even numbered pixel only!
262
+                    autoY -= autoY % 2;
263
+                    automove = 1;
264
+                }
244 265
             }
245 266
             else if (e.getClickCount() == 2) {
246 267
                 int dx = e.getX() - width / 2 - x;
@@ -436,6 +457,10 @@ public class Item implements Serializable, Cloneable {
436 457
         moveRight(dist);
437 458
     }
438 459
 
460
+    protected void animateCharacter(int dx, int dy) {
461
+
462
+    }
463
+
439 464
     public void Animate() {
440 465
         if (automove == 1 && room == null) {
441 466
             automove = 0;
@@ -443,8 +468,21 @@ public class Item implements Serializable, Cloneable {
443 468
         if (automove == 1) {
444 469
             int dx = autoX - x;
445 470
             int dy = autoY - y;
471
+
446 472
             if (dx == 0 && dy == 0) {
447
-                automove = 0;
473
+                if(autoPath.size() > 0) {
474
+                    Node next = autoPath.remove(0);
475
+                    autoX = next.getX();
476
+                    autoY = next.getY();
477
+                    autoX -= autoX % 2; // Even numbered pixel only!
478
+                    autoY -= autoY % 2;
479
+                    dx = autoX - x;
480
+                    dy = autoY - y;
481
+                }
482
+                if(dx == 0 && dy == 0) {
483
+                    automove = 0;
484
+                    return;
485
+                }
448 486
             }
449 487
             if (dx < -28) {
450 488
                 dx = -28;
@@ -458,6 +496,9 @@ public class Item implements Serializable, Cloneable {
458 496
             if (dy > 32) {
459 497
                 dy = 32;
460 498
             }
499
+
500
+            animateCharacter(dx, dy);
501
+
461 502
             if (dx > 0) {
462 503
                 moveRight(dx);
463 504
             }
@@ -472,18 +513,22 @@ public class Item implements Serializable, Cloneable {
472 513
             }
473 514
         }
474 515
         if (automove == 2) {
475
-            if (autoX > 0) {
476
-                moveRight(autoX);
477
-            }
478
-            if (autoX < 0) {
479
-                moveLeft(-autoX);
480
-            }
481
-            if (autoY > 0) {
482
-                moveDown(autoY);
483
-            }
484
-            if (autoY < 0) {
485
-                moveUp(-autoY);
486
-            }
516
+            autoMoveFull();
517
+        }
518
+    }
519
+
520
+    protected void autoMoveFull() {
521
+        if (autoX > 0) {
522
+            moveRight(autoX);
523
+        }
524
+        if (autoX < 0) {
525
+            moveLeft(-autoX);
526
+        }
527
+        if (autoY > 0) {
528
+            moveDown(autoY);
529
+        }
530
+        if (autoY < 0) {
531
+            moveUp(-autoY);
487 532
         }
488 533
     }
489 534
 

+ 5
- 0
src/com/droidquest/materials/Material.java View File

@@ -1,6 +1,7 @@
1 1
 package com.droidquest.materials;
2 2
 
3 3
 import com.droidquest.RoomDisplay;
4
+import com.droidquest.avatars.PaintBrush;
4 5
 import com.droidquest.items.Item;
5 6
 import com.droidquest.levels.Level;
6 7
 
@@ -62,6 +63,10 @@ public class Material implements Serializable, Cloneable {
62 63
     }
63 64
 
64 65
     public boolean Passable(Item item) {
66
+        // The PaintBrush can pass anything
67
+        if(item instanceof PaintBrush) {
68
+            return true;
69
+        }
65 70
         return passable;
66 71
     }
67 72
 

+ 180
- 0
src/com/droidquest/pathfinder/Node.java View File

@@ -0,0 +1,180 @@
1
+package com.droidquest.pathfinder;
2
+
3
+import com.droidquest.materials.Material;
4
+
5
+/**
6
+ * Represents a Node in a path, using the A* algorithm.
7
+ */
8
+public class Node implements Cloneable {
9
+    private int x = -1;
10
+    private int y = -1;
11
+    private Material material = null;
12
+
13
+    private int gCost = 0;
14
+    private int hCost = 0;
15
+    private int fCost = 0;
16
+
17
+    Node parent = null;
18
+
19
+    /**
20
+     * Create a new, empty Node
21
+     */
22
+    public Node() {
23
+        this(-1, -1, null, null);
24
+    }
25
+
26
+    /**
27
+     * Create a new Node with given coordinates
28
+     * @param x Coordinate (of the room array, not screen location)
29
+     * @param y Coordinate (of the room array, not screen location)
30
+     */
31
+    public Node(int x, int y) {
32
+        this(x, y, null, null);
33
+    }
34
+
35
+    /**
36
+     * Create a new room Node with the given coordinates and material
37
+     * @param x Coordinate (of the room array, not screen location)
38
+     * @param y Coordinate (of the room array, not screen location)
39
+     * @param mat Material at the Node location
40
+     */
41
+    public Node(int x, int y, Material mat) {
42
+        this(x, y, null, mat);
43
+    }
44
+
45
+    /**
46
+     * Create a new room Node with a given parent Node (for pathing)
47
+     * @param x Coordinate (of the room array, not screen location)
48
+     * @param y Coordinate (of the room array, not screen location)
49
+     * @param parent current Parent node
50
+     */
51
+    public Node(int x, int y, Node parent) {
52
+        this(x, y, parent, null);
53
+    }
54
+
55
+    /**
56
+     * Create a new room node with a given parent Node and Material
57
+     * @param x Coordinate (of the room array, not screen location)
58
+     * @param y Coordinate (of the room array, not screen location)
59
+     * @param parent current Parent node
60
+     * @param mat Material at the Node location
61
+     */
62
+    public Node(int x, int y, Node parent, Material mat) {
63
+        this.x = x;
64
+        this.y = y;
65
+        this.parent = parent;
66
+        this.material = mat;
67
+    }
68
+
69
+    /**
70
+     * Retrieve the current room location X coordinate (room array, not screen location)
71
+     * @return X coordinate
72
+     */
73
+    public int getX() {
74
+        return x;
75
+    }
76
+
77
+    /**
78
+     * Set the current room location X coordinate (room array, not screen location)
79
+     * @param x coordinate
80
+     */
81
+    public void setX(int x) {
82
+        this.x = x;
83
+    }
84
+
85
+    /**
86
+     * Retrieve the current room location Y coordinate (room array, not screen location)
87
+     * @return y coordinate
88
+     */
89
+    public int getY() {
90
+        return y;
91
+    }
92
+
93
+    /**
94
+     * Set the current room Y coordinate (room array, not screen location)
95
+     * @param y coordinate
96
+     */
97
+    public void setY(int y) {
98
+        this.y = y;
99
+    }
100
+
101
+    /**
102
+     * Retrieve the currently set Material for the Node (or null if not set)
103
+     * @return Material
104
+     * @see com.droidquest.materials.Material
105
+     */
106
+    public Material getMaterial() {
107
+        return material;
108
+    }
109
+
110
+    /**
111
+     * Set the Material for the Node
112
+     * @param material Material
113
+     * @see com.droidquest.materials.Material
114
+     */
115
+    public void setMaterial(Material material) {
116
+        this.material = material;
117
+    }
118
+
119
+    /**
120
+     * Create a clone of this Node
121
+     * @return Node clone (as Object)
122
+     */
123
+    public Object clone() {
124
+        try {
125
+            return super.clone();
126
+        }
127
+        catch(CloneNotSupportedException cnse) {
128
+            System.out.println("Clone not supported!");
129
+            return this;
130
+        }
131
+    }
132
+
133
+    /**
134
+     * Set the gCost (cost to the current Node from the origin)
135
+     * @return int cost
136
+     */
137
+    public int getgCost() {
138
+        return gCost;
139
+    }
140
+
141
+    /**
142
+     * Set the gCost (cost to the current Node from the origin)
143
+     * @param gCost int cost
144
+     */
145
+    public void setgCost(int gCost) {
146
+        this.gCost = gCost;
147
+    }
148
+
149
+    /**
150
+     * Retrieves the hCost (heuristic cost) from the current Node to the end Node
151
+     * @return int cost
152
+     */
153
+    public int gethCost() {
154
+        return hCost;
155
+    }
156
+
157
+    /**
158
+     * Sets the hCost (heuristic cost) from the current Node to the end Node
159
+     * @param hCost int cost
160
+     */
161
+    public void sethCost(int hCost) {
162
+        this.hCost = hCost;
163
+    }
164
+
165
+    /**
166
+     * Retrieves the fCost (full cost) for the Node
167
+     * @return int cost
168
+     */
169
+    public int getfCost() {
170
+        return fCost;
171
+    }
172
+
173
+    /**
174
+     * Sets the fCost (full cost) for the Node
175
+     * @param fCost int cost
176
+     */
177
+    public void setfCost(int fCost) {
178
+        this.fCost = fCost;
179
+    }
180
+}

+ 178
- 0
src/com/droidquest/pathfinder/Pathfinder.java View File

@@ -0,0 +1,178 @@
1
+package com.droidquest.pathfinder;
2
+
3
+import com.droidquest.Room;
4
+import com.droidquest.items.Item;
5
+
6
+import java.util.ArrayList;
7
+import java.util.Collections;
8
+
9
+/**
10
+ * Finds a path between two places on the map, using the A* algorithm
11
+ */
12
+public class Pathfinder {
13
+    private ArrayList<ArrayList<Node>> nodeList = new ArrayList<ArrayList<Node>>();
14
+
15
+    private ArrayList<Node> openList = new ArrayList<Node>();
16
+
17
+    private ArrayList<Node> closedList = new ArrayList<Node>();
18
+
19
+    /**
20
+     * Begin a search for a path. Returns an empty ArrayList if no path found.
21
+     * @param startX int starting X coordinate (not screen location)
22
+     * @param startY int starting Y coordinate (not screen location)
23
+     * @param endX int ending X coordinate (not screen location)
24
+     * @param endY int ending Y coordinate (not screen location)
25
+     * @param player Item player used to verify whether a Node is passable.
26
+     * @return ArrayList of Nodes representing the path, or empty list
27
+     */
28
+    public ArrayList<Node> search(int startX, int startY, int endX, int endY, Item player) {
29
+        ArrayList<Node> results = new ArrayList<Node>();
30
+        if(startY < 0 || startY > nodeList.size() || startX < 0 || startX > nodeList.get(startY).size()) {
31
+            System.out.println("Starting node outside of room bounds!");
32
+            return results;
33
+        }
34
+
35
+        if(endY < 0 || endY > nodeList.size() || endX < 0 || endX > nodeList.get(endY).size()) {
36
+            System.out.println("Ending node outside of room bounds!");
37
+            return results;
38
+        }
39
+
40
+        if(!nodeList.get(startY).get(startX).getMaterial().Passable(player)) {
41
+            System.out.println("Starting node isn't passable!");
42
+            return results;
43
+        }
44
+
45
+        if(!nodeList.get(endY).get(endX).getMaterial().Passable(player)) {
46
+            System.out.println("Ending node isn't passable!");
47
+            return results;
48
+        }
49
+
50
+        Node endNode = nodeList.get(endY).get(endX);
51
+
52
+        // Add nodes adjacent to starting node
53
+        Node startNode = nodeList.get(startY).get(startX);
54
+        startNode.setgCost(0);
55
+        startNode.sethCost(manhattanDistance(startNode, endNode));
56
+        startNode.setfCost(startNode.gethCost());
57
+        startNode.parent = null;
58
+        openList.add(startNode);
59
+
60
+        findLowestCost(results, endNode, player);
61
+
62
+        return results;
63
+    }
64
+
65
+    private void findLowestCost(ArrayList<Node> results, Node endNode, Item player) {
66
+
67
+        while(openList.size() > 0) {
68
+            Node lowestCost = null;
69
+            for (Node node : openList) {
70
+                if (lowestCost == null || node.getfCost() < lowestCost.getfCost()) {
71
+                    lowestCost = node;
72
+                }
73
+            }
74
+
75
+            openList.remove(lowestCost);
76
+            closedList.add(lowestCost);
77
+
78
+            if (lowestCost != null && lowestCost == endNode) {
79
+                Node pathNode = lowestCost;
80
+                while (pathNode.parent != null) {
81
+                    results.add(new Node(pathNode.getX() * 28, pathNode.getY() * 32));
82
+                    pathNode = pathNode.parent;
83
+                }
84
+                Collections.reverse(results);
85
+                return;
86
+
87
+            }
88
+
89
+            addSurroundingNodes(lowestCost, endNode, player);
90
+        }
91
+
92
+        System.out.println("Could not find any nodes to process, no path.");
93
+
94
+    }
95
+
96
+
97
+
98
+
99
+    private void addSurroundingNodes(Node parent, Node endNode, Item player) {
100
+        if(parent == null) {
101
+            return;
102
+        }
103
+
104
+        int x = parent.getX();
105
+        int y = parent.getY();
106
+        for(int deltaY = -1; deltaY <= 1; deltaY++) {
107
+            for(int deltaX = -1; deltaX <=1; deltaX++) {
108
+                if(deltaX != 0 || deltaY != 0) {
109
+                    int checkX = x + deltaX;
110
+                    int checkY = y + deltaY;
111
+                    if(checkY >= 0 && checkY < nodeList.size() && checkX >= 0 && checkX < nodeList.get(checkY).size() && nodeList.get(checkY).get(checkX).getMaterial().Passable(player)) {
112
+                        Node currentNode = nodeList.get(checkY).get(checkX);
113
+                        if(closedList.contains(currentNode)) {
114
+                            continue;
115
+                        }
116
+                        int diagonalCost = 0;
117
+                        if(deltaX != 0 && deltaY != 0) {
118
+
119
+                            // Diagonal, check to make sure other squares are passable
120
+                            if(!nodeList.get(y).get(checkX).getMaterial().Passable(player) || !nodeList.get(checkY).get(x).getMaterial().Passable(player)) {
121
+                                diagonalCost = 500; // don't make impassible, just really expensive
122
+                            }
123
+                        }
124
+                        if(openList.contains(currentNode)) {
125
+                            // Set gCost (10 for orthoginal, 14 for diagonal)
126
+                            int newgCost = parent.getgCost() + ((deltaX == 0 || deltaY == 0) ? 10 : 14) + diagonalCost;
127
+                            if(newgCost < currentNode.getgCost()) {
128
+                                currentNode.parent = parent;
129
+                                currentNode.setgCost(newgCost);
130
+                                currentNode.setfCost(newgCost + manhattanDistance(currentNode, endNode));
131
+                            }
132
+                        }
133
+                        else {
134
+                            openList.add(currentNode);
135
+                            currentNode.parent = parent;
136
+
137
+                            // Set gCost (10 for orthoginal, 14 for diagonal)
138
+                            currentNode.setgCost(parent.getgCost() + ((deltaX == 0 || deltaY == 0) ? 10 : 14) + diagonalCost);
139
+                            currentNode.sethCost(manhattanDistance(currentNode, endNode));
140
+                            currentNode.setfCost(currentNode.getgCost() + currentNode.gethCost());
141
+                        }
142
+                    }
143
+                }
144
+            }
145
+        }
146
+
147
+    }
148
+
149
+    /**
150
+     * Create a new Pathfinder object and initialize with a Room
151
+     * @param room Room for path-finding.
152
+     * @see com.droidquest.Room
153
+     */
154
+    public Pathfinder(Room room) {
155
+        // Generate node array for room
156
+        generate(room);
157
+
158
+    }
159
+
160
+    /**
161
+     * Generate the Node list for a Room. Generally should use new Pathfinder(room) instead of this method
162
+     * @param room Room for path-finding
163
+     */
164
+    public void generate(Room room) {
165
+        for(int y = 0; y < room.RoomArray.length;y++) {
166
+            nodeList.add(new ArrayList<Node>());
167
+            for(int x=0;x<room.RoomArray[y].length;x++) {
168
+                nodeList.get(y).add(new Node(x, y, Room.level.materialAt(x, y, room)));
169
+            }
170
+        }
171
+    }
172
+
173
+    // Use the Manhattan distance as the heuristic
174
+    private int manhattanDistance(Node current, Node end) {
175
+        return 10 * Math.abs(end.getX()-current.getX()) + Math.abs(end.getY()-current.getY());
176
+    }
177
+
178
+}

Loading…
Cancel
Save