/* * Maze * Copyright (C) 2000 Paul Davis, pdavis@lpccomp.bc.ca * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ import java.util.*; import java.awt.*; /** * Draw a 2D maze in an AWT Component. * There is no user input. */ public class Maze2D extends Component implements MazeListener { /** * The maze model. * @see Maze */ private MazeModel model; /** * The width of each displayed cell of the maze. */ private int cellWidth; /** * The size of the maze displayed. */ private Coordinate3D siz; /** * The current Z co-ordinate being displayed. */ private int z; /** * The number of cells to display in the X and Y dimensions. * They will be no larger than the dimensions of the maze. */ private int dispWidth,dispHeight; /** * Create a 2D maze display with a cell size of 20 pixels. * @param model The MazeModel used as the source of the maze. */ public Maze2D(MazeModel model) { this(model,20); } /** * Create a 2D maze display. * @param model The MazeModel used as the source of the maze. * @param cellSize The cell size in pixels. */ public Maze2D(MazeModel model, int cellSize) { this(model, cellSize, model.getSize().x, model.getSize().y); } /** * Create a 2D maze display. * @param model The MazeModel used as the source of the maze. * @param cellSize The cell size in pixels. * @param dispWidth The number of horizontal cells to display at a time. * @param dispHeight The number of vertical cells to display at a time. */ public Maze2D(MazeModel model, int cellSize, int dispWidth, int dispHeight) { this.model = model; if ( dispWidth >= model.getSize().x ) dispWidth = model.getSize().x; if ( dispHeight >= model.getSize().y ) dispHeight = model.getSize().y; this.dispWidth = dispWidth; this.dispHeight = dispHeight; siz = model.getSize(); //System.out.println("model size = " + String.valueOf(siz.x) + // "," + String.valueOf(siz.y)); cellWidth = cellSize; z = 0; model.addMazeListener(this); } /** * From Component.getPreferredSize. */ public Dimension getPreferredSize() { //Dimension d = new Dimension(siz.x * cellWidth, siz.y * cellWidth); //System.out.println("getPreferredSize: " + d.toString()); return new Dimension(dispWidth * cellWidth+1, dispHeight * cellWidth+1); } /** * From interface MazeListener. * The maze has changed, just repaint. */ public void mazeChanged(EventObject e) { repaint(); } /** * Set the Z co-ordinate of the maze being displayed. * Repaints the display. */ public void setZ(int z) { this.z = z; repaint(); } /** * Get the Z co-ordinate of the maze being displayed. */ public int getZ() { return z; } /** * Paint the maze. From Component. */ public void paint(Graphics g) { Dimension s = getSize(); //System.out.println("Maze2D: " + s.toString()); int x,y; int b = cellWidth/3; g.setColor(Color.white); g.fillRect(0,0,s.width,s.height); Coordinate3D current = model.getCurrent(); if ( current != null ) z = current.z; // Figure out the X and Y offsets for when the displayed // size is less than the maze size. int xoff = 0; if ( current != null ) { xoff = current.x - dispWidth/2; if ( xoff < 0 ) xoff = 0; if ( xoff + dispWidth > siz.x ) xoff = siz.x - dispWidth; } int yoff = 0; if ( current != null ) { yoff = current.y - dispHeight/2; if ( yoff < 0 ) yoff = 0; if ( yoff + dispHeight > siz.y ) yoff = siz.y - dispHeight; } // Draw the outside edge. g.setColor(Color.black); for ( y=0 ; y<=dispHeight ; y+=dispHeight ) g.drawLine(0,y*cellWidth,s.width,y*cellWidth); for ( x=0 ; x<=dispWidth ; x+=dispWidth ) g.drawLine(x*cellWidth,0,x*cellWidth,s.height); byte value; for ( y=0 ; y<dispHeight ; y++ ) { for ( x=0 ; x<dispWidth ; x++ ) { value = model.grid(x+xoff,y+yoff,z); // Wall to the left if ( (value & MazeModel.XMI) == 0 ) g.drawLine(x*cellWidth,y*cellWidth, x*cellWidth,(y+1)*cellWidth); // Wall above if ( (value & MazeModel.YMI) == 0 ) g.drawLine(x*cellWidth,y*cellWidth, (x+1)*cellWidth,y*cellWidth); // Pathway up - draw an up arrow. if ( (value & MazeModel.ZPL) != 0 ) { int topx = x*cellWidth+cellWidth/2; int topy = y*cellWidth+3; g.drawLine(topx,topy, topx,topy+cellWidth-6); g.drawLine(topx-2,topy+2,topx,topy); g.drawLine(topx+2,topy+2,topx,topy); } // Pathway Down - draw an down arrow. if ( (value & MazeModel.ZMI) != 0 ) { int botx = x*cellWidth+cellWidth/2; int boty = (y+1)*cellWidth-3; g.drawLine(botx,boty, botx,boty-cellWidth+6); g.drawLine(botx-2,boty-2,botx,boty); g.drawLine(botx+2,boty-2,botx,boty); } /* if ( (value & MazeModel.ZPL) != 0 ) System.out.print('u'); else if ( (value & MazeModel.MARK) != 0 ) System.out.print('.'); else System.out.print(' '); if ( (value & MazeModel.ZMI) != 0 ) System.out.print('d'); else if ( (value & MazeModel.MARK) != 0 ) System.out.print('.'); else System.out.print(' '); */ if ( model.isMarked(new Coordinate3D(x+xoff,y+yoff,z)) ) { g.fillRect(x*cellWidth+b,y*cellWidth+b,b,b); } } } // Draw a red block in the finish cell. Coordinate3D finish = model.getFinish(); if ( finish != null && finish.z == z ) { g.setColor(Color.red); g.fillRect((finish.x-xoff)*cellWidth+b,(finish.y-yoff)*cellWidth+b, b,b); } // Draw a green block in the current play position cell. if ( current != null && current.z == z ) { g.setColor(Color.green); g.fillRect((current.x-xoff)*cellWidth+b,(current.y-yoff)*cellWidth+b, b,b); } } }