Java:Pacman与墙的碰撞检测

2020年6月6日 26点热度 0条评论

我一直在尽力解决Pacman与墙壁之间的碰撞检测问题,但是我的实现似乎无法正常工作

  • 冲突检测完全起作用吗?是
  • 行为是否正确?没有
  • 目前表现如何?当您碰壁时,它会停止吃豆子
    可以移动,但是任何新按键只能移动
    图像轴(取决于按键的向上,向右,向下或向左),
    碰到墙后,它不会将吃豆人移动到当前位置以外。
  • 任何帮助将不胜感激。提前致谢

    GamePanel.java

    package pacman;
    
    import java.awt.Color;
    import java.awt.Graphics;
    import java.awt.Graphics2D;
    import java.awt.Point;
    import java.awt.Rectangle;
    import java.awt.Toolkit;
    import java.awt.event.KeyAdapter;
    import java.awt.event.KeyEvent;
    import javax.swing.JPanel;
    
    public class GamePanel extends JPanel implements Runnable{
        private Thread animator;
        private boolean isRunning;  
        private Map map = new Map();
    
    
        public GamePanel(){
            this.setBackground(Color.BLACK);
            this.setDoubleBuffered(true);
            addKeyListener(new TAdapter());
            setFocusable(true);
        }
    
        @Override
        public void run() {
            isRunning = true;
            System.out.println("Is running? "+isRunning);
            long startTime, timeDiff, sleepTime; 
            startTime = System.currentTimeMillis();
    
            while(isRunning){
                repaint();
                gameUpdate();
    
    
                 timeDiff = System.currentTimeMillis() -  startTime;
                 sleepTime = 5 - timeDiff;
    
                try{
                    Thread.sleep(sleepTime);
                }
                catch(InterruptedException ex){
                    System.exit(0);
                }
                startTime = System.currentTimeMillis();
    
            }   
    //      gameOver(); not implemented yet, will focus on this when I have some basic animation and the game loop working to satisfaction.
        }
    
    
        @Override
        public void addNotify(){
            super.addNotify();
            startGame();
        }
    
        public void startGame(){        
            if(animator == null || !isRunning){
                animator = new Thread(this);
                animator.start();           
            }
        } //end of StartGame method
    
        public void gameUpdate(){   
            map.getPlayer().move();     
            checkCollision();
        } //implementation of ingame updates such as pacman getting killed.
    
    
        public void checkCollision(){ //this is where I officially set collision up
            for(int i = 0; i < map.tiles.length; i++){
                for(int j = 0; j < map.tiles.length; j++){
                    if(map.tiles[i][j] != null){
                        if(map.getPlayer().getPlayerBox().intersects(map.tiles[i][j].getR())){
                            map.getPlayer().setColliding(true);
                            System.out.println("OWW"+map.tiles[i][j].getR().getLocation());
    
                        }               
                    }                           
                }               
            }
        }
        public void paintComponent(Graphics g){ 
            Graphics2D g2d = (Graphics2D) g;
            super.paintComponent(g);
            if(isRunning){
                drawDot(g2d);
                drawPlayer(g2d);
                map.drawMap(g2d);
            }
    
            Toolkit.getDefaultToolkit().sync();
            g.dispose();
    
        }   
    
        public void drawDot(Graphics2D g){
            g.setColor(Color.GREEN);
            for(int x= 0; x < 400; x++){
                for(int y = 0; y < 400; y++){
                    g.drawRect(x * 20, y * 20, 1, 1);
                }
            }
    
        }
    
    
    
    
        public void drawPlayer(Graphics2D g){       
            g.drawImage(map.getPlayer().getImage(), map.getPlayer().getX(),map.getPlayer().getY(), this); 
        }
    
    private class TAdapter extends KeyAdapter{      
    
            @Override
            public void keyPressed(KeyEvent e) {            
                map.getPlayer().keyPressed(e);  
            }
            @Override
    
            public void keyReleased(KeyEvent e) {
                map.getPlayer().keyReleased(e);
            }
        }
    }
    


    Player.java

    package pacman;
    
    
    import java.awt.Image;
    import java.awt.Rectangle;
    import java.awt.event.KeyEvent;
    
    import javax.swing.ImageIcon;
    
    public class Player extends Commons{
        private int dx, dy;
        private int speed = 1;
        private static int playerWidth = 52; //these figures seem off, but that is because the image is not designed correctly or the pacman image is not obeying the logic of not going passed the frame size.
        private static int playerHeight = 82;
        private Rectangle playerBox;
        private Image playerImg  = new ImageIcon(Player.class.getResource("Pacman.png")).getImage();
        private Image playerImgUp  = new ImageIcon(Player.class.getResource("PacmanUp.png")).getImage();
        private Image playerImgLeft  = new ImageIcon(Player.class.getResource("PacmanLeft.png")).getImage();
        private Image playerImgDown  = new ImageIcon(Player.class.getResource("PacmanDown.png")).getImage();
    
        private boolean isColliding = false;
    
    
    
        public Player(){
            this.setX(320);
            this.setY(280);
            playerBox = new Rectangle(this.getX(), this.getY(),40,40);
        }
    
        public void setSpeed(int sp){
            speed = sp;
        }
    
        public Image getImage(){
            if(dy == 1){            
                return playerImgDown;
            } 
            else if(dy == -1){
                return playerImgUp;
            }
            else if(dx == -1){
                return playerImgLeft;
            }
            else 
                return playerImg;       
        }//Responsible for displaying pacman image based on direction of pacman's movement.
    
    
    
        void move(){
            int x = this.getX();
            int y = this.getY();
            /*
             * This is the part where I am trying to implement some degree of logic to stop it from moving
             */
            if(isColliding == false){
                this.setX(x += dx);
                playerBox.setLocation(x, y);
                this.setY(y += dy);
            }else if(isColliding == true){
                this.setColliding(false);
                this.setX(this.getX());
                this.setY(this.getY());
    
            }
    
            if (this.getX() <= 1) {
                this.setX(1);
            }
            if (this.getX() >= 400 - playerWidth) {
                this.setX(400 - playerWidth);
            }
            if (this.getY() <= 2) {
                this.setY(2);
            }
            if (this.getY() >= 400 - playerHeight ) {
                this.setY(400 - playerHeight);
            }
        }//Most simplist form of collision detection, stops pacman from leaving the JFrame
    
        public void keyPressed(KeyEvent e) {
            int key = e.getKeyCode();
    
    
            if(key == KeyEvent.VK_LEFT ){
                dx = -speed;
                dy = 0;
            }
            if(key == KeyEvent.VK_RIGHT){
                dx = speed;
                dy = 0;
            }
    
            if(key == KeyEvent.VK_UP){
                dx = 0;
                dy = -speed;
            }
            if(key == KeyEvent.VK_DOWN){
                dx = 0;
                dy = speed;         
            }
    
            if(key == KeyEvent.VK_ESCAPE){
                System.exit(0);
            }   
        }
    
    
    
        public void keyReleased(KeyEvent e) {
            int key = e.getKeyCode();
            if(key == KeyEvent.VK_LEFT){
                dy = 0;     
            }
            if(key == KeyEvent.VK_RIGHT){
                dy = 0;         
            }
            if(key == KeyEvent.VK_UP){
                dx = 0;         
            }
            if(key == KeyEvent.VK_DOWN){
                dx = 0;         
            }       
        }//end of key release
    
    
    
        public Rectangle getPlayerBox() {
            return playerBox;
        }
    
    
    
    
        public void setPlayerBox(Rectangle playerBox) {
            this.playerBox = playerBox;
        }
    
    
        public boolean isColliding() {
            return isColliding;
        }
    
    
        public void setColliding(boolean isColliding) {
            this.isColliding = isColliding;
        }
    
    
    }// end of class
    

    解决方案如下:

    看起来好像发生了什么事,玩家进入了导致冲突的图块,并且isColliding设置为true。
    游戏更新的下一个迭代调用移动代码,该代码检查玩家的isColliding布尔值。该条件为真,并且不会发生移动。接下来,检查碰撞,并且我们没有移出引起碰撞的图块,因此我们被卡在该图块中。

    我建议在发生碰撞时将玩家移出碰撞瓷砖。

    我们知道玩家正在朝哪个方向移动,因此我们可以使用相反的方向(将dxdy乘以-1)将玩家移出碰撞的方块。