⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 levelgenerator.java

📁 J2ME Game Programming的隋书源代码
💻 JAVA
📖 第 1 页 / 共 2 页
字号:
               {
                  if (dir == UP_DIR)
                     corridorY = lastRoomY - corridorHeight + 1;
                  if (dir == DOWN_DIR)
                     corridorY = lastRoomY + lastRoomH - 1;

                  corridorX = Tools.getRand(Math.max(lastRoomX, newRoomX),
                                            Math.min(lastRoomX + lastRoomW -
                                                     corridorWidth,
                                                     newRoomX + newRoomW -
                                                     corridorWidth));
               }

               // Draw the corridor on the tilemap.
               addRoom(level, corridorX, corridorY, corridorWidth,
                       corridorHeight);

               // Set the last room index to be the room we added (step back by
               // an extra one to skip the corridor just added to connect the
               // new room to the last one).
               lastRoomIndex = roomCount - 2;
            }
         }
      }

      // End point is the second last room we added (last one
      // was the corridor to it)
      setEndPoint(roomX[roomCount - 2] + roomW[roomCount - 2] / 2,
                  roomY[roomCount - 2] + roomH[roomCount - 2] / 2);

      //#ifdef debug
      dump();
      //#endif
      return tileMap;
   }

   /**
    * Sets the exit point in the tile map (the gateway tile).
    * @param tileX The x position of the end point.
    * @param tileY The y position of the end point.
    */
   private final void setEndPoint(int tileX, int tileY)
   {
      tileMap[tileY][tileX] = World.GATEWAY_TILE;
   }

   /**
    * @param b An array of booleans to test.
    * @return True if all the booleans in the array are true.
    */
   private static final boolean areAllTrue(boolean[] b)
   {
      for (int i = 0; i < b.length; i++)
         if (b[i] == false) return false;
      return true;
   }

   /**
    * Based on an array of boolean's this returns a random choice from a limited
    * list of ones that are currently false. The level generator uses this to
    * randomly choose a direction, but only from ones that have not previously
    * been tried (set to true in the array).
    */
   private static final int getRandDir(boolean[] dirs)
   {
      // we only do a random test on the number of available dirs, so lets
      // find out how many there are first
      int numDirs = 0;
      for (int i = 0; i < 4; i++)
         if (!dirs[i]) numDirs++;

      if (numDirs == 0) return 0;

      // now pick one at random
      int n = 0;
      if (numDirs > 1)
         n = Tools.getRand(0, numDirs - 1);

      // and return the dir corresponding to the nth result by figuring
      // the array index of the nth true value
      int c = -1;
      int i = 0;
      while (i < dirs.length)
      {
         if (!dirs[i++]) c++;
         if (c == n) return i - 1;
      }

      return 0;
   }

   /**
    * Checks to see if the supplied rectangle is within 3 tiles of any other
    * room (including corridors).
    * @param tileX The x position of the room to be checked.
    * @param tileY The y position of the room to be checked.
    * @param tilesWide The width of the room to be checked.
    * @param tilesHigh The height of the room to be checked.
    * @return True if the rectangle (room) is within 3 tiles of another.
    */
   private final boolean isRectNearRoom(int tileX, int tileY, int tilesWide,
                                        int tilesHigh)
   {
      for (int i = 0; i < roomCount; i++)
      {
         if (Tools.isIntersectingRect(tileX, tileY, tilesWide, tilesHigh,
                                      roomX[i] - 3, roomY[i] - 3,
                                      roomW[i] + 3, roomH[i] + 3))
         {
            return true;
         }
      }
      return false;
   }

   /**
    * Adds a room to the level by setting all the bytes in the tilemap to be
    * walls. Note that existing wall tiles will be inverted by this process
    * (except for corners) in order to "carve out" doorways where the walls
    * between rooms and corridors overlap.
    * @param level The level number is a relative density level used to fill
    * the room with objects.
    * @param tileX The x position of the new room.
    * @param tileY The y position of the new room.
    * @param tileWidth The width of the new room.
    * @param tileHeight The height of the new room.
    */
   private void addRoom(int level, int tileX, int tileY, int tileWidth,
                        int tileHeight)
   {
      //System.out.println("adding room: " + roomCount + " max=" + roomW.length +
      // " xy=" + x + ", " + y + " tileMapsize=" + tileMap[0].length + "," +
      // tileMap.length);

      // If it's a corridor we dont just add tiles, we invert in order
      // to cut doorways out of the rooms
      addWallsToMap(tileX, tileY, tileWidth, tileHeight);
      roomW[roomCount] = tileWidth;
      roomH[roomCount] = tileHeight;
      roomX[roomCount] = tileX;
      roomY[roomCount] = tileY;
      roomCount++;

      // Add enemy to this room (we base the number on the level they're on)
      int maxEnemy = level + 1;
      if (maxEnemy > 10) maxEnemy = 10;
      int numEnemy = Tools.getRand(0, maxEnemy);

      int numAdded = 0;
      int tries = 0;
      while (numAdded < numEnemy && tries++ < maxEnemy * 2)
      {
         // Pick a random tile and try to add an activator there (may be filled
         // by another one)
         int tx = Tools.getRand(tileX + 1, tileX + tileWidth - 2);
         int ty = Tools.getRand(tileY + 1, tileY + tileHeight - 2);

         if (tileMap[ty][tx] == World.NO_TILE &&
                 (tx != playerStartX && ty != playerStartY))
         {
            numAdded++;

            // Now pick a random enemy type (again factored on the level).
            if (level < 2)
               tileMap[ty][tx] = World.DRONE_ACTIVATOR_TILE;
            else if (level < 3)
               tileMap[ty][tx] =
                       (byte) Tools.getRand(World.DRONE_ACTIVATOR_TILE,
                                            World.TURRET_ACTIVATOR_TILE);
            else
               tileMap[ty][tx] =
                       (byte) Tools.getRand(World.START_ACTIVATOR_TILE + 1,
                                            World.END_ACTIVATOR_TILE - 1);
         }
      }
   }

   /**
    * Toggles tiles in the tilemap to either a wall or an empty space (based on
    * what is there already) in an outline rectangle using the supplied bounding
    * coordinates. Note that corners are NOT inverted, they are always set as
    * walls.
    * @param roomTileX The starting x position of the room to create.
    * @param roomTileY The starting y position of the room to create.
    * @param roomTilesWide The width of the room to create.
    * @param roomTilesHigh The height of the room to create.
    */
   private void addWallsToMap(int roomTileX, int roomTileY,
                              int roomTilesWide, int roomTilesHigh)
   {
      // Add the top and bottom line.
      for (int tileX = roomTileX; tileX < roomTileX + roomTilesWide; tileX++)
      {
         // Invert the tiles along the top.
         invertTile(tileX, roomTileY);
         // Invert the tiles along the bottom.
         invertTile(tileX, roomTileY + roomTilesHigh - 1);
      }

      // Left and right side lines.
      for (int tileY = roomTileY + 1; tileY < roomTileY + roomTilesHigh - 1;
           tileY++)
      {
         // Invert the tiles down the left side.
         invertTile(roomTileX, tileY);
         // Invert the tiles down the right side.
         invertTile(roomTileX + roomTilesWide - 1, tileY);
      }

      // Mark corners as walls (not inverted).
      tileMap[roomTileY][roomTileX] = World.WALL_TILE;
      tileMap[roomTileY][roomTileX + roomTilesWide - 1] = World.WALL_TILE;
      tileMap[roomTileY + roomTilesHigh - 1][roomTileX] = World.WALL_TILE;
      tileMap[roomTileY + roomTilesHigh - 1][roomTileX + roomTilesWide - 1] =
              World.WALL_TILE;
   }

   /**
    * Inverts an existing map tile between either empty or a wall tile.
    * @param tileX The x position of the tile to invert.
    * @param tileY The y position of the tile to invert.
    */
   private void invertTile(int tileX, int tileY)
   {
      // Turn an empty tile into a wall or vice versa.
      if (tileMap[tileY][tileX] == World.WALL_TILE)
         tileMap[tileY][tileX] = World.NO_TILE;
      else
         tileMap[tileY][tileX] = World.WALL_TILE;
   }

   private void dump()
   {
      System.out.println("\t          1         2         3         4         5");
      System.out.println("\t012345678901234567890123456789012345678901234567890");

      for (int ty = 0; ty < height; ty++)
      {
         System.out.print(ty + "\t");

         for (int tx = 0; tx < width; tx++)
         {
            if (tileMap[ty][tx] == World.WALL_TILE)
               System.out.print("#");
            else if (tileMap[ty][tx] == World.GATEWAY_TILE)
               System.out.print("$");
            else if (tileMap[ty][tx] == World.DRONE_ACTIVATOR_TILE)
               System.out.print("D");
            else if (tileMap[ty][tx] == World.TURRET_ACTIVATOR_TILE)
               System.out.print("T");
            else if (tileMap[ty][tx] == World.FIGHTER_ACTIVATOR_TILE)
               System.out.print("F");
            else if (playerStartX == tx && playerStartY == ty)
               System.out.print("X");
            else
               System.out.print(" ");
         }
         System.out.println();
      }

   }
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -