//---------------------------------------------------------//
//
// Granule Ishihama Yoshiaki All right reserved
// ishmnn@cap.bekkoame.ne.jp
//
//---------------------------------------------------------//
import java.awt.*;
import java.applet.*;
import java.io.*;
import java.lang.String;
import java.util.Random;
import java.util.Date;
public class Granules extends Applet implements Runnable
{
Thread runner;
int NUM, WIDTH,HEIGHT,i,j,myPhase=0,st=0;
Graphics g2;
CGranule granule[];
Random nrand;
public void init()
{
Date d=new Date();
nrand=new Random(d.getTime());
WIDTH=this.size().width;
HEIGHT=this.size().height;
String s;
g2=this.getGraphics();
g2.setColor(Color.black);
g2.fillRect(0,0,WIDTH,HEIGHT);
s=getParameter("NUM");
if (s==null)NUM=50;
else NUM = Integer.parseInt(s);
setBackground(Color.black);
setForeground(Color.white);
granule=new CGranule[NUM];
for(i=0;i < NUM;i++){
granule[i]=new CGranule();
granule[i].DoInit(WIDTH,HEIGHT,nrand);
}
}
public void start()
{
if (runner == null)
{
runner= new Thread(this);
runner.start();
}
}
public void stop()
{
if (runner!=null)
{
runner.stop();
runner=null;
}
}
public void run()
{
while (true) {
try { Thread.sleep(10); }
catch (InterruptedException e){};
if ( isVisible() ) {
DomyRun();
offpaint();
}
}
}
public void DomyRun()//----------------------------------//
{
switch(myPhase){
case 0: //------------- Normal State -----------//
st ++; if(st > 400) { st=0; myPhase=10; }
for(i=0;i < NUM;i++) {
int total=0;
double[] LOC,loc;
int[] myCellP,cellp;
LOC=new double[2];
loc=new double[2];
myCellP=new int[2];
cellp =new int[2];
LOC[0]=LOC[1]=0.0;
granule[i].GetCellPoint(myCellP);
for(j=0;j < NUM;j++){
if(j==i) continue;
granule[j].GetCellPoint(cellp);
if(java.lang.Math.abs(myCellP[0] - cellp[0]) < 2 &&
java.lang.Math.abs(myCellP[1] - cellp[1]) < 2){
granule[j].DoGetLoc(loc);
LOC[0] +=loc[0];
LOC[1] +=loc[1];
total ++;
}
}
if(total!=0){
double f1;
f1= total;
loc[0]=LOC[0]/f1;
loc[1]=LOC[1]/f1;
} else {
loc[0]=loc[1]=0.0;
}
granule[i].SetVelocity(loc);
granule[i].Course(nrand);
granule[i].Mechanics();
}
break;
case 10: //--------- Explosion ------------//
for(i=0;i < NUM;i++) granule[i].SetPhase(100);
myPhase=11;
break;
case 11:
for(i=0;i < NUM;i++){
granule[i].Course(nrand);
granule[i].Mechanics();
}
st ++;
if(st > 170){
st=0;
myPhase=0;
for(i=0;i < NUM;i++) granule[i].SetPhase(110);
}
break;
}
}//-----------------------------------------------------//
public void offpaint ()
{
int k;
int[] nn;
nn=new int[2];
for (k=0;k < NUM;k++){
g2.setColor(Color.black);
granule[k].DoGetOldLocInt(nn);
g2.drawLine(nn[0],nn[1],nn[0], nn[1]);
g2.setColor(Color.white);
granule[k].DoGetLocInt(nn);
g2.drawLine(nn[0],nn[1],nn[0], nn[1]);
}
}
public void paint(Graphics g2)
{
//g2.drawImage(offscreen, 0, 0,Color.black,this);
}
}
//------------------------------ CGranule -----------------------//
public class CGranule
{
int phase,st,count,sx,sy;
double[] loc, vct, deltaVCT,oldDelta;
double maxx,minx,maxy,miny,mycenterX,mycenterY;
int[] cellP,oldLoc;
public int rand(Random nrand,int range)
{
return( java.lang.Math.abs(nrand.nextInt()) % range);
}
public void DoInit(int Width,int Height,Random nrand)
{
double f1;
loc=new double[2];
vct=new double[2];
deltaVCT=new double[2];
oldDelta=new double[2];
st=0;
phase=10;
deltaVCT[0]=0;
deltaVCT[1]=0;
sx=Width;
sy=Height;
loc[0]=rand(nrand,sx) - sx/2;
loc[1]=rand(nrand,sy) - sy/2;
f1=rand(nrand,360)-180;
f1 *=0.01745;
vct[0]=java.lang.Math.cos(f1);
vct[1]=java.lang.Math.sin(f1);
maxx=sx/2; minx=-maxx;
maxy=sy/2; miny=-maxy;
mycenterX=maxx;
mycenterY=maxy;
cellP=new int[2];
oldLoc=new int[2];
oldLoc[0]=oldLoc[1]=0;
SetCellPoint();
}
public void Mechanics()
{
vct[0] += deltaVCT[0];
vct[1] += deltaVCT[1];
loc[0] +=vct[0];
loc[1] +=vct[1];
}
public void DoGetLoc(double dst[])
{
dst[0] = loc[0];
dst[1] = loc[1];
}
public void DoGetLocInt(int dst[])
{
dst[0] =(int)( loc[0] + mycenterX);
dst[1] =(int)( loc[1] + mycenterY);
oldLoc[0]=dst[0];
oldLoc[1]=dst[1];
}
public void DoGetOldLocInt(int dst[])
{
dst[0] =oldLoc[0];
dst[1] =oldLoc[1];
}
public void Course(Random nrand)
{
switch(phase) {
case 10: //-------- Normal ----------//
if(CheckClosure()) return;
SetCellPoint();
break;
case 100: //-------- Explosion -------//
{double f1;
f1=rand(nrand,360)-180;
f1 *=0.01745;
deltaVCT[0]=java.lang.Math.cos(f1);
deltaVCT[1]=java.lang.Math.sin(f1);
vct[0]=0;
vct[1]=0;
phase=101;st=0;
}
break;
case 101:
st ++;
if(st > 20){
st=0;
oldDelta[0]=deltaVCT[0];
oldDelta[1]=deltaVCT[1];
deltaVCT[0]=0;
deltaVCT[1]=0;
phase=102;
}
CheckClosure2();
break;
case 102:
st ++;
if(st > 50){
st=0;
deltaVCT[0]=-oldDelta[0] * 0.2;
deltaVCT[1]=-oldDelta[1] * 0.2;
phase=103;
}
CheckClosure2();
break;
case 103:
CheckClosure2();
break;
case 110:
phase=10;
CheckClosure2();
break;
}
}
public boolean CheckClosure()
{
if(loc[0] > maxx) {
if( vct[0] > 0 ){
vct[0]=-vct[0];
deltaVCT[0]=0;
return true;
}
}
if(loc[0] < minx){
if(vct[0] < 0 ){
vct[0]=-vct[0];
deltaVCT[0]=0;
return true;
}
}
if(loc[1] > maxy){
if(vct[1] > 0 ){
vct[1]=-vct[1];
deltaVCT[1]=0;
return true;
}
}
if(loc[1] < miny){
if(vct[1] < 0 ){
vct[1]=-vct[1];
deltaVCT[1]=0;
return true;
}
}
return false;
}
public void CheckClosure2()
{
if(loc[0] > maxx) {
if( vct[0] > 0 ){
vct[0]=-vct[0];
deltaVCT[0]=-deltaVCT[0];
}
}
if(loc[0] < minx){
if(vct[0] < 0 ){
vct[0]=-vct[0];
deltaVCT[0]=-deltaVCT[0];
}
}
if(loc[1] > maxy){
if(vct[1] > 0 ){
vct[1]=-vct[1];
deltaVCT[1]=-deltaVCT[1];
}
}
if(loc[1] < miny){
if(vct[1] < 0 ){
vct[1]=-vct[1];
deltaVCT[1]=-deltaVCT[1];
}
}
}
public void SetCellPoint()
{
int s1,s2,s3,s4;
s1= (int)loc[0] + sx/2;
s2= (int)loc[1] + sy/2;
s3=sx/10;
s4=sy/10;
cellP[0]=s1/s3;
cellP[1]=s2/s4;
}
public void GetCellPoint(int dst[])
{
dst[0]=cellP[0];
dst[1]=cellP[1];
}
public void GetVelocity(double dst[])
{
dst[0]= vct[0];
dst[1]= vct[1];
}
public void SetVelocity(double p0[])
{
double px,py, fp1;
px=p0[0] - loc[0];
py=p0[1] - loc[1];
fp1= myLength2d(px,py);
fp1= fp1/5.0;
if(fp1!=0.0) {
px /=fp1;
py /=fp1;
} else{
px=py=0.0;
}
px -= vct[0];
py -= vct[1];
deltaVCT[0]=px/10.0;
deltaVCT[1]=py/10.0;
}
public double myLength2d(double px,double py)
{
double f;
f=px*px + py*py;
f=java.lang.Math.sqrt(f);
return f;
}
public int GetPhase()
{
return phase;
}
public void SetPhase(int s)
{
phase=s;
}
}