Question

image

I have Jbutton (represented by the envelope) and an ArrayList of lines which the Envelope will go along. Can anyone help me? any ideas or tutorial will be much appreciated.

Was it helpful?

Solution

I assume that your goal is to animate the envelope along the line to provide an animation of data being transferred.

For every line you need first to find the line equation. A line equation is in the form y = a * x + b. If you already have that in the List you mention then that's fine. If on the other hand you have two points instead (start and end positions), use those with the above equation to find a, b for each line.

After you have the equations for your lines then you can use an animation (probably with a SwingWorker or a SwingTimer) that would increase the x coordinate of your envelope at regular intervals and then use the line equation to calculate the new y coordinate.

I hope that helps

Update: Added code snippet for a moving box using a SwingTimer for demonstration

package keymovement;

import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
import javax.swing.Timer;
import javax.swing.UIManager;

public class TestMovingObject {

    static class Envelope {
        double x;
        double y;

        void setPosition(double x, double y) {
            this.x = x;
            this.y = y;
        }
    }

    static class DrawArea extends JPanel {

        Envelope envelope = new Envelope();

        @Override
        protected void paintComponent(Graphics g) {
            super.paintComponent(g);
            g.setColor(Color.red);
            int x = (int) Math.round(envelope.x);
            int y = (int) Math.round(envelope.y);
            g.drawRect(x, y, 20, 20);
        }

        public Envelope getEnvelope() {
            return envelope;
        }
    }

    /**
     * @param args
     */
    public static void main(String[] args) {

        SwingUtilities.invokeLater( new Runnable() {

            @Override
            public void run() {
                try {
                    UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
                } catch (Exception e) {
                    throw new RuntimeException(e);
                }

                JFrame window = new JFrame("Moving box");
                window.setPreferredSize(new Dimension(500, 400));
                window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

                final DrawArea mainArea = new DrawArea();
                window.add(mainArea);
                window.pack();

                window.setLocationRelativeTo(null);
                window.setVisible(true);

                int delay = 20; // execute every 20 milliseconds i.e. 50 times per second  

                Timer timer = new Timer(delay, new ActionListener() {
                    @Override
                    public void actionPerformed(ActionEvent e) {
                        Envelope envelope = mainArea.getEnvelope();
                        double x = envelope.x + 1;  // use smaller increments depending on the desired speed
                        double y = 0.5 * x + 2;     // moving along the line y = 0.5 * x + 2
                        envelope.setPosition(x, y);
                        mainArea.repaint();
                    }
                });
                timer.setRepeats(true);
                timer.start();

            }
        });
    }

}

OTHER TIPS

Can you tell me a very simple example?

In this game, enemies advance toward the player one row or column at time, without calculating any intermediate points. When the destination is stationary, the path is a straight line. The animation is paced by a javax.swing.Timer. See RCModel#move() and RCView#timer for the implementation.

There are some mathematic things to do for you. Check out this article: http://en.wikipedia.org/wiki/Bresenham%27s_line_algorithm

This simple algorithm will tell you each X,Y coordinate on a line between two points. You could use this algorithm to compute all of the positions it needs to visit, store the coordinates in an array, and iterate over the array as you update the position.

There is an alternative helper class:

package snippet;

import java.awt.geom.Point2D;

public class MyVelocityCalculator {

    public static void main(String[] args) {
        Point2D.Double currentPosition = new Point2D.Double();
        Point2D.Double destinationPosition = new Point2D.Double();
        currentPosition.setLocation(100, 100);
        destinationPosition.setLocation(50, 50);
        Double speed = 0.5;

        System.out.println("player was initially at: " + currentPosition);
        while (currentPosition.getX() > destinationPosition.getX()
                && currentPosition.getY() > destinationPosition.getY()) {

            Point2D.Double nextPosition = MyVelocityCalculator.getVelocity(currentPosition, destinationPosition, speed);
            System.out.println("half seconds later player should be at: " + nextPosition);

            currentPosition = nextPosition;

        }
        System.out.println("player destination is at: " + destinationPosition);

    }

    public static final Point2D.Double getVelocity(Point2D.Double currentPosition, Point2D.Double destinationPosition,
            double speed) {
        Point2D.Double nextPosition = new Point2D.Double();
        double angle = calcAngleBetweenPoints(currentPosition, destinationPosition);
        double distance = speed;
        Point2D.Double velocityPoint = getVelocity(angle, distance);
        nextPosition.x = currentPosition.x + velocityPoint.x;
        nextPosition.y = currentPosition.y + velocityPoint.y;
        return nextPosition;
    }

    public static final double calcAngleBetweenPoints(Point2D.Double p1, Point2D.Double p2) {
        return Math.toDegrees(Math.atan2(p2.getY() - p1.getY(), p2.getX() - p1.getX()));
    }

    public static final Point2D.Double getVelocity(double angle, double speed) {
        double x = Math.cos(Math.toRadians(angle)) * speed;
        double y = Math.sin(Math.toRadians(angle)) * speed;
        return (new Point2D.Double(x, y));
    }
}

Instead of print out the position on console you need to draw the control at this position to you graphics element.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top