Моделирование дождя

Я делаю игру в java, и я хочу создать симуляцию облака, заливающего дождь. Предполагается, что облако будет двигаться вправо, пока идет дождь. Перемещение облака не проблема. Это дождь, с которым я борюсь.

То, что я собирался сделать, было с помощью таймера рисовать прямоугольник, который должен был выглядеть как падающий дождь при случайном значении x внутри облака. А затем добавьте 1 к значению y падения каждые 100 миллисекунд. Но я не хочу создавать 100 разных прямоугольников, x переменных и y переменных для каждого дождя.

Любая идея, как я могу это сделать? Предложения оценены!


Это игра 2d.. Извините.

Ответ 1

Я бы рекомендовал просто хранить значения как 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();
}

Ответ 2

Один из подходов - рассмотреть шатер в театре. Вы берете серию лампочек и, освещая их и туша их последовательно, можете имитировать линейное движение.

Точно так же, вместо того, чтобы создавать капли дождя и оживлять их движение, почему бы не создать несколько невидимых капель дождя и показать их и спрятать их последовательно, чтобы имитировать движение вниз. Затем у вас будет серия массивов, представляющих дорожку капли дождя, и вам просто нужно будет прокручивать ее, скрывая текущую, увеличивая указатель на массив и отображая ее.

Ответ 3

Требуется ли запрограммировать дождь? Традиционно это делается с помощью нескольких дождевых спрайтов, которые вы размещаете под облаком и живите так, чтобы казалось, что дождь падает.

Ответ 4

Вот моя реализация java (swing) 2d дождя с каплями, всплеском, ветром и гравитацией

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);
    }
}
}

Ответ 5

Вы можете использовать систему частиц или использовать вектор капель дождя и анимировать их каждые 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();
    }
}