first commit

This commit is contained in:
nix
2026-05-16 11:10:19 +02:00
commit 509c9b3737
172 changed files with 14496 additions and 0 deletions
Executable
+160
View File
@@ -0,0 +1,160 @@
<!DOCTYPE html>
<html lang="fr">
<head>
<meta charset="utf-8" />
<title>Labyrinthe avec niveaux</title>
<style>
body { margin:0; background:#000; color:#fff; font-family:Courier, monospace; }
#wrap { display:flex; flex-direction:column; align-items:center; gap:8px; padding:12px; }
canvas { background:#000; border:2px solid #0ff; box-shadow:0 0 12px #0ff; }
.hud { text-align:center; }
.hint { color:#aaa; font-size:12px; }
</style>
</head>
<body>
<div id="wrap">
<canvas id="game" width="960" height="720"></canvas>
<div id="hud" class="hud"></div>
<div class="hint">Flèches pour bouger • R: restart</div>
</div>
<script>
(() => {
const canvas = document.getElementById('game');
const ctx = canvas.getContext('2d');
const W = canvas.width, H = canvas.height;
// ----- State -----
let COLS, ROWS, CELL, OFFSET_X, OFFSET_Y;
const grid = [];
const player = { c:0, r:0, steps:0 };
const exit = { c:0, r:0 };
const state = { level:1, win:false, startTime:0, best:0 };
// ----- Génération du labyrinthe -----
function index(c,r){ return r*COLS+c; }
function neighbors(c,r){
const n=[];
if(r>0) n.push([c,r-1,0]);
if(c<COLS-1) n.push([c+1,r,1]);
if(r<ROWS-1) n.push([c,r+1,2]);
if(c>0) n.push([c-1,r,3]);
return n;
}
function carveMaze(startC=0,startR=0){
grid.length=0;
for(let r=0;r<ROWS;r++){
for(let c=0;c<COLS;c++){
grid.push({c,r,visited:false,walls:[true,true,true,true]});
}
}
const stack=[];
let current=grid[index(startC,startR)];
current.visited=true; stack.push(current);
while(stack.length){
const cell=stack[stack.length-1];
const cand=neighbors(cell.c,cell.r)
.map(([nc,nr,dir])=>({nc,nr,dir,cell:grid[index(nc,nr)]}))
.filter(o=>!o.cell.visited);
if(cand.length===0){ stack.pop(); }
else{
const pick=cand[(Math.random()*cand.length)|0];
cell.walls[pick.dir]=false;
pick.cell.walls[(pick.dir+2)%4]=false;
pick.cell.visited=true;
stack.push(pick.cell);
}
}
}
// ----- Reset niveau -----
function reset(level=1){
state.level=level;
COLS=20+level*2; ROWS=15+level*2;
CELL=Math.floor(Math.min(W/COLS,H/ROWS));
OFFSET_X=Math.floor((W-COLS*CELL)/2);
OFFSET_Y=Math.floor((H-ROWS*CELL)/2);
carveMaze(0,0);
player.c=0; player.r=0; player.steps=0;
exit.c=COLS-1; exit.r=ROWS-1;
state.startTime=performance.now();
state.win=false;
}
// ----- Input -----
const keys={ArrowUp:false,ArrowRight:false,ArrowDown:false,ArrowLeft:false};
let cooldown=0;
window.addEventListener('keydown',e=>{
if(e.code in keys) keys[e.code]=true;
if(e.code==='KeyR') reset(1);
});
window.addEventListener('keyup',e=>{
if(e.code in keys) keys[e.code]=false;
});
function tryMove(dc,dr,wallIndex){
if(state.win) return;
const cell=grid[index(player.c,player.r)];
if(!cell.walls[wallIndex]){
player.c+=dc; player.r+=dr; player.steps++;
if(player.c===exit.c && player.r===exit.r){
state.win=true;
const elapsed=((performance.now()-state.startTime)/1000)|0;
if(state.level>state.best) state.best=state.level;
setTimeout(()=>reset(state.level+1),1500); // passe au niveau suivant
}
}
}
// ----- Update -----
function update(dt){
cooldown-=dt*1000;
if(cooldown<=0){
if(keys.ArrowUp){ tryMove(0,-1,0); cooldown=100; }
else if(keys.ArrowRight){ tryMove(1,0,1); cooldown=100; }
else if(keys.ArrowDown){ tryMove(0,1,2); cooldown=100; }
else if(keys.ArrowLeft){ tryMove(-1,0,3); cooldown=100; }
}
}
// ----- Draw -----
function draw(){
ctx.fillStyle='#000'; ctx.fillRect(0,0,W,H);
ctx.strokeStyle='#0ff'; ctx.lineWidth=2;
for(const cell of grid){
const x=OFFSET_X+cell.c*CELL, y=OFFSET_Y+cell.r*CELL;
if(cell.walls[0]){ ctx.beginPath(); ctx.moveTo(x,y); ctx.lineTo(x+CELL,y); ctx.stroke(); }
if(cell.walls[1]){ ctx.beginPath(); ctx.moveTo(x+CELL,y); ctx.lineTo(x+CELL,y+CELL); ctx.stroke(); }
if(cell.walls[2]){ ctx.beginPath(); ctx.moveTo(x,y+CELL); ctx.lineTo(x+CELL,y+CELL); ctx.stroke(); }
if(cell.walls[3]){ ctx.beginPath(); ctx.moveTo(x,y); ctx.lineTo(x,y+CELL); ctx.stroke(); }
}
// exit
ctx.fillStyle='#39FF14';
ctx.beginPath();
ctx.arc(OFFSET_X+exit.c*CELL+CELL/2,OFFSET_Y+exit.r*CELL+CELL/2,CELL*0.3,0,Math.PI*2);
ctx.fill();
// player
ctx.fillStyle='#00FFFF';
ctx.beginPath();
ctx.arc(OFFSET_X+player.c*CELL+CELL/2,OFFSET_Y+player.r*CELL+CELL/2,CELL*0.3,0,Math.PI*2);
ctx.fill();
// HUD
const elapsed=((performance.now()-state.startTime)/1000)|0;
document.getElementById('hud').innerHTML=
`Niveau: ${state.level} &nbsp;&nbsp; Pas: ${player.steps} &nbsp;&nbsp; Temps: ${elapsed}s &nbsp;&nbsp; Meilleur: ${state.best}`;
}
// ----- Loop -----
let last=performance.now();
function frame(t){
const dt=(t-last)/1000; last=t;
update(dt); draw();
requestAnimationFrame(frame);
}
reset(1);
requestAnimationFrame(frame);
})();
</script>
</body>
</html>