【问题标题】:Java: Pacman collision detection with wallJava:Pacman 与墙壁的碰撞检测
【发布时间】:2019-12-02 03:45:46
【问题描述】:

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

  • 碰撞检测是否有效?是的
  • 它的行为是否正确?没有
  • 目前表现如何?当你撞墙时它会停止吃豆人 从移动这没关系,但是任何新的按键移动只会改变 图像轴(上、右、下或左取决于按键), 撞墙后,它不会将 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

【问题讨论】:

  • 阅读this article 了解调试代码的技巧。
  • 建议使用Key Bindings 而不是KeyListener,这样您就不需要发布关于您的程序为何停止响应按键输入的新问题。另外,请注意,Swing 不是线程安全的,从事件调度线程之外更新 UI 的状态可能会导致难以复制和诊断的不可预测的行为
  • 嗨@MadProgrammer 感谢您的回复,我们总是很感激。我在过去看到过关于实现键绑定的类似反应。我只想澄清几件事。这个游戏的设计并没有考虑到最佳实践(从代码中可以看出)我的目标很简单尝试找到我自己的解决方案来创建 Pacman(我知道加入 stackoverflow 的讽刺意味)我自己的知识和无论如何,只需完成它。这是我的一个宠物项目/年度决议。我当然会考虑您的建议。再次感谢

标签: java swing collision-detection game-physics custom-painting


【解决方案1】:

看起来发生的情况是玩家进入了一个导致碰撞的图块,并且isColliding 设置为 true。 游戏更新的下一次迭代调用移动代码来检查玩家的isColliding 布尔值。该条件为真,并且没有运动发生。接下来,检查碰撞,我们还没有移出导致碰撞的图块,所以我们被卡在了这个图块中。

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

我们知道玩家移动的方向,因此我们可以使用相反的方向(将dxdy 乘以-1)将玩家移出碰撞瓷砖。

【讨论】:

  • 嗨,特拉维斯,感谢您在我的开篇文章中的回复,感谢您的回复。诚然,我仍在努力在自己的脑海中找到关于移动玩家 x +1、x - 1、y +1 或 y -1 的最佳方法的逻辑。我会接受你的回答。再次感谢:)
  • 我在回答中添加了更多细节。
猜你喜欢
  • 1970-01-01
  • 2016-04-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-05-01
  • 1970-01-01
相关资源
最近更新 更多