Advertisement
Guest User

Untitled

a guest
Feb 19th, 2019
105
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Java 14.24 KB | None | 0 0
  1. class Map
  2. {  
  3.   int mode = CORNER;
  4.  
  5.  
  6.   // Constructor: tmptileSize is the width/height of one tile in pixel
  7.   Map( int tmptileSize ) {
  8.     tileSize = tmptileSize;
  9.     images = new PImage[26];
  10.   }
  11.  
  12.   // Constructor: Loads a map file
  13.   Map( String mapFile ) {
  14.     images = new PImage[26];
  15.     loadFile( mapFile );
  16.   }
  17.  
  18.   //! Sets the mode in which coordinates are specified, supported is CORNER, CENTER, CORNERS
  19.   void mode (int tmpMode) {
  20.     mode=tmpMode;
  21.   }
  22.  
  23.  
  24.   int widthPixel() {
  25.     return w * tileSize;
  26.   }
  27.  
  28.   int heightPixel() {
  29.     return h * tileSize;
  30.   }
  31.  
  32.   // Left border (pixel) of the tile at tile position x
  33.   int leftOfTile(int x) {
  34.     return x * tileSize;
  35.   }
  36.  
  37.   // Right border (pixel) of the tile at tile position x
  38.   int rightOfTile(int x) {
  39.     return (x+1) * tileSize-1;
  40.   }
  41.  
  42.   // Top border (pixel) of the tile at tile position y
  43.   int topOfTile(int y) {
  44.     return y * tileSize;
  45.   }
  46.  
  47.   // Bottom border (pixel) of the tile at tile position y
  48.   int bottomOfTile(int y) {
  49.     return (y+1) * tileSize-1;
  50.   }
  51.  
  52.   //! Center of the tile at tile position x
  53.   int centerXOfTile (int x) {
  54.     return x*tileSize+tileSize/2;
  55.   }
  56.  
  57.   //! Center of the tile at tile position x
  58.   int centerYOfTile (int y) {
  59.     return y*tileSize+tileSize/2;
  60.   }
  61.  
  62.   // Returns the tile at tile position x,y. '_' for invalid positions (out of range)
  63.   char at( int x, int y ) {
  64.     if ( x < 0 || y < 0 || x >= w || y >= h )
  65.       return '_';
  66.     else
  67.       return map[y].charAt(x);
  68.   }
  69.  
  70.   // Returns the tile at pixel position 'x,y', '_' for invalid
  71.   char atPixel (float x, float y) {
  72.     return at (floor(x/tileSize), floor(y/tileSize));
  73.   }
  74.  
  75.   // Sets the tile at tile position x,y
  76.   // Coordinates below 0 are ignored, for coordinates
  77.   // beyond the map border, the map is extended
  78.   void set (int x, int y, char ch) {
  79.     if ( x < 0 || y < 0 ) return;
  80.     extend (x+1, y+1);
  81.     map[y] = replace (map[y], x, ch);
  82.   }
  83.  
  84.   // Sets the tile at image position 'x,y' see set
  85.   void setPixel (int x, int y, char ch) {
  86.     set (x/tileSize, y/tileSize, ch);
  87.   }
  88.  
  89.  
  90.   // Reference to a tile in the map  
  91.   class TileReference {
  92.     // Position in the map in tiles
  93.     int x, y;
  94.     // Position in the map in pixels
  95.     // This position definitely belong to the tile (x,y)
  96.     // where it is on the tile depents on the function returning this reference
  97.     float xPixel, yPixel;
  98.     // Type of the tile
  99.     char tile;
  100.     // Border of that tile in pixel
  101.     int left, right, top, bottom;
  102.     // Center of that tile in pixel
  103.     int centerX, centerY;
  104.  
  105.     // Creates a reference to the tile at (x,y)
  106.     // all other components are taken from the map
  107.     TileReference (int tmpX, int tmpY) {
  108.       x = tmpX;
  109.       y = tmpY;
  110.       setBorders();
  111.       xPixel = centerX;
  112.       yPixel = centerY;
  113.     }
  114.  
  115.     // Computes tile, left, right, top, bottom, centerX, centerY from referenced tile
  116.     void setBorders() {
  117.       tile = at(x, y);
  118.       left = leftOfTile(x);
  119.       right = rightOfTile(x);
  120.       top = topOfTile(y);
  121.       bottom = bottomOfTile(y);
  122.       centerX =  centerXOfTile(x);
  123.       centerY = centerYOfTile(y);
  124.     }
  125.  
  126.  
  127.     // Consider the line xPixel, yPixel towards goalX, goalY.
  128.     // This line must start in tile x, y.
  129.     // Then advanceTowards follows this line until it leaves x, y
  130.     // updating xPixel,yPixel with the point where it leaves
  131.     // and the rest with the tile it enters.
  132.     void advanceTowards (float goalX, float goalY)
  133.     {
  134.       float dX = goalX-xPixel;
  135.       float dY = goalY-yPixel;
  136.       // First try to go x until next tile
  137.       float lambdaToNextX = Float.POSITIVE_INFINITY;
  138.       if (dX>0) {
  139.         float nextX = (x+1)*tileSize;
  140.         lambdaToNextX = (nextX-xPixel)/dX;
  141.       }  
  142.       else if (dX<0) {
  143.         float nextX = x*tileSize;
  144.         lambdaToNextX = (nextX-xPixel)/dX;
  145.       }
  146.       // Then try to go y until next tile
  147.       float lambdaToNextY = Float.POSITIVE_INFINITY;
  148.       if (dY>0) {
  149.         float nextY = (y+1)*tileSize;
  150.         lambdaToNextY = (nextY-yPixel)/dY;
  151.       }  
  152.       else if (dY<0) {
  153.         float nextY = y*tileSize;
  154.         lambdaToNextY = (nextY-yPixel)/dY;
  155.       }
  156.       // Then choose which comes first x, y or goal
  157.       if (lambdaToNextX<lambdaToNextY && lambdaToNextX<1) { // Go x
  158.         xPixel += dX*lambdaToNextX;
  159.         yPixel += dY*lambdaToNextX;
  160.         if (dX>0) x++;
  161.         else x--;
  162.       }
  163.       else if (lambdaToNextY<=lambdaToNextX && lambdaToNextY<1) { // Go y
  164.         xPixel += dX*lambdaToNextY;
  165.         yPixel += dY*lambdaToNextY;
  166.         if (dY>0) y++;
  167.         else y--;
  168.       }
  169.       else {// reached goal in same cell
  170.         xPixel = goalX;
  171.         yPixel = goalY;
  172.       }
  173.     }
  174.   };
  175.  
  176.     // Returns a reference to a given pixel and its tile
  177.     TileReference newRefOfPixel (float pixelX, float pixelY) {
  178.       TileReference ref = new TileReference (floor(pixelX/tileSize), floor(pixelY/tileSize));
  179.       ref.xPixel = pixelX;
  180.       ref.yPixel = pixelY;
  181.       return ref;
  182.     }
  183.  
  184.  
  185.   // True if the rectangle given by x, y, w, h (partially) contains an element with a tile
  186.   // from list. The meaning of x,y,w,h is governed by mode (CORNER, CENTER, CORNERS).
  187.   boolean testTileInRect( float x, float y, float w, float h, String list ) {
  188.     if (mode==CENTER) {
  189.       x-=w/2;
  190.       y-=w/2;
  191.     }
  192.     if (mode==CORNERS) {
  193.       w=w-x;
  194.       h=h-y;
  195.     }
  196.     int startX = floor(x / tileSize),
  197.     startY = floor(y / tileSize),
  198.     endX   = floor((x+w) / tileSize),
  199.     endY   = floor((y+h) / tileSize);
  200.  
  201.     for ( int xx = startX; xx <= endX; ++xx )
  202.     {
  203.       for ( int yy = startY; yy <= endY; ++yy )
  204.       {
  205.         if ( list.indexOf( at(xx, yy) ) != -1 )
  206.           return true;
  207.       }
  208.     }
  209.     return false;
  210.   }
  211.  
  212.   // Like testtileInRect(...) but returns a reference to the tile if one is found
  213.   // and null else. The meaning of x,y,w,h is governed by mode (CORNER, CENTER, CORNERS).
  214.   TileReference findTileInRect( float x, float y, float w, float h, String list ) {
  215.     if (mode==CENTER) {
  216.       x-=w/2;
  217.       y-=w/2;
  218.     }
  219.     if (mode==CORNERS) {
  220.       w=w-x;
  221.       h=h-y;
  222.     }
  223.     int startX = floor(x / tileSize),
  224.     startY = floor(y / tileSize),
  225.     endX   = floor((x+w) / tileSize),
  226.     endY   = floor((y+h) / tileSize);
  227.  
  228.     for ( int xx = startX; xx <= endX; ++xx )
  229.     {
  230.       for ( int yy = startY; yy <= endY; ++yy )
  231.       {
  232.         if ( list.indexOf( at(xx, yy) ) != -1 )
  233.           return new TileReference(xx, yy);
  234.       }
  235.     }
  236.     return null;
  237.   }
  238.  
  239.   // Like findTileInRect(...) but returns a reference to the tile closest to the center
  240.   TileReference findClosestTileInRect( float x, float y, float w, float h, String list ) {
  241.     if (mode==CENTER) {
  242.       x-=w/2;
  243.       y-=w/2;
  244.     }
  245.     if (mode==CORNERS) {
  246.       w=w-x;
  247.       h=h-y;
  248.     }
  249.     float centerX=x+w/2, centerY=y+h/2;
  250.     int startX = floor(x / tileSize),
  251.     startY = floor(y / tileSize),
  252.     endX   = floor((x+w) / tileSize),
  253.     endY   = floor((y+h) / tileSize);
  254.  
  255.     int xFound=-1, yFound=-1;
  256.     float dFound = Float.POSITIVE_INFINITY;
  257.     for ( int xx = startX; xx <= endX; ++xx )
  258.     {
  259.       for ( int yy = startY; yy <= endY; ++yy )
  260.       {
  261.         if ( list.indexOf( at(xx, yy) ) != -1 ) {
  262.           float d = dist(centerXOfTile(xx), centerYOfTile(yy), centerX, centerY);
  263.           if (d<dFound) {
  264.             dFound = d;
  265.             xFound = xx;
  266.             yFound = yy;
  267.           }
  268.         }
  269.       }
  270.     }
  271.     if (dFound<Float.POSITIVE_INFINITY) return new TileReference (xFound, yFound);
  272.     else return null;
  273.   }
  274.  
  275.   // True if the rectangle is completely inside tiles from the list
  276.   //The meaning of x,y,w,h is governed by mode (CORNER, CENTER, CORNERS).
  277.   boolean testTileFullyInsideRect( float x, float y, float w, float h, String list ) {
  278.     if (mode==CENTER) {
  279.       x-=w/2;
  280.       y-=w/2;
  281.     }
  282.     if (mode==CORNERS) {
  283.       w=w-x;
  284.       h=h-y;
  285.     }
  286.     float centerX=x+w/2, centerY=y+h/2;
  287.     int startX = floor(x / tileSize),
  288.     startY = floor(y / tileSize),
  289.     endX   = floor((x+w) / tileSize),
  290.     endY   = floor((y+h) / tileSize);
  291.  
  292.     for ( int xx = startX; xx <= endX; ++xx ) {
  293.       for ( int yy = startY; yy <= endY; ++yy ) {
  294.         if ( list.indexOf( at(xx, yy) ) == -1 ) return false;
  295.       }
  296.     }
  297.     return true;
  298.   }
  299.  
  300.  
  301.   // Searches along the line from x1,y1 to x2,y2 for a tile from list
  302.   // Returns the first found or null if none.
  303.   TileReference findTileOnLine( float x1, float y1, float x2, float y2, String list ) {
  304.     TileReference ref = newRefOfPixel (x1, y1);
  305.     int ctr=0;
  306.     int maxCtr = floor(abs(x1-x2)+abs(y1-y2))/tileSize+3;
  307.     while (ctr<=maxCtr && (ref.xPixel!=x2 || ref.yPixel!=y2)) {
  308.       if (ctr>0) ref.advanceTowards (x2, y2);
  309.       if (list.indexOf(at(ref.x, ref.y))!=-1) {
  310.         ref.setBorders ();
  311.         return ref;
  312.       }
  313.       ctr++;
  314.     }
  315.     if (ctr>maxCtr) println ("Internal error in Map:findTileOnLine");
  316.     return null;
  317.   }
  318.  
  319.   // Returns, whether on the line from x1,y1 to x2,y2 there is a tile from list
  320.   boolean testTileOnLine ( float x1, float y1, float x2, float y2, String list ) {
  321.     return findTileOnLine (x1, y1, x2, y2, list)!=null;
  322.   }
  323.  
  324.   // Draws the map on the screen, where the origin, i.e. left/upper
  325.   // corner of the map is drawn at \c leftX, topY regardless of mode
  326.   void draw( float leftX, float topY ) {
  327.     pushStyle();
  328.     imageMode(CORNER);
  329.     int startX = floor(-leftX / tileSize),
  330.     startY = floor(-topY / tileSize);
  331.     for ( int y = startY; y < startY + height/tileSize + 2; ++y ) {
  332.       for ( int x  = startX; x < startX + width/tileSize + 2; ++x ) {
  333.         PImage img = null;
  334.         char tile = at( x, y );
  335.         if ( tile == '_' )
  336.           img = outsideImage;
  337.         else if ('A'<=tile && tile<='Z')
  338.           img = images[at( x, y ) - 'A'];
  339.         if ( img != null )
  340.           image( img,
  341.           x*tileSize + leftX,
  342.           y*tileSize + topY,
  343.           tileSize, tileSize );
  344.       }
  345.     }
  346.     popStyle();
  347.   }
  348.  
  349.   // Loads a map file
  350.   // element size is obtained from the first image loaded
  351.   void loadFile( String mapFile ) {
  352.     map = loadStrings( mapFile );
  353.     if (map==null)
  354.       throw new Error ("Map "+mapFile+" not found.");
  355.     while (map.length>0 && map[map.length-1].equals (""))
  356.       map = shorten(map);
  357.     h = map.length;
  358.     if ( h == 0 )
  359.       throw new Error("Map has zero size");
  360.     w = map[0].length();
  361.  
  362.     // Load images
  363.     for (char c='A'; c<='Z'; c++)
  364.       images[c - 'A'] = loadImageRelativeToMap (mapFile, c + ".png" );        
  365.     outsideImage = loadImageRelativeToMap (mapFile, "_.png");
  366.  
  367.     for ( int y = 0; y < h; ++y ) {
  368.       String line = map[y];
  369.       if ( line.length() != w )
  370.         throw new Error("Not every line in map of same length");
  371.  
  372.       for ( int x = 0; x < line.length(); ++x ) {
  373.         char c = line.charAt(x);
  374.         if (c==' ' || c=='_') {
  375.         }
  376.         else if ('A'<=c && c<='Z') {
  377.           if (images[c - 'A'] == null)
  378.             throw new Error ("Image for "+c+".png missing");
  379.         }
  380.         else throw new Error("map must only contain A-Z, space or _");
  381.       }
  382.     }    
  383.  
  384.     determinetileSize ();
  385.   }
  386.  
  387.   // Saves the map into a file
  388.   void saveFile (String mapFile) {
  389.     saveStrings (mapFile, map);
  390.   }
  391.  
  392.  
  393.   //********************************************************************************************
  394.   //********* The code below this line is just for internal use of the library *****************
  395.   //********************************************************************************************
  396.  
  397.   // Internal: load and Image and return null if not found
  398.   protected PImage tryLoadImage (String imageFilename) {
  399.     //println("Trying "+imageFilename);
  400.     if (createInput(imageFilename)!=null) {
  401.       //println("Found");
  402.       return loadImage (imageFilename);
  403.     }
  404.     else return null;
  405.   }
  406.  
  407.   // Internal: Loads an image named imageName from a locatation relative
  408.   // to the map file mapFile. It must be either in the same
  409.   // directory, or in a subdirectory images, or in a parallel
  410.   // directory images.
  411.   protected PImage loadImageRelativeToMap (String mapFile, String imageName) {
  412.     File base = new File(mapFile);
  413.     File parent = base.getParentFile();
  414.     PImage img;
  415.     img = tryLoadImage (new File (parent, imageName).getPath());
  416.     if (img!=null) return img;
  417.     img = tryLoadImage (new File (parent, "data/images/"+imageName).getPath());
  418.     if (img!=null) return img;
  419.     img = tryLoadImage (new File (parent, "../data/images/"+imageName).getPath());
  420.     return img;
  421.   }
  422.  
  423.   // Goes through all images loaded and determine stileSize as amx
  424.   // If image sizes are not square and equal a warning message is printed
  425.   protected void determinetileSize () {
  426.     tileSize = 0;
  427.     PImage[] allImages = (PImage[]) append (images, outsideImage);
  428.     for (int i=0; i<allImages.length; i++) if (allImages[i]!=null) {
  429.       if (tileSize>0 &&
  430.         (allImages[i].width!=tileSize || allImages[i].height!=tileSize))
  431.         println ("WARNING: Images are not square and of same size");
  432.       if (allImages[i].width>tileSize)  tileSize = allImages[i].width;
  433.       if (allImages[i].height>tileSize) tileSize = allImages[i].height;
  434.     }
  435.     if (tileSize==0) throw new Error ("No image could be loaded.");
  436.   }
  437.  
  438.   // If the dimension of the map is below width times height
  439.   // _ are appended in each line and full lines are appended
  440.   // such that it is width times height.
  441.   protected void extend (int width, int height) {
  442.     while (height>h) {
  443.       map = append(map, "");
  444.       h++;
  445.     }
  446.     if (w<width) w = width;
  447.     for (int y=0; y<h; y++) {
  448.       while (map[y].length ()<w)
  449.         map[y] = map[y] + "_";
  450.     }
  451.   }
  452.  
  453.   // Replaces s.charAt(index) with ch
  454.   String replace (String s, int index, char ch) {
  455.     return s.substring(0, index)+ch+s.substring(index+1, s.length());
  456.   }
  457.  
  458.  
  459.   // *** variables ***
  460.   // tile x, y is map[y].charAt(x)
  461.   String map[];
  462.   // images[c-'A'] is the image for tile c
  463.   PImage images[];
  464.   // special image drawn outside the map
  465.   PImage outsideImage;
  466.   // map dimensions in tiles
  467.   int w, h;
  468.   // width and height of an element in pixels
  469.   int tileSize;
  470. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement