Create an array of Java points that moves randomly to a specific endpoint

I gave myself a call, and thought that I could ask for help, turning around. I want to use java graphics to draw something that looks like lightning, hitting a given point.

Now I have this one that shoots cheap “lightning” in random directions, and I don’t care where it ends.

lightning[0] = new Point(370,130); //This is a given start point. // Start in a random direction, each line segment has a length of 25 double theta = rand.nextDouble()*2*Math.PI; int X = (int)(25*Math.cos(theta)); int Y = (int)(25*Math.sin(theta)); //Populate the array with more points for (int i = 1 ; i < lightning.length ; i++) { lightning[i] = new Point(X + lightning[i-1].x, Y + lightning[i-1].y); boolean plusminus = rand.nextBoolean(); if (plusminus) theta = theta + rand.nextDouble()*(Math.PI/2); else theta = theta - rand.nextDouble()*(Math.PI/2); X = (int)(25*Math.cos(theta)); Y = (int)(25*Math.sin(theta)); } // Draw lines connecting each point canvas.setColor(Color.WHITE); for (int i = 1 ; i < lightning.length ; i++) { int Xbegin = lightning[i-1].x; int Xend = lightning[i].x; int Ybegin = lightning[i-1].y; int Yend = lightning[i].y; canvas.drawLine(Xbegin, Ybegin, Xend, Yend); //if (Xend != Xbegin) theta = Math.atan((Yend - Ybegin)/(Xend - Xbegin)); // Restrict the angle to 90 degrees in either direction boolean plusminus = rand.nextBoolean(); if (plusminus) theta = theta + rand.nextDouble()*(Math.PI/2); else theta = theta - rand.nextDouble()*(Math.PI/2); // 50/50 chance of creating a half-length off-shoot branch on the end if (rand.nextBoolean()) { int Xoff = (int)(Xend+(12*Math.cos(theta))); int Yoff = (int)(Yend+(12*Math.sin(theta))); canvas.drawLine(Xend, Yend, Xoff, Yoff); } } 

I'm trying to think of a similar way to create this effect, but I mean the last point in the array, predefined, so that lightning can “strike” a certain point. In other words, I want to populate an array of points so that it is random, but still converges at the same endpoint.

Does anyone want to weigh?

+4
source share
2 answers

I think this is a fairly simple, accurate and elegant approach. He uses a strategy of separation and conquest. Start with just 2 values:

  • starting point
  • end point

Calculate the midpoint. The offset, which in the middle means the value of variance (which can be calculated relative to the length). An offset should ideally be normal for a vector connecting the beginning and the end, but you can be cheap by making this offset horizontal if your bolts move mostly vertically, like real lightning. Repeat the above procedure for both (start, offset_mid) and (offset_mid, end), but this time use a smaller number for variance . This is a recursive approach that can end when either the threshold variance or the length of the threshold line segment is reached. When the recursion is unwound, you can draw all segments of the connector. The idea is that the greatest variance occurs at the center of the bolt (when the distance from the beginning to the end is the longest), and with each recursive call, the distance between the points decreases, as well as the variance. Thus, the global dispersion of the bolt will be much larger than any local deviations (for example, a real lightning bolt).

Here are 3 different bolts generated from the same predefined points using this algorithm. These points are (250 100) and (500 800). If you want the bolts to move in any direction (and not just “mostly vertical”), you need to add extra complexity to the point shift code by moving both X and Y by the angle of the bolt.

lightning

And here is some java code for this approach. I used ArrayList , since the divide and conquer approach does not know in advance how many elements it will finish.

 // play with these values to fine-tune the appearance of your bolt private static final double VAR_FACTOR = 0.40; private static final double VAR_DECREASE = 0.55; private static final int MIN_LENGTH = 50; public static ArrayList<Point> buildBolt(Point start, Point end) { ArrayList<Point> bolt = new ArrayList<Point>(); double dx = start.getX() - end.getX(); double dy = start.getY() - end.getY(); double length = Math.sqrt(dx*dx + dy*dy); double variance = length * VAR_FACTOR; bolt.add(start); buildBolt(start, end, bolt, variance); return bolt; } private static void buildBolt(Point start, Point end, List<Point> bolt, double variance) { double dx = start.getX() - end.getX(); double dy = start.getY() - end.getY(); double length = Math.sqrt(dx*dx + dy*dy); if (length > MIN_LENGTH) { int varX = (int) ((Math.random() * variance * 2) - variance); int midX = (start.x + end.x)/2 + varX; int midY = (start.y + end.y)/2; Point mid = new Point(midX, midY); buildBolt(start, mid, bolt, variance * VAR_DECREASE); buildBolt(mid, end, bolt, variance * VAR_DECREASE); } else { bolt.add(end); } return; } 
+4
source

Without any graphical experience, I have this advice: it will be difficult to select a specific point, and then try to reach it “randomly”. Instead, I would recommend creating a straight line from the source to the destination, and then randomly bend parts of it. You can make several passes by bending smaller and smaller segments to a certain limit to get the desired look. Again, I say this without any knowledge of the graphical API.

+1
source

All Articles