/* Gera um novo nivel */ Nivel genNivel(int level, Player* player, Enemy* enemies){ Nivel nivel; clear(); move(0,0); /* Escolhe um tamanho aleatorio para o mapa */ do{ nivel.tamI = rand() % 26; }while(nivel.tamI < 21); do{ nivel.tamJ = rand() % 51; }while(nivel.tamJ < 46); int tamI = nivel.tamI; int tamJ = nivel.tamJ; for(int i = 0; i < tamI; i++){ for(int j = 0; j < tamJ; j++) nivel.mapa[i][j].shown = 0; } nivel.nivel = level; nivel.inimigos = 0; /* Gera o mapa aleatoriamente (apenas muros e espacos vazios) */ genRoom(&nivel); /* Inicializa as posicoes do mapa */ for(int i = 0; i < tamI; i++){ for(int j = 0; j < tamJ; j++){ if(nivel.mapa[i][j].shown == 1){ nivel.mapa[i][j].used = 1; nivel.mapa[i][j].enemyIndice = -1; nivel.mapa[i][j].itemIndice = -1; nivel.mapa[i][j].player = 0; nivel.mapa[i][j].wall = 1; nivel.mapa[i][j].stairs = 0; nivel.mapa[i][j].quantItems = 0; } else{ nivel.mapa[i][j].used = 0; nivel.mapa[i][j].enemyIndice = -1; nivel.mapa[i][j].itemIndice = -1; nivel.mapa[i][j].player = 0; nivel.mapa[i][j].wall = 0; nivel.mapa[i][j].stairs = 0; nivel.mapa[i][j].quantItems = 0; } } } /* Posiciona a escada para o proximo nivel*/ int stairsI, stairsJ; do{ stairsI = rand() % tamI; stairsJ = rand() % tamJ; }while(nivel.mapa[stairsI][stairsJ].used == 1); nivel.mapa[stairsI][stairsJ].used = 1; nivel.mapa[stairsI][stairsJ].stairs = 1; for(int i = stairsI - 1; i <= stairsI + 1; i++){ for(int j = stairsJ - 1; j <= stairsJ + 1; j++){ if(nivel.mapa[i][j].wall == 1){ if((i > 0) && (i < tamI - 1) && (j > 0) && (j < tamJ - 1)){ nivel.mapa[i][j].used = 0; nivel.mapa[i][j].wall = 0; } } } } /* Posiciona boss do nivel */ int flag = 0; if(flag == 0){ if(stairsI - 1 > 0){ nivel.mapa[stairsI - 1][stairsJ].enemyIndice = 0; nivel.mapa[stairsI - 1][stairsJ].used = 1; nivel.inimigos++; enemies[0] = createEnemy(1, stairsI - 1, stairsJ, nivel.nivel); } else flag = 1; } if(flag == 1){ if(stairsI + 1 < tamI - 1){ nivel.mapa[stairsI + 1][stairsJ].enemyIndice = 0; nivel.mapa[stairsI + 1][stairsJ].used = 1; nivel.inimigos++; enemies[0] = createEnemy(1, stairsI + 1, stairsJ, nivel.nivel); } else flag = 2; } if(flag == 2){ if(stairsJ - 1 > 0){ nivel.mapa[stairsI][stairsJ - 1].enemyIndice = 0; nivel.mapa[stairsI][stairsJ - 1].used = 1; nivel.inimigos++; enemies[0] = createEnemy(1, stairsI, stairsJ - 1, nivel.nivel); } else flag = 3; } if(flag == 3){ if(stairsJ + 1 < tamJ - 1){ nivel.mapa[stairsI][stairsJ + 1].enemyIndice = 0; nivel.mapa[stairsI][stairsJ + 1].used = 1; nivel.inimigos++; enemies[0] = createEnemy(1, stairsI, stairsJ + 1, nivel.nivel); } } /* Posiciona o jogador e garante que ele nao esta encostado em um muro (isso pode atrapalhar movimento em corredores) */ do{ (*player).y = rand() % tamI; (*player).x = rand() % tamJ; }while((nivel.mapa[player->y][player->x].used == 1) || (!distancia(player->y, player->x, stairsI, stairsJ, tamI * tamJ))); nivel.mapa[player->y][player->x].used = 1; nivel.mapa[player->y][player->x].player = 1; nivel.mapa[player->y][player->x].stairs = -1; for(int i = player->y - 1; i <= player->y + 1; i++){ for(int j = player->x - 1; j <= player->x + 1; j++){ if(nivel.mapa[i][j].wall == 1){ if((i > 0) && (i < tamI - 1) && (j > 0) && (j < tamJ - 1)){ nivel.mapa[i][j].used = 0; nivel.mapa[i][j].wall = 0; } } } } enemyPositions(nivel, enemies); return nivel; }
void WorldGenerator::genLevelBlueprint( Level& level, Room* rooms, short roomCount ) { //Find the center to start so we can generate in any direction WallSide wallSide = (WallSide)mRand.gen(0, WallSide::Right + 1 ); WallSide prevWallSide = (WallSide)((wallSide + 2) % 4); int attachedX = roomCount * ( ROOM_MAX_DIMENSION + 3 ); int attachedY = roomCount * ( ROOM_MAX_DIMENSION + 3 ); int attempts = 0; int minX = -1; int minY = -1; int maxX = -1; int maxY = -1; //Generate the rooms for(int i = 0; i < roomCount; i++){ //If we have attempted and failed to many times, reset and regen if( attempts > WORLD_GEN_ATTEMPTS ){ //RESET EVERYTHING and start overrr wallSide = (WallSide)mRand.gen(0, WallSide::Right + 1 ); prevWallSide = (WallSide)((wallSide + 2) % 4); attachedX = roomCount * ( ROOM_MAX_DIMENSION + 3 ); attachedY = roomCount * ( ROOM_MAX_DIMENSION + 3 ); minX = -1; minY = -1; maxX = -1; maxY = -1; //Reset all doors for(int r = 0; r <= i; r++){ for(int d = 0; d < ROOM_MAX_DOORS; d++){ rooms[r].doors[d].x = -1; rooms[r].doors[d].y = -1; rooms[r].doors[d].essential = false; } } i = -1; attempts = 0; continue; } genRoom( wallSide, attachedX, attachedY, rooms[ i ] ); //If room collides with another room, try again to generate bool collidesWithOtherRoom = false; for(int p = 0; p < i; p++){ //Top Left if( rooms[i].left >= rooms[p].left && rooms[i].left <= rooms[p].right && rooms[i].top >= rooms[p].top && rooms[i].top <= rooms[p].bottom ){ collidesWithOtherRoom = true; break; } //Top Right if( rooms[i].right >= rooms[p].left && rooms[i].right <= rooms[p].right && rooms[i].top >= rooms[p].top && rooms[i].top <= rooms[p].bottom ){ collidesWithOtherRoom = true; break; } //Bottom Left if( rooms[i].left >= rooms[p].left && rooms[i].left <= rooms[p].right && rooms[i].bottom >= rooms[p].top && rooms[i].bottom <= rooms[p].bottom ){ collidesWithOtherRoom = true; break; } //Bottom Right if( rooms[i].right >= rooms[p].left && rooms[i].right <= rooms[p].right && rooms[i].bottom >= rooms[p].top && rooms[i].bottom <= rooms[p].bottom ){ collidesWithOtherRoom = true; break; } } if( collidesWithOtherRoom ){ attempts++; i--; continue; } //Generate a door along each wall if there is a room on the other side //The door along wallSide is always unScrubable //We only generate doors after the first room has been genned if( i > 0 ){ genDoors( rooms, i, rooms[ i ], rooms[ i - 1 ], wallSide ); } prevWallSide = (WallSide)((wallSide + 2) % 4); wallSide = prevWallSide; if( rooms[ i ].type == Room::Hallway ){ wallSide = (WallSide)((prevWallSide + 2) % 4); }else{ //Make sure the gen them differently while( prevWallSide == wallSide ){ wallSide = (WallSide)mRand.gen(0, WallSide::Right + 1 ); } } switch( wallSide ){ case Front: attachedY = rooms[ i ].bottom + 2; attachedX = mRand.gen( rooms[ i ].left, rooms[ i ].right + 1 ); break; case Left: attachedX = rooms[ i ].right + 2; attachedY = mRand.gen( rooms[ i ].top, rooms[ i ].bottom + 1 ); break; case Back: attachedY = rooms[ i ].top - 2; attachedX = mRand.gen( rooms[ i ].left, rooms[ i ].right + 1 ); break; case Right: attachedX = rooms[ i ].left - 2; attachedY = mRand.gen( rooms[ i ].top, rooms[ i ].bottom + 1 ); break; default: break; } attempts = 0; if( minX < 0 ){ minX = rooms[i].left; } if( minY < 0 ){ minY = rooms[i].top; } if( maxX < 0 ){ maxX = rooms[i].right; } if( maxY < 0 ){ maxY = rooms[i].bottom; } if( minX > rooms[i].left ){ minX = rooms[i].left; } if( maxX < rooms[i].right ){ maxX = rooms[i].right; } if( minY > rooms[i].top ){ minY = rooms[i].top; } if( maxY < rooms[i].bottom ){ maxY = rooms[i].bottom; } } //Extend the bounds a bit minX-=2; minY-=2; maxX+=2; maxY+=2; //Double the scale of the generated space level.init( (maxX - minX) * 2, (maxY - minY) * 2, mLevelRanges->roomCeilingHeight.gen( mRand ) ); //Initialize all to walls for( int i = 0; i < level.getWidth(); i++){ for(int j = 0; j < level.getDepth(); j++){ level.getBlock( i, j ).setWall( ); } } //Convert the rooms from the space level to this level for(int i = 0; i < roomCount; i++){ rooms[i].left -= minX; rooms[i].left *= 2; rooms[i].right -= minX; rooms[i].right *= 2; rooms[i].right++; rooms[i].top -= minY; rooms[i].top *= 2; rooms[i].bottom -= minY; rooms[i].bottom *= 2; rooms[i].bottom++; for(int w = rooms[i].left; w <= rooms[i].right; w++){ for(int d = rooms[i].top; d <= rooms[i].bottom; d++){ //Set inside the room to be open level.getBlock(w, d).setOpen(); //Randomize the tile generated level.getBlock(w, d).setTileID( mRand.gen(0, 16) ); } } //For each created door for(int d = 0; d < ROOM_MAX_DOORS; d++){ if( rooms[i].doors[d].x >= 0 && rooms[i].doors[d].y >= 0 ){ rooms[i].doors[d].x -= minX; rooms[i].doors[d].x *= 2; rooms[i].doors[d].y -= minY; rooms[i].doors[d].y *= 2; if( !rooms[i].doors[d].essential ){ continue; } if( d == 2 ){ rooms[i].doors[d].y++; } if( d == 3 ){ rooms[i].doors[d].x++; } //Create and add door Level::Door door; door.getPosition().x = ( static_cast<float>( rooms[i].doors[d].x ) * 0.3f ); door.getPosition().y = 0.0f; door.getPosition().z = ( static_cast<float>( rooms[i].doors[d].y ) * 0.3f ); door.setYRotation( static_cast<float>( rooms[i].doors[d].side ) * 3.14159f * 0.5f ); door.state = Level::Door::State::Closed; door.facing = (Level::Direction)( rooms[i].doors[d].side ); //Offset position by side switch( rooms[i].doors[d].side ){ case 0: door.getPosition().x += 0.3f; break; case 1: break; case 2: door.getPosition().z += 0.3f; break; case 3: door.getPosition().z += 0.3f; door.getPosition().x += 0.3f; break; default: break; } ushort id = level.addDoor( door ); Level::Door& doorRef = level.getDoor( id ); //Set pointer to door level.getBlock( rooms[i].doors[d].x, rooms[i].doors[d].y ).setDoor( &doorRef ); switch(d){ case 0: level.getBlock( rooms[i].doors[d].x, rooms[i].doors[d].y - 1 ).setOpen(); break; case 1: level.getBlock( rooms[i].doors[d].x - 1, rooms[i].doors[d].y ).setOpen(); break; case 2: level.getBlock( rooms[i].doors[d].x, rooms[i].doors[d].y + 1 ).setOpen(); break; case 3: level.getBlock( rooms[i].doors[d].x + 1, rooms[i].doors[d].y ).setOpen(); break; default: break; } } } } }