📄 dungeongenerator.cpp
字号:
int x = sx; int y = sy; //fprintf(stderr, "\tnotVisitedCount=%d x=%d y=%d\n", notVisitedCount, x, y); int nx = x; int ny = y; int dir = initDirections(); // keep going while you can int stepCount = 0; bool reachedVisited = false; bool inMap = false; while(true) { // take a step in the selected direction switch(dir) { case DIR_N: ny--; break; case DIR_S: ny++; break; case DIR_W: nx--; break; case DIR_E: nx++; break; default: fprintf(stderr, "ERROR: unknown direction selected: %d\n", dir); } // off the map or location already visited inMap = (nx >= 0 && nx < width && ny >= 0 && ny < height); if(!inMap || nodes[nx][ny] != UNVISITED || stepCount++ >= width / 2 || (curvyness > 1 && curvyness < 100 && (int) ((double)curvyness * rand()/RAND_MAX) == 0)) { if(!stopAtVisited && inMap && nodes[nx][ny] != UNVISITED) { reachedVisited = true; } else { // step back nx = x; ny = y; // pick another direction dir = nextDirection(); if(dir == -1) { break; } stepCount = 0; continue; } } // connect to the previous cell switch(dir) { case DIR_N: nodes[x][y] |= N_PASS; if(inMap) nodes[nx][ny] |= S_PASS; break; case DIR_S: nodes[x][y] |= S_PASS; if(inMap) nodes[nx][ny] |= N_PASS; break; case DIR_W: nodes[x][y] |= W_PASS; if(inMap) nodes[nx][ny] |= E_PASS; break; case DIR_E: nodes[x][y] |= E_PASS; if(inMap) nodes[nx][ny] |= W_PASS; break; } if(reachedVisited) { reachedVisited = false; // step back nx = x; ny = y; // pick another direction dir = nextDirection(); if(dir == -1) { break; } stepCount = 0; continue; } // mark the cell visited markVisited(nx, ny); // save last position x = nx; y = ny; // debug //printMaze(); //gets(line); }}void DungeonGenerator::markVisited(int x, int y) { // add to visited int n = (y * width) + x; // has it already been visited? for(int i = 0; i < visitedCount; i++) { if(visited[i] == n) return; } visited[visitedCount++] = n; // remove from not visited for(int i = 0; i < notVisitedCount; i++) { if(notVisited[i] == n) { notVisitedCount--; for(int t = i; t < notVisitedCount; t++) { notVisited[t] = notVisited[t + 1]; } return; } }}bool DungeonGenerator::isVisited(int x, int y) { int n = (y * width) + x; for(int i = 0; i < visitedCount; i++) { if(visited[i] == n) return true; } return false;}void DungeonGenerator::nextNotVisited(int *x, int *y) { // are there no more unvisited locations? if(notVisitedCount <= 0) { *x = *y = -1; return; } // get a random location int index = (int) ((double)notVisitedCount * rand()/RAND_MAX); int n = notVisited[index]; // remove from visited areas notVisitedCount--; for(int i = index; i < notVisitedCount; i++) { notVisited[i] = notVisited[i + 1]; } // break up into x,y coordinates *y = n / width; *x = n % width; // add it to visited visited[visitedCount++] = n;}void DungeonGenerator::nextVisited(int *x, int *y) { // are there no visited locations? if(visitedCount <= 0) { *x = *y = -1; return; } // get a random location int index = (int) ((double)visitedCount * rand()/RAND_MAX); int n = visited[index]; // break up into x,y coordinates *y = n / width; *x = n % width;}int DungeonGenerator::initDirections() { // init all available directions dirCount = DIR_COUNT; for(int i = 0; i < dirCount; i++) { dirs[i] = i; } return dirs[(int) ((double)dirCount * rand()/RAND_MAX)];}int DungeonGenerator::nextDirection() { if(dirCount <= 0) return -1; int index = (int) ((double)dirCount * rand()/RAND_MAX); int dir = dirs[index]; dirCount--; for(int i = index; i < dirCount; i++) { dirs[i] = dirs[i + 1]; } return dir;}void DungeonGenerator::printMaze() { printf("---------------------------------------\n"); int c = 0; for(int y = 0; y < height; y++) { for(int i = 0; i < 3; i++) { for(int x = 0; x < width; x++) { switch(i) { case 0: // top row if((nodes[x][y] & N_PASS)) { printf(" | "); } else { printf(" "); } break; case 1: if((nodes[x][y] & W_PASS)) { printf("-"); } else { printf(" "); } if(nodes[x][y] == UNVISITED) printf(" "); else if(nodes[x][y] & ROOM) printf("*"); else printf("O"); if((nodes[x][y] & E_PASS)) { printf("-"); } else { printf(" "); } break; case 2: // bottom row if((nodes[x][y] & S_PASS)) { printf(" | "); } else { printf(" "); } break; } c++; } printf("\n"); } c++; } printf("---------------------------------------\n");}// draw a pre-rendered location on the mapvoid DungeonGenerator::constructMaze(int locationIndex) { // create the rooms roomCount = location[locationIndex].roomCount; for(int i = 0; i < location[locationIndex].roomCount; i++) { room[i].x = location[locationIndex].roomDimension[i][0]; room[i].y = location[locationIndex].roomDimension[i][1]; room[i].w = location[locationIndex].roomDimension[i][2]; room[i].h = location[locationIndex].roomDimension[i][3]; } // turn location into nodes for(int y = 0; y < location[locationIndex].h; y++) { for(int x = 0; x < location[locationIndex].w; x++) { char c = location[locationIndex].map[y][x]; int nx = location[locationIndex].x + x; int ny = location[locationIndex].y + y; if(nx >= width || ny >= height) { cerr << "Warning: location doesn't fit on map! location:" << location[locationIndex].w << "," << location[locationIndex].h << " map:" << width << "," << height << endl; continue; } switch(c) { case '#': case 'n': case 's': case 'e': case 'w': nodes[nx][ny] = ROOM; break; case '+': nodes[nx][ny] = PASSAGE; break; default: nodes[nx][ny] = UNVISITED; } // open every side for now if(nodes[nx][ny] != UNVISITED) nodes[nx][ny] |= (N_PASS | S_PASS | W_PASS | E_PASS); // add door } } // build walls for(int y = 0; y < location[locationIndex].h; y++) { for(int x = 0; x < location[locationIndex].w; x++) { char c = location[locationIndex].map[y][x]; int nx = location[locationIndex].x + x; int ny = location[locationIndex].y + y; if(nx >= width || ny >= height) { cerr << "Warning: location doesn't fit on map! location:" << location[locationIndex].w << "," << location[locationIndex].h << " map:" << width << "," << height << endl; continue; } switch(c) { case '#': case '+': break; case 'n': nodes[nx][ny] |= N_DOOR; break; case 's': nodes[nx][ny] |= S_DOOR; break; case 'e': nodes[nx][ny] |= E_DOOR; break; case 'w': nodes[nx][ny] |= W_DOOR; break; } } } // seal off some walls for(int y = 0; y < location[locationIndex].h; y++) { for(int x = 0; x < location[locationIndex].w; x++) { //char c = location[locationIndex].map[y][x]; int nx = location[locationIndex].x + x; int ny = location[locationIndex].y + y; if(nx >= width || ny >= height) { cerr << "Warning: location doesn't fit on map! location:" << location[locationIndex].w << "," << location[locationIndex].h << " map:" << width << "," << height << endl; continue; } if(nodes[nx][ny] != UNVISITED) { if(!(nodes[nx][ny] & W_DOOR) && (!nx || nodes[nx - 1][ny] == UNVISITED || ((nodes[nx][ny] & ROOM) && !(nodes[nx - 1][ny] & ROOM)) || (!(nodes[nx][ny] & ROOM) && (nodes[nx - 1][ny] & ROOM) && !(nodes[nx - 1][ny] & E_DOOR)))) { nodes[nx][ny] &= (0xffff - W_PASS); } if(!(nodes[nx][ny] & E_DOOR) && (nx >= width - 1 || nodes[nx + 1][ny] == UNVISITED || ((nodes[nx][ny] & ROOM) && !(nodes[nx + 1][ny] & ROOM)) || (!(nodes[nx][ny] & ROOM) && (nodes[nx + 1][ny] & ROOM) && !(nodes[nx + 1][ny] & W_DOOR)))) { nodes[nx][ny] &= (0xffff - E_PASS); } if(!(nodes[nx][ny] & N_DOOR) && (!ny || nodes[nx][ny - 1] == UNVISITED || ((nodes[nx][ny] & ROOM) && !(nodes[nx][ny - 1] & ROOM)) || (!(nodes[nx][ny] & ROOM) && (nodes[nx][ny - 1] & ROOM) && !(nodes[nx][ny - 1] & S_DOOR)))) { nodes[nx][ny] &= (0xffff - N_PASS); } if(!(nodes[nx][ny] & S_DOOR) && (ny >= height - 1 || nodes[nx][ny + 1] == UNVISITED || ((nodes[nx][ny] & ROOM) && !(nodes[nx][ny + 1] & ROOM)) || (!(nodes[nx][ny] & ROOM) && (nodes[nx][ny + 1] & ROOM) && !(nodes[nx][ny + 1] & N_DOOR)))) { nodes[nx][ny] &= (0xffff - S_PASS); } } } } // other settings monsters = location[locationIndex].monsters;}void DungeonGenerator::updateStatus() { glLoadIdentity(); // glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT ); // glClearColor( 0, 0, 0, 0 ); glDisable( GL_DEPTH_TEST ); glDepthMask(GL_FALSE); glDisable( GL_BLEND ); glDisable( GL_CULL_FACE ); glDisable( GL_TEXTURE_2D ); int MAX_STATUS = 12; int w = 10; int h = 20; glColor4f( 0.25f, 0.20f, 0.15f, 0.15f ); glBegin( GL_QUADS ); glVertex3f( 0, 0, 0 ); glVertex3f( 0, 35 + h + 10, 0); glVertex3f( MAX_STATUS * 2 * w + 20, 35 + h + 10, 0 ); glVertex3f( MAX_STATUS * 2 * w + 20, 0, 0 ); glEnd(); glColor4f(1, 1, 1, 1); scourge->getSDLHandler()->texPrint(20, 25, "Assembling Dungeon Level..."); for(int i = 0; i < MAX_STATUS; i++) { if(i < status) glColor4f(0.7f, 0.10f, 0.15f, 1); else glColor4f(0.5f, 0.5f, 0.5f, 1); glPushMatrix(); glLoadIdentity(); glTranslatef( i * 2 * w + 20, 35, 0 ); glBegin( GL_QUADS ); glVertex3f( 0, 0, 0 ); glVertex3f( 0, h, 0 ); glVertex3f( w, h, 0 ); glVertex3f( w, 0, 0 ); glEnd(); glPopMatrix(); } /* Draw it to the screen */ SDL_GL_SwapBuffers( ); status++; //sleep(1); glEnable( GL_DEPTH_TEST ); glDepthMask(GL_TRUE);}void DungeonGenerator::toMap(Map *map, ShapePalette *shapePal, int locationIndex) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -