function makeEnemy(x, y) { return { t: "enemy", x, y, lastMove: millis(), isAlive: true, }; } function drawEnemies() { for (let enemi of enemies) { let dampingX = 0; let dampingY = 0; if (enemi.isMoving || !enemi.isAlive) { dampingX = Math.sin(millis() / (1800 / gameFrameRate)) * damping; dampingY = Math.cos(millis() / (1800 / gameFrameRate)) * damping; } textSize(cellSize / 1.2); if (enemi.isAlive) { text( "🦈", enemi.x + dampingX - halfCellSize, enemi.y + dampingY + yOffsetDraw - halfCellSize ); if(debug){fill(255, 0, 0); circle(enemi.x + dampingX, enemi.y + dampingY, 8);} } else { text( "💀", enemi.x - halfCellSize, enemi.y + dampingY + yOffsetDraw - halfCellSize ); } } } function moveEnemies() { const playerPosition = positionsToCellsIdx({ x: player1.x, y: player1.y, }); const playerReversPosition = [playerPosition.yi, playerPosition.xi]; for (let enemi of enemies) { const enemiPosition = positionsToCellsIdx({ x: enemi.x, y: enemi.y, }); const enemiReversPosition = [enemiPosition.yi, enemiPosition.xi]; let pathFindTimer = Math.floor(millis() / 100); pathFindTimer = pathFindTimer % 2; if (pathFindTimer === 0) { //const path = bfs(grid, enemiReversPosition, playerReversPosition); // fix this ////const path = findPath(grid, enemiReversPosition, playerReversPosition); } } } //function to judge if a cell is safe or not safeNeighbor = function (r, c) { if (r < 0 || r >= rows) return false; if (c < 0 || c >= cols) return false; if (grid[r][c] !== freePlace) return false; return true; }; //function to identify neighbors of current location exploreLocation = function (location) { let r = location.r; let c = location.c; let allNeighbors = []; //left if (safeNeighbor(r, c - 1)) allNeighbors.push({ r: r, c: c - 1 }); //right if (safeNeighbor(r, c + 1)) allNeighbors.push({ r: r, c: c + 1 }); //top if (safeNeighbor(r - 1, c)) allNeighbors.push({ r: r - 1, c: c }); //bottom if (safeNeighbor(r + 1, c)) allNeighbors.push({ r: r + 1, c: c }); return allNeighbors; }; //find path between two cells findPath = function (grid, start, end) { let gridMap = []; //var row = grid.length; //var col = grid[0].length; var location = { r: start[0], c: start[1], }; var queue = []; queue.push(location); while (queue.length) { var currentLocation = queue.shift(); if (currentLocation.r == end[0] && currentLocation.c == end[1]) { //return currentLocation; let paths = [currentLocation]; while (true) { let r = currentLocation.r; let c = currentLocation.c; let parent = grid[r][c].parent; if (parent == undefined) break; paths.push(parent); currentLocation = { r: parent.r, c: parent.c }; } return paths; } grid[currentLocation.r][currentLocation.c].state = "visited"; var neighbors = exploreLocation(currentLocation); for (neighbor of neighbors) { if (grid[neighbor.r][neighbor.c].state != "visited") { queue.push(neighbor); grid[neighbor.r][neighbor.c]["parent"] = currentLocation; } } } return false; }; //Code to traverse, and print path of route printPath = function (path) { let paths = [path]; while (true) { let r = path.r; let c = path.c; let parent = grid[r][c].parent; if (parent == undefined) break; paths.push(parent); path = { r: parent.r, c: parent.c }; } console.log(paths); }; /* // openAI: // Sure, here's an implementation of the breadth-first search algorithm in JavaScript for finding a // path between two points in a grid: // */ // function bfs(grid, start, end) { // //debugger; // const queue = [start]; // Initialize the queue with the starting point // const visited = new Set(); // Keep track of visited cells // const parent = new Map(); // Map each cell to its parent in the search tree // while (queue.length > 0) { // let curr = queue.shift(); // Take the first cell from the queue // visited.add(curr); // Mark it as visited // // Check if we've reached the end // if (curr[0] === end[0] && curr[1] === end[1]) { // // Trace back the path from the end to the start by following the parent pointers // let path = []; // let currParent = curr; // while (currParent !== undefined && currParent !== null) { // // test on undefined? // path.unshift(currParent); // currParent = parent.get(currParent); // } // return path; // } // // Add unvisited neighbors to the queue // let neighbors = getNeighbors(grid, curr[0], curr[1]); // for (const neighbor of neighbors) { // if (!visited.has(neighbor)) { // queue.push(neighbor); // parent.set(neighbor, curr); // } // } // } // // If we didn't find a path, return null // return null; // } // // Returns an array of unblocked neighbor cells of the given cell // function getNeighbors(grid, row, col) { // const numRows = grid.length; // const numCols = grid[0].length; // let neighbors = []; // if (row > 0 && grid[row - 1][col] === freePlace) { // neighbors.push([row - 1, col]); // } // if (col > 0 && grid[row][col - 1] === freePlace) { // neighbors.push([row, col - 1]); // } // if (row < numRows - 1 && grid[row + 1][col] === freePlace) { // neighbors.push([row + 1, col]); // } // if (col < numCols - 1 && grid[row][col + 1] === freePlace) { // neighbors.push([row, col + 1]); // } // return neighbors; // } /* Here, `grid` is a 2D array of objects representing the cells in the grid. Each object has a `blocked` property that is `true` if the cell is blocked and `false` otherwise. `start` and `end` are arrays representing the coordinates of the starting and ending cells, respectively. The function returns an array of cell coordinates representing the shortest path between the starting and ending cells, or `null` if no path exists. */ /* To use the breadth-first search algorithm to move an object in a grid to a target, you can follow these steps: 1. Create a grid object that represents the state of the grid. Each cell in the grid can be either empty or blocked. You can represent the grid as a 2D array of objects, where each object has a `blocked` property that is `true` if the cell is blocked and `false` otherwise. 2. Create an object that represents the state of the moving object. The object should have a `position` property that is a two-element array representing the current position of the object in the grid. 3. Define a target position that the object needs to reach. 4. Call the `bfs` function with the grid, the starting position of the object, and the target position. This will return an array of cell coordinates representing the shortest path between the starting position and the target position. 5. Move the object one step along the path at a time. For example, you can use `setInterval` to move the object every few milliseconds. The object should move to the next cell in the path until it reaches the target position. Here's some example code that demonstrates these steps: javascript */ // Define the grid // const grid = [ // [{ blocked: false }, { blocked: false }, { blocked: false }], // [{ blocked: false }, { blocked: true }, { blocked: false }], // [{ blocked: false }, { blocked: false }, { blocked: false }], // ]; // // Define the moving object // const object = { // position: [0, 0], // Starting position // }; // // Define the target position // const target = [2, 2]; // Find the shortest path from the object's position to the target //const path = bfs(grid, object.position, target); // Move the object along the path /* let i = 0; const interval = setInterval(() => { if (i < path.length - 1) { // Move the object to the next cell in the path object.position = path[i + 1]; i++; } else { // Stop the interval if the object has reached the target clearInterval(interval); } }, 1000); /* In this example, the `setInterval` function is called every 1000 milliseconds, or 1 second. You can adjust this value to make the object move faster or slower. Also, note that this example assumes that the object can only move to adjacent cells that are not blocked. If you want to allow the object to move diagonally or through blocked cells, you'll need to modify the `getNeighbors` function to include those cases. */