home *** CD-ROM | disk | FTP | other *** search
Java Source | 1996-08-14 | 10.9 KB | 348 lines |
- /*----------------------------------------------------------------------*/
- /* PlayArea -- rolling and dropping area
- This is the real work horse to CopyCat
- - all the important interface stuff is handled here
- - the only contact with the outside world is through the
- changeThings/thingsChange syncronized pair of methods that
- lets PlayArea report to CopyCat when things change
- - PlayArea is event driven until a face is placed and then it
- runs a little demo of placing the face. During the demo
- all the interface stuff is shut down.
- */
- /*----------------------------------------------------------------------*/
- /* Jim Morey - morey@math.ubc.ca - Mar 1,1996 */
- /*----------------------------------------------------------------------*/
-
- import java.awt.image.MemoryImageSource;
- import java.io.*;
- import java.applet.*;
- import java.awt.*;
- import java.net.*;
- import java.lang.*;
- import Solid;
-
- /*----------------------------------------------------------------------*/
- public class PlayArea extends Canvas implements Runnable{
- private final static int IN_A=0, IN_B=1, TRANSLATE=2;
- private final static int THUD=0,SPLAT=1;
- private final static double SMALL_ANG=Math.PI/10;
- private final static int RIVET=4;
-
- public int rotations;
-
- private int W,H,mode=2,newMode=2,startPos,oldPos,startX,startY;
- private int lastPt[],region[][];
- private double angle,ang,vec[][],t;
- private boolean solid_ready=false, start_rot=false, onSolid=false;
- private boolean nochange = true, level1, demo_running=false;
- private Color background;
- private Solid solid;
- private Applet applet;
- private Board board;
- private GroupGraph group;
- private Image im,im_back;
- private Graphics offscreen,off_back;
- private Omatrix tmp,mid;
- private AudioClip sounds[];
-
- /* - - - - - - - - - - - - - - - - - - - - - - */
- PlayArea(Applet applet_,Board board_,Solid solid_,GroupGraph group_,StreamTokenizer token,int wid,int hei,boolean level1_) throws IOException{
- applet = applet_;
- board = board_;
- solid = solid_;
- group = group_;
- level1 = level1_;
- background = Color.lightGray;
- setBackground(background);
-
- resize(wid,hei);
- W = wid;
- H = hei;
-
- sounds = new AudioClip[2];
- URL base = applet.getDocumentBase();
- sounds[THUD] = applet.getAudioClip(base,"thud.au");
- sounds[SPLAT] = applet.getAudioClip(base,"splat.au");
-
- /* .. set up layout of PlayArea .. */
- token.nextToken();
- startPos = (int)token.nval;
- if (level1) startPos =0;
- token.nextToken();
- startX = (int)token.nval;
- token.nextToken();
- startY = (int)token.nval;
-
- lastPt = new int[2];
- vec = new double[2][2];
- region = new int[2][4];
- for (int jim=0;jim<2;jim++){
- for (int morey=0;morey<4;morey++){
- token.nextToken();
- region[jim][morey] = (int)token.nval;
- }
- token.nextToken();
- int angle = (int)token.nval;
- vec[jim][0] = -Math.sin(Math.PI/180*angle);
- vec[jim][1] = Math.cos(Math.PI/180*angle);
- }
-
- tmp = new Omatrix();
- mid = new Omatrix();
-
- im = applet.createImage(W,H);
- im_back = applet.createImage(W,H);
- offscreen = im.getGraphics();
- off_back = im_back.getGraphics();
-
- rotations = 0;
- goToStart(true);
- drawBackdrop();
- solid_ready = true;
- repaint();
- }
-
- /* - - - - - - - - - - - - - - - - - - - - - - */
- public void drawBackdrop() {
- off_back.setColor(background);
- off_back.fillRect(0, 0, W, H);
- drawRoughRegion(IN_A);
- drawRoughRegion(IN_B);
- board.Draw(off_back,solid,group,0,0,true);
- }
-
- /* - - - - - - - - - - - - - - - - - - - - - - */
- public void paint(Graphics g) {
- if (solid_ready) update(g);
- }
- public void update(Graphics g) {
- solid_ready = false;
- offscreen.drawImage(im_back, 0, 0, null);
- if (!demo_running){
- solid.Draw(offscreen,solid.cenx,solid.ceny,0.0);
- } else if (level1)
- solid.Explode(offscreen,solid.cenx,solid.ceny,t);
- else
- solid.Stamp(offscreen,solid.cenx,solid.ceny,t);
-
- g.drawImage(im, 0, 0, null);
- doneDrawing();
- }
-
- /* - - - - - - - - - - - - - - - - - - - - - - */
- public void goToStart(boolean startpos) {
- if (startpos) group.pos = startPos;
- solid.orient = group.element[group.pos];
- solid.cenx = startX;
- solid.ceny = startY;
- mode = TRANSLATE;
- newMode = TRANSLATE;
- }
-
- /* - - - - - - - - - - - - - - - - - - - - - - */
- public boolean mouseUp(java.awt.Event evt, int x, int y) {
- /* .. place the pattern down .. */
- if (onSolid && !demo_running){
- /* .. See if it's close enough to a location that is the same type .. */
- onSolid = false;
- if (board.ClosestFace(x,y,1000) &&
- group.blank[board.face[board.closestface]]==group.blank[group.pos]){
- solid.cenx = board.vertex[board.closestface][0];
- solid.ceny = board.vertex[board.closestface][1];
- board.faceTry[board.closestface] = group.smallestFace[group.pos];
- changedThings();
- if (level1) solid.ExplodePrep(group.tilt);
- else solid.StampPrep(group.tilt);
- new Thread(this).start();
- }
- if (x<0 || x>W || y<0 || y>H) {
- goToStart(false);
- repaint();
- }
- return true;
- }
- return false;
- }
-
- /* - - - - - - - - - - - - - - - - - - - - - - */
- public boolean mouseDown(java.awt.Event evt, int x, int y) {
- /* .. pick up the solid .. */
- if (!demo_running){
- if (Math.abs(x-solid.cenx)<solid.W && Math.abs(y-solid.ceny)<solid.H){
- onSolid = true;
- return true;
- }
- }
- return false;
- }
-
- /* - - - - - - - - - - - - - - - - - - - - - - */
- public boolean mouseDrag(java.awt.Event evt, int x, int y) {
- /* .. move the around the solid -- maybe rotate it .. */
- if (onSolid && !demo_running){
- solid.cenx = x;
- solid.ceny = y;
-
- newMode = TRANSLATE;
- for (int jim=0;jim<2;jim++){
- int chX = (int)((solid.cenx-region[jim][0])*vec[jim][0]+
- (solid.ceny-region[jim][1])*vec[jim][1]);
- int chY = (int)((solid.cenx-region[jim][0])*vec[jim][1]-
- (solid.ceny-region[jim][1])*vec[jim][0]);
- if (chX>=0 && chX<region[jim][2] &&
- chY>=0 && chY<region[jim][3]) newMode = jim;
- }
-
- if (mode == TRANSLATE) {
- if (mode != newMode) {
- mode = newMode;
- start_rot = true;
- }
- }else {
- /* .. mode = IN_A or IN_B .. */
- if (mode != newMode) {
- /* .. not in rotation region anymore .. */
- mode = TRANSLATE;
- if (ang < sign(angle)*angle/2) {
- group.pos = oldPos;
- if (ang>SMALL_ANG) sounds[THUD].play();
- }else {
- if (Math.abs(angle)-ang>SMALL_ANG) sounds[THUD].play();
- rotations++;
- changedThings();
- }
- solid.orient = group.element[group.pos];
- } else {
- /* .. in rotation region .. */
- ang = (vec[mode][0]*(x-lastPt[0]) + vec[mode][1]*(y-lastPt[1]))*
- Math.PI*0.57/solid.W;
- if (ang<0) {
- ang = 0;
- lastPt[0] = x;
- lastPt[1] = y;
- }
- if (ang>Math.abs(angle)) { /* .. finished one rotation .. */
- rotations++;
- changedThings();
- sounds[THUD].play();
- solid.orient = group.element[group.pos];
- start_rot = true;
- } else {
- tmp.Rotation(1,2,sign(angle)*ang);
- solid.orient = mid.Times(tmp.Times(mid.Transpose().Times(group.element[oldPos])));
- }
- }
- }
-
- if (start_rot){
- oldPos = group.pos;
- group.pos = group.arrows[group.pos][mode];
- angle = mid.FindTran(solid.orient,group.element[group.pos]);
- lastPt[0] = x;
- lastPt[1] = y;
- start_rot = false;
- }
-
- repaint();
- return true;
- }
- return false;
- }
-
- /* - - - - - - - - - - - - - - - - - - - - - - */
- public void run(){
- /* .. run a placing demo .. */
- demo_running = true;
- Thread.currentThread().setPriority(Thread.MAX_PRIORITY);
-
- for (t=0;t<1;t+=0.1){
- repaint();
-
- busyDrawing();
- }
-
- sounds[SPLAT].play();
- solid.orient = group.element[group.pos];
- solid.DropFace(off_back,group.tilt, board.vertex[board.closestface][0],
- board.vertex[board.closestface][1],level1);
- busyDrawing();
-
- if (level1) {
- goToStart(true);
- } else {
- for (t=1;t>0;t-=0.1){
- repaint();
- busyDrawing();
- }
- solid.orient = group.element[group.pos];
- }
- demo_running = false;
- busyDrawing();
- repaint();
- }
-
- /* - - - - - - - - - - - - - - - - - - - - - - */
- public double sign(double d) {
- if (d>0) return 1.0;
- else return -1.0;
- }
-
- /* - - - - - - - - - - - - - - - - - - - - - - */
- public void drawRoughRegion(int index) {
- double space1,space2;
- int n1,n2;
-
- n1 = (int)((region[index][2]-1)/(2*RIVET));
- space1 = (double)(region[index][2] - n1*2*RIVET)/(n1-1.0);
- n2 = (int)((region[index][3]-1)/(2*RIVET));
- space2 = (double)(region[index][3] - n2*2*RIVET)/(n2-1.0);
-
- for (int i=0;i<n1;i++)
- for (int j=0;j<n2;j++)
- drawDot((int)(region[index][0] +
- (RIVET+i*(2*RIVET+space1))*vec[index][0] +
- (RIVET+j*(2*RIVET+space2))*vec[index][1]),
- (int)(region[index][1] +
- (RIVET+i*(2*RIVET+space1))*vec[index][1] -
- (RIVET+j*(2*RIVET+space2))*vec[index][0]));
- }
-
- public void drawDot(int x,int y) {
- off_back.setColor(Color.gray);
- off_back.fillArc(x-RIVET,y-RIVET,2*RIVET,2*RIVET,45,180);
- off_back.setColor(Color.white);
- off_back.fillArc(x-RIVET,y-RIVET,2*RIVET,2*RIVET,-120,150);
- off_back.setColor(Color.lightGray);
- off_back.fillArc(x+2-RIVET,y+2-RIVET,2*RIVET-4,2*RIVET-4,0,360);
- }
-
- /* - - - - - - - - - - - - - - - - - - - - - - */
- public synchronized void changedThings() {
- while (nochange == false)
- try{ wait(); } catch (InterruptedException e){}
- nochange = false;
- notifyAll();
- }
-
- /* - - - - - - - - - - - - - - - - - - - - - - */
- public synchronized void thingsChange() {
- while (nochange == true)
- try{ wait(); } catch (InterruptedException e){}
- nochange = true;
- notifyAll();
- }
-
- /* - - - - - - - - - - - - - - - - - - - - - - */
- public synchronized void busyDrawing() {
- try {Thread.sleep(50);} catch (InterruptedException e){}
- while (solid_ready == false)
- try{ wait(); } catch (InterruptedException e){}
- }
-
- /* - - - - - - - - - - - - - - - - - - - - - - */
- public synchronized void doneDrawing() {
- solid_ready = true;
- notifyAll();
- }
- }
-