Java, как заставить персонажа следовать Pathfinding - PullRequest
0 голосов
/ 29 января 2012

После нескольких дней попыток понять и закодировать алогричную схему поиска звезд, которую я теперь понимаю. Я наконец кодирую это и заставляю это работать

так что теперь я хотел бы знать, как я могу заставить своего героя следовать по пути. любой фрагмент кода или пример будут оценены. У меня была идея, как это сделать, но, к сожалению, это не сработало. Заранее спасибо.

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);

}
}

мой класс Астарпата

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;
    }
    }
    }

и вот класс пути, который я получил с сайта Coke and Code. я строю все это с нуля, я пытаюсь понять, конечно, я буду перепечатывать все, как только я понимаю :) извините за дерьмовый код

путь к классу

    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;
    }
}
    }

1 Ответ

1 голос
/ 29 января 2012

Некоторые общие комментарии:

Ваш код довольно сложно прочитать. Пожалуйста, попробуйте использовать значимые имена переменных в будущем (или хотя бы прокомментируйте те, которые не являются). Например: что такое Dx?

Также: hero.drawPlayer (g), кажется, не зависит от цикла, в котором он находится. Так зачем помещать его в цикл? Игрок будет разыгрываться гораздо чаще, чем нужно. Кажется, что карта загружается (из файла!) Каждый раз, когда вызывается paint (). Это кажется ненужным.

К вашей проблеме:

Вы уверены, что эта строка: targetX = x / = 36; верно? Вы не включили класс PathFinding, поэтому я предполагаю, что вы уверены, что он возвращает правильный путь (вы распечатали его или что-то в этом роде)?

В вашем цикле moveit (): path.getX (х) Это просто не выглядит правильно. Я не знаю вашу реализацию класса Path, но я бы предположил, что это какой-то список. Одним вызовом moveit () вы хотите переместить игрока к следующему элементу этого списка, верно? Или, по крайней мере, в направлении этого элемента. Но вы никогда не вызываете path.getFirst или path.getNext, вы, кажется, используете все элементы пути.

// edit: как это сделать:

либо добавьте метод 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 миллисекунд между вызовами для перемещения.

...