Skip to content

Commit 5d7933b

Browse files
committed
A* Search Algorithm
2 parents c5822ec + 33b04cf commit 5d7933b

File tree

5 files changed

+177
-7
lines changed

5 files changed

+177
-7
lines changed

src/com/redomar/game/entities/Dummy.java

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
import com.redomar.game.gfx.Colours;
88
import com.redomar.game.gfx.Screen;
99
import com.redomar.game.level.LevelHandler;
10+
import com.redomar.game.level.Node;
1011

1112
public class Dummy extends Mob {
1213

@@ -17,6 +18,8 @@ public class Dummy extends Mob {
1718
private boolean[] swimType;
1819
private int[] swimColour;
1920
private static double speed = 0.75;
21+
private List<Node> path = null;
22+
private int time = 0;
2023

2124
private Swim swim;
2225

@@ -30,13 +33,10 @@ public Dummy(LevelHandler level, String name, int x, int y, int shirtCol,
3033

3134
public void tick() {
3235

33-
List<Player> players = level.getPlayers(this, 8);
34-
if (players.size() > 0) {
35-
followMovementAI((int) getX(), (int) getY(), (int) Game.getPlayer().getX(), (int) Game
36-
.getPlayer().getY(), xa, ya, speed, this);
37-
}else{
38-
isMoving = false;
39-
}
36+
//List<Player> players = level.getPlayers(this, 8);
37+
aStarMovementAI((int) getX(), (int) getY(), (int) Game.getPlayer().getX(), (int) Game
38+
.getPlayer().getY(), xa, ya, speed, this, path, time);
39+
4040

4141
setSwim(new Swim(level, (int) getX(), (int) getY()));
4242
swimType = getSwim().swimming(isSwimming, isMagma, isMuddy);
@@ -49,6 +49,7 @@ public void tick() {
4949
}
5050

5151
public void render(Screen screen) {
52+
time++;
5253
int xTile = 8;
5354
int yTile = 28;
5455
int walkingSpeed = 4;

src/com/redomar/game/entities/Mob.java

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,12 @@
11
package com.redomar.game.entities;
22

3+
import java.util.List;
34
import java.util.Random;
45

56
import com.redomar.game.level.LevelHandler;
7+
import com.redomar.game.level.Node;
68
import com.redomar.game.level.tiles.Tile;
9+
import com.redomar.game.lib.utils.Vector2i;
710

811
public abstract class Mob extends Entity {
912

@@ -155,6 +158,25 @@ protected boolean isSolid(int xa, int ya, int x, int y) {
155158

156159
return false;
157160
}
161+
162+
protected void aStarMovementAI(int x, int y, int px, int py, double xa,
163+
double ya, double speed, Mob mob, List<Node> path, int time){
164+
xa = 0;
165+
ya = 0;
166+
Vector2i start = new Vector2i(x >> 3, y >> 3);
167+
Vector2i goal = new Vector2i(px >> 3, py >> 3);
168+
path = level.findPath(start, goal);
169+
if(path != null) {
170+
if(path.size() > 0){
171+
Vector2i vector = path.get(path.size() - 1).tile;
172+
if(x < vector.getX() << 3) xa++;
173+
if(x > vector.getX() << 3) xa--;
174+
if(y < vector.getY() << 3) ya++;
175+
if(y > vector.getY() << 3) ya--;
176+
}
177+
}
178+
moveMob(xa, ya, mob);
179+
}
158180

159181
protected void followMovementAI(int x, int y, int px, int py, double xa,
160182
double ya, double speed, Mob mob) {

src/com/redomar/game/level/LevelHandler.java

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@
44
import java.io.File;
55
import java.io.IOException;
66
import java.util.ArrayList;
7+
import java.util.Collections;
8+
import java.util.Comparator;
79
import java.util.List;
810
import java.util.logging.Level;
911

@@ -15,6 +17,7 @@
1517
import com.redomar.game.entities.PlayerMP;
1618
import com.redomar.game.gfx.Screen;
1719
import com.redomar.game.level.tiles.Tile;
20+
import com.redomar.game.lib.utils.Vector2i;
1821
import com.redomar.game.net.packets.Packet01Disconnect;
1922

2023
public class LevelHandler {
@@ -26,6 +29,16 @@ public class LevelHandler {
2629
private String imagePath;
2730
private BufferedImage image;
2831

32+
private Comparator<Node> nodeSorter = new Comparator<Node>() {
33+
34+
public int compare(Node n0, Node n1) {
35+
if(n1.fCost < n0.fCost) return +1;
36+
if(n1.fCost > n0.fCost) return -1;
37+
return 0;
38+
}
39+
40+
};
41+
2942
public LevelHandler(String imagePath) {
3043

3144
if (imagePath != null) {
@@ -194,6 +207,60 @@ public void movePlayer(String username, int x, int y, int numSteps,
194207
player.setMovingDir(movingDir);
195208
}
196209

210+
public List<Node> findPath(Vector2i start, Vector2i goal){
211+
List<Node> openList = new ArrayList<Node>();
212+
List<Node> closedList = new ArrayList<Node>();
213+
Node current = new Node(start, null, 0, getDistance(start, goal));
214+
openList.add(current);
215+
while(openList.size() > 0){
216+
Collections.sort(openList, nodeSorter);
217+
current = openList.get(0);
218+
if(current.tile.equals(goal)){
219+
List<Node> path = new ArrayList<Node>();
220+
while (current.parent != null) {
221+
path.add(current);
222+
current = current.parent;
223+
}
224+
openList.clear();
225+
closedList.clear();
226+
return path;
227+
}
228+
openList.remove(current);
229+
closedList.add(current);
230+
for(int i = 0; i < 9; i++){
231+
if(i == 4) continue;
232+
int x = current.tile.getX();
233+
int y = current.tile.getY();
234+
int xi = (i % 3) - 1;
235+
int yi = (i / 3) - 1;
236+
Tile at = getTile(x + xi,y + yi);
237+
if(at == null) continue;
238+
if(at.isSolid()) continue;
239+
Vector2i a = new Vector2i(x + xi, y + yi);
240+
double gCost = current.gCost + getDistance(current.tile, a);
241+
double hCost = getDistance(a, goal);
242+
Node node = new Node(a, current, gCost, hCost);
243+
if(isVectorInList(closedList, a) && gCost >= node.gCost) continue;
244+
if(!isVectorInList(openList, a) || gCost < node.gCost) openList.add(node);
245+
}
246+
}
247+
closedList.clear();
248+
return null;
249+
}
250+
251+
private boolean isVectorInList(List<Node> list, Vector2i vector){
252+
for(Node n : list){
253+
if(n.tile.equals(vector)) return true;
254+
}
255+
return false;
256+
}
257+
258+
private double getDistance(Vector2i tile, Vector2i goal){
259+
double dx = tile.getX() - goal.getX();
260+
double dy = tile.getY() - goal.getY();
261+
return Math.sqrt(dx * dx + dy * dy);
262+
}
263+
197264
public List<Entity> getEntities(Entity e, int radius){
198265
List<Entity> result = new ArrayList<Entity>();
199266
int ex = (int) e.getX();
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
package com.redomar.game.level;
2+
3+
import com.redomar.game.lib.utils.Vector2i;
4+
5+
public class Node {
6+
7+
public Vector2i tile;
8+
public Node parent;
9+
public double fCost, gCost, hCost;
10+
11+
public Node(Vector2i tile, Node parent, double gCost, double hCost){
12+
this.tile = tile;
13+
this.parent = parent;
14+
this.gCost = gCost;
15+
this.hCost = hCost;
16+
this.fCost = (this.gCost + this.hCost);
17+
}
18+
19+
}
Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
package com.redomar.game.lib.utils;
2+
3+
public class Vector2i {
4+
5+
private int x, y;
6+
7+
public Vector2i(){
8+
set(0, 0);
9+
}
10+
11+
public Vector2i(int x, int y){
12+
set(x, y);
13+
}
14+
15+
public Vector2i(Vector2i vector){
16+
set(vector.x, vector.y);
17+
}
18+
19+
public Vector2i add(Vector2i vector){
20+
this.x += vector.x;
21+
this.y += vector.y;
22+
return this;
23+
}
24+
25+
public Vector2i subtract(Vector2i vector){
26+
this.x -= vector.x;
27+
this.y -= vector.y;
28+
return this;
29+
}
30+
31+
public boolean equals(Object object){
32+
if (!(object instanceof Vector2i)) return false;
33+
Vector2i vector = (Vector2i) object;
34+
if(vector.getX() == this.getX() && vector.getY() == this.getY()) return true;
35+
return false;
36+
}
37+
38+
public void set(int x, int y){
39+
this.x = x;
40+
this.y = y;
41+
}
42+
43+
public int getX() {
44+
return x;
45+
}
46+
47+
public Vector2i setX(int x) {
48+
this.x = x;
49+
return this;
50+
}
51+
52+
public int getY() {
53+
return y;
54+
}
55+
56+
public Vector2i setY(int y) {
57+
this.y = y;
58+
return this;
59+
}
60+
61+
}

0 commit comments

Comments
 (0)