Java Swing Timer和Animation:如何将它组合在一起

时间:2015-02-05 11:16:42

标签: java swing animation sprite

我将再次发布这个问题,试图更精确,并希望我会得到一些帮助,因为这让我发疯。我正在开发一款最多有6名玩家的棋盘游戏,每个游戏都有不同颜色的棋子。我有下面的图像加载在BufferedImage数组中,将其视为精灵:

enter image description here

这是相对代码,将每个彩色模具的每个面放在BufferedImage []中的位置:

private BufferedImage[] initAnimationBuffer() {
    BufferedImage[] result = new BufferedImage[36];
    for (int i = 0; i < 6; i++) {
        for (int j = i; j < 6 + i; j++)
            result[i + j] = DieSprite.getSprite(j, i, 0);

    }

    return result;
}

然后每个玩家根据他的颜色,根据获得的模具值/位置,还将具有包含其颜色面的以下矩阵。换句话说,该矩阵包含图像的“一条线”,并按值索引:

private BufferedImage[][] initExactDieFaces() {
    BufferedImage[][] result = new BufferedImage[6][1];
    int row = -1;
    String myColor = this.coreGame.getMyPartecipant().getColor();
    if (myColor.equals(Constants.COLOR[0])) {
        row = 0;
    } else if (myColor.equals(Constants.COLOR[1])) {
        row = 2;
    } else if (myColor.equals(Constants.COLOR[2])) {
        row = 4;
    } else if (myColor.equals(Constants.COLOR[3])) {
        row = 1;
    } else if (myColor.equals(Constants.COLOR[4])) {
        row = 5;
    } else if (myColor.equals(Constants.COLOR[5])) {
        row = 3;
    }
    int offset = 0;
    for (int i = 0; i < 6; i++) {
        result[i][0] = DieSprite.getSprite(row, i, offset);
        offset += 2;
    }
    return result;
}

我想要的是以下内容: - 当按下“翻转模具”按钮时,我希望(例如)在JPanel内的特定JLabel中显示20个随机模具面(它们应该从第一个数组中获取,AnimationBuffer) - 上一个动画完成后,我想要显示获得的模具启动结果(根据颜色典当,取自ExcatDieFaces)。

为了得到这个,我知道我需要摆动计时器,但我无法将它们全部放在一起;这里是一些startAnimationDie方法的代码,当按下“翻转”按钮时调用该方法:

private void startAnimationDie(final JPanel dieContainer) {

  final BufferedImage[] animationBuffer = initAnimationBuffer();
  final BufferedImage[][] exactDieFaces = initExactDieFaces();
  final AnimationSprite animation = new AnimationSprite(
                    animationBuffer, Constants.DIE_ANIMATION_SPEED);

  /* getting launch value fromt the core Game */
  int launchResult = coreGame.launchDie();
  coreGame.getMyPartecipant().setLastLaunch(launchResult);

  final Timer timer = new Timer(250, new ActionListener() {

  @Override
  public void actionPerformed(ActionEvent e) {

     dieContainer.removeAll();
     dieContainer.updateUI();
     animation.start();
     JLabel resultDie = new JLabel();
     resultDie.setBounds(60, 265, Constants.DIE_SIZE,Constants.DIE_SIZE);
     resultDie.setIcon(new ImageIcon(animationBuffer[new Random().nextInt(36)]));
     dieContainer.add(resultDie);
     dieContainer.updateUI();
     updateUI();
     repaint();

    }
  });

/* animation begins, rolling faces are shown each time the Timer ends*/
for(int i = 0; i<20; i++) 
  timer.start()

/* showing the final face according to the pawn color and the obtained result from the launch */

dieContainer.removeAll();
dieContainer.updateUI();
AnimationSprite resultAnimation = new AnimationSprite(exactDieFaces[launchResult - 1], 6);
resultAnimation.start(); 
resultAnimation.update();
resultDie.setIcon(new ImageIcon(exactDieFaces[launchResult - 1][0]));
resultDie.setBounds(60, 265, Constants.DIE_SIZE, Constants.DIE_SIZE);
dieContainer.add(resultDie);
dieContainer.updateUI();
dieContainer.repaint();

}

我怎样才能让它发挥作用?我想我应该使用Swing.invokeAndWait但是我不能把所有的东西放在一起......你能帮忙吗?

1 个答案:

答案 0 :(得分:5)

  1. 不要打电话给updateUI,除非您正在处理安装外观和感觉,否则它没有按照您的想法行事(而且效率非常低) )
  2. 每次都不要重建UI,这是耗时的工作,这将使动画看起来平静,交错,可能会闪现很多。相反,只需更新标签的icon属性
  3. 即可
  4. 使用单个Timer,允许它递增一个计数器,这样您就可以知道它被调用了多少次,并在每个刻度上更新骰子和计数器。
  5. Timer视为一种循环,在每次迭代(勾选)时,你需要做一些事情(比如递增计数器)

    Die

    (注意 - 当看起来模具已经停止&#34;它是因为图像已经按顺序显示了一次。你可以通过将所有图像放入一个List并使用Collections.shuffle。这样做三次,将结果添加到另一个List应该给你24个,没有重复的序列(好吧,它可能&#34;可能&#34;重复边界,但比使用Math.random;))

    更好
    import java.awt.Dimension;
    import java.awt.EventQueue;
    import java.awt.GridBagConstraints;
    import java.awt.GridBagLayout;
    import java.awt.event.ActionEvent;
    import java.awt.event.ActionListener;
    import java.awt.image.BufferedImage;
    import java.io.File;
    import java.io.IOException;
    import javax.imageio.ImageIO;
    import javax.swing.ImageIcon;
    import javax.swing.JButton;
    import javax.swing.JFrame;
    import javax.swing.JLabel;
    import javax.swing.JPanel;
    import javax.swing.Timer;
    import javax.swing.UIManager;
    import javax.swing.UnsupportedLookAndFeelException;
    
    public class Test {
    
        public static void main(String[] args) {
            new Test();
        }
    
        public Test() {
            EventQueue.invokeLater(new Runnable() {
                @Override
                public void run() {
                    try {
                        UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
                    } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
                        ex.printStackTrace();
                    }
    
                    JFrame frame = new JFrame("Testing");
                    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                    frame.add(new TestPane());
                    frame.pack();
                    frame.setLocationRelativeTo(null);
                    frame.setVisible(true);
                }
            });
        }
    
        public class TestPane extends JPanel {
    
            private BufferedImage[] dice = new BufferedImage[6];
            private JLabel die;
    
            public TestPane() {
                try {
                    BufferedImage img = ImageIO.read(new File("/Users/swhitehead/Documents/Die.png"));
                    int width = 377 / 6;
                    for (int index = 0; index < 6; index++) {
                        dice[index] = img.getSubimage(width * index, 0, width, width);
                    }
                } catch (IOException ex) {
                    ex.printStackTrace();
                }
                setLayout(new GridBagLayout());
                GridBagConstraints gbc = new GridBagConstraints();
                gbc.gridwidth = GridBagConstraints.REMAINDER;
                die = new JLabel(new ImageIcon(dice[0]));
                add(die, gbc);
    
                JButton roll = new JButton("Roll");
                add(roll, gbc);
    
                roll.addActionListener(new ActionListener() {
                    @Override
                    public void actionPerformed(ActionEvent e) {
                        roll.setEnabled(false);
                        Timer timer = new Timer(250, new ActionListener() {
                            private int counter;
                            private int lastRoll;
                            @Override
                            public void actionPerformed(ActionEvent e) {
                                if (counter < 20) {
                                    counter++;
                                    lastRoll = (int)(Math.random() * 6);
                                    System.out.println(counter + "/" + lastRoll);
                                    die.setIcon(new ImageIcon(dice[lastRoll]));
                                } else {
                                    lastDieRollWas(lastRoll);
                                    ((Timer)e.getSource()).stop();
                                    roll.setEnabled(true);
                                }
                            }
                        });
                        timer.start();
                    }
                });
            }
    
            protected void lastDieRollWas(int roll) {
                System.out.println("You rolled " + (roll + 1));
            }
    
            @Override
            public Dimension getPreferredSize() {
                return new Dimension(200, 200);
            }
    
        }
    
    }