import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class Lightning extends JPanel implements MouseMotionListener{
//ScreenCoords (Point2D cannot be instantiated blah blah blah=no idea=wtf?)
private static class ScreenCoords{
public int x,y;
public ScreenCoords(int _x, int _y){
x=_x; y=_y;
}
public ScreenCoords add(ScreenCoords a){ return new ScreenCoords(x+a.x,y+a.y); }
public ScreenCoords sub(ScreenCoords a){ return new ScreenCoords(x-a.x,y-a.y); }
public ScreenCoords mul(int a){ return new ScreenCoords(x*a,y*a); }
public ScreenCoords div(int a){ return new ScreenCoords(x/a,y/a); }
public int getLength(){ return (int)Math.sqrt(x*x+y*y); }
public ScreenCoords getOrtho(){ return new ScreenCoords(-y,x); }
}
//Node-struct
private static class Node{
//member vars
private boolean isLeaf;
private Node[] childNodes;
private ScreenCoords[] vertices;
//final static
private final static int MIN_CHILDNODES=3, MAX_ADDITIONAL_CHILDNODES=4;
private final static int MIN_BIFURCATION=0, MAX_ADDITIONAL_BIFURCATION=3;
//constructor
public Node(ScreenCoords start, ScreenCoords end, int level){
if(level==0){
//end of recursion, creating leaf node
isLeaf=true;
vertices=new ScreenCoords[2];
vertices[0]=start; vertices[1]=end;
}else{
isLeaf=false;
//decide how many child nodes to create
int numberOfChildNodes=
MIN_CHILDNODES+(int)(Math.random()*MAX_ADDITIONAL_CHILDNODES+1);
int numberOfBifurcationNodes=
level+(int)(Math.random()*(MAX_ADDITIONAL_BIFURCATION+1));
//allocate space for all the nodes
childNodes=new Node[numberOfChildNodes+numberOfBifurcationNodes];
//create vertices for child nodes
ScreenCoords[] childVertices=new ScreenCoords[numberOfChildNodes+1];
//first and last vertices already exist: its start and end of parent node
childVertices[0]=start; childVertices[childVertices.length-1]=end;
//creating vertices for the child nodes
//AN DIESER STELLE BELIEBIGES ANDERES VERFAHREN EINSETZEN, DAMITS HÜBSCHER AUSSIEHT!
ScreenCoords connection=end.sub(start);
ScreenCoords ortho=connection.getOrtho().div(8);
double randomConnectionDistance;
for(int i=1; i<numberOfChildNodes; i++){
randomConnectionDistance=Math.random()*2-1d;
childVertices[i]=
start.add(connection.mul(i).div(numberOfChildNodes)
.add(new ScreenCoords((int)(ortho.x*randomConnectionDistance),
(int)(ortho.y*randomConnectionDistance))));
}
//adding the child nodes to the list
for(int i=0; i<numberOfChildNodes; i++){
childNodes[i]=new Node(childVertices[i], childVertices[i+1], level-1);
}
//bifurcations: the first vertex is always "start"
//and the second vertex is always random
double randomRadius, randomAngle;
int radius=connection.getLength()*3/numberOfChildNodes;
for(int i=0; i<numberOfBifurcationNodes; i++){
randomRadius=(1+Math.random())*radius/2;
randomAngle=Math.random()*2*Math.PI;
childNodes[i+numberOfChildNodes]=
new Node(start,start.add(new ScreenCoords((int)(randomRadius*Math.cos(randomAngle)),
(int)(randomRadius*Math.sin(randomAngle)))),
level-1);
}
}
}//end of constructor
public void paint(Graphics g){
if(isLeaf){
g.setColor(Color.WHITE);
g.drawLine(vertices[0].x, vertices[0].y, vertices[1].x, vertices[1].y);
}else{
for(int i=0; i<childNodes.length; i++){
childNodes[i].paint(g);
}
}
}
}//end of Node-class definition
//auto-repaint thread
private static class RepaintThread extends Thread{
private Lightning lightningPanel;
public RepaintThread(Lightning _lightningPanel){
lightningPanel=_lightningPanel;
}
public void run(){
while(true){
if(lightningPanel.lightningOn){
if(Math.random()>0.975){
lightningPanel.lightningOn=false;
}
}else{
if(Math.random()>0.995){
lightningPanel.lightningOn=true;
}
}
if(Math.random()>0.95){
lightningPanel.lightningOn=!lightningPanel.lightningOn;
}
lightningPanel.repaint();
try{
sleep(30);
}catch(InterruptedException e){}
}
}
}
//member vars
//root Node
private Node root;
private int mouseX,mouseY;
public boolean lightningOn;
//constructor
public Lightning(){
super();
mouseX=mouseY=100;
addMouseMotionListener(this);
lightningOn=false;
RepaintThread repaintThread=new RepaintThread(this);
repaintThread.start();
}
//paint
public void paint(Graphics g){
g.setColor(Color.BLACK);
g.fillRect(0, 0, getWidth(), getHeight());
if(lightningOn){
root=new Node(new ScreenCoords(getWidth()/2,100), new ScreenCoords(mouseX, mouseY), 3);
root.paint(g);
}
}
//mouse motion listener
public void mouseMoved(MouseEvent e){
mouseX=e.getX(); mouseY=e.getY();
}
public void mouseDragged(MouseEvent e){}
//main
public static void main(String[] args){
JFrame f=new JFrame("Lightning hits the cursor");
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.setSize(500,500);
f.getContentPane().add(new Lightning());
f.setVisible(true);
}
}