Labyrinthe/labyrinthe.js
2024-05-12 11:33:57 +02:00

226 lines
7.0 KiB
JavaScript
Executable File

// Customize Array to be use as coordinates
Object.defineProperties(Array.prototype, {
"x": {
get: function() { return this[0] },
set: function(x) { this[0] = x }
},
"y": {
get: function() { return this[1] },
set: function(y) { this[1] = y }
}
})
Array.prototype.plus = function (other) {
return this.map((x, i) => x + other[i]);
};
const DIRECTION = {
'BAS': 0,
'GAUCHE': 1,
'DROITE': 2,
'HAUT': 3,
};
const MOUVEMENT = {
'ARRET': [0, 0],
'BAS': [0, 1],
'HAUT': [0, -1],
'GAUCHE': [-1, 0],
'DROITE': [1, 0],
};
const ACTIONS = {
'ArrowUp' : { 'direction': DIRECTION.HAUT, 'mouvement': MOUVEMENT.HAUT },
'z' : { 'direction': DIRECTION.HAUT, 'mouvement': MOUVEMENT.HAUT },
'ArrowDown' : { 'direction': DIRECTION.BAS, 'mouvement': MOUVEMENT.BAS },
's' : { 'direction': DIRECTION.BAS, 'mouvement': MOUVEMENT.BAS },
'ArrowLeft' : { 'direction': DIRECTION.GAUCHE, 'mouvement': MOUVEMENT.GAUCHE },
'q' : { 'direction': DIRECTION.GAUCHE, 'mouvement': MOUVEMENT.GAUCHE },
'ArrowRight': { 'direction': DIRECTION.DROITE, 'mouvement': MOUVEMENT.DROITE },
'd' : { 'direction': DIRECTION.DROITE, 'mouvement': MOUVEMENT.DROITE },
};
const TYPE = {
'MUR': 1,
'SOL': 2,
'PAS': 3,
};
const DIRECTIONS_LABYRINTHE = [MOUVEMENT.BAS, MOUVEMENT.HAUT, MOUVEMENT.GAUCHE, MOUVEMENT.DROITE];
const TAILLE_TUILE = 15;
function dessinerTuile(context, image, x, y) {
context.drawImage(image, TAILLE_TUILE * x, TAILLE_TUILE * y);
}
class Labyrinthe extends Array {
constructor(largeur, hauteur, context, tuiles) {
super();
this.hauteur = hauteur;
this.largeur = largeur;
this.context = context;
this.tuiles = tuiles;
for (var ligne = 0; ligne < hauteur; ligne++) {
this.push(Array(largeur).fill(TYPE.MUR));
}
this.positionInitiale = [1, 1];
this.positionFinale = [largeur - 2, hauteur - 2];
this.creuse(this.positionFinale);
this.construit(this.positionFinale);
}
construit(position) {
for (var direction of Array.from(DIRECTIONS_LABYRINTHE).sort(x => 0.5 - Math.random())) {
var pas1 = position.plus(direction);
var pas2 = pas1.plus(direction);
if (this.type(pas2) == TYPE.MUR) {
this.creuse(pas1);
this.creuse(pas2);
this.construit(pas2);
}
}
}
creuse(position) {
this[position.y][position.x] = TYPE.SOL;
}
type(position) {
if (
0 <= position.x &&
position.x < this.largeur &&
0 <= position.y &&
position.y < this.hauteur
) {
return this[position.y][position.x];
} else {
return -1;
}
}
dessiner() {
this.forEach((ligne, y) => {
ligne.forEach((type, x) => {
dessinerTuile(this.context, this.tuiles[type], x, y);
});
});
}
}
class Souris {
constructor(position, context, sprites) {
this.position = position;
this.context = context;
this.sprites = sprites;
this.futurePosition = this.position;
this.direction = DIRECTION.DROITE;
this.mouvement = MOUVEMENT.ARRET;
this.tailleSprite = 48;
this.animationSprite = 0;
this.animation = 0;
}
bouger(touche, labyrinthe) {
if (touche in ACTIONS) {
this.direction = ACTIONS[touche].direction;
this.mouvement = ACTIONS[touche].mouvement;
var futurePosition = this.position.plus(this.mouvement);
if ([TYPE.SOL, TYPE.PAS].includes(labyrinthe.type(futurePosition))) {
labyrinthe[this.position.y][this.position.x] = TYPE.PAS;
this.futurePosition = futurePosition;
return true;
} else {
this.mouvement = MOUVEMENT.ARRET;
this.animation = 0;
return false;
}
} else {
return False;
}
}
dessiner() {
this.context.drawImage(
this.sprites,
this.tailleSprite * this.animationSprite,
this.tailleSprite * this.direction,
this.tailleSprite,
this.tailleSprite,
TAILLE_TUILE * this.position.x - 17 + this.mouvement.x * this.animation,
TAILLE_TUILE * this.position.y - 12 + this.mouvement.y * this.animation,
this.tailleSprite,
this.tailleSprite
);
}
}
window.onload = function () {
var canvas = document.getElementById('canvas');
var ctx = canvas.getContext('2d');
var fromage = document.getElementById('fromage');
var sourisSprites = document.getElementById('souris');
var tuiles = {};
tuiles[TYPE.MUR] = document.getElementById('mur');
tuiles[TYPE.SOL] = document.getElementById('sol');
tuiles[TYPE.PAS] = document.getElementById('pas');
var touchesPressees = new this.Set();
var largeur = Math.floor(window.innerWidth / TAILLE_TUILE);
largeur = largeur - ((largeur + 1) % 2);
var hauteur = Math.floor(window.innerHeight / TAILLE_TUILE);
hauteur = hauteur - ((hauteur + 1) % 2);
canvas.width = largeur * TAILLE_TUILE;
canvas.height = hauteur * TAILLE_TUILE;
var labyrinthe = new Labyrinthe(largeur, hauteur, ctx, tuiles);
var souris = new Souris(labyrinthe.positionInitiale, ctx, sourisSprites);
window.onkeydown = function (event) {
if (event.key in ACTIONS) {
touchesPressees.add(event.key);
return false;
} else {
return true;
}
};
window.onkeyup = function (event) {
if (event.key in ACTIONS) {
touchesPressees.delete(event.key);
return false;
} else {
return true;
}
};
var timerID;
timerID = setInterval(function () {
if (touchesPressees.size > 0) souris.animationSprite = (souris.animationSprite + 1) % 3;
if (souris.mouvement != MOUVEMENT.ARRET) {
souris.animation += 5;
if (souris.animation >= TAILLE_TUILE) {
souris.animation = 0;
souris.position = souris.futurePosition;
if (
souris.position.x == labyrinthe.positionFinale.x &&
souris.position.y == labyrinthe.positionFinale.y
) {
window.alert('Miam miam !');
clearInterval(timerID);
}
}
}
if (souris.animation == 0) {
souris.mouvement = MOUVEMENT.ARRET;
for (touche of Array.from(touchesPressees).reverse()) {
if (souris.bouger(touche, labyrinthe)) break;
}
}
labyrinthe.dessiner();
dessinerTuile(ctx, fromage, labyrinthe.positionFinale.x, labyrinthe.positionFinale.y);
souris.dessiner();
}, 40);
};