#import "Maze.h" #include #include "Random.h" #import @implementation Maze #define CELL_SIZE 5.0f #define HALF_CELL_SIZE (CELL_SIZE * 0.5f) #define CELL_COLOR_LUMINANCE_BIAS 1.0f - (id) init { self = [super init]; if (self == nil) { return nil; } sizeX = 0; sizeY = 0; sizeZ = 0; cells = NULL; return self; } - (void) dealloc { if (cells != NULL) { free(cells); } [super dealloc]; } - (void) generateNewMazeWithSizeX: (int) x sizeY: (int) y sizeZ: (int) z { int * indexArray; int cellIndex, cellIndex2; int swapIndex; int arraySize; int tempIndex; int wallIndex; int numberOfPartitions; int oldPartitionID, newPartitionID; BOOL * wallToKnockDown1, * wallToKnockDown2; if (cells != NULL) { free(cells); } sizeX = x; sizeY = y; sizeZ = z; arraySize = (sizeX * sizeY * sizeZ); cells = (MazeCell *) malloc(sizeof(MazeCell) * arraySize); indexArray = (int *) malloc(sizeof(int) * arraySize); for (cellIndex = 0; cellIndex < arraySize; cellIndex++) { swapIndex = (uirand() % arraySize); tempIndex = indexArray[cellIndex]; indexArray[cellIndex] = indexArray[swapIndex]; indexArray[swapIndex] = tempIndex; } free(indexArray); for (cellIndex = 0; cellIndex < arraySize; cellIndex++) { cells[cellIndex].leftWall = YES; cells[cellIndex].rightWall = YES; cells[cellIndex].bottomWall = YES; cells[cellIndex].topWall = YES; cells[cellIndex].backWall = YES; cells[cellIndex].frontWall = YES; cells[cellIndex].red = ufrand(1.0f); cells[cellIndex].green = ufrand(1.0f); cells[cellIndex].blue = ufrand(1.0f); if ((cells[cellIndex].red + cells[cellIndex].green + cells[cellIndex].blue) < CELL_COLOR_LUMINANCE_BIAS) { float maximum; maximum = cells[cellIndex].red; if (cells[cellIndex].green > maximum) maximum = cells[cellIndex].green; if (cells[cellIndex].blue > maximum) maximum = cells[cellIndex].blue; if (maximum == 0.0f) { cells[cellIndex].red = 1.0f; cells[cellIndex].green = 1.0f; cells[cellIndex].blue = 1.0f; } else { cells[cellIndex].red /= maximum; cells[cellIndex].green /= maximum; cells[cellIndex].blue /= maximum; } } cells[cellIndex].partitionID = cellIndex; } numberOfPartitions = arraySize; while (numberOfPartitions > 1) { cellIndex = (uirand() % arraySize); wallIndex = (uirand() % 6); if ((cellIndex % sizeX) == 0 && wallIndex == 0) wallIndex = 1; if ((cellIndex % sizeX) == (sizeX - 1) && wallIndex == 1) wallIndex = 0; if (((cellIndex / sizeX) % sizeY) == 0 && wallIndex == 2) wallIndex = 3; if (((cellIndex / sizeX) % sizeY) == (sizeY - 1) && wallIndex == 3) wallIndex = 2; if ((((cellIndex / sizeY) / sizeX) % sizeZ) == 0 && wallIndex == 4) wallIndex = 5; if ((((cellIndex / sizeY) / sizeX) % sizeZ) == (sizeZ - 1) && wallIndex == 5) wallIndex = 4; switch (wallIndex) { case 0: cellIndex2 = (cellIndex - 1); wallToKnockDown1 = &cells[cellIndex].leftWall; wallToKnockDown2 = &cells[cellIndex2].rightWall; break; case 1: cellIndex2 = (cellIndex + 1); wallToKnockDown1 = &cells[cellIndex].rightWall; wallToKnockDown2 = &cells[cellIndex2].leftWall; break; case 2: cellIndex2 = (cellIndex - sizeX); wallToKnockDown1 = &cells[cellIndex].bottomWall; wallToKnockDown2 = &cells[cellIndex2].topWall; break; case 3: cellIndex2 = (cellIndex + sizeX); wallToKnockDown1 = &cells[cellIndex].topWall; wallToKnockDown2 = &cells[cellIndex2].bottomWall; break; case 4: cellIndex2 = (cellIndex - (sizeX * sizeY)); wallToKnockDown1 = &cells[cellIndex].backWall; wallToKnockDown2 = &cells[cellIndex2].frontWall; break; case 5: cellIndex2 = (cellIndex + (sizeX * sizeY)); wallToKnockDown1 = &cells[cellIndex].frontWall; wallToKnockDown2 = &cells[cellIndex2].backWall; break; default: continue; } if (cells[cellIndex2].partitionID != cells[cellIndex].partitionID) { *wallToKnockDown1 = NO; *wallToKnockDown2 = NO; newPartitionID = cells[cellIndex].partitionID; oldPartitionID = cells[cellIndex2].partitionID; for (cellIndex = 0; cellIndex < arraySize; cellIndex++) { if (cells[cellIndex].partitionID == oldPartitionID) { cells[cellIndex].partitionID = newPartitionID; } } numberOfPartitions--; } } switch (uirand() % 6) { case 0: lastCellIndex = (((uirand() % sizeY) * sizeX) + ((uirand() % sizeZ) * (sizeX * sizeY))); firstCellIndex = (((uirand() % sizeY) * sizeX) + ((uirand() % sizeZ) * (sizeX * sizeY)) + (sizeX - 1)); cells[lastCellIndex].leftWall = NO; break; case 1: lastCellIndex = (((uirand() % sizeY) * sizeX) + ((uirand() % sizeZ) * (sizeX * sizeY)) + (sizeX - 1)); firstCellIndex = (((uirand() % sizeY) * sizeX) + ((uirand() % sizeZ) * (sizeX * sizeY))); cells[lastCellIndex].rightWall = NO; break; case 2: lastCellIndex = (((uirand() % sizeZ) * (sizeX * sizeY)) + (uirand() % sizeX)); firstCellIndex = (((uirand() % sizeZ) * (sizeX * sizeY)) + ((sizeY - 1) * sizeX) + (uirand() % sizeX)); cells[lastCellIndex].bottomWall = NO; break; case 3: lastCellIndex = (((uirand() % sizeZ) * (sizeX * sizeY)) + ((sizeY - 1) * sizeX) + (uirand() % sizeX)); firstCellIndex = (((uirand() % sizeZ) * (sizeX * sizeY)) + (uirand() % sizeX)); cells[lastCellIndex].topWall = NO; break; case 4: lastCellIndex = (((uirand() % sizeY) * sizeX) + (uirand() % sizeX)); firstCellIndex = ((((sizeZ - 1) * (sizeX * sizeY)) + (uirand() % sizeY) * sizeX) + (uirand() % sizeX)); cells[lastCellIndex].backWall = NO; break; case 5: lastCellIndex = ((((sizeZ - 1) * (sizeX * sizeY)) + (uirand() % sizeY) * sizeX) + (uirand() % sizeX)); firstCellIndex = (((uirand() % sizeY) * sizeX) + (uirand() % sizeX)); cells[lastCellIndex].frontWall = NO; break; } } - (int) cellIndexForGridPositionX: (int) x Y: (int) y Z: (int) z { return ((z * sizeX * sizeY) + (y * sizeX) + x); } - (IntVector) gridPositionForCellIndex: (int) cellIndex { IntVector position; position.x = (cellIndex % sizeX); position.y = ((cellIndex / sizeX) % sizeY); position.z = (((cellIndex / sizeY) / sizeX) % sizeZ); return position; } - (Vector) spatialPositionForCellIndex: (int) cellIndex { Vector position; position.x = ((CELL_SIZE * (cellIndex % sizeX)) + HALF_CELL_SIZE); position.y = ((CELL_SIZE * ((cellIndex / sizeX) % sizeY)) + HALF_CELL_SIZE); position.z = ((CELL_SIZE * (((cellIndex / sizeY) / sizeX) % sizeZ)) + HALF_CELL_SIZE); return position; } - (int) firstCellIndex { return firstCellIndex; } - (int) lastCellIndex { return lastCellIndex; } - (MazeCell *) cellAtIndex: (int) cellIndex { return &cells[cellIndex]; } - (void) draw { int cellIndexX, cellIndexY, cellIndexZ, cellIndex; Vector position; GLfloat vertices[12]; GLfloat colors[16]; glEnable(GL_POLYGON_OFFSET_FILL); glPolygonOffset(1.0f, 1.0f); glVertexPointer(3, GL_FLOAT, 0, vertices); glEnableClientState(GL_VERTEX_ARRAY); glColorPointer(4, GL_FLOAT, 0, colors); glEnableClientState(GL_COLOR_ARRAY); for (cellIndexZ = 0; cellIndexZ < sizeZ; cellIndexZ++) { for (cellIndexY = 0; cellIndexY < sizeY; cellIndexY++) { for (cellIndexX = 0; cellIndexX < sizeX; cellIndexX++) { cellIndex = ((cellIndexZ * sizeX * sizeY) + (cellIndexY * sizeX) + cellIndexX); position.x = ((CELL_SIZE * (cellIndex % sizeX)) + HALF_CELL_SIZE); position.y = ((CELL_SIZE * ((cellIndex / sizeX) % sizeY)) + HALF_CELL_SIZE); position.z = ((CELL_SIZE * (((cellIndex / sizeY) / sizeX) % sizeZ)) + HALF_CELL_SIZE); colors[0] = colors[4] = colors[8] = colors[12] = cells[cellIndex].red; colors[1] = colors[5] = colors[9] = colors[13] = cells[cellIndex].green; colors[2] = colors[6] = colors[10] = colors[14] = cells[cellIndex].blue; colors[3] = colors[7] = colors[11] = colors[15] = 1.0f; if (cells[cellIndex].leftWall) { vertices[0] = position.x - HALF_CELL_SIZE; vertices[1] = position.y - HALF_CELL_SIZE; vertices[2] = position.z - HALF_CELL_SIZE; vertices[3] = position.x - HALF_CELL_SIZE; vertices[4] = position.y + HALF_CELL_SIZE; vertices[5] = position.z - HALF_CELL_SIZE; vertices[6] = position.x - HALF_CELL_SIZE; vertices[7] = position.y + HALF_CELL_SIZE; vertices[8] = position.z + HALF_CELL_SIZE; vertices[9] = position.x - HALF_CELL_SIZE; vertices[10] = position.y - HALF_CELL_SIZE; vertices[11] = position.z + HALF_CELL_SIZE; glDrawArrays(GL_TRIANGLE_FAN, 0, 4); } if (cells[cellIndex].rightWall) { vertices[0] = position.x + HALF_CELL_SIZE; vertices[1] = position.y - HALF_CELL_SIZE; vertices[2] = position.z - HALF_CELL_SIZE; vertices[3] = position.x + HALF_CELL_SIZE; vertices[4] = position.y - HALF_CELL_SIZE; vertices[5] = position.z + HALF_CELL_SIZE; vertices[6] = position.x + HALF_CELL_SIZE; vertices[7] = position.y + HALF_CELL_SIZE; vertices[8] = position.z + HALF_CELL_SIZE; vertices[9] = position.x + HALF_CELL_SIZE; vertices[10] = position.y + HALF_CELL_SIZE; vertices[11] = position.z - HALF_CELL_SIZE; glDrawArrays(GL_TRIANGLE_FAN, 0, 4); } if (cells[cellIndex].bottomWall) { vertices[0] = position.x - HALF_CELL_SIZE; vertices[1] = position.y - HALF_CELL_SIZE; vertices[2] = position.z - HALF_CELL_SIZE; vertices[3] = position.x - HALF_CELL_SIZE; vertices[4] = position.y - HALF_CELL_SIZE; vertices[5] = position.z + HALF_CELL_SIZE; vertices[6] = position.x + HALF_CELL_SIZE; vertices[7] = position.y - HALF_CELL_SIZE; vertices[8] = position.z + HALF_CELL_SIZE; vertices[9] = position.x + HALF_CELL_SIZE; vertices[10] = position.y - HALF_CELL_SIZE; vertices[11] = position.z - HALF_CELL_SIZE; glDrawArrays(GL_TRIANGLE_FAN, 0, 4); } if (cells[cellIndex].topWall) { vertices[0] = position.x - HALF_CELL_SIZE; vertices[1] = position.y + HALF_CELL_SIZE; vertices[2] = position.z - HALF_CELL_SIZE; vertices[3] = position.x + HALF_CELL_SIZE; vertices[4] = position.y + HALF_CELL_SIZE; vertices[5] = position.z - HALF_CELL_SIZE; vertices[6] = position.x + HALF_CELL_SIZE; vertices[7] = position.y + HALF_CELL_SIZE; vertices[8] = position.z + HALF_CELL_SIZE; vertices[9] = position.x - HALF_CELL_SIZE; vertices[10] = position.y + HALF_CELL_SIZE; vertices[11] = position.z + HALF_CELL_SIZE; glDrawArrays(GL_TRIANGLE_FAN, 0, 4); } if (cells[cellIndex].backWall) { vertices[0] = position.x - HALF_CELL_SIZE; vertices[1] = position.y - HALF_CELL_SIZE; vertices[2] = position.z - HALF_CELL_SIZE; vertices[3] = position.x + HALF_CELL_SIZE; vertices[4] = position.y - HALF_CELL_SIZE; vertices[5] = position.z - HALF_CELL_SIZE; vertices[6] = position.x + HALF_CELL_SIZE; vertices[7] = position.y + HALF_CELL_SIZE; vertices[8] = position.z - HALF_CELL_SIZE; vertices[9] = position.x - HALF_CELL_SIZE; vertices[10] = position.y + HALF_CELL_SIZE; vertices[11] = position.z - HALF_CELL_SIZE; glDrawArrays(GL_TRIANGLE_FAN, 0, 4); } if (cells[cellIndex].frontWall) { vertices[0] = position.x - HALF_CELL_SIZE; vertices[1] = position.y - HALF_CELL_SIZE; vertices[2] = position.z + HALF_CELL_SIZE; vertices[3] = position.x - HALF_CELL_SIZE; vertices[4] = position.y + HALF_CELL_SIZE; vertices[5] = position.z + HALF_CELL_SIZE; vertices[6] = position.x + HALF_CELL_SIZE; vertices[7] = position.y + HALF_CELL_SIZE; vertices[8] = position.z + HALF_CELL_SIZE; vertices[9] = position.x + HALF_CELL_SIZE; vertices[10] = position.y - HALF_CELL_SIZE; vertices[11] = position.z + HALF_CELL_SIZE; glDrawArrays(GL_TRIANGLE_FAN, 0, 4); } } } } glPolygonOffset(0.0f, 0.0f); glDisable(GL_POLYGON_OFFSET_FILL); glLineWidth(5.0); colors[0] = colors[4] = colors[8] = colors[12] = 0.0f; colors[1] = colors[5] = colors[9] = colors[13] = 0.0f; colors[2] = colors[6] = colors[10] = colors[14] = 0.0f; colors[3] = colors[7] = colors[11] = colors[15] = 1.0f; for (cellIndexZ = 0; cellIndexZ < sizeZ; cellIndexZ++) { for (cellIndexY = 0; cellIndexY < sizeY; cellIndexY++) { for (cellIndexX = 0; cellIndexX < sizeX; cellIndexX++) { cellIndex = ((cellIndexZ * sizeX * sizeY) + (cellIndexY * sizeX) + cellIndexX); position.x = ((CELL_SIZE * (cellIndex % sizeX)) + HALF_CELL_SIZE); position.y = ((CELL_SIZE * ((cellIndex / sizeX) % sizeY)) + HALF_CELL_SIZE); position.z = ((CELL_SIZE * (((cellIndex / sizeY) / sizeX) % sizeZ)) + HALF_CELL_SIZE); if (cells[cellIndex].leftWall) { vertices[0] = position.x - HALF_CELL_SIZE; vertices[1] = position.y - HALF_CELL_SIZE; vertices[2] = position.z - HALF_CELL_SIZE; vertices[3] = position.x - HALF_CELL_SIZE; vertices[4] = position.y + HALF_CELL_SIZE; vertices[5] = position.z - HALF_CELL_SIZE; vertices[6] = position.x - HALF_CELL_SIZE; vertices[7] = position.y + HALF_CELL_SIZE; vertices[8] = position.z + HALF_CELL_SIZE; vertices[9] = position.x - HALF_CELL_SIZE; vertices[10] = position.y - HALF_CELL_SIZE; vertices[11] = position.z + HALF_CELL_SIZE; glDrawArrays(GL_LINE_LOOP, 0, 4); } if (cells[cellIndex].rightWall) { vertices[0] = position.x + HALF_CELL_SIZE; vertices[1] = position.y - HALF_CELL_SIZE; vertices[2] = position.z - HALF_CELL_SIZE; vertices[3] = position.x + HALF_CELL_SIZE; vertices[4] = position.y - HALF_CELL_SIZE; vertices[5] = position.z + HALF_CELL_SIZE; vertices[6] = position.x + HALF_CELL_SIZE; vertices[7] = position.y + HALF_CELL_SIZE; vertices[8] = position.z + HALF_CELL_SIZE; vertices[9] = position.x + HALF_CELL_SIZE; vertices[10] = position.y + HALF_CELL_SIZE; vertices[11] = position.z - HALF_CELL_SIZE; glDrawArrays(GL_LINE_LOOP, 0, 4); } if (cells[cellIndex].bottomWall) { vertices[0] = position.x - HALF_CELL_SIZE; vertices[1] = position.y - HALF_CELL_SIZE; vertices[2] = position.z - HALF_CELL_SIZE; vertices[3] = position.x - HALF_CELL_SIZE; vertices[4] = position.y - HALF_CELL_SIZE; vertices[5] = position.z + HALF_CELL_SIZE; vertices[6] = position.x + HALF_CELL_SIZE; vertices[7] = position.y - HALF_CELL_SIZE; vertices[8] = position.z + HALF_CELL_SIZE; vertices[9] = position.x + HALF_CELL_SIZE; vertices[10] = position.y - HALF_CELL_SIZE; vertices[11] = position.z - HALF_CELL_SIZE; glDrawArrays(GL_LINE_LOOP, 0, 4); } if (cells[cellIndex].topWall) { vertices[0] = position.x - HALF_CELL_SIZE; vertices[1] = position.y + HALF_CELL_SIZE; vertices[2] = position.z - HALF_CELL_SIZE; vertices[3] = position.x + HALF_CELL_SIZE; vertices[4] = position.y + HALF_CELL_SIZE; vertices[5] = position.z - HALF_CELL_SIZE; vertices[6] = position.x + HALF_CELL_SIZE; vertices[7] = position.y + HALF_CELL_SIZE; vertices[8] = position.z + HALF_CELL_SIZE; vertices[9] = position.x - HALF_CELL_SIZE; vertices[10] = position.y + HALF_CELL_SIZE; vertices[11] = position.z + HALF_CELL_SIZE; glDrawArrays(GL_LINE_LOOP, 0, 4); } if (cells[cellIndex].backWall) { vertices[0] = position.x - HALF_CELL_SIZE; vertices[1] = position.y - HALF_CELL_SIZE; vertices[2] = position.z - HALF_CELL_SIZE; vertices[3] = position.x + HALF_CELL_SIZE; vertices[4] = position.y - HALF_CELL_SIZE; vertices[5] = position.z - HALF_CELL_SIZE; vertices[6] = position.x + HALF_CELL_SIZE; vertices[7] = position.y + HALF_CELL_SIZE; vertices[8] = position.z - HALF_CELL_SIZE; vertices[9] = position.x - HALF_CELL_SIZE; vertices[10] = position.y + HALF_CELL_SIZE; vertices[11] = position.z - HALF_CELL_SIZE; glDrawArrays(GL_LINE_LOOP, 0, 4); } if (cells[cellIndex].frontWall) { vertices[0] = position.x - HALF_CELL_SIZE; vertices[1] = position.y - HALF_CELL_SIZE; vertices[2] = position.z + HALF_CELL_SIZE; vertices[3] = position.x - HALF_CELL_SIZE; vertices[4] = position.y + HALF_CELL_SIZE; vertices[5] = position.z + HALF_CELL_SIZE; vertices[6] = position.x + HALF_CELL_SIZE; vertices[7] = position.y + HALF_CELL_SIZE; vertices[8] = position.z + HALF_CELL_SIZE; vertices[9] = position.x + HALF_CELL_SIZE; vertices[10] = position.y - HALF_CELL_SIZE; vertices[11] = position.z + HALF_CELL_SIZE; glDrawArrays(GL_LINE_LOOP, 0, 4); } } } } } @end