几天后,我想了解并编码A星寻路算法,我现在明白了。 我最终编码并使其工作
所以现在我想知道的是我如何让我的英雄走这条路。 任何代码snipet或示例将不胜感激。 我有一个关于如何做到这一点的想法,但不幸的是它没有工作,提前谢谢你。
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.MouseMotionListener;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.*;
public class GameBoard extends JPanel implements ActionListener,Runnable{
private Thread game;
private volatile boolean running=false;
Map m;
Player hero;
Path path;
AstarPathfinder p1;
int targetX,targetY;
int dir=0;
public GameBoard ()
{
//setSize(620,720);
setBackground(Color.gray);
setFocusable(true);
requestFocus();
hero=new Player();
hero.setX(3/36);
hero.setY(3/36);
addMouseListener(new MouseAdapter()
{
public void mouseClicked(MouseEvent e) {
handleMousePressed(e.getX(), e.getY());
}
});
addMouseMotionListener(new MouseMotionListener() {
public void mouseDragged(MouseEvent e) {
// System.out.println("mouse dragged");
}
public void mouseMoved(MouseEvent e) {
//handleMouseMoved(e.getX(), e.getY());
}
});
}
private void handleMousePressed(int x, int y)
{
targetX=x /= 36;
targetY=y/= 36;
p1=new AstarPathfinder ();
path=p1.PathFinding(hero.getX()/36, hero.getY()/36, targetX,targetY);
repaint();
}
public void startGame()
{
if(game==null|| !running)
{
game=new Thread(this);
game.start();
running=true;
}
}
@Override
public void run()
{
while(running)
{
moveit();
try {
Thread.sleep(5);
} catch (InterruptedException ex) {
Logger.getLogger(GameBoard.class.getName()).log(Level.SEVERE, null, ex);
}
}
}
public void moveit()
{
for(int x=0; x<14; x++)
{
for(int y=0;y<14;y++)
{
if (path != null)
{
if (path.contains(x,y))
{
if(path.getX(x)<hero.getX()){
hero.x-=1;
}
else if(path.getX(x)> hero.getX())
{
hero.x+=1;
}
if(path.getY(y)< hero.getY())
{
hero.y-=1;
}
else if(path.getY(y)> hero.getY())
{
hero.y+=1;
}
}
}
}
}
}
@Override
public void paint(Graphics g)
{
m=new Map();
m.OpenFile();
m.ReadFile();
m.CloseFile();
for(int y=0; y<14; y++)
{
for(int x=0; x<14; x++)
{
if(m.getMap(x, y).equals("g"))
{
g.drawImage(m.getGrass(), x*36, y*36, this);
}
if(m.getMap(x, y).equals("b"))
{
g.drawImage(m.getBlock(), x*36, y*36, this);
}
if(m.getMap(x, y).equals("d"))
{
g.drawImage(m.getDirt(), x*36, y*36, this);
}
if(m.getMap(x, y).equals("t"))
{
g.drawImage(m.getGOAL(), x*36, y*36, this);
}
if (path != null)
{
if (path.contains(x,y))
{
g.setColor(Color.YELLOW);
g.fillRect(x*36, y*36,19,19);
}
}
}
}
}
@Override
public void addNotify()
{//build in jpanel method
super.addNotify();
///donc quand le jpanel est en marche partir le jeu.
startGame();
}
@Override
public void actionPerformed(ActionEvent e) {
throw new UnsupportedOperationException("Not supported yet.");
}
}
结束我的实体类
public class Entity {
int x, y, dx, dy;
public Entity() {
x = 0;
y = 0;
dx = 0;
dy = 0;
}
public Entity(int xe, int ye) {
this.x = xe;
this.y = ye;
}
public int getDx() {
return dx;
}
public void setDx(int dx) {
this.dx = dx;
}
public int getDy() {
return dy;
}
public void setDy(int dy) {
this.dy = dy;
}
public int getX() {
return x;
}
public void setX(int x) {
this.x = x;
}
public int getY() {
return y;
}
public void setY(int y) {
this.y = y;
}
}
班主任
import java.awt.Graphics;
import java.awt.Image;
import javax.swing.ImageIcon;
public class Player extends Entity {
private Image p;
public Player()
{
super();
p=new ImageIcon("C:/Java/Prj/src/images/player.png").getImage();
}
public Image getPlayer()
{
return p;
}
/* public void move(char d)
{
if(d=='d')
this.x+=this.dx;
this.y+=this.dy;
}*/
public void drawPlayer(Graphics g)
{
g.drawImage(this.p,this.x,this.y,null);
}
}
我的Astarpath课程
enter code here
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
public class AstarPathfinder {
LinkedList<Node> closed = new LinkedList();
LinkedList<Node> open = new LinkedList();
int newH, newF, newG, ndlength = 14;
Node[][] nodes = new Node[ndlength][ndlength];
Path path;
public AstarPathfinder() {
for (int i = 0; i < ndlength; i++) {
for (int j = 0; j < ndlength; j++) {
nodes[i][j] = new Node(i, j);
}
}
}
public Path PathFinding(int sx, int sy, int tx, int ty) {
Node start = nodes[sx][sy];
Node target = nodes[tx][ty];
start.g = 0;
start.h = estimateCost(start, target);
start.f = start.g + start.h;
start.parent = null;
open.add(start);
while (open.size() != 0) {
Node current = null;
if (open.size() == 0) {
System.out.println("aucune route/no possible road");
}
current = getCurrent();
if (current == target) {
//System.out.println("reach the target: " + target);
break;
}
open.remove(current);
closed.add(current);
List<Node> neighbors = (List<Node>) createNeighbors(current);
for (int k = 0; k < neighbors.size(); k++) {
Node neighborNode = neighbors.get(k);
if (closed.contains(neighborNode)) {
continue;
}
newG = current.g + 10;// + estimateDistance(current, neighborNode);
newH = estimateCost(neighborNode, target);
newF = newG + newH;
if (newG < neighborNode.g) {
neighborNode.parent = current;
neighborNode.h = newH;
neighborNode.g = newG;
neighborNode.f = newF;
}
if ((!open.contains(neighborNode)) && !(closed.contains(neighborNode))) {
open.add(neighborNode);
neighborNode.parent = current;
neighborNode.h = newH;
neighborNode.g = newG;
neighborNode.f = newF;
}
}//endloopfor
}//end while
path = new Path();
Node target2 = target;
while (target2 != start) {
path.prependStep(target2.x, target2.y);
target2 = target2.parent;
}
path.prependStep(start.x, start.y);
return path;
}
public int estimateCost(Node node1, Node node2) {
float resultat;
float dx = node1.x - node2.x;
float dy = node1.y - node2.y;
resultat = Math.abs((dx * dx) + (dy + dy));
resultat += resultat * 0.001;
return (int) resultat;
}
/**
* cette fonction perment de retourner le noeud courant
* @return
*/
private Node getCurrent() {
Node currentNode = null;
int maxintf = open.size();
int minf = 1000000;
for (int i = 0; i < maxintf; i++) {
Node node = (Node) open.get(i);
if (node.f < minf) {
currentNode = node;
}
}
return currentNode;
}
/**
* Fontion permettant de trouver les 8 voisins
*/
private List<Node> createNeighbors(Node cnodes) {
int i = cnodes.x;
int j = cnodes.y;
List<Node> neighbors = new ArrayList<Node>();
int indiceup = cnodes.x - 1;
int indicedown = cnodes.x + 1;
int indiceleft = cnodes.y - 1;
int indiceright = cnodes.y + 1;
if (indiceup > -1) {
neighbors.add(nodes[indiceup][cnodes.y]);
}
if (indicedown < 14) {
neighbors.add(nodes[indicedown][cnodes.y]);
}
if (indiceleft > -1) {
neighbors.add(nodes[cnodes.x][indiceleft]);
}
if (indiceright < 14) {
neighbors.add(nodes[cnodes.x][indiceright]);
}
return neighbors;
}
public class Node {
int g = 0;//cost
int h = 0;//heuristic
int f = g;//f+g
Node parent;
int x, y;
boolean visited;
public Node(int x, int y) {
this.x = x;
this.y = y;
this.visited = false;
}
public boolean isVisited() {
return visited;
}
public void setVisited(boolean visited) {
this.visited = visited;
}
public int getF() {
return f;
}
public void setF(int f) {
this.f = f;
}
public int getG() {
return g;
}
public void setG(int g) {
this.g = g;
}
public int getH() {
return h;
}
public void setH(int h) {
this.h = h;
}
public Node getParent() {
return parent;
}
public void setParent(Node parent) {
this.parent = parent;
}
}
}
这是我从可乐和代码网站获得的路径类。我从头开始构建整件事我正在努力理解当然,一旦我理解,我会重新输入所有内容:)抱歉这个糟糕的代码
路径类
import java.util.ArrayList;
public class Path {
/** The list of steps building up this path */
private ArrayList steps = new ArrayList();
/**
* Create an empty path
*/
public Path() {
}
/**
* Get the length of the path, i.e. the number of steps
*
* @return The number of steps in this path
*/
public int getLength() {
return steps.size();
}
/**
* Get the step at a given index in the path
*
* @param index The index of the step to retrieve. Note this should
* be >= 0 and < getLength();
* @return The step information, the position on the map.
*/
public Step getStep(int index) {
return (Step) steps.get(index);
}
/**
* Get the x coordinate for the step at the given index
*
* @param index The index of the step whose x coordinate should be retrieved
* @return The x coordinate at the step
*/
public int getX(int index) {
return getStep(index).x;
}
/**
* Get the y coordinate for the step at the given index
*
* @param index The index of the step whose y coordinate should be retrieved
* @return The y coordinate at the step
*/
public int getY(int index) {
return getStep(index).y;
}
/**
* Append a step to the path.
*
* @param x The x coordinate of the new step
* @param y The y coordinate of the new step
*/
public void appendStep(int x, int y) {
steps.add(new Step(x,y));
}
/**
* Prepend a step to the path.
*
* @param x The x coordinate of the new step
* @param y The y coordinate of the new step
*/
public void prependStep(int x, int y) {
steps.add(0, new Step(x, y));
}
/**
* Check if this path contains the given step
*
* @param x The x coordinate of the step to check for
* @param y The y coordinate of the step to check for
* @return True if the path contains the given step
*/
public boolean contains(int x, int y) {
return steps.contains(new Step(x,y));
}
/**
* A single step within the path
*
* @author Kevin Glass
*/
public class Step {
/** The x coordinate at the given step */
private int x;
/** The y coordinate at the given step */
private int y;
/**
* Create a new step
*
* @param x The x coordinate of the new step
* @param y The y coordinate of the new step
*/
public Step(int x, int y) {
this.x = x;
this.y = y;
}
/**
* Get the x coordinate of the new step
*
* @return The x coodindate of the new step
*/
public int getX() {
return x;
}
/**
* Get the y coordinate of the new step
*
* @return The y coodindate of the new step
*/
public int getY() {
return y;
}
/**
* @see Object#hashCode()
*/
public int hashCode() {
return x*y;
}
/**
* @see Object#equals(Object)
*/
public boolean equals(Object other) {
if (other instanceof Step) {
Step o = (Step) other;
return (o.x == x) && (o.y == y);
}
return false;
}
}
}
答案 0 :(得分:1)
一些一般性意见:
您的代码很难阅读。 请尝试在将来使用有意义的变量名称(或至少评论那些不具有的变量名称)。例如:什么是Dx?
另外:hero.drawPlayer(g)似乎独立于它所处的循环。那么为什么要把它放在循环中呢?玩家将被抽出的方式超出需要。 看来每次调用paint()时都会加载地图(从文件中!)。这似乎是不必要的。
解决您的问题:
你确定这一行:targetX = x / = 36;是正确的? 你没有包含PathFinding类,所以我假设你确定它返回正确的路径(你打印出来的东西)?
在你的moveit()循环中: path.getX(x)的 那看起来不对劲。我不知道你的Path类的实现,但我会认为它是某种列表。在moveit()的一次调用中,你想将玩家移动到该列表的下一个元素,对吧?或者至少在该元素的方向上。但是你永远不会调用path.getFirst或path.getNext,你似乎使用了路径的所有元素。
//编辑:关于如何做到这一点:
在路径中添加pop方法:
public Step popStep() {
Step temp = steps.get(0);
steps.remove(0);
return temp;
}
并使用它或在某处添加一个计数器(如果以后需要完整路径)。
然后将您的移动方法更改为:
public void moveit() {
Step nextStep = path.popStep();
hero.setX(nextStep.getX());
hero.setY(nextStep.getY());
}
这样玩家将始终移动到您路径的下一步。 此外,您可能希望在两次拨打电话之间等待超过5毫秒。