2009-04-21 2 views
4

Возможно, я ошибаюсь, поэтому, пожалуйста, будьте милы. Я разрабатываю Java-игру, и я нахожусь на стадии тестирования движения/анимации персонажа.Вызов перерисовки из другого класса на Java?

«Лицо» может двигаться вверх по левому и правому краю сетки. Класс, в который вставляется сетка, является классом gamePanel. Кнопки находятся в классе gameControlPanel.

У меня есть кнопка, которая порождает человека на сетке. Затем у меня есть кнопка, чтобы переместить человека вверх и вниз влево и вправо.

Когда нажата кнопка перемещения вверх, она вызывает метод перемещения вверх от класса человека. (На данный момент, я только тестирование одного «человека» в то время.) В этом методе есть следующий код ...

int move = 10; 
while(move!=0) 
{ 
    setTopLeftPoint(new Point((int)getTopLeftPoint().getX(), 
           (int)getTopLeftPoint().getY() - 3)); 

    try 
    { 
     Thread.sleep(300); 
    } catch (InterruptedException e) 
    { 
     // TODO Auto-generated catch block 
     e.printStackTrace(); 
    } 
    move-=1; 
} 

Проблема заключается в том, что я не могу назвать repaint для класса gamePanel из класса Person. Чтобы обойти это, я создал таймер в классе gamePanel, который переписывает каждые 20 мс.

Когда я нажимаю кнопку «вверх» после того, как человек порожден, кнопка остается нажатой до тех пор, пока циклы цикла while не будут завершены, а затем изображение круга отображается на квадрате квадрата выше.

Я постараюсь ответить на любые вопросы, касающиеся этого.

ответ

1

Если вы хотите перекрасить в определенный промежуток времени, javax.swing.Timer, вероятно, является для вас классом. В конкретном случае repaint вы можете вызывать его из потока, отличного от EDT, но вы можете столкнуться с трудностями, поскольку теперь имеете дело с несколькими потоками.

+0

Я считаю, что несколько потоков слишком сложны для меня. У меня есть другой вопрос, который люди должны рассматривать как своего рода ответ на этот вопрос. Я решил сделать логическую перерисовку на каждом тике таймера 100 мс. – Relequestual

0

У меня нет опыта создания игр, но наличие петли для управления всей анимацией является фундаментальным аспектом игрового программирования. В большинстве простых игр 2d есть только 1 цикл, чтобы отобразить большую часть его анимации.

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

Это позволит каждому объекту нарисоваться на графическом объекте. Хотя это всего лишь один из способов сделать это.

synchronized (entities) { 
    for (Entity e : entities) { 
     e.draw(g); 
     e.doAction(); 
    } 
} 
+0

Да, я действительно делаю это, однако, когда нажата кнопка «вверх», я должен изменить положение на -3 вверх, используя цикл while. Картина не меняется. Я просто думаю, что я могу сделать это немного неправильно. – Relequestual

+0

Думаю, я вижу. Мне кажется, вы делаете движение своего человека в той же теме, что и в игровом цикле. Поэтому да, ваш человек действительно движется, но во время движения (во время цикла) ваш основной цикл не перерисовывается, потому что он ждет человек, чтобы двигаться, спать и двигаться и т. д. Это не хорошая практика, но вы можете создать новый поток, чтобы сделать движение вашего человека. –

+0

Хорошо, я могу это сделать. Если это не хорошая практика, как я должен это делать? – Relequestual

0

Включена ли кнопка нажатием кнопки потока событий вашего графического интерфейса?

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

Для получения дополнительной информации о резьбонарезке см. Starting a thread.

+0

Я не уверен, что понимаю, что вы имеете в виду в своем вопросе. Насколько мне известно, я не занимался резьбой. Я по-прежнему новичок в java. В предыдущем ответе остались некоторые комментарии, которые кажутся полезными. – Relequestual

+0

Я только попросил вас убедиться, если вы не сделали что-то очень эзотерическое, ответ почти наверняка «да». Создание собственной потоковой передачи является альтернативой предложенному выше SwingWorker. –

+0

Я думаю, что я использую SwingWorker или другой поток, может быть, я немного усложняю ситуацию. Я собираюсь задать еще один вопрос по этому вопросу. Спасибо за вашу помощь. – Relequestual

2

repaint() не сразу перерисовывает GUI. Скорее, он отправляет сообщение в поток AWT, говоря ему, чтобы рисовать при следующей удобной возможности. Когда это получит шанс, оно перекрасит ваше приложение. Однако, если вы делаете это в обработчике событий, поток AWT уже занят, и вам нужно выйти из обработчика, чтобы вернуть управление обработчику AWT.

Как правило, вы не можете выполнять любые длительные вычисления по потоку AWT (в том числе в обработчиках событий), так как они перестанут реагировать на другие события, пока ваши вычисления не будут выполнены сделанный. Это часто будет отображаться пользователю в виде застрявших кнопок, как описано. Чтобы обойти это, используйте SwingWorker, который может выполнять вычисления в отдельном потоке.

Наконец, что-то, что нужно знать (но не обязательно менять), заключается в том, что таймеры и сон не гарантируют, когда они пробудятся. Скорее, они гарантируют, что они не пробудятся до истечения времени, но теоретически могут спать бесконечно. Кроме того, не все машины имеют разрешение таймера 1 мс. В частности, на многих машинах Windows таймеры имеют разрешение 55 мс, поэтому таймер 20 мс может дать странные результаты.

+1

Спасибо за эту полезную информацию. Я все еще на очень базовых этапах тестирования игры, поэтому кто знает. Я коротко посмотрел на swingworker, но это выглядит очень запутанным для меня: S – Relequestual

+0

The SwingWorker определенно то, что вы хотите здесь. Как и многие Java, у него крутая кривая обучения, но как только вы это выясните, вам, вероятно, больше не понадобится этот таймер. –

Смежные вопросы