distribution animation
This commit is contained in:
parent
662ee8fd10
commit
8d04e99a85
2 changed files with 151 additions and 14 deletions
|
|
@ -39,6 +39,13 @@ class Hand {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
shuffle() {
|
||||||
|
for (let i = this.tiles.length - 1; i > 0; i--) {
|
||||||
|
const j = Math.floor(Math.random() * (i + 1));
|
||||||
|
[this.tiles[i], this.tiles[j]] = [this.tiles[j], this.tiles[i]];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
flatten() {
|
flatten() {
|
||||||
if (this.drawn) {
|
if (this.drawn) {
|
||||||
this.tiles.push(this.drawn);
|
this.tiles.push(this.drawn);
|
||||||
|
|
@ -107,7 +114,7 @@ class Discard {
|
||||||
}
|
}
|
||||||
|
|
||||||
class Game {
|
class Game {
|
||||||
constructor() {
|
constructor(skipInitialDeal = false) {
|
||||||
this.discards = [
|
this.discards = [
|
||||||
new Discard(),
|
new Discard(),
|
||||||
new Discard(),
|
new Discard(),
|
||||||
|
|
@ -115,20 +122,33 @@ class Game {
|
||||||
new Discard()
|
new Discard()
|
||||||
];
|
];
|
||||||
this.wall = new Draw();
|
this.wall = new Draw();
|
||||||
this.hands = [
|
|
||||||
this.wall.drawHand(),
|
if (skipInitialDeal) {
|
||||||
this.wall.drawHand(),
|
this.hands = [
|
||||||
this.wall.drawHand(),
|
new Hand(),
|
||||||
this.wall.drawHand()
|
new Hand(),
|
||||||
];
|
new Hand(),
|
||||||
for (let hand of this.hands) {
|
new Hand()
|
||||||
hand.sort();
|
];
|
||||||
|
} else {
|
||||||
|
this.hands = [
|
||||||
|
this.wall.drawHand(),
|
||||||
|
this.wall.drawHand(),
|
||||||
|
this.wall.drawHand(),
|
||||||
|
this.wall.drawHand()
|
||||||
|
];
|
||||||
|
for (let hand of this.hands) {
|
||||||
|
hand.sort();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
this.firstDealer = Math.floor(Math.random() * 4) * 0;
|
this.firstDealer = Math.floor(Math.random() * 4) * 0;
|
||||||
this.turn = this.firstDealer;
|
this.turn = this.firstDealer;
|
||||||
this.repeat = 0;
|
this.repeat = 0;
|
||||||
|
|
||||||
this.draw(this.turn);
|
if (!skipInitialDeal) {
|
||||||
|
this.draw(this.turn);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
newDeal(hasRepeat = false) {
|
newDeal(hasRepeat = false) {
|
||||||
|
|
|
||||||
|
|
@ -344,14 +344,15 @@
|
||||||
startButton.addEventListener('click', () => {
|
startButton.addEventListener('click', () => {
|
||||||
startScreen.style.display = 'none';
|
startScreen.style.display = 'none';
|
||||||
gameCenter.style.display = 'flex';
|
gameCenter.style.display = 'flex';
|
||||||
// Instancier une nouvelle partie et afficher les mains
|
// Instancier une nouvelle partie avec mains vides pour distribution animée
|
||||||
game = new Game();
|
game = new Game(true);
|
||||||
renderHands();
|
// Lancer l'animation de distribution
|
||||||
updateTurnIndicator();
|
distributeHands();
|
||||||
});
|
});
|
||||||
|
|
||||||
// Déclarer les variables et fonctions ici pour qu'elles soient accessibles partout
|
// Déclarer les variables et fonctions ici pour qu'elles soient accessibles partout
|
||||||
let game;
|
let game;
|
||||||
|
let isDistributing = false;
|
||||||
// Charger le menu
|
// Charger le menu
|
||||||
fetch('/components/menu.html')
|
fetch('/components/menu.html')
|
||||||
.then(r => r.text())
|
.then(r => r.text())
|
||||||
|
|
@ -373,6 +374,119 @@
|
||||||
|
|
||||||
// Instancier une nouvelle partie et afficher les mains
|
// Instancier une nouvelle partie et afficher les mains
|
||||||
|
|
||||||
|
async function distributeHands() {
|
||||||
|
isDistributing = true;
|
||||||
|
// Distribution 4 par 4, puis 1 par 1 comme dans la vraie vie
|
||||||
|
// 3 rounds de 4 tuiles par joueur = 12 tuiles
|
||||||
|
for (let round = 0; round < 3; round++) {
|
||||||
|
for (let player = 0; player < 4; player++) {
|
||||||
|
for (let i = 0; i < 4; i++) {
|
||||||
|
game.hands[player].tiles.push(game.wall.drawTile());
|
||||||
|
}
|
||||||
|
renderHands();
|
||||||
|
await new Promise(resolve => setTimeout(resolve, 300));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Distribution finale : 1 par 1 pour la 13e tuile
|
||||||
|
for (let player = 0; player < 4; player++) {
|
||||||
|
game.hands[player].tiles.push(game.wall.drawTile());
|
||||||
|
renderHands();
|
||||||
|
await new Promise(resolve => setTimeout(resolve, 300));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Trier les mains avec animation pour le joueur
|
||||||
|
const playerHandContainer = document.getElementById('hand-0').querySelector('.hand-tiles');
|
||||||
|
const playerTiles = game.hands[0].tiles;
|
||||||
|
const playerTileDivs = Array.from(playerHandContainer.children);
|
||||||
|
|
||||||
|
// Créer un map pour associer chaque tuile à son élément DOM
|
||||||
|
const tileToElement = new Map();
|
||||||
|
playerTileDivs.forEach((div, index) => {
|
||||||
|
tileToElement.set(playerTiles[index], div);
|
||||||
|
});
|
||||||
|
|
||||||
|
// Enregistrer les positions avant tri (en pixels relatifs au conteneur)
|
||||||
|
const originalPositions = new Map();
|
||||||
|
playerTileDivs.forEach((div, index) => {
|
||||||
|
originalPositions.set(div, index * (60 + 5)); // calcul basé sur width + gap
|
||||||
|
});
|
||||||
|
|
||||||
|
// Trier les mains
|
||||||
|
for (let hand of game.hands) {
|
||||||
|
hand.sort();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Récupérer les nouvelles positions
|
||||||
|
const newPositions = new Map();
|
||||||
|
game.hands[0].tiles.forEach((tile, newIndex) => {
|
||||||
|
newPositions.set(tileToElement.get(tile), newIndex * (60 + 5));
|
||||||
|
});
|
||||||
|
|
||||||
|
// Appliquer une translation pour que les éléments restent à leur place visuelle
|
||||||
|
playerTileDivs.forEach(div => {
|
||||||
|
const originalX = originalPositions.get(div);
|
||||||
|
const newX = newPositions.get(div);
|
||||||
|
const deltaX = originalX - newX;
|
||||||
|
|
||||||
|
div.style.transform = `translateX(${deltaX}px)`;
|
||||||
|
div.style.transition = 'none';
|
||||||
|
});
|
||||||
|
|
||||||
|
// Forcer un reflow
|
||||||
|
void playerHandContainer.offsetWidth;
|
||||||
|
|
||||||
|
// Ré-ordonner les éléments dans le DOM selon le tri
|
||||||
|
const sortedDivs = game.hands[0].tiles.map(tile => tileToElement.get(tile));
|
||||||
|
sortedDivs.forEach(div => playerHandContainer.appendChild(div));
|
||||||
|
|
||||||
|
// Forcer un autre reflow
|
||||||
|
void playerHandContainer.offsetWidth;
|
||||||
|
|
||||||
|
// Animer vers les positions finales
|
||||||
|
playerTileDivs.forEach(div => {
|
||||||
|
div.style.transition = 'transform 0.6s ease-in-out';
|
||||||
|
div.style.transform = 'translateX(0)';
|
||||||
|
});
|
||||||
|
|
||||||
|
// Attendre la fin de l'animation
|
||||||
|
await new Promise(resolve => setTimeout(resolve, 600));
|
||||||
|
|
||||||
|
// Nettoyer les styles
|
||||||
|
playerTileDivs.forEach(div => {
|
||||||
|
div.style.transition = '';
|
||||||
|
div.style.transform = '';
|
||||||
|
});
|
||||||
|
|
||||||
|
// Re-rendre les bots sans animation
|
||||||
|
for (let i = 1; i < 4; i++) {
|
||||||
|
const botHandDiv = document.getElementById(`hand-${i}`);
|
||||||
|
const botHandTiles = document.createElement('div');
|
||||||
|
botHandTiles.className = 'hand-tiles';
|
||||||
|
|
||||||
|
for (let k = 0; k < game.hands[i].tiles.length; k++) {
|
||||||
|
const tileDiv = document.createElement('div');
|
||||||
|
tileDiv.innerHTML = `<svg class="tile tile-back" viewBox="0 0 310 410" height="82" width="60">
|
||||||
|
<image href="/img/Regular/Gray.svg" x="10" y="10" height="410" width="310"/>
|
||||||
|
<image href="/img/Regular/Back.svg" x="0" y="0" height="410" width="310"/>
|
||||||
|
</svg>`;
|
||||||
|
botHandTiles.appendChild(tileDiv);
|
||||||
|
}
|
||||||
|
|
||||||
|
const botHandWithDraw = botHandDiv.querySelector('.hand-with-draw') || botHandDiv;
|
||||||
|
const oldHandTiles = botHandWithDraw.querySelector('.hand-tiles');
|
||||||
|
if (oldHandTiles) oldHandTiles.remove();
|
||||||
|
botHandWithDraw.insertBefore(botHandTiles, botHandWithDraw.firstChild);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Le joueur 0 pioche sa tuile supplémentaire
|
||||||
|
await new Promise(resolve => setTimeout(resolve, 500));
|
||||||
|
game.draw(game.turn);
|
||||||
|
renderHands();
|
||||||
|
updateTurnIndicator();
|
||||||
|
isDistributing = false;
|
||||||
|
}
|
||||||
|
|
||||||
function renderHands() {
|
function renderHands() {
|
||||||
for (let i = 0; i < 4; i++) {
|
for (let i = 0; i < 4; i++) {
|
||||||
const handDiv = document.getElementById(`hand-${i}`);
|
const handDiv = document.getElementById(`hand-${i}`);
|
||||||
|
|
@ -397,6 +511,9 @@
|
||||||
const handleClick = (() => {
|
const handleClick = (() => {
|
||||||
const tileToDiscard = tile;
|
const tileToDiscard = tile;
|
||||||
return () => {
|
return () => {
|
||||||
|
// Ne rien faire pendant la distribution
|
||||||
|
if (isDistributing) return;
|
||||||
|
|
||||||
// Trouver l'index actuel de la tuile
|
// Trouver l'index actuel de la tuile
|
||||||
const currentIdx = game.hands[0].tiles.findIndex(t => t === tileToDiscard);
|
const currentIdx = game.hands[0].tiles.findIndex(t => t === tileToDiscard);
|
||||||
if (currentIdx !== -1) {
|
if (currentIdx !== -1) {
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue