Проблемы с апплетом Java с методом Paint

Пока я довел этот апплет до рабочей стадии; Единственная проблема в том, что это работает, только если мышь движется; Если мышь не двигать, то все останавливается. Он снова начинает работать, если мышь перемещается.

Это работает так: метод рисования вызывается методом mouseMoved. Каждый раз, когда мышь перемещается, она переходит к методу рисования, и игра продолжается. Проблема возникает из-за того, что метод mouseMoved не вызывается, поэтому метод рисования не вызывается, и все просто приостанавливается, пока мышь не будет перемещена.

Я пробовал следующее:

Наличие рекурсивного метода рисования, поэтому он будет вызывать сам себя. Проблема в том, что тогда mouselistener не работает, потому что программа занята рисованием кучи движущихся вещей.

Я также пытался использовать потоки, чтобы mouselistener прерывал метод рисования. Это не сработало, хотя это могло быть потому, что я не понимаю, как работают потоки. Если кто-нибудь знает, как это реализовать, похоже, это сработает.

Вот фрагмент кода проблемных областей;

  public void paint( Graphics gr) {
     if( Earth != null){

        displayWorld(Earth);
        for(int a =0; a < 100; a++){      
           Earth.run();
           Earth.Worlds.get(2).forceMove(x,y);
          }
        try
        {
           Thread.sleep(100);  
        }
           catch (InterruptedException ie)
           {}   
     }

  }

public void mouseMoved( MouseEvent e ) {
     x = e.getX();
     y = e.getY();
     Graphics gr = getGraphics();      
    paint(gr);
  }  

person rockclimber    schedule 23.08.2012    source источник
comment
О, пропустил это в прошлый раз, не вызывайте Thread.sleep в методе рисования. Это неправильное место для этого   -  person MadProgrammer    schedule 23.08.2012


Ответы (2)


Итак, ваш процесс рисования зависит от движения мыши?? Итак, вам нужен какой-то способ сообщить апплету, чтобы он обновлялся??

private javax.swing.Timer paintTimer;

public void start() {
    // Your normal setup...

    paintTimer = new javax.swing.Timer(250, new ActionListener() {
        public void actionPerformed(ActionEvent evt) {
            Graphics gr = getGraphics();      
            paint(gr);
        }
    });
    paintTimer.setRepeats(true);
    paintTimer.setCoalesce(true);
    paintTimer.start();
}

public void mouseMoved( MouseEvent e ) {
    x = e.getX();
    y = e.getY();

    // You could wait for the timer to trigger the repaint for you...
    repaintTimer.restart();

    Graphics gr = getGraphics();      
    paint(gr);
}  

Однако вам придется поиграть со временем

person MadProgrammer    schedule 23.08.2012
comment
Не используйте здесь javax.swing.Timer. Нет никаких причин. Вы смотрели на java.util.Timer? - person obataku; 23.08.2012
comment
@veer, почему бы и нет? Что мне не хватает? - person MadProgrammer; 23.08.2012
comment
Почему Graphics gr = getGraphics(); paint(gr);, а не просто repaint();? - person Andrew Thompson; 23.08.2012
comment
@AndrewThompson, потому что это то, что мне дали. Я не хотел предполагать, как была обновлена ​​графика. Если ОП использует обычный процесс перерисовки, то да, вы правы (как обычно;)), но у меня не было доказательств, чтобы предложить это так или иначе: P - person MadProgrammer; 23.08.2012
comment
Я не хотел предполагать, что мне это тоже не нравится, что, вероятно, объясняет, почему я такой большой поклонник SSCCE. ;) +1 - person Andrew Thompson; 23.08.2012
comment
@AndrewThompson, если бы это был обычный вопрос апплета, я бы предложил его, но, учитывая, что это вопрос, связанный с игрой, я не знал, рисуют ли они сначала в буфер или нет, а рендерят позже ...: P - person MadProgrammer; 23.08.2012
comment
Большое спасибо, ребята! Работает отлично, спасибо таймеру. Я использовал javax.swing.Timer. - person rockclimber; 23.08.2012

Я бы посоветовал еще раз взглянуть на темы. Это довольно стандартная проблема в программировании игр (и в других областях программирования тоже) — у вас есть один поток, вечно зацикленный, содержащий вашу игровую логику. Он обновляет позицию вашего игрока, вычисляет, оценивает здоровье и т. д. или спит, если нечего делать. Если выполнена работа, требующая перерисовки графики апплета, тогда ваш поток вызывает repaint(), который отправляет запрос на перерисовку в поток диспетчеризации событий (специальный поток, который автоматически создается в каждой Java-программе).

Когда игрок перемещает мышь или вводит данные с клавиатуры, ваши прослушиватели событий обновляют структуры данных вашей программы (и проверяют основной поток, если он спит).

Эти ссылки на предыдущие вопросы StackOverflow, касающиеся игр Java, могут быть хорошей отправной точкой:

Лучший способ реализовать игровой цикл без зависания потока пользовательского интерфейса

игровой цикл — потоки

удачи!

person Dan O    schedule 23.08.2012
comment
Хорошая идея; Я уверен, что делать это правильно с потоками будет полезно в долгосрочной перспективе, особенно когда я перейду к другим проектам. Я обязательно буду использовать темы для следующих версий/уровней, если я сделаю больше. - person rockclimber; 23.08.2012