📄 levelgenerator.java
字号:
{
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 + -