移动时如何让动画移动?

时间:2013-04-03 21:56:52

标签: java swing object animation jpanel

所以现在,当你按下它时它只是在屏幕上移动,但我也希望它移动它的腿以便它做一些事情,而不仅仅是站着不动。关于如何做到这一点的任何提示?我知道它会来回移动第二条腿指针,但我不知道该怎么做

Class Stick2:

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



public class Stick2 extends JFrame implements ActionListener {

    // Declares constants 
    public static final int FRAME_WIDTH = 500;
    private static final int FRAME_HEIGHT = 500;
    private static final int FRAME_X_ORIGIN = 150;
    private static final int FRAME_Y_ORIGIN  = 200;
    private static final int BUTTON_WIDTH =80;
    private static final int BUTTON_HEIGHT = 30;

    JPanel buttonPanel, panel;

    MovingBanner2 myBanner;
    JButton startButton, stopButton;

    Thread thrd;


    public static void main(String[] args) 
    {
        Stick2 frame = new Stick2();
        frame.setVisible(true);
    }

    public Stick2(){


         Container contentPane= getContentPane();

        // Sets Frame
        setSize(FRAME_WIDTH,FRAME_HEIGHT);
        setResizable(false);
        setTitle("Animation");
        setLocation(FRAME_X_ORIGIN, FRAME_Y_ORIGIN);

        // Sets layout manager
        contentPane.setLayout(new BorderLayout(10,0));


        buttonPanel = new JPanel();

        JButton startButton = new JButton("Start");
        startButton.setSize(BUTTON_WIDTH, BUTTON_HEIGHT);
        buttonPanel.add(startButton);
        startButton.addActionListener(this);

        JButton stopButton = new JButton("Stop");
        stopButton.setSize(BUTTON_WIDTH,BUTTON_HEIGHT);
        buttonPanel.add(stopButton);
        stopButton.addActionListener(this);

        contentPane.add (buttonPanel, BorderLayout.SOUTH);

        // Creates a balloon
        myBanner = new MovingBanner2();
        panel = myBanner;
        panel.setBorder(BorderFactory.createLineBorder(Color.BLUE));
        contentPane.add(panel, BorderLayout.CENTER);



    }

    public void actionPerformed (ActionEvent event){
        JButton clickedButton = (JButton) event.getSource();

        String buttonText = clickedButton.getText();

        if (buttonText.equals("Stop")) {

            myBanner.stopAnimation();
            thrd = null;
        }
        else {

            myBanner.startAnimation();
            thrd = new Thread (myBanner);
            thrd.start();


       }
    }            
}

Class MovingBanner2:

class MovingBanner2 extends JPanel implements Runnable {

        private int x;

        private Boolean animate;

        int bodyX = 250;
        int bodyY1 = 160;
        int bodyY2 = 210;
        int armHeight = 190;
        int armLength = bodyX + 30;
        int armLength1 = bodyX - 30;
        int legY = 340;

        public MovingBanner2() {
            x=10;
            animate = true;
        }

        // Draws the String
        public void paintComponent (Graphics g) {
            super.paintComponent(g);

            g.setColor(Color.RED);
            //g.drawString("I love Java", x,50);
            g.drawLine(bodyX + x, bodyY1, bodyX + x, bodyY2); //body
            g.drawOval(bodyX + x - 15, bodyY1 - 40, 40, 40); //head
            g.drawLine(armLength + x,armHeight,  armLength1 + x, armHeight); //arms
            g.drawLine(bodyX + x, bodyY2, bodyX + 20 + x,legY); //leg
            g.drawLine(bodyX + x, bodyY2, bodyX - 20 + x, legY);    //leg
        }

        public void run() {
            while (animate) { 
                changeX();
                repaint();     
                try {Thread.sleep(100); } catch(Exception e){};
            }
        }



        public void changeX() {

            if (x <= Stick2.FRAME_WIDTH - 240)
                 x++;
            else x = 10;

        }

        public void stopAnimation() {
            animate = false;
        }

        public void startAnimation() {
            animate = true;
        }
}

1 个答案:

答案 0 :(得分:3)

这个问题可能有很多答案。我能想到的最好的就是设计某种“循环”。

循环是动画可以运行的已知时间段。在这个例子中,它是1秒。

然后,您需要提供一系列Animatable个对象,这些对象会随着时间的推移通知周期的变化,这样就可以相应地进行更改。您也可以忽略那些不需要循环的元素的循环。

目的是提供一个单一的动画引擎,它可以一次性更新整个状态,而不是尝试使用多个线程/定时器,这可能会降低系统性能。

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.GridBagLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.text.NumberFormat;
import java.util.ArrayList;
import java.util.List;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.Timer;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;

public class TestAnimation06 {

    public static void main(String[] args) {
        new TestAnimation06();
    }

    public TestAnimation06() {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                try {
                    UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
                } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
                }

                JFrame frame = new JFrame("Testing");
                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                frame.setLayout(new BorderLayout());
                frame.add(new TestPane());
                frame.pack();
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);
            }
        });
    }

    public interface Animatable {
        public void update(float progress);
    }

    public class AnimationEngine {

        private List<Animatable> animations;
        private int cycleTime = 1000;
        private long startTime = -1;

        public AnimationEngine() {
            animations = new ArrayList<>(25);
            Timer timer = new Timer(40, new ActionListener() {
                @Override
                public void actionPerformed(ActionEvent e) {
                    if (startTime < 0) {
                        startTime = System.currentTimeMillis();
                    }
                    long duration = System.currentTimeMillis() - startTime;
                    float progress = (float)duration / (float)cycleTime;
                    if (duration >= cycleTime) {
                        progress = 1f;
                        startTime = System.currentTimeMillis();
                    }
                    for (Animatable animatable : animations) {
                        animatable.update(progress);
                    }
                }
            });
            timer.setRepeats(true);
            timer.setCoalesce(true);
            timer.start();
        }

        public void add(Animatable animatable) {
            animations.add(animatable);
        }

    }

    public class TestPane extends JPanel {

        private AnimationEngine engine;

        public TestPane() {
            setLayout(null);
            engine = new AnimationEngine();
            Legs legs = new Legs();
            Walker walker = new Walker(legs);
            engine.add(legs);
            engine.add(walker);
            walker.setSize(walker.getPreferredSize());
            add(walker);
        }

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

        @Override
        protected void paintComponent(Graphics g) {
            super.paintComponent(g);
            Graphics2D g2d = (Graphics2D) g.create();
            g2d.dispose();
        }
    }

    public class Walker extends JPanel implements Animatable {

        private int speed = 2;

        public Walker(Legs legs) {
            setLayout(new GridBagLayout());
            add(legs);
        }

        @Override
        public void update(float progress) {
            Container parent = getParent();
            int width = parent.getWidth();
            int xPos = getX() + speed;
            if (xPos <= 0) {
                speed *= -1;
                xPos = 0;
            } else if (xPos + getWidth() >= width) {
                speed *= -1;
                xPos = width - getWidth();
            }
            System.out.println(xPos);
            setLocation(xPos, (parent.getHeight() - getHeight()) / 2);
            repaint();
        }

    }

    public class Legs extends JPanel implements Animatable {

        private float frameProgress;

        public Legs() {
            setOpaque(false);
        }

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

        @Override
        public void update(float progress) {
            frameProgress = progress;
            repaint();
        }

        @Override
        protected void paintComponent(Graphics g) {
            super.paintComponent(g); 
            int width = getWidth();
            int height = getHeight();

            g.setColor(Color.BLACK);
            g.drawLine(width / 2, 0, (int)(width * frameProgress), height);
            g.drawLine(width / 2, 0, width - (int)(width * frameProgress), height);
        }

    }

}