* Выход из игровой системы поиска пути - PullRequest
0 голосов
/ 25 марта 2020

Я создаю игру, в которой ИИ badGuy пытается преследовать меня, пока я использую клавиши со стрелками, чтобы уйти. В моем основном у меня есть попытка ловить блок, если игрок пытается выйти за границу экрана. Однако по какой-то причине, когда я нажимаю на кнопку «Пуск», я получаю исключение, которое у меня распечатывается системой, говоря «ИГРА НАД, вы вышли из карты». Без моего метода reCalcPath в классе badguy этого не произойдет, поэтому проблема должна быть в этом методе.

Для этого метода у меня есть массив карт. Этот массив является логическим массивом 40x40 с размером 20x20 пикселей / ячеек / квадратов, который утверждает, что если я щелкнул по этой позиции ячейки, если ранее был ложным, нарисовал белый квадрат и наоборот. Теперь я подумал: проверьте положение ячейки badGuy, затем проверьте все его соседние ячейки, если состояние этой ячейки ложное, т.е. ячейка не окрашена (что означает, что в этом смысле стена не блокирует его), а затем проверьте расстояние между ним и моим игроком. Я использую евклидово дистанционное приближение, рассматривая xPlayer-xbadGuy, yPLayer-xBadGuy как противоположные и смежные стороны треугольника. С помощью Пифагора я получаю гипотенузу. Сделайте это для каждой соседней клетки, та, у которой наименьшая гипотенуза, означает наименьшее расстояние. Теперь это не работает вообще, так как, когда его называют, игра вылетает. Игнорируйте метод перемещения, поскольку он не имеет значения, если recalcpath не будет работать

Main


import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import java.awt.image.*;
import java.io.*;

public class AStarMaze extends JFrame implements Runnable, MouseListener, MouseMotionListener, KeyListener {

    // member data
    private boolean isInitialised = false;
    private BufferStrategy strategy;
    private Graphics offscreenBuffer;
    public boolean map[][] = new boolean[40][40];
    private boolean isGameRunning = false;
    private BadGuy badguy;
    private Player player;
    private int startI, startJ;
    private int endI, endJ;

    private String pFilePath, bgFilePath;

    // constructor
    public AStarMaze () {

        //Display the window, centred on the screen
        Dimension screensize = java.awt.Toolkit.getDefaultToolkit().getScreenSize();
        int x = screensize.width/2 - 400;
        int y = screensize.height/2 - 400;
        setBounds(x, y, 800, 800);
        setVisible(true);
        this.setTitle("A* Pathfinding Demo");

        bgFilePath = "C:\\Users\\brads\\IdeaProjects\\PathfindingAssignment\\src\\badguy.png";
        pFilePath = "C:\\Users\\brads\\IdeaProjects\\PathfindingAssignment\\src\\player.png";
        // load raster graphics and instantiate game objects
        ImageIcon icon = new ImageIcon(bgFilePath);
        Image img = icon.getImage();
        badguy = new BadGuy(img);
        icon = new ImageIcon(pFilePath);
        img = icon.getImage();
        player = new Player(img);

        // create and start our animation thread
        Thread t = new Thread(this);
        t.start();

        // initialise double-buffering
        createBufferStrategy(2);
        strategy = getBufferStrategy();
        offscreenBuffer = strategy.getDrawGraphics();

        // register the Jframe itself to receive mouse and keyboard events
        addMouseListener(this);
        addMouseMotionListener(this);
        addKeyListener(this);

        // initialise the map state
        for (x=0;x<40;x++) {
            for (y=0;y<40;y++) {
                map[x][y]=false;
            }
        }

        isInitialised = true;
    }

    public boolean[][] getMap(){
        return map;
    }

    // thread's entry point
    public void run() {
        long loops=0;
        while ( 1==1 ) {
            // 1: sleep for 1/5 sec
            try {
                Thread.sleep(100);
            } catch (InterruptedException e) { }
        try {
            // 2: animate game objects
            if (isGameRunning) {
                loops++;
                player.move(map); // player moves every frame
                if (loops % 3 == 0) // badguy moves once every 3 frames
                    badguy.reCalcPath(map,player.x,player.y);
                  //  badguy.move(map, player.x, player.y);
            }

            // 3: force an application repaint
            this.repaint();
        }
        catch(IndexOutOfBoundsException e){

            System.out.println("GAME OVER, you exited the map");
            System.exit(-1);
        }

        }
    }

    private void loadMaze() {
        String filename = "C:\\Users\\brads\\IdeaProjects\\PathfindingAssignment\\maze.txt";
        String textinput = null;
        try {
            BufferedReader reader = new BufferedReader(new FileReader(filename));
            textinput = reader.readLine();
            reader.close();
        }
        catch (IOException e) { }

        if (textinput!=null) {
            for (int x=0;x<40;x++) {
                for (int y=0;y<40;y++) {
                    map[x][y] = (textinput.charAt(x*40+y)=='1');
                }
            }
        }
    }

    private void saveMaze() {
        // pack maze into a string
        String outputtext="";
        for (int x=0;x<40;x++) {
            for (int y=0;y<40;y++) {
                if (map[x][y])
                    outputtext+="1";
                else
                    outputtext+="0";
            }
        }

        try {
            String filename = "C:\\Users\\brads\\IdeaProjects\\PathfindingAssignment\\maze.txt";
            BufferedWriter writer = new BufferedWriter(new FileWriter(filename));
            writer.write(outputtext);
            writer.close();
        }
        catch (IOException e) { }
    }

    // mouse events which must be implemented for MouseListener
    public void mousePressed(MouseEvent e) {
        if (!isGameRunning) {
            // was the click on the 'start button'?
            int x = e.getX();
            int y = e.getY();
            if (x>=15 && x<=85 && y>=40 && y<=70) {
                isGameRunning=true;
                return;
            }
            // or the 'load' button?
            if (x>=315 && x<=385 && y>=40 && y<=70) {
                loadMaze();
                return;
            }
            // or the 'save' button?
            if (x>=415 && x<=485 && y>=40 && y<=70) {
                saveMaze();
                return;
            }
        }

        // determine which cell of the gameState array was clicked on
        int x = e.getX()/20;
        int y = e.getY()/20;
        // toggle the state of the cell
        map[x][y] = !map[x][y];
        // throw an extra repaint, to get immediate visual feedback
        this.repaint();
        // store mouse position so that each tiny drag doesn't toggle the cell
        // (see mouseDragged method below)
        prevx=x;
        prevy=y;
    }

    public void mouseReleased(MouseEvent e) {}

    public void mouseEntered(MouseEvent e) {}

    public void mouseExited(MouseEvent e) {}

    public void mouseClicked(MouseEvent e) {}
    //

    // mouse events which must be implemented for MouseMotionListener
    public void mouseMoved(MouseEvent e) {}

    // mouse position on previous mouseDragged event
    // must be member variables for lifetime reasons
    int prevx=-1, prevy=-1;
    public void mouseDragged(MouseEvent e) {
        // determine which cell of the gameState array was clicked on
        // and make sure it has changed since the last mouseDragged event
        int x = e.getX()/20;
        int y = e.getY()/20;
        if (x!=prevx || y!=prevy) {
            // toggle the state of the cell
            map[x][y] = !map[x][y];
            // throw an extra repaint, to get immediate visual feedback
            this.repaint();
            // store mouse position so that each tiny drag doesn't toggle the cell
            prevx=x;
            prevy=y;
        }
    }
    //

    // Keyboard events
    public void keyPressed(KeyEvent e) {
        if (e.getKeyCode()==KeyEvent.VK_LEFT)
            player.setXSpeed(-1);
        else if (e.getKeyCode()==KeyEvent.VK_RIGHT)
            player.setXSpeed(1);
        else if (e.getKeyCode()==KeyEvent.VK_UP)
            player.setYSpeed(-1);
        else if (e.getKeyCode()==KeyEvent.VK_DOWN)
            player.setYSpeed(1);
    }

    public void keyReleased(KeyEvent e) {
        if (e.getKeyCode()==KeyEvent.VK_LEFT || e.getKeyCode()==KeyEvent.VK_RIGHT)
            player.setXSpeed(0);
        else if (e.getKeyCode()==KeyEvent.VK_UP || e.getKeyCode()==KeyEvent.VK_DOWN)
            player.setYSpeed(0);
    }

    public void keyTyped(KeyEvent e) { }
    //

    // application's paint method
    public void paint(Graphics g) {
        if (!isInitialised)
            return;

        g = offscreenBuffer; // draw to offscreen buffer

        // clear the canvas with a big black rectangle
        g.setColor(Color.BLACK);
        g.fillRect(0, 0, 800, 800);

        // redraw the map
        g.setColor(Color.WHITE);
        for (int x=0;x<40;x++) {
            for (int y=0;y<40;y++) {
                if (map[x][y]) {
                    g.fillRect(x*20, y*20, 20, 20);
                }
            }
        }
        // redraw the player and badguy
        // paint the game objects
        player.paint(g);
        badguy.paint(g);

        if (!isGameRunning) {
            // game is not running..
            // draw a 'start button' as a rectangle with text on top
            // also draw 'load' and 'save' buttons
            g.setColor(Color.GREEN);
            g.fillRect(15, 40, 70, 30);
            g.fillRect(315, 40, 70, 30);
            g.fillRect(415, 40, 70, 30);
            g.setFont(new Font("Times", Font.PLAIN, 24));
            g.setColor(Color.BLACK);
            g.drawString("Start", 22, 62);
            g.drawString("Load", 322, 62);
            g.drawString("Save", 422, 62);
        }

        // flip the buffers
        strategy.show();
    }

    // application entry point
    public static void main(String[] args) {
        AStarMaze w = new AStarMaze();
    }

}

Класс игрока



import java.awt.Graphics;
import java.awt.Image;


public class Player {

    Image myImage;
    int x=0,y=0;
    int xSpeed=0, ySpeed=0;

    public Player( Image i ) {
        myImage=i;
        x=10;
        y=35;
    }

    public void setXSpeed( int x ) {
        xSpeed=x;
    }

    public void setYSpeed( int y ) {
        ySpeed=y;
    }

    public void move(boolean map[][]) {
        int newx=x+xSpeed;
        int newy=y+ySpeed;
        if (!map[newx][newy]) {
            x=newx;
            y=newy;
        }
    }

    public void paint(Graphics g) {
        g.drawImage(myImage, x*20, y*20, null);
    }

}

Плохой парень



import java.awt.Graphics;
import java.awt.Image;

public class BadGuy {

    Image myImage;
    int x=0,y=0;
    int distanceX = 0, distanceY = 0;
    boolean hasPath=false;

    public BadGuy( Image i ) {
        myImage=i;
        x = 30;
        y = 10;
    }

    public void reCalcPath(boolean map[][],int targx, int targy) {
//         TO DO: calculate A* path to targx,targy, taking account of walls defined in map[][]
        int totalDistance = 0;
        for (int i = -1; i <= 1; i++) {
            for (int j = -1; j <= 1; j++) {
                if (!map[(x / 20) + i][(y / 20) + j]) {
                    if ((((targx - x) ^ 2) + ((targy - y) ^ 2)) <= totalDistance) {

                        totalDistance = (((targx - x) ^ 2) + ((targy - y) ^ 2));
                        x = ((x / 20) + i);
                        y = ((y / 20) + j);
                        return;

                    }
                }
            }
        }
            System.out.println("Not working");
    }


//    public void move(boolean map[][],int targx, int targy) {
//        if (hasPath) {
//            // TO DO: follow A* path, if we have one defined
//        }
//        else if(map[x / 20][y / 20]) {
//            hasPath = false;
//        }
//    }
    public void paint(Graphics g) {
        g.drawImage(myImage, x*20, y*20, null);
    }

}

1 Ответ

0 голосов
/ 25 марта 2020

Ваш блок catch вызывается исключением IndexOutOfBoundsException. Один простой способ найти дополнительную информацию о вашей ошибке - записать или вывести трассировку стека. Вы можете сделать это в своем коде, добавив e.printStackTrace() к вашему блоку перехвата:

        catch(IndexOutOfBoundsException e){
            System.out.println("GAME OVER, you exited the map");
            e.printStackTrace()
            System.exit(-1);
        }

Это должно показать вам номер строки, которая вызывает вашу проблему.

Просмотр кода в вашем Метод reCalcPath, мое обоснованное предположение - это строка, вызывающая проблему: if (!map[(x / 20) + i][(y / 20) + j]) {. Если либо (x / 20) + i, либо (y / 20) + j меньше 0 или больше размеров вашей карты, он выдаст исключение IndexOutOfBoundsException, которое вы видите. В случае, когда вы начинаете и x = 30, y = 10, i = -1 и j = -1, это приводит к отображению [0] [- 1].

Это то, что известно как крайний случай. Вам нужно проверить случай, когда ваши x и y находятся по краям сетки. В этой ситуации соседние ячейки сетки находятся за пределами карты и выдают исключение.

...