2012-05-30 3 views
2

У меня есть (какая должна быть) простая проблема для решения, и я открыт для других способов ее решения. Я открыт для других решений.Несколько таймеров качания

Проблема: Мы используем java swing для отображения графики пошаговой игры на основе плитки. Я использую jlabels с иконками, абсолютно позиционированными.

Чтобы анимировать движение, я использую свинг таймер, который обновляет местоположение на 4 пикселя в то время, медленно перемещая право спрайта, левое и т.д.

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

Спрайт перемещается вниз, никогда не двигается вправо, и если я смотрю исполнение с помощью какой-либо консоли, ясно, что оба таймера работают одновременно. Я сделал много денег в Интернете, и я не смог найти способ сказать таймер качания не выполнять, пока первый таймер не остановится, и если я попытаюсь заняться - подождите, пока один таймер не закончит (yuck) пользовательский интерфейс никогда не отображается вообще (явно шаг в неправильном направлении).

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

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

Заранее благодарим за любой совет, который у вас может быть.

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

So. У нас есть две функции, каждая из которых имеет таймер, который запускает цикл анимации, один для перемещения вниз и справа по диагонали, один для движения вниз.

public class TestClass { 
static int counter = 0; 
static int counter2 = 0; 
static Timer timerC; 
static Timer timerX; 

public static void main(String[] args) { 
    moveC(); 
    moveX(); 
} 

public static void moveC() { 
    int delay = 200; // milliseconds 

    timerC = new Timer(delay, null); 
    timerC.addActionListener(new ActionListener() { 
     public void actionPerformed(ActionEvent evt) { 
      if (counter < 32) { 
       counter = counter + 4; 
       System.out.println("*C*"); 
      } else { 
       timerC.stop(); 
       System.out.println("*C STOP*"); 
      } 

     } 
    }); 
    timerC.start(); 
} 

public static void moveX() { 
    int delay = 200; // milliseconds 

    timerX = new Timer(delay, null); 
    timerX.addActionListener(new ActionListener() { 
     public void actionPerformed(ActionEvent evt) { 
      if (counter < 32) { 
       counter = counter + 4; 
       System.out.println("*X*"); 
      } else { 
       timerX.stop(); 
       System.out.println("*X STOP*"); 
      } 

     } 
    }); 
    timerX.start(); 
} 

}

То, что я хотел бы видеть здесь в конце концов будет

*C* 
*C* 
*C* 
*C* 
*C STOP* 
*X* 
*X* 
*X* 
*X* 
*X STOP* 

То, что я на самом деле получаю

*C* 
*X* 
*C* 
*X* 
*C* 
*X* 
*C* 
*X* 
*C STOP* 
*X STOP* 

Точка Я пытаюсь получить в здесь выполняется один цикл анимации до завершения, затем другой.

Еще раз спасибо.

+0

Для лучшей помощи рано, опубликовать [SSCCE] (HTTP: //sscce.org/). –

+0

Что значит «оба таймера работают одновременно». Я вижу только код для одного таймера, и этот таймер работает один раз. Просьба уточнить и рассмотреть возможность создания и публикации [sscce] (http://sscce.org). Также, пожалуйста, очистите форматирование кода, так как если ваш код будет легче читать и понимать, у нас будет больше шансов дать вам хороший совет. –

+0

Я бы использовал для этого очередь. –

ответ

5

Не используйте несколько таймеров, а только один таймер, который имеет дело с каждым направлением по мере необходимости. Вам нужна какая-то очередь для хранения информации о направлении, либо официальной очереди, либо коллекции, которую вы используете в качестве очереди (сначала сначала, сначала), а затем ваш таймер извлекает направление из этой очереди по мере ее запуска. Например, здесь я использую модель моего JList как моя очередь путем удаления и использования Direction, который был добавлен первым (в верхней части JList):

import java.awt.GridLayout; 
import java.awt.event.*; 
import javax.swing.*; 

public class TimerPlay extends JPanel { 
    private DefaultListModel directionJListModel = new DefaultListModel(); 
    private JList directionJList = new JList(directionJListModel); 
    JButton startTimerButton = new JButton(
     new StartTimerBtnAction("Start Timer")); 

    public TimerPlay() { 
     ActionListener directionBtnListener = new ActionListener() { 

     @Override 
     public void actionPerformed(ActionEvent actEvt) { 
      String actionCommand = actEvt.getActionCommand(); 
      Direction dir = Direction.valueOf(actionCommand); 
      if (dir != null) { 
       directionJListModel.addElement(dir); 
      } 
     } 
     }; 
     JPanel directionBtnPanel = new JPanel(new GridLayout(0, 1, 0, 10)); 
     for (Direction dir : Direction.values()) { 
     JButton dirBtn = new JButton(dir.toString()); 
     dirBtn.addActionListener(directionBtnListener); 
     directionBtnPanel.add(dirBtn); 
     } 

     add(directionBtnPanel); 
     add(new JScrollPane(directionJList)); 
     add(startTimerButton); 
    } 

    private class StartTimerBtnAction extends AbstractAction { 
     protected static final int MAX_COUNT = 20; 

     public StartTimerBtnAction(String title) { 
     super(title); 
     } 

     @Override 
     public void actionPerformed(ActionEvent arg0) { 
     startTimerButton.setEnabled(false); 

     int delay = 100; 
     new Timer(delay, new ActionListener() { 
      private int count = 0; 
      private Direction dir = null; 

      @Override 
      public void actionPerformed(ActionEvent e) { 
       if (count == MAX_COUNT) { 
        count = 0; // restart 
        return; 
       } else if (count == 0) { 
        if (directionJListModel.size() == 0) { 
        ((Timer)e.getSource()).stop(); 
        startTimerButton.setEnabled(true); 
        return; 
        } 
        // extract from "queue" 
        dir = (Direction) directionJListModel.remove(0); 
       } 
       System.out.println(dir); // do movement here 
       count++; 

      } 
     }).start(); 
     } 
    } 

    private static void createAndShowGui() { 
     TimerPlay mainPanel = new TimerPlay(); 

     JFrame frame = new JFrame("TimerPlay"); 
     frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
     frame.getContentPane().add(mainPanel); 
     frame.pack(); 
     frame.setLocationByPlatform(true); 
     frame.setVisible(true); 
    } 

    public static void main(String[] args) { 
     SwingUtilities.invokeLater(new Runnable() { 
     public void run() { 
      createAndShowGui(); 
     } 
     }); 
    } 

} 

enum Direction { 
    UP, DOWN, LEFT, RIGHT; 
} 
+2

+1 для [sscce] (http://sscce.org/). Является ли 'MAX_COUNT' произвольным значением для демонстрации? – trashgod

+0

@trash: да, точно. Это вполне может быть переменной. Благодарю. 1+ backatcha за хороший совет. –

+1

Я вижу это, хороший, правый – mKorbel

3

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

3
  • положить все Icon с в том или иной форме массива

  • создать единые Качели Timer с короткой задержкой

  • в свинге ActionListener, принимать каждый `иконку из массива, GetBounds с экрана , переместить значок на один шаг

  • повторить до достижения цели.

+0

+1 Подобно этому [игра] (http://robotchase.sourceforge.net/). – trashgod