Java乒乓游戏的AI/对手表现不如预期。

huangapple go评论51阅读模式
英文:

Java pong game AI/opponent is not acting as it should

问题

我注意到你正在开发一个Java乒乓球游戏,但你的AI表现异常。AI的移动速度快,看起来像瞬间移动,而且经常卡住。以下是你的代码的一些建议修复:

  1. Opponent类的move方法中,你有一些逻辑错误。你在下面的条件中增加了1,但实际上应该减少1来尝试追踪球:
if(opponent.y <= ballPos){
    opponent.y = opponent.y + 1;
}

if(opponent.y >= ballPos){
    opponent.y = opponent.y = - 1;
}

修改为:

if(opponent.y < ballPos){
    opponent.y = opponent.y + 1;
}

if(opponent.y > ballPos){
    opponent.y = opponent.y - 1;
}
  1. GamePlay类中的collision方法,你检查了两次球与对手的碰撞,这是多余的。只需要一次碰撞检测:
if(ball.ball.intersects(opponent.opponent)){
    ball.right = !ball.right; // 反转球的方向
}
  1. 你在GamePlay类中的actionPerformed方法中抛出了UnsupportedOperationException异常,这会导致程序出现问题。你可以删除这个方法,因为它似乎是多余的。

  2. Board类中,paint方法应该使用@Override注解:

@Override
public void paintComponent(Graphics g) {
    // ...
}
  1. 为了使对手更平滑地跟随球,你可以尝试实现一个更智能的移动策略,而不仅仅是根据球的位置上下移动。你可以根据球的位置和速度来调整对手的移动。

这些是一些修复你游戏中AI问题的建议。希望这些能帮助你改进你的游戏。如果你有更多问题或需要进一步的帮助,请随时提出。

英文:

I am coding a Java pong game that is almost complete except that the AI is acting quite oddly I am not sure why it's acting the way it does honestly.

It seems to move up and down rather quickly and has a tendency to appear to teleport and get stuck then suddenly teleport.
Main class to start things:

public class Pong {

	Board board = new Board();  
   
   public void frame() {
		JFrame b = new JFrame("Pong");
		b.setSize(905,705);
		b.setLocation(300,60);
		b.setResizable(false);
		b.setVisible(true);
		b.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);        
		b.add(board);
   }

   public static  void main(String[] args) {
	   Pong start = new Pong();
	   start.frame();
   }
}

The board class:

public class Board extends JPanel {

    GamePlay play = new GamePlay(0,0,900,900);

    public Board(){
       // addKeyListener((KeyListener) play.player);
        addKeyListener((KeyListener) play);
        setFocusable(true);

    }

    public void paint(Graphics g) {
            Graphics2D g2 = (Graphics2D) g;
            g2.setColor(Color.black);
            g2.fill(play.a);
            g.setColor(Color.WHITE);
            board(g);
            g2.setColor(Color.white);
            g2.fill(play.opponent.opponent);
            g2.fill(play.ball.ball);

            if(play.playerScore == 5){
                g.setColor(Color.WHITE);	
                g.setFont(new Font("game over",Font.BOLD,20));
                g.drawString("You win!", 300, 300);
                g.drawString("press space bar to restart.", 300, 350);
            }
            if (play.opponentScore == 5){
                g.setColor(Color.WHITE);	
                g.setFont(new Font("game over",Font.BOLD,20));
                g.drawString("You lose!", 300, 300);
                g.drawString("press space bar to restart.", 300, 350);
            }

            repaint();
    }

    public void board(Graphics g) {
            Graphics2D g2d = (Graphics2D) g;
            Stroke stroke1 = new BasicStroke(4f);
            g2d.setColor(Color.white);
            g2d.setStroke(stroke1);
            g2d.drawRect(20, 50, 850, 600);
            g2d.setColor(Color.white);
            float[] dashingPattern2 = {10f, 4f};
            Stroke stroke2 = new BasicStroke(4f, BasicStroke.CAP_BUTT,
            BasicStroke.JOIN_MITER, 1.0f, dashingPattern2, 0.0f);
            g2d.setStroke(stroke2);
            g2d.drawLine(435, 50, 435, 650);
            g.setFont(new Font("arial",Font.PLAIN,30));
            g.drawString(""+play.playerScore, 20, 35);
            g.drawString(""+play.opponentScore, 855, 35);
    }

}

The GamePlay class is more or less just to make things run:

public class GamePlay extends JPanel implements ActionListener,KeyListener {
	
    public int x,y,z,c;
    public int playerScore = 0;
    public int opponentScore = 0;
    boolean over = false;
    Rectangle a;

    Opponent opponent = new Opponent(835,300,15,80);
    Ball ball = new Ball(400,350,20,20);

    public GamePlay(int x,int y,int z,int c){
        this.x = x;
        this.y = y;
        this.z = z;
        this.c = c;
        a = new Rectangle(x, y, z, c);

        timer.start();

    }

    public void collision(){
        opponent.move();

        opponent.getBallPos(ball.ball.y);

        if(ball.ball.intersects(opponent.opponent)){
            ball.right = false;

        }        


        if(ball.ball.intersects(opponent.opponent)){
            ball.right = false;
        }

        if(ball.ball.x >= 862){
            playerScore = playerScore + 1;
        }

        if(ball.ball.x <= 4){
            opponentScore = opponentScore + 1;

        }
    }


    Timer timer = new Timer(5, new ActionListener() {
        @Override
        public void actionPerformed(ActionEvent e) {
            //opponent.move();

            collision();


            if(playerScore ==5 || opponentScore == 5){
                over = true;
                timer.stop();
            }

            //repaint the screen
            if(ball.right == false){
                //collision();
               // opponent.move();

                ball.move();
            //repaint();

            }

            if(ball.right == true){
            //collision();
                //opponent.move();

                ball.move();
            //repaint();

            }

            

        }
    });


    @Override
    public void actionPerformed(ActionEvent arg0) {
        // TODO Auto-generated method stub
        throw new UnsupportedOperationException("Unimplemented method 'actionPerformed'");
    }


    @Override
    public void keyPressed(KeyEvent e) {
        if(e.getKeyCode() == KeyEvent.VK_SPACE) {
            if(over == true){
                timer.start();
                opponentScore = 0;
                playerScore = 0;
                opponent.opponent.x = 835;
                opponent.opponent.y = 300;
                over = false;
                repaint();


            }

       }
  
    }


    @Override
    public void keyReleased(KeyEvent arg0) {

    }


    @Override
    public void keyTyped(KeyEvent arg0) {

    }



}

The balls class (of course it controls the ball):

public class Ball extends JPanel{
	
    public int ballXpos;
    public int ballYpos;
    public int ballWidth;
    public int ballHeight;
    boolean right = false;
    boolean up = true;
    Random random = new Random();

    Rectangle ball;

    public Ball(int ballXpos, int ballYpos, int ballWidth, int ballHeight){
        this.ballXpos = ballXpos;
		this.ballYpos = ballYpos;
		this.ballWidth = ballWidth;
        this.ballWidth = ballHeight;
        up = random.nextBoolean();
        right = random.nextBoolean();
		ball = new Rectangle(ballXpos, ballYpos, ballWidth, ballHeight);

        //move();
    } 

/* to make the ball move properly when hit by paddles have it boolean paddels up means the ball direction means up down moving paddle means ball goes down
 * can be down using boolean true and false but maybe can be done with less lines of code using variebles
 * 
 */
    public void move(){
        if(right == false){
           
            ball.x = ball.x - 1;
        }
        
        if(right == true){
            
            ball.x = ball.x + 1;
            
        }
        if(up == true){
            ball.y = ball.y - 1;
        }

        if(up == false){
            ball.y = ball.y + 1;

        }

        if(ball.x >= 863){
            ball.x = 400;
            up = random.nextBoolean();
            right = random.nextBoolean();

        }

        if(ball.x <= 3){
            ball.x = 400;
            up = random.nextBoolean();
            right = random.nextBoolean();
        }

        if(ball.y <= 38){
            up = false;
        }

        if(ball.y >= 630){
            up = true;
        }
    }
}

And the AI class:

public class Opponent {
public int opponentXpos;
public int opponentYpos;
public int opponentWidth;
public int opponentHeight;
public int ballPos;
Rectangle opponent;
public Opponent(int opponentXpos, int opponentYpos, int opponentWidth, int opponentHeight){
this.opponentXpos = opponentXpos;
this.opponentYpos = opponentYpos;
this.opponentWidth = opponentWidth;
this.opponentWidth = opponentHeight;
opponent = new Rectangle(opponentXpos, opponentYpos, opponentWidth, opponentHeight);
}
public void move(){
if(opponent.y >= 570){
opponent.y = 570 ;
}
if(opponent.y <= 50){
opponent.y = 50;
}
if(opponent.y <= ballPos){
opponent.y = opponent.y + 1;
}
if(opponent.y >= ballPos){
opponent.y = opponent.y = - 1;
}
if(opponent.y == ballPos){
opponent.y = opponent.y;
}
}
public void getBallPos(int ball){
this.ballPos = ball;
}

}

I have tried to move around where I call for the opponents move method, I have negated the issue somewhat but cannot fix it completely.

I expect of course the paddle to move smoothly like the ball does and try to follow the ball rather than moving up and down the way it does.

Maybe I need to implement a separate action listener for the AI rather than using the one for the ball.

答案1

得分: 0

问题已解决。

在对手类中,将移动改为以下内容。

public void move(int ballY){

    if(opponent.y >= 566){
        opponent.y = 566 ;
    }

    if(opponent.y <= 50){
        opponent.y = 50;
    }

    if (opponent.y < ballY) {
        down = true;
        up = false;
        opponent.y += 3;

    } else if (opponent.y > ballY) {
        down = false;
        up = true;
        opponent.y -= 3;
    }
}

在GamePlay类中进行更改,添加另一个定时器。

Timer timer2 = new Timer(17, new ActionListener() {
    @Override
    public void actionPerformed(ActionEvent e) {
        opponent.move(ball.ball.y);
        collision();
    }
});
英文:

Issue is solved.

Int the opponent class change the movement into this.

public void move(int ballY){
if(opponent.y &gt;= 566){
opponent.y = 566 ;
}
if(opponent.y &lt;= 50){
opponent.y = 50;
}
if (opponent.y  &lt; ballY) {
down = true;
up = false;
opponent.y += 3;
} else if (opponent.y  &gt; ballY) {
down = false;
up = true;
opponent.y -= 3;
}

In the GamePlay class change it like this adding another timer.

Timer timer2 = new Timer(17, new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
opponent.move(ball.ball.y);
collision();
}
});

huangapple
  • 本文由 发表于 2023年3月7日 22:58:40
  • 转载请务必保留本文链接:https://go.coder-hub.com/75663618.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定