如何以波浪形图案移动物体?

时间:2011-12-01 14:25:42

标签: java

我知道以下代码会直接移动一个对象。如何让物体以波浪线行进?我知道x变量需要额外的东西。

public void draw(Graphics2D g) 
        {
            g.setColor(Color.WHITE);
            g.fillOval ((int) (x - r), (int) (y - r), (int)
                    (2 * r),
                    (int) (2 * r));

            y++;


            if (y - r > height)
                y = -r;
        }

6 个答案:

答案 0 :(得分:5)

使用正弦或余弦函数计算y作为x的函数。

乘以正弦或余弦函数以增加幅度(它的高度)

y = 100 * sin(x) // will make it have peaks of -100 and 100

除以x以增加周期。 (峰之间的距离)

y = sin(x/2) // will make it take twice the x distance between peaks.

这样的事情:

public void draw(Graphics2D g) 
    {
        g.setColor(Color.WHITE);
        g.fillOval ((int) (x - r), (int) (y - r), (int)
                (2 * r),
                (int) (2 * r));

        x++; // Left to right movement
        // Example, modify the multipliers as necessary
        y = 100 * Math.sin(Math.toDegrees(x/4))
    }

答案 1 :(得分:2)

在函数中包含sin(x)或cos(x)将提供规则的波形图案,不规则图案需要更复杂的函数

答案 2 :(得分:1)

我知道你已经接受了一个答案,但这里有一些东西可以从我掀起的内容中获得额外的灵感......

package wavy;

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.util.Timer;
import java.util.TimerTask;
import javax.swing.JFrame;
import javax.swing.JPanel;

public class Wavy {

    public static void main(String[] args) {

        final JFrame frame = new JFrame("Wavy!");

        final WavyPanel wp = new WavyPanel();

        frame.getContentPane().add(wp, BorderLayout.CENTER);

        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        final Ticker t = new Ticker(wp);
        final Repainter r = new Repainter(wp);

        frame.pack();
        frame.setVisible(true);

        final Timer tickTimer = new Timer();
        final Timer paintTimer = new Timer();

        paintTimer.schedule(r, 1000, 50);
        tickTimer.schedule(t, 1000, 10);

    }

    private static class WavyPanel extends JPanel {

        private final Dimension size = new Dimension(640, 480);
        private int amplitude = 50;
        private int frequency = 5;

        private int x = 0;
        private double y = size.height / 2;
        private int yBase = 0;

        WavyPanel() {

            super(true);

        }

        @Override
        protected void paintComponent(final Graphics g) {

            final Graphics2D g2 = (Graphics2D)g;

            g2.setColor(Color.WHITE);
            g2.fillRect(0, 0, size.width, size.height);

            g2.setColor(Color.BLACK);
            g2.fillOval(x, (int)y, 30, 30);

        }

        @Override
        public Dimension getPreferredSize() {
            return size;
        }

        @Override
        public Dimension getMinimumSize() {
            return size;
        }

        @Override
        public Dimension getMaximumSize() {
            return size;
        }

        public void tick() {

            //Move a pixel to the right; loop over to the left when reaching edge
            x = (++x) % size.width;

            //Length of one full wave = panel width divided by frequency
            final int waveLength = size.width / frequency;

            //Incrementing yBase; capping off at wavelength
            yBase = (++yBase) % waveLength;

            //Normalizing to [0..1]
            final double normalized = (double)yBase / (double)waveLength;

            //Full wave at 2*pi, means...
            final double radians = normalized * Math.PI * 2;

            //Getting the sine
            final double sine = Math.sin(radians);

            //Multiplying with amplitude, add to center position and we have our y
            y = (int)(sine * amplitude) + size.height/2;

        }

    }

    private static class Ticker extends TimerTask {

        private final WavyPanel panel;

        Ticker(final WavyPanel panel) {

            this.panel = panel;

        }

        @Override
        public void run() {

            panel.tick();

        }

    }

    private static class Repainter extends TimerTask {

        private final WavyPanel panel;

        Repainter(final WavyPanel panel) {

            this.panel = panel;

        }

        @Override
        public void run() {

            panel.repaint();

        }

    }

}

这应该以大约每秒20帧的速度运行。您可以通过将paintTimer.schedule(r, 1000, 50)的第二个参数设置为较低来增加此值。通过降低(加速)或增加(慢)tickTimer.schedule(t, 1000, 50)的第二个参数,可以改变移动速度。

更改WavyPanel的amplitude字段将更改圆圈的移动高度/低度。将frequency更改为较高的值会导致较短的波浪,而较低的值会产生较长的波浪。

通过一些额外的工作,您可以添加控件以即时更改幅度和频率。一些补充说明:

  • 您可能希望为tick()方法添加一些安全措施,以确保在一次调用已经运行时,将跳过其他调用,直到完成第一次调用。否则,计算可能会因短时间间隔而失败。这里可以使用信号量。
  • 由于三角计算并不是最便宜的,你可以考虑缓存一些结果(例如在数组中)以便重复使用,如果要播放许多类似的动画,或者还有更多的绘图正在进行中。

答案 3 :(得分:0)

我希望我能解释这一点。可以使用x或y坐标的正弦或余弦。我不是在使用java的机器上,所以我现在无法做出示例..

答案 4 :(得分:0)

你是对的,你需要更新x和y变量以获得波浪线。以下是水平线上下波动的一般策略:

  1. 选择具有所需形状的函数f(x)。这将用于计算y的值。 (例如,您可以使用y = amplitude * Math.sin(frequency * x)来获得给定幅度和频率的常规正弦波。)
  2. 如有必要,请编写实现您功能的代码。
  3. 将x设置为某个初始值。
  4. draw中,在绘制椭圆之前,请计算y = f(x);。绘制椭圆,然后增加x。如有必要,请重置x以使其保持在范围内。
  5. 如果您想要一条左右波浪的垂直线,只需颠倒上面xy的角色即可。如果你想让椭圆向反方向移动,只需在步骤4中递减而不是递增。

答案 5 :(得分:0)

此样本用于正弦图上的点(一行长度的线)和使用的时钟。

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

public class RunSwing extends JPanel {
    static int x1 = 500;
    static int y1 = 500;
    static int x2 = x1;
    static int y2 = y1;
    final static int vectorLength = 100;
    final static int sinx2 = x2;
    final static int siny2 = y2;
    static double count = 0;
    private static RunSwing run = new RunSwing();

    final Timer print = new Timer(1000, new ActionListener() {
        @Override
        public void actionPerformed(final ActionEvent e) {
            //increaseSinusGraph();
            increaseClockVector();
            count+=6; //for clock for 1 second
            /*count++;//for sinus*/
            if (count % 360 == 0)
                System.out.println((count / 360) + " minute passed");
        }
    });


    RunSwing() {
        print.start();
    }

    public static void main(String[] args) {
        JFrame frame = new JFrame("amir");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.add(run);
        frame.setSize(1100, 700);
        frame.setVisible(true);
    }

    static void increaseClockVector() {
        double cos = Math.cos(Math.toRadians(count));
        double sin = Math.sin(Math.toRadians(count));
        y2 = siny2 + (int) (vectorLength * sin);
        x2 = sinx2 + (int) (vectorLength * cos);
    }

    static void increaseSinusGraph() {
        double sin = Math.sin(Math.toRadians(count));
        y2 = siny2 + (int) (vectorLength * sin);
        x2++;
    }

    private void createPoint(Graphics g) {
        Graphics2D g2d = (Graphics2D) g;
        g2d.drawLine(x2, y2, x2 + 1, y2 + 1);
    }

    @Override
    public void paintComponent(Graphics g) {
        super.paintComponent(g);
        g.setColor(new Color(0, 0, 0));
        g.drawLine(x1, y1, x2, y2);//for clock
        /*g.drawLine(x2, y2, x2+1, y2+1);//for sinus*/
        repaint();
    }
}