home *** CD-ROM | disk | FTP | other *** search
/ The Net: Ultimate Internet Guide / WWLCD1.ISO / pc / java / enzykbad / java / playarea.java < prev    next >
Encoding:
Java Source  |  1996-08-14  |  10.9 KB  |  348 lines

  1. /*----------------------------------------------------------------------*/
  2. /* PlayArea -- rolling and dropping area 
  3.        This is the real work horse to CopyCat 
  4.        - all the important interface stuff is handled here
  5.        - the only contact with the outside world is through the 
  6.            changeThings/thingsChange syncronized pair of methods that
  7.            lets PlayArea report to CopyCat when things change
  8.        - PlayArea is event driven until a face is placed and then it 
  9.            runs a little demo of placing the face.  During the demo
  10.            all the interface stuff is shut down.
  11.                                                                         */
  12. /*----------------------------------------------------------------------*/
  13. /*             Jim Morey  -  morey@math.ubc.ca  -  Mar 1,1996           */
  14. /*----------------------------------------------------------------------*/
  15.   
  16. import java.awt.image.MemoryImageSource;
  17. import java.io.*;
  18. import java.applet.*;
  19. import java.awt.*;
  20. import java.net.*;
  21. import java.lang.*;
  22. import Solid;
  23.  
  24. /*----------------------------------------------------------------------*/
  25. public class PlayArea extends Canvas implements Runnable{
  26.   private final static int IN_A=0, IN_B=1, TRANSLATE=2;
  27.   private final static int THUD=0,SPLAT=1;
  28.   private final static double SMALL_ANG=Math.PI/10;
  29.   private final static int RIVET=4;
  30.  
  31.   public int rotations;
  32.  
  33.   private int W,H,mode=2,newMode=2,startPos,oldPos,startX,startY;
  34.   private int lastPt[],region[][];
  35.   private double angle,ang,vec[][],t;
  36.   private boolean solid_ready=false, start_rot=false, onSolid=false;
  37.   private boolean nochange = true, level1, demo_running=false;
  38.   private Color background;
  39.   private Solid solid;
  40.   private Applet applet;
  41.   private Board board;
  42.   private GroupGraph group;
  43.   private Image im,im_back;
  44.   private Graphics offscreen,off_back;
  45.   private Omatrix tmp,mid;
  46.   private AudioClip sounds[];
  47.  
  48.   /* -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  - */
  49.   PlayArea(Applet applet_,Board board_,Solid solid_,GroupGraph group_,StreamTokenizer token,int wid,int hei,boolean level1_) throws IOException{
  50.     applet = applet_;
  51.     board = board_;
  52.     solid = solid_;
  53.     group = group_;
  54.     level1 = level1_;
  55.     background = Color.lightGray; 
  56.     setBackground(background);
  57.  
  58.     resize(wid,hei);
  59.     W = wid;
  60.     H = hei;
  61.  
  62.     sounds = new AudioClip[2];
  63.     URL base = applet.getDocumentBase();
  64.     sounds[THUD] = applet.getAudioClip(base,"thud.au");
  65.     sounds[SPLAT] = applet.getAudioClip(base,"splat.au");
  66.     
  67.     /* .. set up layout of PlayArea .. */
  68.     token.nextToken();
  69.     startPos = (int)token.nval;
  70.     if (level1) startPos =0;
  71.     token.nextToken();
  72.     startX = (int)token.nval;
  73.     token.nextToken();
  74.     startY = (int)token.nval;
  75.  
  76.     lastPt = new int[2];
  77.     vec = new double[2][2];
  78.     region = new int[2][4];
  79.     for (int jim=0;jim<2;jim++){
  80.       for (int morey=0;morey<4;morey++){
  81.         token.nextToken();
  82.         region[jim][morey] = (int)token.nval;
  83.       }
  84.       token.nextToken();
  85.       int angle  = (int)token.nval;
  86.       vec[jim][0] = -Math.sin(Math.PI/180*angle); 
  87.       vec[jim][1] = Math.cos(Math.PI/180*angle); 
  88.     }
  89.  
  90.     tmp = new Omatrix();
  91.     mid = new Omatrix();
  92.  
  93.     im = applet.createImage(W,H);
  94.     im_back = applet.createImage(W,H);
  95.     offscreen = im.getGraphics();
  96.     off_back = im_back.getGraphics(); 
  97.  
  98.     rotations = 0;
  99.     goToStart(true);
  100.     drawBackdrop();
  101.     solid_ready = true;
  102.     repaint();
  103.   }
  104.  
  105.   /* -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  - */
  106.   public void drawBackdrop() {
  107.     off_back.setColor(background);
  108.     off_back.fillRect(0, 0, W, H);
  109.     drawRoughRegion(IN_A);
  110.     drawRoughRegion(IN_B);
  111.     board.Draw(off_back,solid,group,0,0,true);
  112.    }
  113.  
  114.   /* -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  - */
  115.   public void paint(Graphics g) {
  116.     if (solid_ready) update(g);
  117.   }
  118.   public void update(Graphics g) {
  119.     solid_ready = false;
  120.     offscreen.drawImage(im_back, 0, 0, null);
  121.     if (!demo_running){
  122.       solid.Draw(offscreen,solid.cenx,solid.ceny,0.0);
  123.     } else if (level1)
  124.       solid.Explode(offscreen,solid.cenx,solid.ceny,t);  
  125.     else
  126.       solid.Stamp(offscreen,solid.cenx,solid.ceny,t);  
  127.  
  128.     g.drawImage(im, 0, 0, null);
  129.     doneDrawing();
  130.   }
  131.  
  132.   /* -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  - */
  133.   public void goToStart(boolean startpos) {
  134.     if (startpos) group.pos = startPos;
  135.     solid.orient = group.element[group.pos];
  136.     solid.cenx = startX;
  137.     solid.ceny = startY;
  138.     mode = TRANSLATE;
  139.     newMode = TRANSLATE;
  140.   }
  141.  
  142.   /* -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  - */
  143.   public boolean mouseUp(java.awt.Event evt, int x, int y) {
  144.     /* .. place the pattern down .. */
  145.     if (onSolid && !demo_running){
  146.       /* .. See if it's close enough to a location that is the same type .. */
  147.       onSolid = false;
  148.       if (board.ClosestFace(x,y,1000) && 
  149.         group.blank[board.face[board.closestface]]==group.blank[group.pos]){
  150.         solid.cenx = board.vertex[board.closestface][0];
  151.         solid.ceny = board.vertex[board.closestface][1];
  152.         board.faceTry[board.closestface] = group.smallestFace[group.pos];
  153.         changedThings();
  154.         if (level1) solid.ExplodePrep(group.tilt);
  155.         else solid.StampPrep(group.tilt);
  156.         new Thread(this).start();
  157.       }
  158.       if (x<0 || x>W || y<0 || y>H) {
  159.         goToStart(false);
  160.         repaint();
  161.       }
  162.       return true;
  163.     }
  164.     return false;
  165.   }
  166.  
  167.   /* -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  - */
  168.   public boolean mouseDown(java.awt.Event evt, int x, int y) {
  169.     /* .. pick up the solid .. */
  170.     if (!demo_running){
  171.       if (Math.abs(x-solid.cenx)<solid.W && Math.abs(y-solid.ceny)<solid.H){
  172.         onSolid = true;
  173.         return true;
  174.       }
  175.     }
  176.     return false;
  177.   }
  178.  
  179.   /* -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  - */
  180.   public boolean mouseDrag(java.awt.Event evt, int x, int y) {
  181.     /* .. move the around the solid -- maybe rotate it .. */
  182.     if (onSolid && !demo_running){
  183.       solid.cenx = x;
  184.       solid.ceny = y;
  185.   
  186.       newMode = TRANSLATE;
  187.       for (int jim=0;jim<2;jim++){
  188.         int chX = (int)((solid.cenx-region[jim][0])*vec[jim][0]+
  189.              (solid.ceny-region[jim][1])*vec[jim][1]);
  190.         int chY = (int)((solid.cenx-region[jim][0])*vec[jim][1]-
  191.              (solid.ceny-region[jim][1])*vec[jim][0]);
  192.         if (chX>=0 && chX<region[jim][2] && 
  193.             chY>=0 && chY<region[jim][3]) newMode = jim;
  194.       }
  195.       
  196.       if (mode == TRANSLATE) {
  197.         if (mode != newMode) {
  198.           mode = newMode;
  199.           start_rot = true;
  200.         }  
  201.       }else {  
  202.         /* .. mode = IN_A or IN_B .. */
  203.         if (mode != newMode) { 
  204.           /* .. not in rotation region anymore .. */
  205.           mode = TRANSLATE;
  206.           if (ang < sign(angle)*angle/2) {
  207.             group.pos = oldPos;
  208.             if (ang>SMALL_ANG) sounds[THUD].play();
  209.           }else {
  210.             if (Math.abs(angle)-ang>SMALL_ANG) sounds[THUD].play();
  211.             rotations++;
  212.             changedThings();
  213.           }
  214.           solid.orient = group.element[group.pos];
  215.         } else { 
  216.           /* .. in rotation region .. */
  217.           ang = (vec[mode][0]*(x-lastPt[0]) + vec[mode][1]*(y-lastPt[1]))*
  218.                 Math.PI*0.57/solid.W;
  219.           if (ang<0) {
  220.             ang = 0;
  221.             lastPt[0] = x;
  222.             lastPt[1] = y;
  223.           }
  224.           if (ang>Math.abs(angle)) { /* .. finished one rotation .. */
  225.             rotations++;
  226.             changedThings();
  227.             sounds[THUD].play();
  228.             solid.orient = group.element[group.pos];
  229.             start_rot = true;
  230.           } else {
  231.             tmp.Rotation(1,2,sign(angle)*ang);
  232.             solid.orient = mid.Times(tmp.Times(mid.Transpose().Times(group.element[oldPos])));
  233.           }
  234.         }
  235.       }
  236.   
  237.       if (start_rot){
  238.         oldPos = group.pos;
  239.         group.pos = group.arrows[group.pos][mode];
  240.         angle = mid.FindTran(solid.orient,group.element[group.pos]);
  241.         lastPt[0] = x;
  242.         lastPt[1] = y;
  243.         start_rot = false;
  244.       }
  245.              
  246.       repaint();
  247.       return true;
  248.     }
  249.     return false;
  250.   }
  251.  
  252.   /* -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  - */
  253.   public void run(){
  254.     /* .. run a placing demo .. */
  255.     demo_running = true;
  256.     Thread.currentThread().setPriority(Thread.MAX_PRIORITY);
  257.  
  258.     for (t=0;t<1;t+=0.1){ 
  259.       repaint();
  260.  
  261.       busyDrawing();
  262.     }
  263.   
  264.     sounds[SPLAT].play();
  265.     solid.orient = group.element[group.pos];
  266.     solid.DropFace(off_back,group.tilt, board.vertex[board.closestface][0],
  267.       board.vertex[board.closestface][1],level1);
  268.     busyDrawing();
  269.  
  270.     if (level1) {
  271.       goToStart(true);
  272.     } else {
  273.       for (t=1;t>0;t-=0.1){ 
  274.         repaint();
  275.         busyDrawing();
  276.       }
  277.       solid.orient = group.element[group.pos];
  278.     }
  279.     demo_running = false;
  280.     busyDrawing();
  281.     repaint();
  282.   }
  283.  
  284.   /* -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  - */
  285.   public double sign(double d) {
  286.     if (d>0) return 1.0;
  287.     else return -1.0;
  288.   }
  289.  
  290.   /* -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  - */
  291.   public void drawRoughRegion(int index) {
  292.     double space1,space2;
  293.     int n1,n2;
  294.  
  295.     n1 = (int)((region[index][2]-1)/(2*RIVET));
  296.     space1 = (double)(region[index][2] - n1*2*RIVET)/(n1-1.0);
  297.     n2 = (int)((region[index][3]-1)/(2*RIVET));
  298.     space2 = (double)(region[index][3] - n2*2*RIVET)/(n2-1.0);
  299.  
  300.     for (int i=0;i<n1;i++)
  301.       for (int j=0;j<n2;j++)
  302.         drawDot((int)(region[index][0] + 
  303.             (RIVET+i*(2*RIVET+space1))*vec[index][0] + 
  304.             (RIVET+j*(2*RIVET+space2))*vec[index][1]),
  305.             (int)(region[index][1] + 
  306.             (RIVET+i*(2*RIVET+space1))*vec[index][1] - 
  307.             (RIVET+j*(2*RIVET+space2))*vec[index][0]));
  308.   }
  309.  
  310.   public void drawDot(int x,int y) {
  311.     off_back.setColor(Color.gray);
  312.     off_back.fillArc(x-RIVET,y-RIVET,2*RIVET,2*RIVET,45,180);
  313.     off_back.setColor(Color.white);
  314.     off_back.fillArc(x-RIVET,y-RIVET,2*RIVET,2*RIVET,-120,150);
  315.     off_back.setColor(Color.lightGray);
  316.     off_back.fillArc(x+2-RIVET,y+2-RIVET,2*RIVET-4,2*RIVET-4,0,360); 
  317.   }
  318.  
  319.   /* -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  - */
  320.   public synchronized void changedThings() {
  321.     while (nochange == false)
  322.       try{ wait(); } catch (InterruptedException e){}
  323.     nochange = false;
  324.     notifyAll();
  325.   }
  326.  
  327.   /* -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  - */
  328.   public synchronized void thingsChange() {
  329.     while (nochange == true)
  330.       try{ wait(); } catch (InterruptedException e){}
  331.     nochange = true;
  332.     notifyAll();
  333.   }
  334.  
  335.   /* -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  - */
  336.   public synchronized void busyDrawing() {
  337.     try {Thread.sleep(50);} catch (InterruptedException e){}
  338.     while (solid_ready == false)
  339.       try{ wait(); } catch (InterruptedException e){}
  340.   }
  341.  
  342.   /* -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  - */
  343.   public synchronized void doneDrawing() {
  344.     solid_ready = true;
  345.     notifyAll();
  346.   }
  347. }
  348.