//Trial Car
let cols, rows;
let grid = [];
let cars = [];
let cellSize = 50;
let canvas = 700;
//Initialising for Car figures
let carColor;
let posX, posY;
let carWidth = 50;
let carHeight = carWidth/2.5;
let wheelWidth = carWidth * 0.2;
let wheelHeight = wheelWidth/2.5;
let velocity=0;
let carFigs = [];
function setup() {
frameRate (2);
createCanvas(700, 700);
cols = width / cellSize; //14
rows = height / cellSize;//14
background(220);
drawGrid();
// Initialize the grid
for (let i = 0; i < cols; i++) {
grid[i] = [];
for (let j = 0; j < rows; j++) {
grid[i][j] = 0; // 0 means empty cell
}
}
// Create multiple cars with random start and goal positions
for (let i = 0; i < 4; i++) {
let start = randomPosition();
//console.log("start "+start);
let goal;
do {
goal = randomPosition();
//console.log("end "+goal);
} while (arraysEqual(start, goal));
carColor = color(random(255), random(255), random(255));
console.log("color and start "+start +" "+ carColor);
cars.push(new Car(i, start, goal, carColor));
//setup the car
posX = start[0];//width/2;
posY = start[1];//height/2;
carFigs.push(new CarFigure(i,posX,posY,carColor));
}
for(let fig of carFigs){
console.log("fig");
fig.drawCarFigure();
}
}
function draw() {
let positions = cars.map(car => `${car.position}`);//current position of all cars, eg positions=["2,3", "5,4", "1,1"]
for (let car of cars) {
if (!car.path.length || arraysEqual(car.position, car.goal)) {
//car.recalculatePath();
} else {
if (!positions.includes(`${car.path[1]}`)) {// if car's next move doesn't have another car there, then no problem move
//car.move();
} else {
//car.recalculatePath();// if car's next move has another car there, then recalculate
}
}
car.draw();
}
}
function drawGrid() { //Set
//Black Grids and Border
stroke("black");
strokeWeight(3);
for (let i = 0; i < cols; i++) {
for (let j = 0; j < rows; j++) {
noFill();
rect(i * cellSize, j * cellSize, cellSize, cellSize); //cellsize=50
}
}
//White Dotted Lines
stroke("white");
strokeWeight(3);
for (let i = 0; i <= cellSize*cols; i+=cellSize) {//cellsize=50
var interval=25;
var interval2 = 50;
for (let j = 0; j <= cellSize*rows; j+=cellSize) {
noFill();
line(i, interval, j,interval);
line(i, interval2, j,interval2);
setLineDash([5, 5]);
interval+=50;
interval2+=50;
}
}
}
// Utility function to draw dotted lines
function setLineDash(list) {
drawingContext.setLineDash(list);
}
// Utility function to generate a random position
function randomPosition() {
return [floor(random(cols)), floor(random(rows))];
}
class Car {
constructor(id, start, goal, col) {
this.id = id;
this.position = start;
this.goal = goal;
this.color = col;
this.path = [];
this.drawDestinationGrid();
this.recalculatePath();
}
recalculatePath() {
this.path = aStar(this.position, this.goal);
}
move() {
if (this.path.length > 1) {
this.position = this.path[1]; // Move to the next step
this.path.shift();
}
}
draw() {
//fill(this.color);
//rect(this.position[0] * cellSize, this.position[1] * cellSize, cellSize, cellSize);
}
drawDestinationGrid() { //Not working
//To highlight the destination of each car
//stroke(this.color);
//strokeWeight(3);
//rect(this.position[0] * cellSize, this.position[1] * cellSize, cellSize/2, cellSize/2); //cellsize=50
}
}
class CarFigure {
constructor(id, posX, posY, carColor) {
this.id = id;
this.posX = posX;
this.posY = posY;
this.carColor = carColor;
this.drawCarFigure();
}
drawCarFigure(){
//car body
fill(this.carColor);
noStroke();
console.log("pos x and y: "+this.posX + " "+ this.posY );
rect(this.posX * cellSize, this.posY * cellSize, cellSize, cellSize);
//rect(this.posX, this.posY, this.posX+1, this.posY+1);
fill(0);
//left top wheel
rect(this.posX-carWidth/2 + wheelWidth/2, this.posY - carHeight/2-wheelHeight/2, wheelWidth, wheelHeight);
//right top wheel
rect(this.posX+carWidth/2 - wheelWidth/2, this.posY - carHeight/2-wheelHeight/2, wheelWidth, wheelHeight);
//left bottom wheel
rect(this.posX-carWidth/2 + wheelWidth/2, this.posY + carHeight/2+wheelHeight/2, wheelWidth, wheelHeight);
//right bottom wheel
rect(this.posX+carWidth/2 - wheelWidth/2, this.posY + carHeight/2+wheelHeight/2, wheelWidth, wheelHeight);
}
/*move() {
if (this.path.length > 1) {
this.position = this.path[1]; // Move to the next step
this.path.shift();
}
}
draw() {
fill(this.color);
rect(this.position[0] * cellSize, this.position[1] * cellSize, cellSize, cellSize);
}
drawDestinationGrid() { //Not working
//To highlight the destination of each car
stroke(this.color);
strokeWeight(3);
rect(this.position[0] * cellSize, this.position[1] * cellSize, cellSize, cellSize); //cellsize=50
}*/
}
function aStar(start, goal) {
let openList = [];
let closedList = new Set();
let gScore = {};
let fScore = {};
let cameFrom = {};
gScore[`${start}`] = 0;
fScore[`${start}`] = heuristic(start, goal);
openList.push(start);
while (openList.length > 0) {
let current = openList.reduce((a, b) => (fScore[a] < fScore[b] ? a : b));
if (arraysEqual(current, goal)) {
return reconstructPath(cameFrom, current);
}
openList = openList.filter(node => !arraysEqual(node, current));
closedList.add(`${current}`);
for (let neighbor of getNeighbors(current)) {
if (closedList.has(`${neighbor}`) || cars.some(car => arraysEqual(car.position, neighbor))) continue;
let tentativeGScore = gScore[`${current}`] + 1;
if (tentativeGScore < (gScore[`${neighbor}`] || Infinity)) {
cameFrom[`${neighbor}`] = current;
gScore[`${neighbor}`] = tentativeGScore;
fScore[`${neighbor}`] = tentativeGScore + heuristic(neighbor, goal);
if (!openList.some(n => arraysEqual(n, neighbor))) {
openList.push(neighbor);
}
}
}
}
return [];
function heuristic([x1, y1], [x2, y2]) {
return abs(x1 - x2) + abs(y1 - y2);
}
function reconstructPath(cameFrom, current) {
let path = [current];
while (cameFrom[`${current}`]) {
current = cameFrom[`${current}`];
path.unshift(current);
}
return path;
}
function getNeighbors([x, y]) {
let neighbors = [
[x + 1, y], [x - 1, y],
[x, y + 1], [x, y - 1]
];
return neighbors.filter(([nx, ny]) => nx >= 0 && nx < cols && ny >= 0 && ny < rows);
}
}
function arraysEqual(a, b) {
return a[0] === b[0] && a[1] === b[1];
}