Here is [a] java (swing) implementation of 2d rain with drops, splash, wind and gravity
All is clearly described here : https://stackoverflow.com/questions/11295986/simulating-rain
Here is [a] java (swing) implementation of 2d rain with drops, splash, wind and gravity
All is clearly described here : https://stackoverflow.com/questions/11295986/simulating-rain
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); | |
} | |
} |
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 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); | |
} | |
} |
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()); | |
} | |
} |