I've been trying to write some code to generate a maze of any given size (made up of 32x32 tiles), but have run into an odd issue with the rendering code, in that only square mazes will be textured correctly.

I have a single .png file with all possible wall textures, and the floor texture, and dependent on the placement of walls around the currently selected wall during the texturing methods, the correct part of this .png should be selected to make walls blend together nicely. However, as mentioned before, this only works with square mazes (note, rendering is being done with vertex buffer objexts).

Here's the code for generating the maze (currently, it just randomly fills the space with walls, I plan to adjust this part to actually generate a solvable maze once I fix this issue):

public void run() { // The maze is part of a thread called World, which runs alongside a Renderer thread
    mazeWidth = 20;
    mazeHeight = 15;
    maze = new byte[mazeWidth][mazeHeight];
}

public static void setUpMaze() {
    for (int x = 0; x < mazeWidth; x++) {
        for (int y = 0; y < mazeHeight; y++) {
            // TODO Make proper maze generation code
            maze[x][y] = (byte) mazeGenerator.nextInt(2);
        }
    }
}

The code to generate the vertices for the triangles to be drawn:

private float[] getMazeGrid() { // The 12 comes from the number of coordinates needed to define a square/single tile - 2 triangles, 6 vertices, 2 coordinates per vertex
    float[] mazeGrid = new float[12 * World.mazeWidth * World.mazeHeight];
    int yOffset = 0;
    int xOffset = 0;
        // The if statements adjust the minimum x/y coordinates for each tile, the for iterates through the tiles
        for (int i = 0; i < World.mazeWidth * World.mazeHeight; i++) {
            if (i % World.mazeWidth == 0) {
                xOffset = 0;
            } else {
                xOffset += 32;
            }
            if (i % World.mazeWidth == 0 && i != 0) {
                yOffset += 32;
            }
            // The code below defines one square of the grid
            mazeGrid[12 * i + 0] = xOffset;
            mazeGrid[12 * i + 1] = yOffset;
            mazeGrid[12 * i + 2] = xOffset;
            mazeGrid[12 * i + 3] = yOffset + 32;
            mazeGrid[12 * i + 4] = xOffset + 32;
            mazeGrid[12 * i + 5] = yOffset + 32;
            mazeGrid[12 * i + 6] = xOffset + 32;
            mazeGrid[12 * i + 7] = yOffset + 32;
            mazeGrid[12 * i + 8] = xOffset + 32;
            mazeGrid[12 * i + 9] = yOffset;
            mazeGrid[12 * i + 10] = xOffset;
            mazeGrid[12 * i + 11] = yOffset;                
        }
    return mazeGrid;
}

And the code for determining which part of the texture should be used:

private float[] getTexCoords(int x, int y) {
    texNumKey = 0;
    if (World.maze[x][y] == 1) {
        if (y > 0) {
            if (World.maze[x][y - 1] == 1) texNumKey += 1;
        }
        if (x > 0) {
            if (World.maze[x - 1][y] == 1) texNumKey += 2;
        }
        if (x < World.mazeWidth - 1) {
            if (World.maze[x + 1][y] == 1) texNumKey += 4;
        }
        if (y < World.mazeHeight - 1) {
            if (World.maze[x][y + 1] == 1) texNumKey += 8;
        }
    } else if (World.maze[x][y] == 0) {
        texNumKey = 16;
    }
    return texMap.get(texNumKey);
}

NB: texMap is a HashMap which contains float arrays with texture coordinates to be used by the texture coordinate buffer, keyed with a number from 0-16. The code above iterates through the grid and checks the spaces around the current tile, and selects the correct texture coordinates for that wall type.

Finally, the vertex buffer object code - setting up the VBOs:

public void setUp() {
    initialiseTextureMap();

    vertexData = BufferUtils.createFloatBuffer(12 * World.mazeWidth * World.mazeHeight);
    vertexData.put(getMazeGrid());
    vertexData.flip();

    textureData = BufferUtils.createFloatBuffer(12 * World.mazeWidth * World.mazeHeight);
    for (int x = 0; x < World.mazeWidth; x++) {
        for (int y = 0; y < World.mazeHeight; y++) {
            textureData.put(getTexCoords(x, y));
        }
    }
    textureData.flip();

    vboVertexHandle = glGenBuffers();
    glBindBuffer(GL_ARRAY_BUFFER, vboVertexHandle);
    glBufferData(GL_ARRAY_BUFFER, vertexData, GL_STATIC_DRAW);
    glBindBuffer(GL_ARRAY_BUFFER, 0);

    vboTextureCoordHandle = glGenBuffers();
    glBindBuffer(GL_ARRAY_BUFFER, vboTextureCoordHandle);
    glBufferData(GL_ARRAY_BUFFER, textureData, GL_STATIC_DRAW);
    glBindBuffer(GL_ARRAY_BUFFER, 0);
}

And drawing the VBOs:

public void draw() {            // Draws the entity
    glBindTexture(GL_TEXTURE_2D, loadTexture(this.textureKey).getTextureID());

    glBindBuffer(GL_ARRAY_BUFFER, this.vboVertexHandle);
    glVertexPointer(2, GL_FLOAT, 0, 0);

    glBindBuffer(GL_ARRAY_BUFFER, this.vboTextureCoordHandle);
    glTexCoordPointer(2, GL_FLOAT, 0, 0);

    glEnableClientState(GL_VERTEX_ARRAY);
    glEnableClientState(GL_TEXTURE_COORD_ARRAY);
    glDrawArrays(GL_TRIANGLES, 0, 12 * World.mazeWidth * World.mazeHeight);
    glDisableClientState(GL_TEXTURE_COORD_ARRAY);
    glDisableClientState(GL_VERTEX_ARRAY);

    glBindBuffer(GL_ARRAY_BUFFER, 0);
}

Most unexplained variable names should be fairly self explanatory, they are defined in the abstract superclass, or in the "Maze" class constructor.

So, for clarity, the above code works perfectly when I set the values of mazeWidth, and mazeHeight to the same value as one another, but if they are different, then textures are not assigned to tiles correctly - here is are examples of the code working, and failing, the top is a 10 x 10 maze, and the bottom 10 x 11: Maze Examples

EDIT: After switching the x and y for loops in the texture coordinate buffer setup: Maze Example 2

If you need any other information/I've missed something important out, let me know.

有帮助吗?

解决方案

Your problem is the combination of the for loops for x and y and the push method. You were looping down columns first, rather than across rows first. - the put assumes row first looping.

This will fix the problem quickly:

for (int y = 0; y < World.mazeHeight; y++) {
    for (int x = 0; x < World.mazeWidth; x++) {
       textureData.put(getTexCoords(x, y));
    }
}

Your texture selection will have to be updated too, mirrored on the diagonal. For example, if you were selecting a texture with the path going South, it will now be drawn with the path going East.

其他提示

in setup

try changing

for (int x = 0; x < World.mazeWidth; x++) {
    for (int y = 0; y < World.mazeHeight; y++) {
        textureData.put(getTexCoords(x, y));
    }
}

to

for (int y = 0; y < World.mazeHeight; y++) {
    for (int x = 0; x < World.mazeWidth; x++) {
        textureData.put(getTexCoords(x, y));
    }
}
许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top