// File: Cube.java // Author: Alberg, Mehta, & Ward // // Last Update: 11-28-96 // import java.awt.*; class Face extends Polygon { public static final int XINC = 17; public static final int YINC = 10; static int cx = -1; static int cy = -1; static Color bg; Color edgecolor = Color.black; Polygon p; // Face inherits all properties of Polygon but // a separate instance of a new Polygon must be // declared for each move / rotate. public Face(){ super(); } public boolean Inside(int x, int y) { if (p != null) return p.inside(x, y); return false; } public boolean Visible(){ return p != null; } public static void SetDrawingConstants(int newcx, int newcy, Color newbg) { cx = newcx; cy = newcy; bg = newbg; } public static void DrawBackground(Graphics g, Dimension d) { int begx = (cx / XINC) * XINC; int begy = (cy / YINC) * YINC; int i, y; g.setColor(Color.gray); for (int j = cy - begy; j < d.height; j+= YINC){ if (cy > j) y = cy - j; else y = j - cy; if ((begx / XINC) % 2 == (y / YINC) % 2) i = cx - begx; else i = cx - begx + XINC; for (; i < d.width; i += 2 * XINC){ if (j <= cy || (i - cx)/XINC > y/YINC || (cx - i)/XINC > y/YINC) g.fillOval(i, j, 1, 1); } } g.setColor(Color.gray); g.drawLine(cx, 0, cx, cy); g.drawLine(cx, cy, cx - begx, cy + (begx / XINC)*YINC); g.drawLine(cx, cy, cx + begx, cy + (begx / XINC)*YINC); int[] xpoints = {cx, cx - 3*XINC, cx, cx + 3*XINC}; int[] ypoints = {cy + 10*YINC, cy + 13*YINC, cy + 16*YINC, cy + 13*YINC}; Polygon base = new Polygon(xpoints, ypoints, 4); g.setColor(new Color(220, 220, 220)); g.fillPolygon(base); g.setColor(Color.lightGray); g.drawLine(cx, cy + 10 * YINC, cx - 3 * XINC, cy + 13 * YINC); g.drawLine(cx, cy + 10 * YINC, cx + 3 * XINC, cy + 13 * YINC); g.drawLine(cx - 3*XINC, cy + 13 * YINC, cx, cy + 16 * YINC); g.drawLine(cx + 3*XINC, cy + 13 * YINC, cx, cy + 16 * YINC); g.drawLine(cx - XINC, cy + 11*YINC, cx + 2*XINC, cy + 14*YINC); g.drawLine(cx + XINC, cy + 11*YINC, cx - 2*XINC, cy + 14*YINC); g.drawLine(cx - 2*XINC, cy + 12*YINC, cx + XINC, cy + 15*YINC); g.drawLine(cx + 2*XINC, cy + 12*YINC, cx - XINC, cy + 15*YINC); g.setColor(Color.gray); xpoints[0] = cx - 13*XINC; xpoints[1] = cx - 26*XINC; xpoints[2] = cx; ypoints[0] = cy + 13*YINC; ypoints[1] = cy + 26*YINC; ypoints[2] = cy + 26*YINC; Polygon left = new Polygon(xpoints, ypoints, 3); g.fillPolygon(left); xpoints[0] = cx + 13*XINC; xpoints[1] = cx + 26*XINC; xpoints[2] = cx; Polygon right = new Polygon(xpoints, ypoints, 3); g.fillPolygon(right); g.setColor(Color.lightGray); g.drawLine(0, 0, 0, d.height); g.drawLine(2*cx - 1, 0, 2*cx - 1, d.height); g.setColor(Color.black); } void Draw(Graphics g, Color color, Color linecolor) { p = new Polygon(xpoints, ypoints, npoints); g.setColor(color); g.fillPolygon(p); g.setColor(linecolor); g.drawPolygon(p); } public static int CurrX(int x, int y, int z) { return (cx + (y - x) * XINC); } public static int CurrY(int x, int y, int z) { return (cy + (x + y - 2 * z) * YINC); } } class Xface extends Face { Color color = new Color(127, 0, 0); public Xface(){ super(); npoints = 4; } public void Draw(int x, int y, int z, Graphics g) { int basex = cx + (y - x) * XINC; int basey = cy + (x + y - 2 * z) * YINC; xpoints[0] = basex; xpoints[1] = basex - XINC; xpoints[2] = basex - XINC; xpoints[3] = basex; ypoints[0] = basey; ypoints[1] = basey - YINC; ypoints[2] = basey + YINC; ypoints[3] = basey + 2 * YINC; Draw(g, color, edgecolor); } public void Undraw(int x, int y, int z, Graphics g) { int basex = cx + (y - x) * XINC; int basey = cy + (x + y - 2 * z) * YINC; xpoints[0] = basex; xpoints[1] = basex - XINC; xpoints[2] = basex - XINC; xpoints[3] = basex; ypoints[0] = basey; ypoints[1] = basey - YINC; ypoints[2] = basey + YINC; ypoints[3] = basey + 2 * YINC; Draw(g, bg, bg); } } class Yface extends Face { Color color = new Color(191, 0, 0); public Yface(){ super(); npoints = 4; } public void Draw(int x, int y, int z, Graphics g) { int basex = cx + (y - x) * XINC; int basey = cy + (x + y - 2 * z) * YINC; xpoints[0] = basex; xpoints[1] = basex + XINC; xpoints[2] = basex + XINC; xpoints[3] = basex; ypoints[0] = basey; ypoints[1] = basey - YINC; ypoints[2] = basey + YINC; ypoints[3] = basey + 2 * YINC; Draw(g, color, edgecolor); } public void Undraw(int x, int y, int z, Graphics g) { int basex = cx + (y - x) * XINC; int basey = cy + (x + y - 2 * z) * YINC; xpoints[0] = basex; xpoints[1] = basex + XINC; xpoints[2] = basex + XINC; xpoints[3] = basex; ypoints[0] = basey; ypoints[1] = basey - YINC; ypoints[2] = basey + YINC; ypoints[3] = basey + 2 * YINC; Draw(g, bg, bg); } } class Zface extends Face { Color color = new Color(255, 0, 0); public Zface(){ super(); npoints = 4; } public void Draw(int x, int y, int z, Graphics g) { int basex = cx + (y - x) * XINC; int basey = cy + (x + y - 2 * z) * YINC; xpoints[0] = basex; xpoints[1] = basex - XINC; xpoints[2] = basex; xpoints[3] = basex + XINC; ypoints[0] = basey; ypoints[1] = basey - YINC; ypoints[2] = basey - 2 * YINC; ypoints[3] = basey - YINC; Draw(g, color, edgecolor); } public void Undraw(int x, int y, int z, Graphics g) { int basex = cx + (y - x) * XINC; int basey = cy + (x + y - 2 * z) * YINC; xpoints[0] = basex; xpoints[1] = basex - XINC; xpoints[2] = basex; xpoints[3] = basex + XINC; ypoints[0] = basey; ypoints[1] = basey - YINC; ypoints[2] = basey - 2 * YINC; ypoints[3] = basey - YINC; Draw(g, bg, bg); } } class Shadow extends Zface { public Shadow(){ super(); color = Color.gray; this.edgecolor = color; } } public class Cube { static Cube [][][] Grid = new Cube[13][13][8]; int x; int y; int z; static final int MinX = 0; static final int MaxX = 13; static final int MinY = 0; static final int MaxY = 13; static final int MinZ = 0; static final int MaxZ = 8; Piece parent; Xface xface = new Xface(); Yface yface = new Yface(); Zface zface = new Zface(); Shadow shadow = new Shadow(); public Cube(int x, int y, int z, Piece parent) { this.x = x; this.y = y; this.z = z; this.parent = parent; Grid[x][y][z] = this; } void Draw(Graphics g) { if ((x < MaxX-1 && Grid[x+1][y][z] == null) || (x == MaxX-1)) xface.Draw(x, y, z, g); if ((y < MaxY-1 && Grid[x][y+1][z] == null) || (y == MaxY-1)) yface.Draw(x, y, z, g); if ((z < MaxZ-1 && Grid[x][y][z+1] == null) || (z == MaxZ-1)) zface.Draw(x, y, z, g); } void DrawShadow(Graphics g, int x, int y) { shadow.Draw(x, y, -1, g); } boolean Detect(int mousex, int mousey) { boolean xf, yf, zf; xf = yf = zf = false; if (xface.Visible()) xf = xface.Inside(mousex, mousey); if (yface.Visible()) yf = yface.Inside(mousex, mousey); if (zface.Visible()) zf = zface.Inside(mousex, mousey); return (xf || yf || zf); } Face whichFace(int mousex, int mousey) { if(xface.Inside(mousex, mousey)) return xface; else if(yface.Inside(mousex, mousey)) return yface; else if(zface.Inside(mousex, mousey)) return zface; else return null; } // this is only called by the piece class void removeFromGrid(Graphics g) { Grid[x][y][z] = null; Undraw(x, y, z, g); } // this is only called by the piece class void placeAt(int newX, int newY, int newZ) { x = newX; y = newY; z = newZ; Grid[x][y][z] = this; } void Undraw (int x, int y, int z, Graphics g) { shadow.Undraw(x, y, -1, g); if ((x < MaxX-1 && Grid[x+1][y][z] == null) || (x == MaxX-1)) xface.Undraw(x, y, z, g); if ((y < MaxY-1 && Grid[x][y+1][z] == null) || (y == MaxY-1)) yface.Undraw(x, y, z, g); if ((z < MaxZ-1 && Grid[x][y][z+1] == null) || (z == MaxZ-1)) zface.Undraw(x, y, z, g); } static public void Redraw(Graphics g) { int i, j, k; boolean drawn = false; // draw shadows first for (j = MinY; j < MaxY; ++j){ for (i = MinX; i < MaxX; ++i){ for (k = 1; !drawn && k < MaxZ; ++k){ if (Grid[i][j][k] != null && Grid[i][j][0] == null){ Grid[i][j][k].DrawShadow(g, i, j); drawn = true; } } drawn = false; } } // now redraw cubes for (k = 0; k < MaxZ; ++k){ for (j = MinY; j < MaxY; ++j){ for (i = MinX; i < MaxX; ++i){ if (Grid[i][j][k] != null) Grid[i][j][k].Draw(g); } } } } static public Cube FindCube(int mousex, int mousey) { for (int k = MaxZ - 1; k >= 0; --k){ for (int j = MaxY - 1; j >= MinY; --j){ for (int i = MaxX - 1; i >= MinX; --i){ if (Grid[i][j][k] != null && Grid[i][j][k].Detect(mousex, mousey)) { return Grid[i][j][k]; } } } } return null; } } class Piece { private Cube [] cube = new Cube[4]; private int id; public Piece (int x, int y, int z, int id) { this.id = id; cube[0] = new Cube (x, y, z, this); switch(id){ case 1: cube[1] = new Cube(x+1, y, z, this); cube[2] = new Cube(x, y, z+1, this); break; case 2: cube[1] = new Cube(x, y-1, z, this); cube[2] = new Cube(x, y-1, z+1, this); cube[3] = new Cube(x, y+1, z, this); break; case 3: cube[1] = new Cube(x, y-1, z, this); cube[2] = new Cube(x, y+1, z, this); cube[3] = new Cube(x+1, y, z, this); break; case 4: cube[1] = new Cube(x, y+1, z, this); cube[2] = new Cube(x, y, z+1, this); cube[3] = new Cube(x, y-1, z+1, this); break; case 5: cube[1] = new Cube(x, y+1, z, this); cube[2] = new Cube(x+1, y, z, this); cube[3] = new Cube(x+1, y, z+1, this); break; case 6: cube[1] = new Cube(x, y+1, z, this); cube[2] = new Cube(x, y+1, z+1, this); cube[3] = new Cube(x+1, y, z, this); break; case 7: cube[1] = new Cube(x, y, z+1, this); cube[2] = new Cube(x, y+1, z, this); cube[3] = new Cube(x+1, y, z, this); break; } } void moveZ(int direction, Soma s) { int numCubes = (id == 1 ? 3 : 4); //Check if move is possible for(int i=0; i < numCubes; ++i) if(cubeAt(cube[i].x, cube[i].y, cube[i].z + direction)){ s.showStatus("Can't move this way"); try{ Thread.sleep(500); } catch(InterruptedException e){} s.showStatus(""); return; // move not possible } // else s.showStatus(""); //Remove and erase all cubes; has to be done for all cubes before //placing them removeFromGrid(s.getGraphics()); //Place cubes in new positions for(int i=0; i < numCubes; ++i) cube[i].placeAt(cube[i].x, cube[i].y, cube[i].z +direction); s.display(); } void moveX(int direction, Soma s) { int numCubes = (id == 1 ? 3 : 4); for(int i=0; i < numCubes; ++i) if(cubeAt(cube[i].x + direction, cube[i].y, cube[i].z)){ s.showStatus("Can't move this way"); try{ Thread.sleep(500); } catch(InterruptedException e){} s.showStatus(""); return; // move not possible } // else s.showStatus(""); removeFromGrid(s.getGraphics()); for(int i=0; i < numCubes; ++i) cube[i].placeAt(cube[i].x +direction, cube[i].y, cube[i].z); s.display(); } void moveY(int direction, Soma s) { int numCubes = (id == 1 ? 3 : 4); for(int i=0; i < numCubes; ++i) if(cubeAt(cube[i].x, cube[i].y + direction, cube[i].z)){ s.showStatus("Can't move this way"); try{ Thread.sleep(500); } catch(InterruptedException e){} s.showStatus(""); return; // move not possible } // else s.showStatus(""); removeFromGrid(s.getGraphics()); for(int i=0; i < numCubes; ++i) cube[i].placeAt(cube[i].x, cube[i].y +direction, cube[i].z); s.display(); } private boolean cubeAt(int x, int y, int z) { if( (x >= Cube.MinX && x < Cube.MaxX) && (y >= Cube.MinY && y < Cube.MaxY) && (z >= Cube.MinZ && z < Cube.MaxZ) ) { if(Cube.Grid[x][y][z] == null) return false; else if(Cube.Grid[x][y][z].parent == this) return false; else return true; } else return true; } void rotateZ(boolean counterClockwise, Cube cubeClicked, Soma s) { int numCubes = (id == 1 ? 3 : 4); int newX[] = new int[numCubes]; int newY[] = new int[numCubes]; for(int i=0; i < numCubes; ++i) { int dx = cubeClicked.x - cube[i].x; int dy = cubeClicked.y - cube[i].y; if(counterClockwise) { dx = -dx; dy = -dy; } newX[i] = cubeClicked.x - dy; newY[i] = cubeClicked.y + dx; if(cubeAt(newX[i], newY[i], cube[i].z)){ s.showStatus("Can't move this way"); try{ Thread.sleep(500); } catch(InterruptedException e){} s.showStatus(""); return; // rotate not possible } // else s.showStatus(""); } removeFromGrid(s.getGraphics()); for(int i=0; i < numCubes; ++i) cube[i].placeAt(newX[i], newY[i], cube[i].z); s.display(); } void rotateX(boolean counterClockwise, Cube cubeClicked, Soma s) { int numCubes = (id == 1 ? 3 : 4); int newY[] = new int[numCubes]; int newZ[] = new int[numCubes]; for(int i=0; i < numCubes; ++i) { int dy = cubeClicked.y - cube[i].y; int dz = cubeClicked.z - cube[i].z; if(counterClockwise) { dy = -dy; dz = -dz; } newY[i] = cubeClicked.y - dz; newZ[i] = cubeClicked.z + dy; if(cubeAt(cube[i].x, newY[i], newZ[i])){ s.showStatus("Can't move this way"); try{ Thread.sleep(500); } catch(InterruptedException e){} s.showStatus(""); return; // rotate not possible } // else s.showStatus(""); } removeFromGrid(s.getGraphics()); for(int i=0; i < numCubes; ++i) cube[i].placeAt(cube[i].x, newY[i], newZ[i]); s.display(); } void rotateY(boolean counterClockwise, Cube cubeClicked, Soma s) { int numCubes = (id == 1 ? 3 : 4); int newZ[] = new int[numCubes]; int newX[] = new int[numCubes]; for(int i=0; i < numCubes; ++i) { int dz = cubeClicked.z - cube[i].z; int dx = cubeClicked.x - cube[i].x; if(counterClockwise) { dz = -dz; dx = -dx; } newZ[i] = cubeClicked.z - dx; newX[i] = cubeClicked.x + dz; if(cubeAt(newX[i], cube[i].y, newZ[i])){ s.showStatus("Can't move this way"); try{ Thread.sleep(500); } catch(InterruptedException e){} s.showStatus(""); return; // rotate not possible } // else s.showStatus(""); } removeFromGrid(s.getGraphics()); for(int i=0; i < numCubes; ++i) cube[i].placeAt(newX[i], cube[i].y, newZ[i]); s.display(); } void removeFromGrid(Graphics g) { int numCubes = (id == 1 ? 3 : 4); for(int i=0; i < numCubes; ++i) cube[i].removeFromGrid(g); } void rotateTable() { int numCubes = (id == 1 ? 3 : 4); for(int i=0; i < numCubes; ++i) { cube[i].placeAt(cube[i].y, Cube.MaxX-1 - cube[i].x, cube[i].z); } } }