Thursday, 2 April 2020

From Maze to Dungeon

This post is mainly for readers of my book "Learn To Program, with Games and JavaScriptas it takes a maze generated using the code in the last post on this blog and converts a maze to an array suitable for use in the Ray Casting project featured in that book.

I added a text area control and another canvas to the HTML from the maze generating project plus a button to trigger the new code.

<body> <div id="dvViewer"> <canvas id="cvView"></canvas> <button id="btnCode">Generate Code</button> </div> <div> <textarea id="taCode" rows = "15" cols="80"></textarea> </div> <div> <canvas id="cvMap"></canvas> </div> <script src="main.js"></script> </body>

Then added two lines to the initialise() function to add an event listener to the button:

function initialise() { view.canvas = document.getElementById("cvView"); view.ctx = view.canvas.getContext("2d"); view.canvas.width = maze.cellsWide * (maze.side + maze.wallWidth) + maze.wallWidth; view.canvas.height = maze.cellsHigh * (maze.side + maze.wallWidth) + maze.wallWidth; let btn = document.getElementById("btnCode"); btn.addEventListener("mousedown", convert); buildMaze(); renderView(); }

The button mouse down event calls a function called convert() which takes the maze and generates JavaScript code to convert the maze to a two dimensional JavaScript array.

The convert() function calls another called codeRow() that generates two arrays for each row of cells in the maze. One generates a value of "1" for each wall to the side of a cell and the second manages the walls between the current row and the next (or edge of the maze).

function codeRow(row){ let cells = " [", floor = " ["; for(let j = 0; j < maze.cellsWide; j++){ if([row][j].left){ cells += "1,0,"; floor += "1,"; } else { cells += "0,0,"; floor += "1,"; } floor +=[row][j].down ? "1," : "0,"; } return cells + "1],\n" + floor + "1],\n"; }

The convert() function creates the array to which the codeRow() function contributes and outputs the generated JavaScript code to the text area control.

function convert(){ let tc = document.getElementById("taCode"); tc.value = "var grid1 = [\n"; tc.value += " [" + "1,".repeat(maze.cellsWide*2) + "1],\n"; for(let i = 0; i < maze.cellsHigh; i++){ tc.value += codeRow(i); } tc.value += " ];"; let gd = eval(tc.value.substr(12)); // Never use eval() at all ever drawMap(gd); }

The convert() function then does something that I would advise was not a good idea in any production code (but is OK here in a demonstrator) as it passes the array to the eval() function to convert the code into an actual array that can be accessed by the running JavaScript.

The array featured in the text area is passed to a function called drawMap() that is pretty similar to the one used in the book's Ray casting project.

function drawMap(grid) { let cvs = document.getElementById("cvMap"); let ctx = cvs.getContext("2d"); let height = grid.length; let width = grid[0].length; cvs.width = width * maze.side; cvs.height = height * maze.side; ctx.fillStyle = "grey"; for(let h = 0; h < height; h++){ for(let w = 0; w < width; w++){ if(grid[h][w] !== 0){ ctx.fillRect(w * maze.side, h * maze.side, maze.side, maze.side); } } } }

The code now takes a maze and creates a block of code as text ready to paste into a ray casting project and just to check we can show how that would be rendered within that project.



and finally

No comments:

Post a Comment