3 Commits

Author SHA1 Message Date
Sysy's
edea5e0972 Remove rotatorButton on lvl 1 2026-03-31 13:15:38 +02:00
Sysy's
f3809db72b Merge branch 'feature/grid' of https://git.ninolbt.com/Nono/Projet_48h into feature/grid 2026-03-31 13:12:34 +02:00
Sysy's
68b6493e50 Add rotator buttons and auto-rotating mirrors
Introduce a new rotator button tile and mirror auto-rotation feature. CSS adds styles for rotator buttons and locked mirror display. JS: add legend entry and rotatorButtons config, track activeRotatorButtons and rotatorIntervals, implement rotateMirrorStep, isMirrorControlledByButton, syncRotatorButtons and stopAllRotatorButtons; wire rotator behavior into traceLaser and loadGrid so rotator buttons activate intervals that rotate target mirrors automatically and lock out manual rotation. Refactor rotateMirror to reuse rotation step logic and ensure rotator intervals are cleared when advancing levels.
2026-03-31 13:11:30 +02:00
2 changed files with 132 additions and 27 deletions

View File

@@ -208,6 +208,14 @@ main {
background-position: center; background-position: center;
} }
.button-rotator {
background-color: #DADEEF;
background-image: url("../img/tiles/ButtonProfile.svg"), url("../img/tiles/Tuile.svg");
background-size: 100% 100%;
background-repeat: no-repeat;
background-position: center;
}
.button-active { .button-active {
opacity: 0.7; opacity: 0.7;
} }
@@ -308,6 +316,10 @@ main {
justify-content: center; justify-content: center;
} }
.btn-mirror-locked {
cursor: default;
}
.mirror-img { .mirror-img {
width: 80%; width: 80%;
height: 80%; height: 80%;

View File

@@ -20,6 +20,7 @@ const legend = {
cable: 16, cable: 16,
captorTurn: 17, captorTurn: 17,
cableVertical: 18, cableVertical: 18,
rotatorButton: 20,
}; };
const laserColors = { const laserColors = {
@@ -107,6 +108,9 @@ const doorGroups = {
"4,8": 2, "4,8": 2,
}; };
const rotatorButtons = {
};
let laserDirection = { dx: 0, dy: 0 }; let laserDirection = { dx: 0, dy: 0 };
let laserSegments = {}; let laserSegments = {};
let mirrorOrientations = {}; let mirrorOrientations = {};
@@ -114,6 +118,8 @@ let glassPlacements = {};
let activatedButtons = {}; let activatedButtons = {};
let openedDoors = {}; let openedDoors = {};
let isLevelFinished = false; let isLevelFinished = false;
let activeRotatorButtons = {};
let rotatorIntervals = {};
function getCurrentLevel() { function getCurrentLevel() {
return levels[currentLevelIndex]; return levels[currentLevelIndex];
@@ -196,6 +202,74 @@ function openDoorsFromButton(x, y) {
} }
} }
function getRotatorButtonConfig(x, y) {
return rotatorButtons[`${y},${x}`];
}
function isMirrorControlledByButton(x, y) {
const rotatorEntries = Object.values(rotatorButtons);
for (let i = 0; i < rotatorEntries.length; i++) {
const rotatorConfig = rotatorEntries[i];
if (rotatorConfig.mirrorX === x && rotatorConfig.mirrorY === y) {
return true;
}
}
return false;
}
function rotateMirrorStep(x, y, angleStep) {
const coordKey = `${y},${x}`;
if (getCurrentLevel()[y][x] !== legend.mirror) {
return;
}
let currentAngle = mirrorOrientations[coordKey] || 0;
currentAngle = (currentAngle + angleStep) % 360;
if (currentAngle < 0) {
currentAngle += 360;
}
mirrorOrientations[coordKey] = currentAngle;
}
function syncRotatorButtons() {
const rotatorKeys = Object.keys(rotatorButtons);
for (let i = 0; i < rotatorKeys.length; i++) {
const key = rotatorKeys[i];
const config = rotatorButtons[key];
const isActive = activeRotatorButtons[key] === true;
if (isActive && !rotatorIntervals[key]) {
rotatorIntervals[key] = window.setInterval(() => {
rotateMirrorStep(config.mirrorX, config.mirrorY, -22.5);
traceLaser();
}, 1000);
}
if (!isActive && rotatorIntervals[key]) {
window.clearInterval(rotatorIntervals[key]);
delete rotatorIntervals[key];
}
}
}
function stopAllRotatorButtons() {
const intervalKeys = Object.keys(rotatorIntervals);
for (let i = 0; i < intervalKeys.length; i++) {
const key = intervalKeys[i];
window.clearInterval(rotatorIntervals[key]);
}
rotatorIntervals = {};
}
function saveLaserSegment(x, y, direction, color) { function saveLaserSegment(x, y, direction, color) {
laserSegments[`${y},${x}`] = { laserSegments[`${y},${x}`] = {
direction: { ...direction }, direction: { ...direction },
@@ -361,13 +435,20 @@ function loadGrid() {
case legend.mirror: case legend.mirror:
cell.classList.add("mirror"); cell.classList.add("mirror");
const currentAngle = mirrorOrientations[`${y},${x}`] || 0; const currentAngle = mirrorOrientations[`${y},${x}`] || 0;
const btnMirror = document.createElement("button");
btnMirror.classList.add("btn-mirror");
btnMirror.type = "button";
const img = document.createElement("img"); const img = document.createElement("img");
img.src = "../../assets/img/tiles/Mirror.svg"; img.src = "../../assets/img/tiles/Mirror.svg";
img.classList.add("mirror-img"); img.classList.add("mirror-img");
img.style.transform = `rotate(${currentAngle}deg)`; img.style.transform = `rotate(${currentAngle}deg)`;
if (isMirrorControlledByButton(x, y)) {
const mirrorDisplay = document.createElement("div");
mirrorDisplay.classList.add("btn-mirror", "btn-mirror-locked");
mirrorDisplay.appendChild(img);
cell.appendChild(mirrorDisplay);
} else {
const btnMirror = document.createElement("button");
btnMirror.classList.add("btn-mirror");
btnMirror.type = "button";
btnMirror.appendChild(img); btnMirror.appendChild(img);
btnMirror.onmousedown = (event) => { btnMirror.onmousedown = (event) => {
event.preventDefault(); event.preventDefault();
@@ -378,6 +459,7 @@ function loadGrid() {
}; };
btnMirror.oncontextmenu = (event) => event.preventDefault(); btnMirror.oncontextmenu = (event) => event.preventDefault();
cell.appendChild(btnMirror); cell.appendChild(btnMirror);
}
break; break;
case legend.door: case legend.door:
cell.classList.add("door"); cell.classList.add("door");
@@ -400,6 +482,12 @@ function loadGrid() {
cell.classList.add("button-active"); cell.classList.add("button-active");
} }
break; break;
case legend.rotatorButton:
cell.classList.add("button", "button-rotator");
if (activatedButtons[`${y},${x}`]) {
cell.classList.add("button-active");
}
break;
case legend.wall: case legend.wall:
cell.classList.add("wall"); cell.classList.add("wall");
break; break;
@@ -442,20 +530,7 @@ function loadGrid() {
} }
function rotateMirror(x, y, isRightClick) { function rotateMirror(x, y, isRightClick) {
const coordKey = `${y},${x}`; rotateMirrorStep(x, y, isRightClick ? 22.5 : -22.5);
if (getCurrentLevel()[y][x] !== legend.mirror) {
return;
}
let currentAngle = mirrorOrientations[coordKey] || 0;
currentAngle = (currentAngle + (isRightClick ? 22.5 : -22.5)) % 360;
if (currentAngle < 0) {
currentAngle += 360;
}
mirrorOrientations[coordKey] = currentAngle;
traceLaser(); traceLaser();
} }
@@ -463,6 +538,7 @@ function traceLaser() {
laserSegments = {}; laserSegments = {};
activatedButtons = {}; activatedButtons = {};
openedDoors = {}; openedDoors = {};
activeRotatorButtons = {};
isLevelFinished = false; isLevelFinished = false;
const level = getCurrentLevel(); const level = getCurrentLevel();
@@ -575,6 +651,21 @@ function traceLaser() {
} }
break; break;
case legend.rotatorButton:
if (currentLaserColor === laserColors.red) {
const rotatorKey = `${currentY},${currentX}`;
activatedButtons[rotatorKey] = true;
activeRotatorButtons[rotatorKey] = true;
saveLaserSegment(currentX, currentY, laserDirection, currentLaserColor);
} else if (currentLaserColor === laserColors.yellow) {
saveLaserSegment(currentX, currentY, laserDirection, currentLaserColor);
} else if (currentLaserColor === laserColors.blue) {
laserDirection = reverseLaser(laserDirection);
} else {
laserActive = false;
}
break;
case legend.demiWallCornerUpLeft: case legend.demiWallCornerUpLeft:
laserDirection = reflectLaser(laserDirection, 135); laserDirection = reflectLaser(laserDirection, 135);
break; break;
@@ -597,6 +688,7 @@ function traceLaser() {
} }
} }
syncRotatorButtons();
loadGrid(); loadGrid();
if (isLevelFinished) { if (isLevelFinished) {
@@ -615,6 +707,7 @@ function nextLevel() {
currentLevelIndex++; currentLevelIndex++;
isLevelFinished = false; isLevelFinished = false;
stopAllRotatorButtons();
if (currentLevelIndex >= levels.length) { if (currentLevelIndex >= levels.length) {
currentLevelIndex = 0; currentLevelIndex = 0;