Files
tigrou/flask_base/templates/pokemon.html

371 lines
12 KiB
HTML

<!DOCTYPE html>
<html lang="fr">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Jeu Pokémon</title>
<link rel="stylesheet" href="../static/style.css">
</head>
<body>
{% include 'header.html' %}
<div class="proprimon-content">
<div class="battle">
<h1>LIBREMON</h1>
<style>
#log {
width: 90%;
height: 200px;
border: 1px solid #555;
padding: 10px;
margin-top: 15px;
background: #111;
color: white;
white-space: pre-line;
overflow-y: auto; /* Scroll vertical */
display: flex;
flex-direction: column; /* Les nouveaux messages vont en bas */
gap: 4px;
}
.proprimon-log {
width: 90%;
height: 200px;
border: 1px solid #555;
padding: 10px;
margin-top: 15px;
background: #111;
color: white;
white-space: pre-line;
overflow-y: auto;
display: flex;
flex-direction: column;
gap: 4px;
}
/* ----- PANEL LATÉRAL POUR LE LEADERBOARD ----- */
.proprimon-sidepanel {
position: fixed;
left: 0;
top: 0;
width: 260px;
height: 100vh;
overflow-y: auto;
background: #1c1c1c;
color: white;
padding: 20px;
box-shadow: 4px 0 12px rgba(0,0,0,0.4);
border-right: 2px solid #333;
z-index: 1200;
}
.proprimon-sidepanel h2 {
text-align: center;
font-size: 20px;
margin-bottom: 15px;
}
.proprimon-sidepanel-entry {
margin: 8px 0;
padding: 4px;
background: #2a2a2a;
border-radius: 4px;
}
/* ----- DÉCALAGE DU JEU POUR ÉVITER LE PANEL ----- */
.proprimon-content {
margin-left: 280px; /* Pour ne pas passer sous le panneau */
padding: 10px;
}
</style>
<div class="proprimon-sidepanel">
<h2>Classement des joueurs</h2>
<div id="leaderboardDiv"></div>
</div>
<div class="battle">
<h2>Battez les logiciels propriétaires en utilisant leur alter-ego libre !</h2>
<div class="row">
<div id = "scoreDiv">Score: 0</div>
<div class="monster" id="enemy">
<div class="enemy-img-container">
<img id="enemyImg" src="ennemi.png" alt="Ennemi">
</div>
<span id="ennemyName">Ennemi</span><br>
<span id="enemyHp">HP: 30</span>
<span id="enemyInfo" class="tooltip" data-tooltip="">?</span>
</div>
<div class="monster" id="player">
<div class="enemy-img-container">
<img id="enemyImg" src="../static/pinguin(1).gif" alt="Ennemi" style=" width:100px;height:100px;">
</div>
Joueur<br>
<span id="playerHp">HP: 30</span>
</div>
</div>
<div id="attacksDiv"></div>
<button id="runBtn">Fuir</button>
<div id="log" class="proprimon-log">Un ennemi sauvage apparaît !</div>
</div>
<script>
const outils_list = {{ data|tojson }};
//récupérer le leaderbord
let leaderboardDiv = document.getElementById("leaderboardDiv");
let leaderboardData = [];
fetch("/api/leaderboard") // [{name: "Player1", score: 5}, ...]
.then(response => response.json())
.then(data => {
leaderboardData = data["leaderboard"];
leaderboardData.sort((a, b) => b.score - a.score); // trier par score décroissant
leaderboardDiv.innerHTML = "";
leaderboardData.forEach((entry, index) => {
const entryDiv = document.createElement("div");
entryDiv.textContent = `${index + 1}. ${entry.name} - ${entry.score} ennemis vaincus`;
leaderboardDiv.appendChild(entryDiv);
});
});
//refresh every 10 seconds
setInterval(() => {
fetch("/api/leaderboard")
.then(response => response.json())
.then(data => {
leaderboardData = data["leaderboard"];
leaderboardData.sort((a, b) => b.score - a.score); // trier par score décroissant
leaderboardDiv.innerHTML = "";
leaderboardData.forEach((entry, index) => {
const entryDiv = document.createElement("div");
entryDiv.textContent = `${index + 1}. ${entry.name} - ${entry.score} ennemis vaincus`;
leaderboardDiv.appendChild(entryDiv);
});
});
}, 10000);
function getAgainstNames(itemName) {
const item = outils_list.find(i => i.open_source_name === itemName);
return item ? item.against_name : null;
}
let playerHp = 30;
let enemyHp = 30;
let score = 0;
const max = outils_list.length;
let playerInv = [];
let lastEnnemyNumber = -1;
let ennemyNumber = -1;
const log = document.getElementById("log");
const ennemyName = document.getElementById("ennemyName");
const playerHpBox = document.getElementById("playerHp");
const enemyHpBox = document.getElementById("enemyHp");
addRandomItemToInventory();
addRandomItemToInventory();
function addRandomItemToInventory() { // Add a NEW random item to player's inventory.
let nbItems = playerInv.length;
if(nbItems < max)
{
let newItem;
let found = false;
while(!found){
let randIndex = Math.floor(Math.random()*max);
newItem = outils_list[randIndex];
found = true;
for(let i=0; i<nbItems; i++){
if(playerInv[i].name == newItem.open_source_name){
found = false; // already have this item
break;
}
}
}
playerInv.push({name: newItem.open_source_name});
addLog(`Vous avez obtenu un nouvel outil open source : **${newItem.open_source_name}** !`);
}
}
function updateUI() {
playerHpBox.textContent = "HP: " + Math.max(0, playerHp);
enemyHpBox.textContent = "HP: " + Math.max(0, enemyHp);
document.getElementById("scoreDiv").textContent = "Score: " + score;
}
function addLog(text) {
const entry = document.createElement("div");
entry.textContent = text;
log.appendChild(entry);
// Scroll automatique vers le bas
log.scrollTop = log.scrollHeight;
}
const attacksDiv = document.getElementById("attacksDiv");
function setCombat(){
enemyHp = 30;
updateUI();
lastEnnemyNumber = ennemyNumber;
ennemyNumber = Math.floor(Math.random()*max);
//il faut que l'ennemi soit dans le against d'un des items du joueur
let found = false;
while(!found){
ennemyNumber = Math.floor(Math.random()*max);
for(let i=0; i<playerInv.length; i++){
if(getAgainstNames(playerInv[i].name) == outils_list[ennemyNumber].against_name && ennemyNumber != lastEnnemyNumber){
found = true;
break;
}
}
}
ennemyName.textContent = outils_list[ennemyNumber].against_name;
document.getElementById("enemyInfo").setAttribute("data-tooltip", outils_list[ennemyNumber].description_against);
document.getElementById("enemyImg").src = outils_list[ennemyNumber].icon_against_link;
createAttackButtons();
}
function playerAttack(index) {
const atk = playerInv[index];
if(getAgainstNames(atk.name) == ennemyName.textContent){
var dmg = enemyHp; // instant win
addLog(`Vous utilisez **${atk.name}** et infligez ${dmg} dégâts !\nC'est super efficace !`);
} else {
var dmg = Math.floor(Math.random() * 5) + 2; // 2-6
addLog(`Vous utilisez **${atk.name}** et infligez ${dmg} dégâts !\nMais ce n'est pas très efficace...`);
playerHp -= 5; // dommage punitif
addLog(`Le fait d'avoir utilisé ${atk.name} contre ${ennemyName.textContent} vous blesse de 5 dégâts en retour !`);
}
enemyHp -= dmg;
updateUI();
if (enemyHp <= 0) {
addLog(`${ennemyName.textContent} est vaincu !`);
addRandomItemToInventory();
score += 1;
if(score >= 50){
addLog("Félicitations ! Vous avez atteint le score maximum de 50 ennemis vaincus et remporté la partie !");
attacksDiv.innerHTML = ""; // Remove attack buttons
fetch("/api/leaderboard", {
method: "POST",
headers: {"Content-Type": "application/json"},
body: JSON.stringify({name: prompt("Entrez votre nom"), score: score})
});
return;
}
updateUI();
attacksDiv.innerHTML = ""; // Clear attack buttons during transition
setCombat();
addLog("\nUn nouvel ennemi sauvage apparaît !");
return;
}
// Riposte
setTimeout(() => {
const edmg = Math.floor(Math.random() * 6) + 3;
playerHp -= edmg;
addLog(
`Vous utilisez ${atk.name} et infligez ${dmg} dégâts !\n` +
`${ennemyName.textContent} riposte et inflige ${edmg} dégâts !`
);
updateUI();
if (playerHp <= 0) {
let nom = prompt("Entrez votre nom pour le classement");
if(nom){
addLog("Vous êtes K.O.");
addLog(`Score final : ${score} ennemis vaincus.`);
attacksDiv.innerHTML = ""; // Remove attack buttons
fetch("/api/leaderboard", {
method: "POST",
headers: {"Content-Type": "application/json"},
body: JSON.stringify({name: nom, score: score})
});
}
else{
addLog("Vous êtes K.O");
addLog(`Score final : ${score} ennemis vaincus.`);
attacksDiv.innerHTML = ""; // Remove attack buttons
}
}
}, 500);
}
function createAttackButtons() {
attacksDiv.innerHTML = "";
playerInv.forEach((atk, index) => {
const btn = document.createElement("button");
btn.onclick = () => playerAttack(index);
const data = outils_list.find(x => x.open_source_name === atk.name);
// Conteneur icône
const iconContainer = document.createElement("div");
iconContainer.className = "attack-icon-container";
const iconImg = document.createElement("img");
iconImg.src = data.icon_op_link;
iconImg.alt = data.open_source_name;
iconContainer.appendChild(iconImg);
btn.appendChild(iconContainer); // mettre l'icône avant le texte
// Texte du bouton
const textNode = document.createTextNode(atk.name + " "); // espace avant le "?"
btn.appendChild(textNode);
// Tooltip
const info = document.createElement("span");
info.className = "tooltip";
info.setAttribute("data-tooltip", data ? data.description_op : "Aucune description");
info.textContent = "?";
btn.appendChild(info);
attacksDiv.appendChild(btn);
});
}
document.getElementById("runBtn").onclick = () => {
let nom = prompt("Entrez votre nom pour le classement");
if(nom){
addLog("Vous avez fui le combat !");
fetch("/api/leaderboard", {
method: "POST",
headers: {"Content-Type": "application/json"},
body: JSON.stringify({name: nom, score: score})
});
}
else{
addLog("Vous avez fui le combat !");
}
attacksDiv.innerHTML = ""; // Remove attack buttons
};
setCombat();
</script>
</div>
</body>
</html>