How to avoid shape exceeding the border of frame i

2019-09-12 15:57发布

问题:

I have this program that when pressing arrow keys it exceeds the frame. However I want the shape to bounce back when exceeding that border. Can anyone help me on this.

  {
    JFrame frame = new JFrame("PacMan");
    PacManObject panel = new PacManObject();
    panel.setFocusable(true);
    panel.setRequestFocusEnabled(true);
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    frame.setSize(600,600);
    frame.setVisible(true);

    frame.add(panel); 
    panel.addKeyListener(panel);


}

public static void main(String[] args) {
    Runnable runnable = new Runnable(){

        @Override
        public void run() {
            new PacMan();
        }

    };EventQueue.invokeLater(runnable);
}

class PacManObject extends JPanel implements KeyListener{

    private int xLocation = 100;
    private int yLocation = 100;
    private int mouth = 280;
    private int angle = 45;
    private int xrandomLocation = 300;
    private int yrandomLocation = 400;
    private int xLocationEyes = 115;
    private int yLocationEyes = 115;

Where I draw my shapes

    @Override
    public void paintComponent(Graphics graphics)
    {
        super.paintComponent(graphics);

        //pacman
        graphics.setColor(Color.yellow);
        graphics.fillArc(xLocation, yLocation, 100, 100, angle, mouth);

        //eyes
        graphics.setColor(Color.BLACK);
        graphics.fillOval(xLocationEyes, yLocationEyes, 20, 20);
        food(graphics);
    }

When pressing the arrow keys

    @Override
    public void keyPressed(KeyEvent keyboard) {

        int keyboardPress = keyboard.getKeyCode();
         if(keyboardPress == KeyEvent.VK_RIGHT){
             xLocation += 30;
             xLocationEyes += 30;
             angle = 45;
             repaint();
         }
         else if(keyboardPress == KeyEvent.VK_LEFT){

             angle = -145;
             xLocation -= 30;
             xLocationEyes -= 30;
             repaint();
         }
     }

回答1:

Put in a range check which uses something like

if (xLocation + 100 >= getWidth()) { 
    xLocation = getWidth() - 100;
} else if (xLocation < 0) {
    xLocation = 0;
}

You should do the same thing for yLocation

Generally speaking, you should have a main/game loop which is responsible for updating the current state of the game (based on the current state of inputs and other requirements (like the AI of the ghosts)) and schedules updates to the UI.

This way, you would set a flag in your key handler, which the main/game loop would check, update the state of the player and the schedule the repaint. This overcomes the inherent issue of the delay between the first key press event and the repeated events.

I'd also consider using the key bindings API over KeyListener.

Perhaps, have a look at How to Use Key Bindings, How to use Swing Timers and How to eliminate delay in keyPress? for some more ideas