Riichi/frontend/pages/riichi/chap5.html
2026-03-13 22:55:41 +01:00

365 lines
No EOL
10 KiB
HTML

<!DOCTYPE html>
<html lang="fr">
<head>
<meta charset="UTF-8">
<title>Tuto Riichi</title>
<link rel="stylesheet" href="/frontend/css/style.css">
<link rel="stylesheet" href="/frontend/css/text.css">
<link rel="stylesheet" href="/frontend/css/speech-bubble.css">
<link rel="stylesheet" href="/frontend/css/hand.css">
<style>
#menu {
position: relative;
z-index: 10;
}
#mascotte {
position: absolute;
top: 670px;
right: 100px;
z-index: 999;
transform: scaleX(-1);
cursor: pointer;
}
#mascotte img {
width: 250px;
height: auto;
display: block;
}
.speech-bubble {
position: absolute;
top: 250px;
right: 170px;
z-index: 1;
display: none;
}
.speech-bubble.visible {
display: flex;
}
#tiles-container {
display: flex;
justify-content: center;
align-items: flex-start;
gap: 10px;
padding: 20px;
}
:root {
--game_radius: 1100px;
}
#game-center {
position: absolute;
top: 0px;
left: 350px;
display: flex;
align-items: center;
justify-content: center;
min-height: 100vh;
}
#game {
position: relatives;
width: var(--game_radius);
height: var(--game_radius);
}
#hand-0 {
position: absolute;
transform: translate(-50%, 50%);
bottom: -10%;
left: 50%;
display: flex;
flex-direction: row;
align-items: flex-end;
gap: 5px;
padding: 20px 0 0 20px;
}
#hand-1 {
position: absolute;
transform: translate(-50%, -400%) rotate(-90deg) translate(0%, 450%);
bottom: -10%;
left: 50%;
display: flex;
flex-direction: row;
align-items: flex-end;
gap: 5px;
padding: 20px 0 0 20px;
}
.hand-tiles {
display: flex;
flex-direction: row;
gap: 5px;
}
.hand-with-draw {
display: flex;
flex-direction: row;
align-items: flex-end;
}
.draw-tile {
margin-left: 12px;
position: relative;
top: 0;
display: inline-block;
}
#hand-2 {
position: absolute;
transform: translate(-50%, -400%) rotate(180deg) translate(0%, 450%);
bottom: -10%;
left: 50%;
display: flex;
flex-direction: row;
align-items: flex-end;
gap: 5px;
padding: 20px 0 0 20px;
}
#hand-3 {
position: absolute;
transform: translate(-50%, -400%) rotate(90deg) translate(0%, 450%);
bottom: -10%;
left: 50%;
display: flex;
flex-direction: row;
align-items: flex-end;
gap: 5px;
padding: 20px 0 0 20px;
}
.player-tile:hover {
transform: translateY(-15px);
transition: transform 0.2s;
z-index: 2;
}
#discard-0 {
position: absolute;
transform: translate(-50%, 50%);
bottom: 25%;
left: 50%;
display: flex;
flex-direction: row;
gap: 2px;
flex-wrap: wrap;
width: 400px;
padding: 10px;
}
#discard-1 {
position: absolute;
transform: translate(-50%, -400%) rotate(-90deg) translate(0%, 450%);
bottom: -25%;
left: 50%;
display: flex;
flex-direction: row;
gap: 2px;
flex-wrap: wrap;
width: 400px;
padding: 10px;
}
#discard-2 {
position: absolute;
transform: translate(-50%, -400%) rotate(180deg) translate(0%, 450%);
bottom: -25%;
left: 50%;
display: flex;
flex-direction: row;
gap: 2px;
flex-wrap: wrap;
width: 400px;
padding: 10px;
}
#discard-3 {
position: absolute;
transform: translate(-50%, -400%) rotate(90deg) translate(0%, 450%);
bottom: -25%;
left: 50%;
display: flex;
flex-direction: row;
gap: 2px;
flex-wrap: wrap;
width: 400px;
padding: 10px;
}
#discard-0 div,
#discard-1 div,
#discard-2 div,
#discard-3 div {
flex-shrink: 0;
}
.discard-tile svg {
height: 50px;
width: 35px;
}
</style>
</head>
<body>
<div id="menu"></div>
<h1>Chapitre 5</h1>
<div class="speech-bubble">
<div class="speech-text" id="speech-text"></div>
</div>
<div id="mascotte"></div>
<div id="game-center">
<div id="game">
<div id="hand-0"></div>
<div id="discard-0"></div>
<div id="hand-1"></div>
<div id="discard-1"></div>
<div id="hand-2"></div>
<div id="discard-2"></div>
<div id="hand-3"></div>
<div id="discard-3"></div>
</div>
</div>
<script src="/frontend/js/fr/texts.js"></script>
<script src="/frontend/js/tile.js"></script>
<script type="module">
import { Game } from '/frontend/js/game.js';
window.addEventListener('DOMContentLoaded', () => {
// Charger le menu
fetch('/components/menu.html')
.then(r => r.text())
.then(html => document.getElementById('menu').innerHTML = html);
// Afficher la mascotte et le texte
const mascotteEl = document.getElementById('mascotte');
mascotteEl.innerHTML = '<img src="/img/tilineau/idle.png" alt="Tilineau">';
document.getElementById('speech-text').innerHTML = texts.riichi.chap5;
// Toggle bulle de dialogue au clic sur la mascotte
const speechBubble = document.querySelector('.speech-bubble');
mascotteEl.addEventListener('click', () => {
speechBubble.classList.toggle('visible');
mascotteEl.innerHTML = speechBubble.classList.contains('visible')
? '<img class="explaining" src="/img/tilineau/explaining.png" alt="Tilineau">'
: '<img src="/img/tilineau/idle.png" alt="Tilineau">';
});
// Instancier une nouvelle partie et afficher les mains
const game = new Game();
function renderHands() {
for (let i = 0; i < 4; i++) {
const handDiv = document.getElementById(`hand-${i}`);
handDiv.innerHTML = '';
// Conteneur main + draw
const handWithDraw = document.createElement('div');
handWithDraw.className = 'hand-with-draw';
// Sous-div pour les tuiles de la main
const handTiles = document.createElement('div');
handTiles.className = 'hand-tiles';
for (let k = 0; k < game.hands[i].tiles.length; k++) {
const tile = game.hands[i].tiles[k];
const tileDiv = document.createElement('div');
// Ajouter la classe 'player-tile' uniquement pour le joueur
if (i === 0) {
tileDiv.className = 'player-tile';
tileDiv.innerHTML = tile.getSVG();
tileDiv.style.cursor = 'pointer';
const handleClick = (() => {
const tileToDiscard = tile;
return () => {
// Trouver l'index actuel de la tuile
const currentIdx = game.hands[0].tiles.findIndex(t => t === tileToDiscard);
if (currentIdx !== -1) {
game.discard(0, currentIdx);
game.nextTurn();
renderHands();
renderDiscards();
playBotsSequentially();
}
};
})();
tileDiv.addEventListener('click', handleClick);
} else {
// Bots : afficher le dos
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>`;
}
handTiles.appendChild(tileDiv);
}
handWithDraw.appendChild(handTiles);
// Afficher la tuile draw si elle existe
if (game.hands[i].drawn) {
const drawDiv = document.createElement('div');
drawDiv.className = 'draw-tile';
if (i === 0) {
drawDiv.classList.add('player-tile');
drawDiv.innerHTML = game.hands[i].drawn.getSVG();
drawDiv.style.cursor = 'pointer';
const drawnTile = game.hands[i].drawn;
const handleDrawnClick = (() => {
return () => {
// Défausser la tuile piochée (index === tiles.length)
game.discard(0, game.hands[0].tiles.length);
game.nextTurn();
renderHands();
renderDiscards();
playBotsSequentially();
};
})();
drawDiv.addEventListener('click', handleDrawnClick);
} else {
drawDiv.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>`;
}
handWithDraw.appendChild(drawDiv);
}
handDiv.appendChild(handWithDraw);
}
}
function renderDiscards() {
for (let i = 0; i < 4; i++) {
const discardDiv = document.getElementById(`discard-${i}`);
discardDiv.innerHTML = '';
for (const tile of game.discards[i].tiles) {
const tileDiv = document.createElement('div');
tileDiv.className = 'discard-tile';
tileDiv.innerHTML = tile.getSVG();
discardDiv.appendChild(tileDiv);
}
}
}
async function playBotsSequentially() {
// Les bots jouent après le joueur humain
while (game.turn !== 0) {
await new Promise(resolve => setTimeout(resolve, 800));
game.botPlay();
game.nextTurn();
renderHands();
renderDiscards();
}
game.draw(0);
renderHands();
renderDiscards();
}
renderHands();
});
</script>
</body>
</html>