Как избавиться от мерцания, которое появляется во время моей анимации? - PullRequest
2 голосов
/ 01 ноября 2009

Я учу Java, создавая небольшую игру в JApplet. У меня небольшая проблема с анимацией моего спрайта.

Вот код:

this.sprite.setBounds(0,0,20,17);

this.sprite.setIcon(this.rangerDown);
for(int i = 0; i< 16;i++)
{
    this.sprite.setBounds(this.sprite.getX(), this.sprite.getY()+1, 20, 17);
    this.sprite.update(this.sprite.getGraphics());

    try{
        Thread.currentThread().sleep(100);
    }catch(InterruptedException e){
}

}

Это оставило некоторое мерцание во время анимации. Как только анимация заканчивается, мерцание исчезает, но это отчасти уродливо ... Думаю, есть какой-то шаг, который я пропустил. Я использую этот метод, потому что сейчас он дает лучший результат, но я бы хотел остаться без AWT, если это возможно, используя Swing.

Есть идеи как избавиться от мерцания?

Спасибо за чтение.

Снимок экрана (не удается опубликовать изображения, извините).

Ответы [ 2 ]

2 голосов
/ 01 ноября 2009

Проблема в двойной буферизации.

в апплетах: Двойная буферизация выполняется практически автоматически. Вызовите repaint () вместо рисования в вашем методе.

В Swing есть много способов сделать это. Я обычно иду по маршруту BufferStrategy. Когда вы инициализируете свой фрейм, сделайте это:

JFrame frame;
... code to init frame here
frame.createBufferStrategy(2);

Тогда в ваших методах розыгрыша:

Graphics g = getBufferStrategy().getDrawGraphics();
..code to do drawing here...
g.dispose();
getBufferStrategy().show();
2 голосов
/ 01 ноября 2009

Это не тень. Это граница вашего спрайта. Он просто черный и выглядит как тень. Если вы измените величину сдвига спрайта (скажем, на 50 пикселей, а не только на 1), вы поймете, что я имею в виду.

Чтобы исправить это, вам нужно также рисовать фон каждый раз, когда вы обновляете местоположение вашего спрайта. Хотя это, вероятно, приведет к мерцанию.

Правильный способ сделать это - изменить способ рисования объектов. Вам нужно переопределить метод paintComponent вашей панели, а затем просто вызывать repaint каждый раз, когда вы обновляете расположение своих спрайтов.

EDIT:

См. Этот пример кода для базового использования. ПРИМЕЧАНИЕ. Это НЕ то, как вы должны писать анимацию, используя потоки. Я написал это, чтобы показать вам, что происходит в методе paintComponent, и написал поток анимации, чтобы показать, что упомянутая вами «тень» исчезла. НИКОГДА не иметь бесконечного цикла выполнения в потоке:)

import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;

import javax.swing.JFrame;
import javax.swing.JPanel;


public class Test {

    public static void main(String[] args) {
        JFrame f = new JFrame("Test");
        MyPanel c = new MyPanel();
        f.getContentPane().add(c);
        f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        f.setSize(350, 100);
        f.setVisible(true);
    }

}

class MyPanel extends JPanel {

    int x = 0;
    boolean toTheRight = true;

    public MyPanel() {
        new Thread(new Runnable() {

            @Override
            public void run() {
                while (true) {
                    x = (toTheRight)?x+5:x-5;
                    if (x>300)
                        toTheRight = false;
                    if (x<0)
                        toTheRight = true;
                    repaint();
                    try {
                        Thread.sleep(50);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
        }).start();
    }

    @Override
    protected void paintComponent(Graphics g) {
        Graphics2D g2 = (Graphics2D)g.create();
        g2.setPaint(Color.white);
        g2.fillRect(0, 0, getWidth(), getHeight());
        g2.setPaint(Color.red);
        g2.fillOval(x-2, 50, 4, 4);
    }

}
...