Правильно отображать спрайт с резьбой - PullRequest
1 голос
/ 06 февраля 2012

Я использую поток для отображения анимации со спрайтом.

Explosion e2 = new Explosion(this, x2, y2, explosion);    
new Thread(e2).start();

И в классе взрыва у меня есть:

public void run()
{
    ActionListener taskPerformer = new ActionListener() {
          public void actionPerformed(ActionEvent evt) {
              cursor++;
          }
    };

    Timer timer = new Timer(50, taskPerformer);

    while(cursor < (sprite.getNbSprite()-1))
    {           
        timer.start();

        drawExplosion();    
    }
    timer.stop();

    compteur--;

}

public void drawExplosion()
{       
    Graphics g = board.getGraphics();
    board.repaint();
    Graphics2D g2d = (Graphics2D)g;
    g2d.drawImage(sprite.getSprite(cursor), x, y, this);
g.dispose();
}

Но во время отображения у меня естьПроблема, между каждым изображением спрайта есть пробел.Например, если дисплей мерцает.

Как отображать жидкость?Спасибо

РЕДАКТИРОВАТЬ ----------------------- У меня есть еще один вопрос.В моем классе Board я помещаю свой взрыв в ArrayList.Но я должен удалить объект в ArrayList, когда закончится поток взрыва.Есть ли у меня ArrayList для хранения всей моей нити взрыва, и по окончании нити я удаляю объект в ArrayList взрыва.Общественный класс расширяет JPanel {

Mouse mouse;
ArrayList<Explosion> explosions;
Sprite explosion;

public Board() 
{           
    mouse = new Mouse(this);

    explosion = new Sprite(320,320,5,5,"files/explosion2.png");

    explosions = new ArrayList();

    setDoubleBuffered(true); 

    this.addMouseListener(mouse);
}

public void addExplosion(int x, int y)
{


    for(int i=0; i<100; i++)
    {
        int x2 = (int)(Math.random() * 450);
        int y2 = (int)(Math.random() * 450);

        Explosion e2 = new Explosion(this, x2, y2, explosion);


        explosions.add(e2);

        new Thread(e2).start();

    }

}

public void removeExplosion(Explosion e)
{
    explosions.remove(e);

}


public void paint(Graphics g) {
    super.paint(g);

    Graphics2D g2d = (Graphics2D)g;

    for(int i=0; i<explosions.size(); i++)
    {
        g2d.drawImage(explosion.getSprite(explosions.get(i).getCursorI()), explosions.get(i).getX(), explosions.get(i).getY(), this);
    }

    g.dispose();
}

}

Ответы [ 3 ]

2 голосов
/ 06 февраля 2012

Вы, похоже, делаете много вещей неправильно, в том числе

  • совершаете вызовы Swing в фоновом потоке (ваш код ActionListener / Timer)
  • многократно и без необходимости вызываете start на Timerобъект.Я понятия не имею, что вы пытаетесь сделать с этим битом кода.
  • Получение объекта Graphics через getGraphics(), который не получает постоянный объект Graphics.

Вместо этого

  • используйте SwingWorker или Swing Timer для анимации спрайта
  • Выполните все вызовы Swing в EDT, если только из документации API не известно, что метод является поточно-безопасным - отредактируйте:Вы уже говорили об этом в предыдущих ответах здесь.
  • Прочтите в руководствах по Swing, как рисовать на Swing, включая использование BufferedImage и рисование в методе paintComponent JComponent или одного изего дочерние элементы (например, JPanel).

Если вы все еще застряли, подумайте о создании и публикации sscce , который демонстрирует вашу проблему.

1 голос
/ 06 февраля 2012

Метод Timer.start() используется для запуска таймера и должен вызываться только один раз .Это приводит к тому, что объект ActionListener вызывается с интервалом, указанным в конструкторе Timer.В вашем случае он будет увеличивать переменную cursor каждые 50 миллисекунд.

Возможно, вы захотите изучить метод, называемый двойная буферизация .Это предполагает использование двух буферов изображений для рендеринга изображений на экране.Это работает так: вместо того, чтобы рисовать изображение прямо на экране, вы рисуете его в буфере в памяти.Вы отображаете кадр на экране только тогда, когда закончите рендеринг всего кадра .Это помогает устранить мерцание.

Для второго кадра вы делаете то же самое, только вы рисуете во второй буфер, поскольку первый буфер в настоящее время используется для отображения изображения на экране.Когда вы закончите рисовать второй кадр, вы затем отправляете на экран буфер second и используете буфер first для рендеринга следующего кадра и т. Д.

Рендеринг каждого кадра в памяти перед отображением на экране должен помочь устранить мерцание.

1 голос
/ 06 февраля 2012

В Swing вы должны делать все, что касается Swing, в EDT.

// This actually calls paint() in the Swing EDT  
board.repaint(); 
// This runs on your main thread 
// (Never paint anything outside of the EDT!)
g2d.drawImage(sprite.getSprite(cursor), x, y, this); 

Вы видите какое-то мерцание, потому что на board нарисована какая-то картина в двух разных нитях и нарисованы две разные вещи.

Что вам нужно сделать, это создать class BoardWithSprite extend JPanel который переопределяет свой метод paintComponent(g) так, что он рисует спрайт.

Тогда вы можете просто позвонить boardWithSprite.repaint(), и он будет правильно рисовать на Swing EDT.

...