345 lines
9.0 KiB
JavaScript
345 lines
9.0 KiB
JavaScript
// Legend of grid case
|
|
|
|
const legend = {
|
|
empty: 0,
|
|
laser: 1,
|
|
coloredLaser: 2,
|
|
mirror: 3,
|
|
door: 4,
|
|
button: 5,
|
|
wall: 6,
|
|
demiWall: 7,
|
|
target: 8,
|
|
ligthLaser: 9,
|
|
}
|
|
|
|
// Grid test
|
|
|
|
let level1 = [
|
|
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
|
|
[0, 0, 3, 0, 0, 0, 8, 0, 0, 0, 0, 0, 0, 0, 0],
|
|
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
|
|
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
|
|
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
|
|
[0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0],
|
|
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
|
|
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
|
|
[1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0],
|
|
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
|
|
]
|
|
|
|
// Player position
|
|
let playerX = 0;
|
|
let playerY = 0;
|
|
|
|
// Function to save initial orientation of mirrors
|
|
let laserDirection = { dx: 0, dy: 0 };
|
|
let mirrorOrientations = {};
|
|
|
|
function initializeMirrorOrientations() {
|
|
mirrorOrientations = {}; // Reset
|
|
for (let y = 0; y < level1.length; y++) {
|
|
for (let x = 0; x < level1[y].length; x++) {
|
|
if (level1[y][x] === legend.mirror) {
|
|
mirrorOrientations[`${y},${x}`] = 0; // Default angle
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
// Function to print grid
|
|
let mirrorCoordinates = [];
|
|
|
|
function loadGrid() {
|
|
const mapDiv = document.getElementById("map"); // Div with map in DOM
|
|
mapDiv.innerHTML = "";
|
|
|
|
for (let y = 0; y < level1.length; y++) {
|
|
const lign = document.createElement("div");
|
|
lign.classList.add("lign");
|
|
|
|
for (let x = 0; x < level1[y].length; x++) {
|
|
const cell = document.createElement("div");
|
|
cell.classList.add("cell");
|
|
|
|
switch (level1[y][x]) {
|
|
case legend.empty:
|
|
cell.classList.add("empty");
|
|
break;
|
|
case legend.laser:
|
|
cell.classList.add("laser");
|
|
break;
|
|
case legend.coloredLaser:
|
|
cell.classList.add("colored-laser");
|
|
break;
|
|
case legend.mirror:
|
|
const currentAngle = mirrorOrientations[`${y},${x}`] || 0;
|
|
const btnMirror = document.createElement("button");
|
|
btnMirror.classList.add("btn-mirror");
|
|
btnMirror.style.transform = `rotate(${currentAngle}deg)`;
|
|
btnMirror.style.width = "100%";
|
|
cell.appendChild(btnMirror);
|
|
cell.classList.add("mirror");
|
|
break;
|
|
case legend.door:
|
|
cell.classList.add("door");
|
|
break;
|
|
case legend.button:
|
|
cell.classList.add("button");
|
|
break;
|
|
case legend.wall:
|
|
cell.classList.add("wall");
|
|
break;
|
|
case legend.demiWall:
|
|
cell.classList.add("demi-wall");
|
|
break;
|
|
case legend.target:
|
|
cell.classList.add("target");
|
|
break;
|
|
case legend.ligthLaser:
|
|
cell.classList.add("light-laser");
|
|
if (laserDirection.dx === 0) {
|
|
cell.classList.add("laser-vertical");
|
|
} else {
|
|
cell.classList.add("laser-horizontal");
|
|
}
|
|
break;
|
|
}
|
|
|
|
if (x === playerX && y === playerY) {
|
|
cell.classList.add("player-cursor");
|
|
}
|
|
|
|
lign.appendChild(cell);
|
|
}
|
|
|
|
mapDiv.appendChild(lign);
|
|
}
|
|
}
|
|
|
|
loadGrid();
|
|
|
|
// Function to rotate mirror
|
|
|
|
function rotateMirror(x, y) {
|
|
const coordKey = `${y},${x}`;
|
|
|
|
// See if it's a mirror
|
|
if (level1[y][x] !== legend.mirror) {
|
|
return
|
|
};
|
|
|
|
let currentAngle = mirrorOrientations[coordKey] || 0;
|
|
|
|
// Rotation
|
|
currentAngle = (currentAngle + 45) % 360;
|
|
|
|
// Save
|
|
mirrorOrientations[coordKey] = currentAngle;
|
|
|
|
// Print laser light
|
|
traceLaser(true);
|
|
}
|
|
|
|
|
|
// Function to trace
|
|
|
|
let isLevelFinished = false;
|
|
|
|
function traceLaser() {
|
|
// Reset light laser from previous trace
|
|
for (let y = 0; y < level1.length; y++) {
|
|
for (let x = 0; x < level1[y].length; x++) {
|
|
if (level1[y][x] === legend.ligthLaser) {
|
|
level1[y][x] = legend.empty;
|
|
}
|
|
}
|
|
}
|
|
|
|
let startLaserX;
|
|
let startLaserY;
|
|
|
|
// Search laser
|
|
for (let y = 0; y < level1.length; y++) {
|
|
for (let x = 0; x < level1[y].length; x++) {
|
|
if (level1[y][x] === legend.laser) {
|
|
startLaserX = x;
|
|
startLaserY = y;
|
|
laserDirection = { dx: 1, dy: 0 };
|
|
break;
|
|
}
|
|
}
|
|
if (startLaserX !== undefined) break;
|
|
}
|
|
|
|
// If laser not found -> return
|
|
if (startLaserX === undefined) {
|
|
return;
|
|
}
|
|
|
|
let currentX = startLaserX;
|
|
let currentY = startLaserY;
|
|
let laserActive = true;
|
|
const maxIterations = 1000; // Prevent infinite loops
|
|
let iterations = 0;
|
|
|
|
while (laserActive && iterations < maxIterations) {
|
|
iterations++;
|
|
|
|
currentX += laserDirection.dx;
|
|
currentY += laserDirection.dy;
|
|
|
|
// Out of bounds
|
|
if (currentX < 0 || currentX >= level1[0].length || currentY < 0 || currentY >= level1.length) {
|
|
laserActive = false;
|
|
break;
|
|
}
|
|
|
|
const cellType = level1[currentY][currentX];
|
|
|
|
switch (cellType) {
|
|
case legend.laser:
|
|
case legend.coloredLaser:
|
|
laserActive = false;
|
|
break;
|
|
|
|
case legend.empty:
|
|
level1[currentY][currentX] = legend.ligthLaser;
|
|
break;
|
|
|
|
case legend.target:
|
|
level1[currentY][currentX] = legend.ligthLaser;
|
|
laserActive = false;
|
|
isLevelFinished = true;
|
|
break;
|
|
|
|
case legend.mirror:
|
|
const mirrorAngle = mirrorOrientations[`${currentY},${currentX}`] || 0;
|
|
|
|
if (mirrorAngle === 0 || mirrorAngle === 180) {
|
|
laserDirection.dy = -laserDirection.dy;
|
|
} else {
|
|
if (mirrorAngle === 90 || mirrorAngle === 270) {
|
|
laserDirection.dx = -laserDirection.dx;
|
|
}
|
|
|
|
if (mirrorAngle === 45 || mirrorAngle === 225) {
|
|
const tempDx = laserDirection.dx;
|
|
laserDirection.dx = laserDirection.dy;
|
|
laserDirection.dy = tempDx;
|
|
}
|
|
|
|
if (mirrorAngle === 135 || mirrorAngle === 315) {
|
|
const tempDx = laserDirection.dx;
|
|
laserDirection.dx = -laserDirection.dy;
|
|
laserDirection.dy = -tempDx;
|
|
}
|
|
}
|
|
break;
|
|
|
|
case legend.wall:
|
|
laserActive = false;
|
|
break;
|
|
|
|
case legend.demiWall:
|
|
laserActive = false;
|
|
break;
|
|
|
|
case legend.door:
|
|
laserActive = false;
|
|
break;
|
|
|
|
case legend.button:
|
|
level1[currentY][currentX] = legend.ligthLaser;
|
|
laserActive = false;
|
|
break;
|
|
|
|
default:
|
|
level1[currentY][currentX] = legend.ligthLaser;
|
|
break;
|
|
}
|
|
}
|
|
|
|
loadGrid();
|
|
|
|
if (isLevelFinished) {
|
|
finish();
|
|
}
|
|
}
|
|
|
|
traceLaser();
|
|
|
|
// If level finishh -> call this function
|
|
function finish() {
|
|
setTimeout(() => {
|
|
alert("Réussi !");
|
|
}, 100);
|
|
}
|
|
|
|
|
|
// Get player inputs arrows, qwerty and azerty
|
|
|
|
document.addEventListener("keydown", (e) => {
|
|
|
|
// If level finish -> don't move
|
|
if (isLevelFinished === true) {
|
|
return;
|
|
}
|
|
|
|
switch (e.key) {
|
|
case "ArrowUp":
|
|
movePlayer(0, -1);
|
|
break;
|
|
case "w":
|
|
movePlayer(0, -1);
|
|
break;
|
|
case "z":
|
|
movePlayer(0, -1);
|
|
break;
|
|
case "ArrowDown":
|
|
movePlayer(0, 1);
|
|
break;
|
|
case "s":
|
|
movePlayer(0, 1);
|
|
break;
|
|
case "ArrowLeft":
|
|
movePlayer(-1, 0);
|
|
break;
|
|
case "a":
|
|
movePlayer(-1, 0);
|
|
break;
|
|
case "q":
|
|
movePlayer(-1, 0);
|
|
break;
|
|
case "ArrowRight":
|
|
movePlayer(1, 0);
|
|
break;
|
|
case "d":
|
|
movePlayer(1, 0);
|
|
break;
|
|
case "Enter":
|
|
rotateMirror(playerX, playerY);
|
|
break;
|
|
}
|
|
});
|
|
|
|
// Player move
|
|
|
|
function movePlayer(x, y) {
|
|
const newX = playerX + x;
|
|
const newY = playerY + y;
|
|
|
|
if (newX < 0 || newX >= level1[0].length) {
|
|
return
|
|
};
|
|
|
|
if (newY < 0 || newY >= level1.length) {
|
|
return
|
|
};
|
|
|
|
playerX = newX;
|
|
playerY = newY;
|
|
|
|
loadGrid();
|
|
} |