0

因此,我正在尝试制作带有程序生成等的 Roguelike 游戏。但是我在角色处理方面遇到了麻烦。问题是当我想用键盘移动角色时,它只是改变它的坐标——它当然应该这样做,但我在屏幕上看不到它。我在这个网站上阅读了一些答案,这对我有所帮助,但并没有完全解决问题。
所以,我注意到我做错了什么,这里有一些代码(希望它不会太长):

public class PanelTest extends JPanel implements KeyListener{


    private static final long serialVersionUID = 1L;
    private Game game;
    private int width, height;
    private int tileSize;

    public PanelTest(Game game, int tileSize) {
        super();

        this.game = game;
        this.tileSize = tileSize;
        this.width = game.getMap().getWidth()*tileSize;
        this.height = game.getMap().getHeight()*tileSize;

        this.addKeyListener(this);

        setPreferredSize(new Dimension(width, height));
        setRequestFocusEnabled(true);
        requestFocus();
        setVisible(true);

    }

    public void paintComponent(Graphics g){
        super.paintComponent(g);
        for(int i=0; i < game.getMap().getWidth(); i++){
            for(int j=0; j < game.getMap().getHeight(); j++){
                g.setColor(game.getMap().getColor(i,j));
                g.fillRect(i*tileSize, j*tileSize, tileSize, tileSize);
            }
        }
// print the correct coordinates
        System.out.println(game.getPlayer().getX()+" "+game.getPlayer().getY());
    }

    @Override
    public void keyPressed(KeyEvent e) {
        // TODO Auto-generated method stub
        switch(e.getKeyCode()){
        case(KeyEvent.VK_Z) : game.getPlayer().moveUp();break;
        case(KeyEvent.VK_S) : game.getPlayer().moveDown(); break;
        case(KeyEvent.VK_Q) : game.getPlayer().moveLeft(); break;
        case(KeyEvent.VK_D) : game.getPlayer().moveRight(); break; 
        }
        revalidate();
        repaint();

    }

    public void addNotify() {
        super.addNotify();
        requestFocus();
    }

    @Override
    public void keyReleased(KeyEvent e) {
        // TODO Auto-generated method stub

    }

    @Override
    public void keyTyped(KeyEvent e) {
        // TODO Auto-generated method stub

    }

    public static void main(String[] args){
        JFrame frame = new JFrame();
        frame.setBounds(0, 0, 400, 400);

        Map map = MapFactory.createNewEmptyMap();
        RoomMaker rm = new RoomMaker(map.getWidth()/7,map);
        TunnelMaker tm = new TunnelMaker(rm, map);
        rm.carveOut();
        tm.carveOut();
        Room r = rm.getRandomRoom();
        Player p = new Player(map, r.getxCenter(),r.getyCenter());
        Game game = new Game(map,p);

        frame.getContentPane().add(new PanelTest(game, 10));
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.pack();
        frame.setVisible(true);
    }


}

希望能帮到你,谢谢!

4

1 回答 1

1

By default a JPanel uses a FlowLayout.

It looks like your code is changing a players position, but then you invoke revalidate() which causes the layout manager code to be invoked and the location of your component is recalculated again.

So for games where you have random movement you want to use a null layout and you don't need to invoke revalidate() and repaint() since your code is not responsible for invoking the setLocation() method directly.

See also Motion Using the Keyboard for problems with using a keyListener.

setRequestFocusEnabled(true);
requestFocus();
setVisible(true);

The above is not needed. The two properties you are setting to true default to true. You can't request focus on a component unless the component is displayed on a visible GUI, so adding that code here does nothing. Also, the proper method to use would be requestFocusInWindow(), not requestFocus().

于 2013-10-27T21:33:52.387 回答