如何在java

时间:2017-06-09 08:31:38

标签: java swing animation timer

我正在努力弄清楚计时器类是如何工作的,我可以使用它。我在网上寻找答案虽然我找到了一个对我这样的初学者来说很容易的解释。如果有人发送了一个很好的计时器类的链接,或者甚至可以向我解释我应该在我的代码中做什么,我将非常感激。谢谢!

    public class movement {
    private JComponent jt; // the JLabel (my game character)
    private InputMap ip;
    private ActionMap ap;
    private String comm; // the ActionMapKey
    private KeyStroke key;
    private int movement;
public movement(JComponent jt, InputMap ip,ActionMap ap, String comm,KeyStroke key,int movement){
    this.jt = jt;
    this.ip = ip;
    this.ap= ap;
    this.comm = comm;
    this.key = key;
    this.movement = movement;
}
public void newAction(){
    this.ip  = this.jt.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW);
    this.ip.put(key, comm);
    this.ap = this.jt.getActionMap();
    this.ap.put(this.comm, new AbstractAction() {


        @Override
        public void actionPerformed(ActionEvent arg0) {
            int originaly = jt.getY();
            if(key ==  KeyStroke.getKeyStroke(KeyEvent.VK_UP,0)){



                if(originaly==jt.getY()){
                    // how do i make this action animated? i want the JLabel to look like its moving up (like a jump) 
                    // after the up key is pressed 
                    // i dont really understand how to use the timer class to make it animated .. thanks!
                    jt.setBounds(jt.getX(),jt.getY()+movement , 50, 50);
                    //timer pause for 0.1 secs
                    jt.setBounds(jt.getX(),jt.getY()+movement , 50, 50);
                    //timer pause for 0.1 secs...
                    // can also be in a while loop until the y is 50 higher than original y. 
                }

            }
            else{
            jt.setBounds(jt.getX()+movement,jt.getY() , 50, 50);
            }
        }
    });

}
}

2 个答案:

答案 0 :(得分:1)

好的,所以问题不在于计时器,而是了解动画是如何实现的。

  • 动画是一种状态随时间的变化
  • Timer是伪循环,在迭代之间具有指定的延迟

好的,这有什么用呢?好吧,基本上,你需要制作一个物体的概念,从它的当前位置移动到新的位置然后再向后移动(向上和向下跳跃)

这是Timer进入的地方。Timer提供了一个州和下一个州之间的延迟,这应该足够让用户感知

这是一个非常基本的例子,但它证明了基本原理。密钥绑定Action不负责更改位置,它负责更改状态,然后由Timer执行操作。为什么?想象一下,现在你有其他键绑定(左和右),它们不应该改变对象的状态,因为这些更改可能会发生冲突。相反,他们设置了一个状态标志,然后用于确定状态更新时应该发生什么。

该对象具有yPos,并且可以通过更改值(yDelta)执行操作,该更改值会影响实际应用于对象的更改。当jumptrue时,对象会移动到它的最高高度并再次向下移动。完成此循环后,jump状态将被重置,这意味着您无法继续按空格键以在空中执行多次跳转...因为这是不可能的;)

import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.io.IOException;
import javax.swing.AbstractAction;
import javax.swing.ActionMap;
import javax.swing.InputMap;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.KeyStroke;
import javax.swing.Timer;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;

public class Test {

    public static void main(String[] args) throws IOException {
        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 int yPos = 200;
        private int yDelta = -1;

        private boolean jump = false;

        public TestPane() {
            InputMap im = getInputMap(WHEN_IN_FOCUSED_WINDOW);
            ActionMap am = getActionMap();

            im.put(KeyStroke.getKeyStroke(KeyEvent.VK_SPACE, 0), "space");
            am.put("space", new AbstractAction() {
                @Override
                public void actionPerformed(ActionEvent e) {
                    jump = true;
                }
            });
            Timer timer = new Timer(5, new ActionListener() {
                @Override
                public void actionPerformed(ActionEvent e) {
                    if (jump) {
                        if (yPos > 200) {
                            yPos = 200;
                            yDelta *= -1;
                            jump = false;
                        } else if (yPos < 150) {
                            yPos = 150;
                            yDelta *= -1;
                        } else {
                            yPos += yDelta;
                        }
                        repaint();
                    }
                }
            });
            timer.start();
        }

        @Override
        public Dimension getPreferredSize() {
            return new Dimension(200, 200);
        }

        @Override
        protected void paintComponent(Graphics g) {
            super.paintComponent(g);
            Graphics2D g2d = (Graphics2D) g.create();
            int x = (getWidth() - 5) / 2;
            g2d.fillRect(x, yPos - 10, 10, 10);
            g2d.dispose();
        }

    }

}

很多无聊的理论

TL; DR

现在,这是一个过于简化的例子,它没有讨论像帧速率,地毯或重力这样的东西来命名一些东西。你可以看看this example,它展示了变量delta的概念,它随着时间的推移而降级,应用了(非常基本的)引力概念。

还有其他方法可以实现类似的结果,具体取决于您想要做什么,但它们围绕着相同的概念。

如果你真的很勇敢,那么你可以看看How can I implement easing functions with a thread,它贬低(相当糟糕的恕我直言)缓和概念 - 或变速动画。您还可以查看Java image move along points in list and use linear interpolation,其中讨论了更多关于变量动画路径的信息 - 其中t(时间)是可变的,这允许您根据动画播放的时间长度计算动画的值。你希望它玩多久。

如果你想知道为什么我会提到它 - 那是因为你可以做like this这些事情,这极大地扩展了你可以做的事情。

但是,所有这些事情的核心是Timer

答案 1 :(得分:-1)

好的,当你说“计时器暂停0.1秒”时,我想你可以使用Thread.sleep(100); 100 - &gt; 100毫秒我在这里看不到计时器的需要。 Thread.sleep(int)只会暂停执行代码一段特定的毫秒数。