// Cloned by Singireddy bhavana on 8 Nov 2024 from World "New World (clone by Singireddy bhavana) (clone by Singireddy bhavana) (clone by Singireddy bhavana)" by Singireddy bhavana
// Please leave this clone trail here.
// Cloned by Singireddy bhavana on 8 Nov 2024 from World "New World (clone by Singireddy bhavana) (clone by Singireddy bhavana)" by Singireddy bhavana
// Please leave this clone trail here.
// Cloned by Singireddy bhavana on 8 Nov 2024 from World "New World (clone by Singireddy bhavana)" by Singireddy bhavana
// Please leave this clone trail here.
// Cloned by Singireddy bhavana on 8 Nov 2024 from World "New World" by Singireddy bhavana
// Please leave this clone trail here.
// Cloned by bhavana singireddy on 8 Nov 2024 from World "2D traffic World with "autonomous cars" using A* pathfinding" by singireddy bhavana
// Please leave this clone trail here.
//---- normal P5 code -------------------------------------------------------
// Set up global variables for the grid, cars, and other settings
let cols = 20; // Number of columns in the grid
let rows = 20; // Number of rows in the grid
let grid = []; // 2D array for the grid structure
let cellSize = 35; // Size of each grid cell
let cars = []; // Array to hold car objects
let simulationRunning = true; // Automatically start the simulation
let moveInterval = 15; // Number of frames to wait between moves
// Array of colors for the cars
const carColors = ["#FF5733", "#33FF57", "#3357FF", "#FF33A8"];
// Function to set up the canvas and initialize the grid and cars
function setup()
{
createCanvas(cols * cellSize, rows * cellSize); // Setting canvas size
frameRate(30); // Setting a moderate frame rate to control overall speed
initializeGrid(); // Initializing the grid structure
placeCars(4); // Placing 4 cars in random start and end positions
drawGrid(); // Drawing the grid layout
}
// Function to continuously draw the simulation
function draw()
{
if (!simulationRunning) return; // Only run if simulation is active
background(240); // Light background color
drawGrid(); // Draw the grid with streets and blocks
// Move and display each car at the specified interval
if (frameCount % moveInterval === 0) {
cars.forEach(car => {
car.move();
});
}
// Display each car
cars.forEach(car => {
car.display();
});
}
// Function to initialize the grid with streets and blocks
function initializeGrid() {
for (let i = 0; i < cols; i++) {
grid[i] = [];
for (let j = 0; j < rows; j++) {
// Define streets: every second row and column is a street
if (i % 2 === 0 || j % 2 === 0) {
grid[i][j] = { x: i, y: j, isStreet: true }; // Street cell
} else {
grid[i][j] = { x: i, y: j, isStreet: false }; // Block cell
}
}
}
}
// Function to draw the grid layout
function drawGrid() {
for (let i = 0; i < cols; i++) {
for (let j = 0; j < rows; j++) {
if (grid[i][j].isStreet) {
fill(220); // Light gray for streets
stroke(180); // Darker gray for street edges
} else {
fill(50); // Dark gray for blocks
stroke(100); // Lighter edge for blocks
}
rect(i * cellSize, j * cellSize, cellSize, cellSize);
// Draw intersections as special markers
if (grid[i][j].isStreet && i % 2 === 0 && j % 2 === 0) {
fill(255, 255, 100); // Yellow for intersections
ellipse((i + 0.5) * cellSize, (j + 0.5) * cellSize, cellSize * 0.3, cellSize * 0.3);
}
}
}
}
// Class defining car properties and methods
class Car {
constructor(x, y, destination, color) {
this.x = x;
this.y = y;
this.destination = destination;
this.path = [];
this.color = color;
this.waitCounter = 0;
this.findPath(); // Initial path calculation
}
// Calculate path using A* algorithm
findPath() {
this.path = aStarPath(this.x, this.y, this.destination.x, this.destination.y);
}
// Move the car along its path
move() {
if (this.path.length > 0) {
let nextStep = this.path[0];
if (!isCarBlocking(this, nextStep.x, nextStep.y)) {
this.path.shift(); // Move to next step if not blocked
this.x = nextStep.x;
this.y = nextStep.y;
this.waitCounter = 0;
} else {
this.waitCounter++; // Increase wait time if blocked
if (this.waitCounter > 5) {
this.findPath(); // Recalculate path if waiting too long
this.waitCounter = 0;
}
}
}
}
// Display the car on the grid
display() {
fill(this.color);
noStroke();
ellipse((this.x + 0.5) * cellSize, (this.y + 0.5) * cellSize, cellSize * 0.6, cellSize * 0.6);
}
}
// Place a given number of cars at random start and destination points
function placeCars(numCars) {
for (let i = 0; i < numCars; i++) {
let startX, startY, destX, destY;
do {
startX = floor(random(cols));
startY = floor(random(rows));
destX = floor(random(cols));
destY = floor(random(rows));
} while (!grid[startX][startY].isStreet || !grid[destX][destY].isStreet || (startX === destX && startY === destY));
let car = new Car(startX, startY, { x: destX, y: destY }, carColors[i % carColors.length]);
car.findPath();
cars.push(car);
}
}
// A* algorithm to calculate path
function aStarPath(startX, startY, goalX, goalY) {
let openSet = [{ x: startX, y: startY, g: 0, h: heuristic(startX, startY, goalX, goalY) }];
let cameFrom = {};
let closedSet = new Set();
while (openSet.length > 0) {
openSet.sort((a, b) => (a.g + a.h) - (b.g + b.h));
let current = openSet.shift();
if (current.x === goalX && current.y === goalY) {
return reconstructPath(cameFrom, current);
}
closedSet.add(`${current.x},${current.y}`);
let neighbors = getNeighbors(current);
for (let neighbor of neighbors) {
if (closedSet.has(`${neighbor.x},${neighbor.y}`) || !grid[neighbor.x][neighbor.y].isStreet) {
continue;
}
let gScore = current.g + 1;
let hScore = heuristic(neighbor.x, neighbor.y, goalX, goalY);
let openNode = openSet.find(n => n.x === neighbor.x && n.y === neighbor.y);
if (!openNode || gScore < openNode.g) {
cameFrom[`${neighbor.x},${neighbor.y}`] = current;
if (!openNode) {
openSet.push({ x: neighbor.x, y: neighbor.y, g: gScore, h: hScore });
}
}
}
}
return [];
}
// Reconstruct path from end to start
function reconstructPath(cameFrom, current) {
let totalPath = [current];
while (`${current.x},${current.y}` in cameFrom) {
current = cameFrom[`${current.x},${current.y}`];
totalPath.push(current);
}
return totalPath.reverse();
}
// Manhattan distance heuristic
function heuristic(x1, y1, x2, y2) {
return abs(x1 - x2) + abs(y1 - y2);
}
// Get neighboring cells
function getNeighbors(node) {
let directions = [
{ x: 1, y: 0 }, { x: -1, y: 0 },
{ x: 0, y: 1 }, { x: 0, y: -1 }
];
return directions
.map(dir => ({ x: node.x + dir.x, y: node.y + dir.y }))
.filter(n => n.x >= 0 && n.x < cols && n.y >= 0 && n.y < rows);
}
// Check if any car is blocking the path
function isCarBlocking(car, x, y) {
return cars.some(otherCar => otherCar !== car && otherCar.x === x && otherCar.y === y);
}