All pastes #112660 Raw Edit

Stuff

public text v1 · immutable
·published 2006-08-03 02:52 UTC
rendered paste body
/*
 * $Id$
 *
 * $Log$
 */

/* Lots of graphical/image libraries are needed here. */
import java.awt.Canvas;
import java.awt.Component;
import java.awt.Container;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.image.BufferedImage;
import java.awt.image.FilteredImageSource;
import java.awt.image.RGBImageFilter;
import javax.swing.ImageIcon;
import javax.swing.JFrame;

/**
 * Represents an image that can be broken into pieces. The pieces are basically tiles for
 * a game map and must all be the same height/width.
 * 
 * @author  Andy Fanton  (arf3827@cs.rit.edu)
 * @author Jessica D. Bayliss (jdb@cs.rit.edu)
 *
 */
public class TiledImage {

  /** The default tile height in pixels */
  public static final int DEFAULT_TILE_HEIGHT = 32;
  /** The default tile width in pixels */
  public static final int DEFAULT_TILE_WIDTH = 32;
  
  /* The big image containing sub-images (representing tiles on a game map) */
  protected BufferedImage image;

  /* The big image's height/width and rows/cols */
  protected int height, width, rows, cols; 

  /* Where the big image comes from */
  protected String sourceFile;
    
  /**
   * Creates a TiledImage from a default file name. Problems occur if the default
   * is not in the right place in the file system.
   */
  public TiledImage() {
    // The PondMazeEditor has a hard coded reference to a default load
    // file in it. The variable is called TILESET. Call the constructor
    // below with the TILESET variable in PondMazeEditor.
    this(PondMazeEditor.TILESET); 
  }
  
  /**
   * Creates a TiledImage from a given filename. 
   * 
   * @param  fileName  The file to create the tiled image from.
   */
  public TiledImage( String fileName ) {
    // use the this operator and call the method below with the variables:
    // filename, DEFAULT_TILE_HEIGHT, and DEFAULT_TILE_WIDTH
    this(fileName,DEFAULT_TILE_HEIGHT,DEFAULT_TILE_WIDTH); 

  }


  /**
   * Full Constructor
   *  
   * @param  fileName  the name of the file to create the image from
   * @param  tileHeight    the height of the individual tiles
   * @param  tileWidth     the width of the individual tiles
   */
  public TiledImage( String fileName, int tileHeight, int tileWidth ) {
    // ah-ha! we must do the actual work of creating the image here

    // setup the instance variables with the appropriate value:
    // sourceFile should have value fileName
    // height should have value tileHeight
    // width should have value tileWidth
    sourceFile=fileName;
    height=tileHeight;
    width=tileWidth;
        
    // Get an icon representing the file
    // Icons are of type ImageIcon, so we must create a new 
    // ImageIcon object with the fileName as an argument.
    // Then set rows/cols to be the icon height/width 
    // divided by the tile height/width
    // so that we're only dealing with the appropriate icon size.
    ImageIcon icon=new ImageIcon(fileName);
    rows=icon.getIconHeight()/tileHeight;
    cols=icon.getIconWidth()/tileWidth;     
    // Give the image variable a value:
    // image should be of type BufferedImage which is created with the values
    // cols*width, rows*height, and BufferedImage.TYPE_INT_RGB
    image=new BufferedImage(cols*width,rows*height,BufferedImage.TYPE_INT_RGB);
    // Get the source image:
    // sourceImage is of type Image and is gotten from the above
    // BufferedImage with its method
    // called getImage() (no args)
    Image sourceImage=icon.getImage(); 
    // Draw image into buffer - if we don't do this, 
    // we get black where we should draw
    // Uncomment the following code for this part:
    Graphics g = image.getGraphics();
    g.drawImage( sourceImage, 0, 0, null );
     
  }
    
  /**
   * Filters the image to create transparency. Assume that this
   * method works.
   * 
   * @param sourceImage
   * @return
   */
  public void addTransparency( Component context, final int backgroundColor ) {
    
    // Create anonymous RBG Filter 
    // Anonymous classes are covered in CS2 and give you a way to create very small
    // classes inside of methods (with their own methods/var's for cases where there isn't enough stuff there
    // to bother creating a separate class file for it. You will notice that the parent class
    // (TiledImage) creates a couple of extra class files (TiledImage$1.class, etc.) and these
    // anonymous classes are the reason for that.
    RGBImageFilter filter = 
      new RGBImageFilter() {
	  { canFilterIndexColorModel = true; }
	  public int filterRGB( int x, int y, int rgb ) {
	    if ( rgb == backgroundColor ) {
	      //System.out.println( "(" + x + "," + y + "):clear " );
	      return 0x000000ff;
	    } else {
	      //System.out.println( "(" + x + "," + y + "):" + rgb );
	      return rgb;
	    }
	  }
	};
    
    // Create a filtered image source
    FilteredImageSource newSource = 
      new FilteredImageSource( image.getSource(), filter );
    
    // Create new image using a given component
    Image newImage = context.createImage( newSource );
    image = new BufferedImage( cols * width, rows * height,
			       BufferedImage.TYPE_INT_RGB );

    // make sure we draw into the buffer
    Graphics g = image.getGraphics();
    g.drawImage( newImage, 0, 0, null );
  }
  
  /**
   * Gets the whole image represented by this object
   * 
   * @return  the image held by this object
   */
  public Image getFullImage(){
    // return the real image variable instead of null
    return image;
  }
  
  /**
   * Gets the specified tile as an image
   * 
   * @param  x  the x index of the desired tile
   * @param  y  the y index of the desired tile
   * @return
   */
  public Image getImage( int x, int y ) {
    // Image has a method called getSubimage that should be called with
    // x*width, y*height, width-1, and height-1
    // That subimage should then be returned
    return image.getSubimage(x*width,y*height,width-1,height-1); 
  }
  
  /**
   * Gets the specified tile as an image icon
   * 
   * @param  row  the row index of the desired tile
   * @param  col  the col index of the desired tile
   * @return
   */
  public ImageIcon getIcon( int row, int col ) {
    // return a new ImageIcon object that is created with the Image returned
    // by getImage above with the appropriate row/col
    return new ImageIcon(getImage(col,row)); 
  }
  
  /**
   * Gets all of the tiles as an array of images
   * 
   * @return  an image array containing all of the tiles
   */
  public Image[][] getImages() {
    // oooooh, double array
    Image[][] returnArray = new Image[rows][cols];
    
    // now write the double for loop that calls getImage across
    // all columns and then incrementing rows. Note that columns are in
    // the x direction (horizontal) and rows are in the y direction (vertical). 
    // Then return the array. 
    for(int i=0;i<rows;i++){
      for(int j=0;j<cols;j++){
        returnArray[i][j]=getImage(j,i);
      }
    }
  
    return returnArray;
  }
  
  /**
   * Get the height of each tile 
   *
   * @return  the tile height
   */
  public int getTileHeight(){
    // return the real height variable
    return height;
  }
  
  /**
   * Get the width of each tile
   *
   * @return  the tile width
   */
  public int getTileWidth(){
    // return the real width variable
    return width;
  }

  /**
   * Gets all of the tiles as an array of image icons
   * 
   * @return  an image icon array containing all of the tiles
   */
  public ImageIcon[][] getIcons() {
     
    ImageIcon[][] returnArray = new ImageIcon[rows][cols];

    // go through a double for look and give the return array
    // a list of icons - call getIcon with the two for loop indices
    // as arguments.
    for(int i=0;i<rows;i++){
      for(int j=0;j<cols;j++){
        returnArray[i][j]=getIcon(j,i);
      }
    }  
    // Then return the array.
    return returnArray;
  }


  /**
   * Gets all of the tiles as a single-dimension array
   * 
   * @return  a single dimension array holding all of the icons
   */
  public ImageIcon[] getIconList() {
    ImageIcon[] iconList = new ImageIcon[rows * cols];
    int offset = 0;
    
    // This should be a double for loop that goes across columns
    // and then rows, except that it returns a single dimensional
    // array - you'll have to do some basic "offset" math inside
    // the array brackets to figure out where the icons should go
    // getIcon(i, j) (if i and j are your indices) will be assigned
    // to each element in the imageList variable. You just have to
    // figure out how to put them into a 1d array in the correct order.
    for(int i=0;i<rows;i++){
      for(int j=0;j<cols;j++){
        iconList[offset+j]=getIcon(i,j);
      }
      offset+=cols;
    }
    return iconList;
  }

  /**
   * Gets all of the tiles as a single-dimension array
   * 
   * @return  a single dimension array holding all of the icons
   */
  public Image[] getImageList() {
    
    Image[] imageList = new Image[rows * cols];
    int offset = 0;

    // This is almost exactly like the above except that it
    // assigns images rather than icons: getImage(i, j)
    // Again, there's a double for loop involved.
    for(int i=0;i<rows;i++){
      for(int j=0;j<cols;j++){
        imageList[offset+j]=getImage(i,j);
      }
      offset+=cols;
    } 

    // Now return the image list.
    return imageList;
  }
 
  /**
   * Gets the file from which this image was made
   * 
   * @return  name of image file
   */
  public String getSource() {
    // return the real sourceFile variable 
    return sourceFile;
  }
  
  /**
   * Main method; tests this object. This is a very basic version of a test class involving
   * showing several images and tiling them across the screen. Can you test more of the
   * functionality of the class by drawing different items in different places???
   * 
   * @param  args The image file to use as a test file.
   */
  public static void main( String[] args ) {
     
    // when you have pieces of code finished, uncomment 
    // this code or write more to test your code.
    
    // Make sure there was at least one command line argument
    if ( args.length < 1 ) {
      System.out.println( "Please specify image file" );
      System.exit(0);
    }
        
    // Create test object
    final ImageIcon sourceImage = new ImageIcon( args[0] );
    final TiledImage testImage = new TiledImage( args[0] );
    final Image[][] images = testImage.getImages();
    
    // Create GUI
    JFrame frame = new JFrame();
    frame.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE );
    // set the window size - you may need to change it as you change this class
    frame.setSize( 250, 250 );
    
    // Create anonymous canvas
    // Anonymous classes are covered in CS2 and give you a way to create very small
    // classes inside of methods (with their own methods/var's for cases where there isn't enough stuff there
    // to bother creating a separate class file for it. You will notice that the parent class
    // (TiledImage) creates a couple of extra class files (TiledImage$1.class, etc.) and these
    // anonymous classes are the reason for that.
    Canvas canvas = new Canvas(){
	public void paint( Graphics g ) {
	  for ( int i = 0; i < images.length; i++ ) {
	    for ( int j = 0; j < images[i].length; j++ ) {
                        g.drawImage( images[i][j], i * 32, j * 32, 32, 32, null );
	    }
	  }
	}
      };
    
    Container content = frame.getContentPane();
    content.add( canvas, null, 0 );
    frame.setVisible( true );

  
  }
}