0

私の楕円が右に動かない理由はありますか? ゲームループがありますが、サイクルごとに右に 2 ピクセルずつ移動するのではなく、どういうわけか円が表示された場所にとどまります。奇妙なことに、実際にペイントする前にループに入ります。しかし、グラフィックスオブジェクトが(固定位置に)表示されます。

public class GamePanel extends JPanel implements Runnable {

    public static int WIDTH = 1024;
    public static int HEIGHT = WIDTH / 16 * 9;
    private Thread t1;
    boolean running;
    private int FPS = 60;
    private long optimalTime = 1000 / FPS;
    private int heroX = 200;
    private int heroY = 200;


    public void addNotify(){
        Dimension size = new Dimension(WIDTH,HEIGHT);
        setPreferredSize(size);
        setFocusable(true);
        requestFocus();
        running = true;
        t1 = new Thread(this);
        t1.start();
    }



    public void paintComponent (Graphics g){
        super.paintComponent(g);
        Graphics2D g2 = (Graphics2D) g;
        g2.setColor(Color.WHITE);
        g2.fillRect(0, 0, WIDTH, HEIGHT);
        g2.setColor(Color.BLACK);
        g2.fillOval(heroX, heroY, 50, 50);
        g2.dispose();
    }


    public void run() {
        long startTime;
        long passedTime;
        long waitTime;
        while (running){
            startTime = System.nanoTime();
            System.out.println("Runs");
            update();
            draw();
            repaint();
            passedTime = System.nanoTime() - startTime;
            waitTime = optimalTime - passedTime / 1000000;
            try {
                if (waitTime <= 0){
                    waitTime = 2;
                }
                Thread.sleep(waitTime);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }

    }



    private void draw() {


    }



    private void update() {

        heroX += 2;

    }

}
4

2 に答える 2

1

スレッドを使用する代わりに、swingタイマーを使用する必要があります。バックグラウンドで時間のかかる処理を行う必要がある場合は、SwingWorkersを使用してください。本当に必要な場合は、swing で独自のスレッドを使用することは可能ですが (それを行うにはねじれたユーザー ケースが必要です)、スレッドその使用方法を十分に把握するまでは、それを実行しようとしないでください。スイング付き。

public class GamePanel extends JPanel {
    private static final int DELAY = 1000 / 60;
    private final Timer timer;
    // ...

    private int heroX = 200;
    private int heroY = 200;

    public GamePanel() {
        timer = new Timer(DELAY, new ActionListener() {
            @Override
            public void actionPerformed(final ActionEvent e) {
                update();
                repaint();
            }
        });
        // ...
    }

    // No need to make this public
    @Override
    protected void paintComponent (Graphics g) {
        // ...
    }

    @Override
    public Dimension getPreferredSize() {
        // Overriding is cleaner than using set*Size(). Search old questions to see why
    }

    public void startAnimation() {
         timer.start();
    }

    public void stopAnimation() {
         timer.stop();
    }

    // Remove addNotify() and run()
}
于 2013-07-31T10:30:29.747 に答える
0

読んでテストした後、私はこれをやりたかっただけです。paintComponent が EDT の外部にある場合でも、意図したとおりに機能します。

public class GamePanel extends JPanel implements Runnable {

    public static int WIDTH = 1024;
    public static int HEIGHT = WIDTH / 16 * 9;
    private int cordX = WIDTH / 2;
    private Thread t1;
    private boolean running = true;

    public void addNotify() {
       super.addNotify();
       Dimension size = new Dimension (WIDTH, HEIGHT);
       setPreferredSize(size);
       t1 = new Thread(this);
       t1.start();
     }

    public void paintComponent(Graphics g) {
        g.setColor(Color.WHITE);
        g.fillRect(0, 0, WIDTH, HEIGHT);
        g.setColor(Color.BLACK);
        g.fillOval(cordX, HEIGHT /2 , 20, 20);
    }

    public void run() {
        while(running) {
            cordX += 2;
            repaint();
            try {
                    Thread.sleep(17);
                } catch (InterruptedException e) {
                    e.printStackTrace();
            }
        }  
}
于 2013-08-01T10:19:17.930 に答える