Java 移动物体和计时器

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/21868170/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-13 11:09:47  来源:igfitidea点击:

Moving objects and timers

javaswinganimationtimeraffinetransform

提问by Thatdude1

I have a screen with say 500 width and 400 height, and I have a vector with a bunch of shapes. let say the vector has 2 different shapes for example. I want the object to randomly pop up from the bottom of the screen reach a certain ascent and then fall back down (similar to game fruit ninja, where the fruits are my shapes).

我有一个宽度为 500 和高度为 400 的屏幕,我有一个带有一堆形状的矢量。例如,假设向量有 2 个不同的形状。我希望物体从屏幕底部随机弹出,达到一定的上升然后再下降(类似于游戏水果忍者,水果是我的形状)。

In my main (view) I have a vector of shapes of which i instantiate the timers, add to array and place them in the buttom of the screen using the translate function. My timer takes in an action listener which basically changes the translate of the shape to move up till ascent and then down, but my problem is that all the shapes start at the same time regardless.

在我的主(视图)中,我有一个形状向量,我将其实例化了定时器,添加到数组中并使用 translate 函数将它们放置在屏幕的底部。我的计时器接收一个动作监听器,它基本上改变了形状的平移,向上移动,然后向上移动,然后向下移动,但我的问题是,不管怎样,所有形状都同时开始。

Something like this:

像这样的东西:

        Shape f = new Shape(new Area(new Ellipse2D.Double(0, 50, 50, 50)));   
        f.translate(0, 400);   
        f.timer = new Timer( 10 , taskPerformer);    
        f.timer.start();    
        vector.add(f);    


        Shape f2 = new Shape(new Area(new Rectangle2D.Double(0, 50, 50, 50)));    
        f2.translate(200, 400);    
        f2.timer = new Timer( 10 , taskPerformer);    
        f2.timer.setInitialDelay(5000);    
        f2.timer.start();    
        vector.add(f2);

and my action listener:

和我的动作监听器:

        Random generator = new Random();            
        ActionListener taskPerformer = new ActionListener() {
                public void actionPerformed(ActionEvent evt) {
                   //...Perform a task...
             for (Shape s : model.getShapes()) {
                // Scale object using translate
                // once reached ascent drop down
                // translate to diffrenet part of the bottom of the screen
                // delay its timer
                }    
                update();
                //basically repaints      
            }

    };

I'm running into problems that all shapes follow the same timer, and begin to pop up at the same time (no delay) ...

我遇到了所有形状都遵循相同计时器的问题,并且同时开始弹出(无延迟)......

Any suggestions on how to avoid this or if there is a different approach i should try

关于如何避免这种情况的任何建议,或者是否有不同的方法,我应该尝试

采纳答案by Paul Samsotha

"I want the object to randomly pop up from the bottom of the screen reach a certain ascent and then fall back down"

“我希望物体从屏幕底部随机弹出,达到一定的上升,然后再下降”

See the runnable example below. What I do is pass a radomDelayedStartto the Shape. Every tick of the timer, the randomDelayedStartdecreases til it reaches 0, that's when the flag to be drawn in raised. Most of the logic is in the Shapeclass methods, which are called in the Timers Actionlistener. Everything is done in oneTimer. For the ascent, I just used a hard coded 50, but you can also pass a random ascent to the Shape. Let me know if you have any questions. I tried to made the code as clear as possible.

请参阅下面的可运行示例。我所做的是将 a 传递radomDelayedStartShape. 计时器的每个滴答声都会randomDelayedStart减少,直到它达到 0,这就是要绘制的标志升起的时候。大多数逻辑在Shape类方法中,它们在Timers中调用Actionlistener。一切都合而为一Timer。对于上升,我只使用了硬编码 50,但您也可以将随机上升传递给Shape. 如果您有任何问题,请告诉我。我试图使代码尽可能清晰。

enter image description here

在此处输入图片说明

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
import javax.swing.Timer;

public class RandomShape extends JPanel {

    private static final int D_HEIGHT = 500;
    private static final int D_WIDTH = 400;
    private static final int INCREMENT = 8;
    private List<Shape> shapes;
    private List<Color> colors;
    private Timer timer = null;

    public RandomShape() {
        colors = createColorList();
        shapes = createShapeList();

        timer = new Timer(30, new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                for (Shape shape : shapes) {
                    shape.move();
                    shape.decreaseDelay();
                    repaint();
                }
            }
        });
        JButton start = new JButton("Start");
        start.addActionListener(new ActionListener(){
            public void actionPerformed(ActionEvent e) {
                timer.start();
            }
        });
        JButton reset = new JButton("Reset");
        reset.addActionListener(new ActionListener(){
            public void actionPerformed(ActionEvent e) {
                shapes = createShapeList();
                timer.restart();
            }
        });

        JPanel panel = new JPanel();
        panel.add(start);
        panel.add(reset);
        setLayout(new BorderLayout());
        add(panel, BorderLayout.PAGE_START);
    }

    @Override
    protected void paintComponent(Graphics g) {
        super.paintComponent(g);
        for (Shape shape : shapes) {
            shape.drawShape(g);
        }
    }

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

    private List<Color> createColorList() {
        List<Color> list = new ArrayList<>();
        list.add(Color.BLUE);
        list.add(Color.GREEN);
        list.add(Color.ORANGE);
        list.add(Color.MAGENTA);
        list.add(Color.CYAN);
        list.add(Color.PINK);
        return list;
    }

    private List<Shape> createShapeList() {
        List<Shape> list = new ArrayList<>();
        Random random = new Random();
        for (int i = 0; i < 20; i++) {
            int randXLoc = random.nextInt(D_WIDTH);
            int randomDelayedStart = random.nextInt(100);
            int colorIndex = random.nextInt(colors.size());
            Color color = colors.get(colorIndex);
            list.add(new Shape(randXLoc, randomDelayedStart, color));
        }

        return list;
    }

    class Shape {

        int randXLoc;
        int y = D_HEIGHT;
        int randomDelayedStart;
        boolean draw = false;
        boolean down = false;
        Color color;

        public Shape(int randXLoc, int randomDelayedStart, Color color) {
            this.randXLoc = randXLoc;
            this.randomDelayedStart = randomDelayedStart;
            this.color = color;
        }

        public void drawShape(Graphics g) {
            if (draw) {
                g.setColor(color);
                g.fillOval(randXLoc, y, 30, 30);
            }
        }

        public void move() {
            if (draw) {
                if (y <= 50) {
                    down = true;
                }

                if (down) {
                    y += INCREMENT;
                } else {
                    y -= INCREMENT;
                }
            }
        }

        public void decreaseDelay() {
            if (randomDelayedStart <= 0) {
                draw = true;
            } else {
                randomDelayedStart -= 1;
            }
        }

    }

    public static void main(String[] args) {
        SwingUtilities.invokeLater(new Runnable() {
            public void run() {
                JFrame frame = new JFrame();
                frame.add(new RandomShape());
                frame.pack();
                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);
            }
        });
    }
}