/*

Great expectations!

Meeting your darlings!

After a whole year.

What ever went wrong?


Coding: sh0dan

Sound: sinus

Gfx: constrict

dadah:   mer' str›m.
         [more power]

Ind:  The Party 1997
       ||
       \/
      The Darkening '97

*/

import java.awt.*;
import java.awt.image.*;
import java.applet.*;

public class santa extends java.applet.Applet implements Runnable {

   Graphics backGC;
   Dimension backSize;
   AudioClip sine;
   AudioClip svin;
	  char separated[];
	  Thread killme = null;
	  boolean threadSuspended = false;
   Dimension oD;
   Image oI;
   Graphics oG;
   Image sh0dan;
   MediaTracker tracker;
   int counter = 0;
   int where = 0;
   long startTime;
   long lastTime;
   int param=1;
   int greypixels[];
   int greypixels2[];
   int alphapixels[];
   int redpixels[];
   int greenpixels[];
   int bluepixels[];
   int redpixels2[];
   int greenpixels2[];
   int bluepixels2[];
   int splitpixels[];
   int newpixels[];
   int splitwidth;
   int splitheight;
   int splitsize;
   int useimage=1;
//   int[] spritexpos;
//   int spriteoffset;
//   int sprx2;
//   int spry2;
//   int sprite;
//   int nextbeat=0;
   ImageConsumer ic;
   Image[] load;
//                              //0        1            2              3              4        5        6          7            8            9          10         11          12          13      14         15
   String imgnames[] = {"TEATERST.gif","CURTAIN.gif","CAPTURED.GIF","BACK2.jpg","ST12.gif","ST22.gif","ST32.gif","ST42.gif","coding.gif","sound.gif","gfx.gif","ms.jpg","fadeback.gif","TP.gif","TD.gif","the-end.gif"};
   String animnames[] = {"ENGEL4.gif","ENGEL4-2.gif"};
   int nametable[] = new int[3];
   Point namepos[] = new Point[3];
   int lastname = 0;
   int lastnametime=0;
   int coltable[] = new int[256];
   int redcoltable[] = new int[256];
   int greencoltable[] = new int[256];
   int bluecoltable[] = new int[256];
//plasma
   int sinetable[] = new int[256];
   int coun=0;
   int punchtablex[];
   int punchtabley[];
   int xplat=25;
//blob
   boolean occupied[];
   int horblobpix[];
   int verblobpix[];
   double horblobstep[];
   double verblobstep[];
   double horblobplace[];
   double verblobplace[];
//anims
   boolean firstframe=true;

public void init() {
   load = new Image[imgnames.length];
   sine = getAudioClip(getCodeBase(), "sine.au");
   svin = getAudioClip(getCodeBase(), "svin.au");

   tracker = new MediaTracker(this);
   for (int i=0;i<imgnames.length;i++) {
	    load[i] = getImage(getCodeBase(), imgnames[i]);
     System.out.println("Getting #"+i+" Named:"+imgnames[i]);
     tracker.addImage(load[i],0);
   }

   resize(600,450);
   Dimension d = size();
   if ( (oG == null)
          || (d.width != oD.width)
          || (d.height != oD.height) ) {
            oD = d;
            oI = createImage(d.width, d.height);
            oG = oI.getGraphics();
   }
   try {
      tracker.waitForID(0);
   } catch (InterruptedException  e) {
   }
   wait(3000);
 }

public void start() {
   where=0;
	  if(killme == null) {
     killme = new Thread(this);
     killme.start();
	  }
 }

public void stop() {
	  killme = null;
   sine.stop();
   svin.stop();
   System.out.println("eat up your autechre grease lumps!!");
 }

public void run() {
   Thread.currentThread().setPriority(Thread.MIN_PRIORITY);
   startTime = System.currentTimeMillis();
	  while (killme != null) {
	    try {
	      Thread.sleep(40);} catch (InterruptedException e){}
	    repaint();
	  }
	  killme = null;
 }

public void paint(Graphics g) {
   update(g);
 }


public synchronized void update(Graphics g) {
//intro: at start where=0 - at end where<1000  !!
   long offsetTime= System.currentTimeMillis()-startTime;
   if (System.currentTimeMillis()-lastTime>0) {

   if (offsetTime<10000) {
       if (offsetTime>2000) {
         intro(g,(int) offsetTime-2000);
       } else if (where<20) {
         cls();
         g.drawImage(oI, 0, 0, this);
         where=20;
       }
     }
//one: at start where<1000 - at end where<2000  !!
     else
     if (offsetTime<38000) {
       one(g,(int) offsetTime-10000);
     }
//two: at start where<2000 - at end where<3000  !!
     else
   if (offsetTime<45000) {
       two(g,(int) offsetTime-38000);
     }
     else
   if (offsetTime<57500) {
       three(g,(int) offsetTime-45000);
     }
     lastTime= System.currentTimeMillis();
   }
 }


// intro: T‘ppe venter, g†r op...

public void intro(Graphics g,int offsetTime) {
   if (offsetTime<1000) {
     if (where<100) {
       cls();
       oG.drawImage(load[3],0,0,this);
       drawTheatre(5,0);
       sine.play();
       where=100;
     }
   } else
   if (offsetTime<8000) {
     cls();
     oG.drawImage(load[3],0,0,this);
     drawTheatre(7000,offsetTime-1000);
   }
   g.drawImage(oI, 0, 0, this);
 }

// One: De 4 starttexter kommer

public void one(Graphics g,int offsetTime) {
   if (offsetTime<4000) {
       shakeImg(8000, offsetTime,load[4],new Point(42,202),10);
   } else
   if (offsetTime<8000) {
       shakeImg(8000, offsetTime,load[5],new Point(80,200),10);
   } else
   if (offsetTime<12000) {
       shakeImg(8000, offsetTime,load[6],new Point(85,150),10);
   } else
   if (offsetTime<16000) {
       shakeImg(8000, offsetTime,load[7],new Point(76,200),10);
   } else
   if (offsetTime<20000) {
     if (where<1050) {
       oG.drawImage(load[2],0,0,this);
       oG.drawImage(load[8],237,212,this);
       where=1050;
     }
   } else
   if (offsetTime<24000) {
     if (where<1100) {
       oG.drawImage(load[2],0,0,this);
       oG.drawImage(load[9],203,216,this);
       where=1100;
     }
   } else
   if (offsetTime<28000) {
     if (where<1200) {
       oG.drawImage(load[2],0,0,this);
       oG.drawImage(load[10],219,210,this);
       where=1200;
     }
   } else
   if (offsetTime<64000) {
     cls();
   }
   g.drawImage(oI, 0, 0, this);
 }

// Skift + slut
public void two(Graphics g,int offsetTime) {
   if (offsetTime<2000) {
     if (where<2000) {
       cls();
       sine.stop();
       where=2000;
     }

   } else
   if (offsetTime<2500) {
     if (where<2100) {
       svin.play();
       where=2100;
     }
   } else
   if (offsetTime<4000) {
     if (where<2200) {
       where=2200;
       oG.drawImage(load[11],0,0,this);
     }
   } else
   if (offsetTime<5150) {
     if (where<2300) {
       where=2300;
       oG.setColor(new Color(255,255,255));
       oG.fillRect(0,0,600,450);
       where=2300;
     } else if (where<2400) {
       oG.setColor(new Color(0,0,0));
       oG.fillRect(0,0,600,450);
       oG.drawImage(load[11],0,0,this);
       where=2400;
     }
   }
   g.drawImage(oI, 0, 0, this);
 }
//(137,116)-(505,199); (108,113)-(535,178)
public void three(Graphics g,int offsetTime) {
   if (offsetTime<2500) {
     if (where<3000) {
       svin.stop();
       oG.drawImage(load[12],0,0,this);
       oG.drawImage(load[13],137,116,this);
       splitImageGrey(load[13]);
       where=3000;
     }
   } else
   if (offsetTime<5000) {
     fadeoutGrey(2500,offsetTime-2500,137,116);
   } else
   if (offsetTime<7500) {
     if (where<3100) {
       splitImageGrey(load[14]);
       where=3100;
     }
     fadein(2500,offsetTime-5000,108,113);
   } else
   if (offsetTime<10000) {
   } else
   if (offsetTime<12500) {
     if (where<3200) {
       where=3200;
       oG.drawImage(load[15],259,390,this);
     }
   }
   g.drawImage(oI, 0, 0, this);
 }


public void cls() {
   oG.setColor(new Color(0,0,0));
   oG.fillRect(0, 0, oD.width, oD.height);
 }

public void drawTheatre(int length, int offset) {
   double l=(double)offset/(double)length;
   Point pos = new Point(50,(int)(-25-l*370));
   oG.drawImage(load[1],pos.x,pos.y,this);
   oG.drawImage(load[0],0,0,this);
 }

private void wait(int milliSecs) {
   try {
     Thread.sleep(milliSecs);
   } catch (InterruptedException e) {
   }
 }


public void shakeImg(int length, int offset,Image img,Point pos,int width) {
   double l=(double)offset/(double)length;
   pos=new Point(pos.x+(int)(width*(Math.sin(l*Math.PI*8))),pos.y+(int)(width*(Math.cos(l*Math.PI*8))));
   oG.drawImage(load[2],0,0,this);
   oG.drawImage(img,pos.x,pos.y,this);
 }

public int bounce(int length,int current,int from,int to) {
   int diff=to-from;
   int ypos=from+(int)(diff*Math.sin(Math.PI/2*current/length));
   return ypos;
 }

public void slideImages(int length,int current) {
   int x1=40+(int)(50*Math.cos(Math.PI*8*current/length))+50*(int)(Math.sin(Math.PI*8*current/length));
   int x2=240+(int)(50*Math.cos(Math.PI*16*current/length))+50*(int)(Math.sin(Math.PI*8*current/length));
   int x3=180+(int)(20*Math.sin(Math.PI*16*current/length));
   int y1=(int)(140*current/length+20*Math.cos(Math.PI*16*current/length))-20;
   int y2=140-(int)(200*current/length+20*Math.cos(Math.PI*16*current/length));
   int y3=(int)(100*current/length+20*Math.sin(Math.PI*8*current/length));
   oG.drawImage(load[6], x1, y1, this);
   oG.drawImage(load[4], x2, y2, this);
   oG.drawImage(load[3], x3, y3, this);
 }


public Image maketext(Font font,String text,Point border) {
   oG.setFont(font);
   FontMetrics metrics = oG.getFontMetrics();
   Image rImage=createImage(metrics.stringWidth(text)+border.x,metrics.getHeight()+border.y);
   Graphics rG= rImage.getGraphics();
   rG.drawString(text,border.x,metrics.getAscent()+border.y);
   return rImage;
 }

public void drawtext(Font font,String text,Point pos) {
   oG.setFont(font);
   FontMetrics metrics = oG.getFontMetrics();
   if (pos.x==-1) {
     pos=new Point(160-metrics.stringWidth(text)/2,pos.y);
   }
   if (pos.y==-1) {
     pos=new Point(pos.x,100-metrics.getHeight()/2);
   }
   oG.drawString(text,pos.x,metrics.getAscent()+pos.y);
 }

public void fadetext(int length,int offset,Color fromBackColor,Color toBackColor,Color fromTextColor,Color toTextColor) {
    int br,bg,bb;
    int tr,tba,tg;

    br=Math.abs(fromBackColor.getRed()+(toBackColor.getRed()-fromBackColor.getRed())*offset/length);
    bg=Math.abs(fromBackColor.getGreen()+(toBackColor.getGreen()-fromBackColor.getGreen())*offset/length);
    bb=Math.abs(fromBackColor.getBlue()+(toBackColor.getBlue()-fromBackColor.getBlue())*offset/length);

    oG.setColor(new Color(br,bg,bb));
    oG.fillRect(0,0,320,200);

    tr = Math.abs(fromTextColor.getRed()+(toTextColor.getRed()-fromTextColor.getRed())*offset/length);
    tg = Math.abs(fromTextColor.getGreen()+(toTextColor.getGreen()-fromTextColor.getGreen())*offset/length);
    tba= Math.abs(fromTextColor.getBlue()+(toTextColor.getBlue()-fromTextColor.getBlue())*offset/length);

    oG.setColor(new Color(tr,tg,tba));
 }

public void fadeColor(int length,int offset,Color fromBackColor,Color toBackColor) {
    int br,bb,bg;

    br=Math.abs(fromBackColor.getRed()+(toBackColor.getRed()-fromBackColor.getRed())*offset/length);
    bg=Math.abs(fromBackColor.getGreen()+(toBackColor.getGreen()-fromBackColor.getGreen())*offset/length);
    bb=Math.abs(fromBackColor.getBlue()+(toBackColor.getBlue()-fromBackColor.getBlue())*offset/length);

    oG.setColor(new Color(br,bg,bb));
 }

public void fadeoutGrey(int length,int current,int x,int y) {
   long startTime= System.currentTimeMillis();
   long diffTime;

     int percent=100-(100*current/length);
     maketables(percent);

     for (int i=0; i<splitsize; i++) {
        newpixels[i]=(coltable[greypixels[i]]<<8)+(coltable[greypixels[i]]<<16)+coltable[greypixels[i]]+(255<<24);
     }

     oG.drawImage(createImage(new MemoryImageSource(splitwidth,splitheight,newpixels,0,splitwidth)),x,y,this);
     diffTime=System.currentTimeMillis()-startTime;

//     System.out.print(diffTime+"ms * ");
 }


public void fadein(int length,int current,int x,int y) {
   long startTime= System.currentTimeMillis();
   long diffTime;

     int percent=100*current/length;
     maketables(percent);

     for (int i=0; i<splitsize; i++) {
        newpixels[i]=(coltable[greypixels[i]]<<8) | (coltable[greypixels[i]]<<16) | coltable[greypixels[i]] | 255<<24;
     }

     oG.drawImage(createImage(new MemoryImageSource(splitwidth,splitheight,newpixels,0,splitwidth)),x,y,this);
     diffTime=System.currentTimeMillis()-startTime;

     System.out.print(diffTime+"ms * ");
 }



public void maketables(int percent) {
   for (int i=0; i<256;i++) {
     coltable[i]=(i*percent)/100;
   }
 }

public void maketables(int percent,int red,int green,int blue) {
   for (int i=0; i<256;i++) {
     redcoltable[i]=blue+((i-blue)*percent/100);
     greencoltable[i]=green+((i-green)*percent/100);
     bluecoltable[i]=red+((i-red)*percent/100);
   }
 }


public void splitImageGrey(Image img) {
   splitwidth = img.getWidth(this);
   splitheight = img.getHeight(this);
   splitsize = splitheight*splitwidth;
   splitpixels = new int[splitsize];
   greypixels = new int[splitsize];
   greypixels2 = new int[splitsize];
   newpixels = new int[splitsize];

   PixelGrabber pg = new PixelGrabber(img,0,0,splitwidth,splitheight,splitpixels,0,splitwidth);
   try {
      pg.grabPixels();
   } catch (InterruptedException e)   {
   }
   for (int i=0; i<splitsize; i++) {
     greypixels[i]=((splitpixels[i]&0x000000ff)+((splitpixels[i]&0x0000ff00)>>8)+((splitpixels[i]&0x00ff0000)>>16))/3;
   }
   System.out.println("width="+splitwidth+" height="+splitheight+" Size="+splitsize);

 }

}


