10

我正在用Java制作游戏,我想创建一个正在倾盆大雨的云的模拟。云应该在下雨时向右移动。移动云没有问题。这是我正在努力应对的雨。

我想做的是用计时器来绘制一个矩形,这应该看起来像在云内部随机 x 值下的雨。然后每 100 毫秒将 drop 的 y 值加 1。但我不想为每个雨滴创建 100 个不同的矩形、x 变量和 y 变量。

知道我怎么能做到这一点吗?建议赞赏!


这是一个 2d 游戏.. 对不起。

4

5 回答 5

3

是否需要对雨滴进行编程?传统上,这将通过放置在云下并设置动画的一些雨精灵来完成,以使其看起来像正在下雨。

于 2012-07-02T14:55:22.627 回答
3

一种方法是考虑在剧院设置一个选框。你拿一系列灯泡,通过依次点亮和熄灭它们,你可以模拟线性运动。

同样,与其创建雨滴并为其运动设置动画,不如创建多个不可见的雨滴并按顺序显示和隐藏它们以模拟向下运动。然后,您将有一系列表示雨滴轨迹的数组,您只需循环遍历,隐藏当前的,递增数组指针并显示那个。

于 2012-07-02T14:51:22.977 回答
2

这是我的 2d 雨的 java (swing) 实现,带有水滴、飞溅、风和重力

import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.awt.geom.Ellipse2D;
import java.awt.geom.Line2D;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.Random;
import javax.swing.JFrame;
import javax.swing.JPanel;

public class Main {

 public static void main( String [] args ) {
     JFrame frame = new JFrame();
     frame.setSize(800, 300);
     final RPanel rPanel=new RPanel();
     frame.add(rPanel);
     frame.setVisible( true );
     frame.addWindowListener(new WindowAdapter() {
        @Override
        public void windowClosing(WindowEvent e) {
            super.windowClosing(e);
            rPanel.stop();
            System.exit(0);
        }
    });
}
}

class RPanel extends JPanel {
//*********SETTINGS****************************
private float mWind = 2.05f;
private float mGravity = 9.8f;
private double mRainChance = 0.99; // from 0 to 1

private int mRepaintTimeMS = 16;
private float mRainWidth=1;
private double mDdropInitialVelocity = 20;
private double mDropDiam = 2;
private Color mColor=new Color(0, 0, 255);
//*********************************************

private ArrayList<Rain> rainV;
private ArrayList<Drop> dropV;
private UpdateThread mUpdateThread;

public RPanel() {
    rainV = new ArrayList<>();
    dropV = new ArrayList<>();

    mUpdateThread=new UpdateThread();
    mUpdateThread.start();
}

public void stop() {
    mUpdateThread.stopped=true;
}

public int getHeight() {
    return this.getSize().height;
}

public int getWidth() {
    return this.getSize().width;
}

private class UpdateThread extends Thread {
    public volatile boolean stopped=false;
    @Override
    public void run() {
        while (!stopped) {
            RPanel.this.repaint();
            try {
                Thread.sleep(mRepaintTimeMS);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}

@Override
public void paintComponent(Graphics g) {
    super.paintComponent(g);
    Graphics2D g2 = (Graphics2D) g;
    g2.setStroke(new BasicStroke(mRainWidth));
    g2.setColor(mColor);

    //DRAW DROPS
    Iterator<Drop> iterator2 = dropV.iterator();
    while (iterator2.hasNext()) {
        Drop drop = iterator2.next();
        drop.update();
        drop.draw(g2);

        if (drop.y >= getHeight()) {
            iterator2.remove();
        }
    }

    //DRAW RAIN
    Iterator<Rain> iterator = rainV.iterator();
    while (iterator.hasNext()) {
        Rain rain = iterator.next();
        rain.update();
        rain.draw(g2);

        if (rain.y >= getHeight()) {
            //create new drops (2-8)
            long dropCount = 1 + Math.round(Math.random() * 4);
            for (int i = 0; i < dropCount; i++) {
                dropV.add(new Drop(rain.x, getHeight()));
            }
            iterator.remove();

        }
    }

    //CREATE NEW RAIN
    if (Math.random() < mRainChance) {
        rainV.add(new Rain());
    } 
}

//*****************************************
class Rain {
    float x;
    float y;
    float prevX;
    float prevY;

    public Rain() {
        Random r = new Random();
        x = r.nextInt(getWidth());
        y = 0;
    }

    public void update() {
        prevX = x;
        prevY = y;

        x += mWind;
        y += mGravity;
    }

    public void draw(Graphics2D g2) {
        Line2D line = new Line2D.Double(x, y, prevX, prevY);
        g2.draw(line);
    }
}

//*****************************************
private class Drop {

    double x0;  
    double y0;  
    double v0; //initial velocity
    double t;  //time
    double angle;
    double x;
    double y;

    public Drop(double x0, double y0) {
        super();
        this.x0 = x0;
        this.y0 = y0;

        v0 = mDdropInitialVelocity;
        angle = Math.toRadians(Math.round(Math.random() * 180)); //from 0 - 180 degrees
    }

    private void update() {
        // double g=10;
        t += mRepaintTimeMS / 100f;
        x = x0 + v0 * t * Math.cos(angle);
        y = y0 - (v0 * t * Math.sin(angle) - mGravity * t * t / 2);
    }

    public void draw(Graphics2D g2) {
        Ellipse2D.Double circle = new Ellipse2D.Double(x, y, mDropDiam, mDropDiam);
        g2.fill(circle);
    }
}
}
于 2013-10-09T09:50:01.760 回答
2

我建议只将值存储为对象的 ArrayList。

class Raindrop {
    private int x;
    private int y;

    public void fall() {
        y--;
    }
}

然后创建一个泛型类型的 ArrayList。

ArrayList<Raindrop> drops = new ArrayList<Raindrop>();

让每一滴落下,

for (int i=0; i<drops.length(); i++) {
    drops.get(i).fall();
}
于 2012-07-02T14:59:00.397 回答
0

您可以使用粒子系统或使用雨滴矢量并每 X 毫秒为它们设置动画。粒子系统库的链接:http ://code.google.com/p/jops/

矢量的示例代码:

import java.util.Vector;
// In your class
Vector raindrops;
void animate()
{
    ListIterator iter = raindrops.listIterator;
    while (iter.hasNext()) {
        ((Raindrop)iter.next()).moveDown();
    }
}
于 2012-07-02T14:54:58.760 回答