JS - Warum funktioniert der Button nicht Richtig?
Ich wollte ein simples Spiel mit JS programmieren und wollte einen Refresh des Bildschirms einfügen. An sich funktioniert das auch, jedoch reagiert der Button nicht immer. Je schneller der Refresh erfolgt, desto schlechter Funktioniert der Button. Kann mir da vielleicht jemand helfen?
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<link href="miner.css" rel="stylesheet">
<script src="miner.js"></script>
</head>
<body>
<div class="monitor" id="monitor">
<h1>Mine Tycoon</h1>
<div>Mines: <font id="minesCounter">0</font></div><br>
<div id="buyMineButton">
<p class="button" onclick="buyMine()">Buy mine Cost: <font id="minesPrice">1</font></p>
</div>
</div>
</body>
</html>
body{
background-color: #393939;
color: #ffffff;
}
h1{
text-align: center;
}
.button{
height: auto;
width: 180px;
border-radius: 15px;
outline: 2px solid red;
outline-offset: 4px;
text-align: center;
}
.buttonGreen{
height: auto;
width: 180px;
border-radius: 15px;
outline: 2px solid green;
outline-offset: 4px;
text-align: center;
}
var money = 100;
var mines = 0;
var minesPrice = 1;
var miners = 0;
var coal = 0;
var copper = 0;
var iron = 0;
var cobalt = 0;
var gold = 0;
var platinum = 0;
var diamond = 0;
var reload = 10;
function buyMine(){
mines++;
money -= minesPrice;
minesPrice = minesPrice*2;
}
function loop(){
setInterval(function(){
refreshScreen();
},1000/reload)
}
function refreshScreen(){
minesCounter.innerHTML = mines;
if(money < minesPrice){
document.getElementById("buyMineButton").innerHTML = "<p class='button'>Buy mine Cost: <font id='minesPrice'></font></p>"
}else{
document.getElementById("buyMineButton").innerHTML = "<p class='buttonGreen' onclick='buyMine()'>Buy mine Cost: <font id='minesPrice'></font></p>"
}
document.getElementById("minesPrice").innerHTML = minesPrice;
}
loop();
1 Antwort
Das ständige Überschreiben sämtlicher Kindknoten ist ein unnötiger Aufwand, zumal dadurch auch immer die Event Handler neu gebunden werden müssen.
Die font-Tags können allesamt aus dem Dokument entfernt werden, denn sie gehören nicht zum Standard. Du kannst sie durch span-Tags ersetzen.
Des Weiteren würde sich ein button-Element semantisch doch viel besser eignen als ein Paragraph. Das visuelle Erscheinungsbild kann man mit CSS überschreiben.
<div>Mines: <span id="minesCounter">0</span></div>
<div>
<button class="button" id="buyMineButton" onclick="buyMine()" type="button">Buy mine Cost: <span id="minesPrice">1</span></button>
</div>
Die Elemente, die du immer wieder benötigst, würde ich global zwischenspeichern. So müssen sie nicht ständig neu im DOM gesucht werden. Ebenso brauchst du kein innerHTML-Property nutzen, wenn du stets nur Textknoten ändern möchtest.
const buyMineButton = document.getElementById("buyMineButton");
const minesPriceElement = document.getElementById("minesPrice");
let canBuy = true;
function refreshScreen() {
minesCounter.textContent = mines;
if (money < minesPrice) {
buyMineButton.setAttribute("class", "button");
canBuy = false;
}
else {
buyMineButton.setAttribute("class", "buttonGreen");
canBuy = true;
}
minesPriceElement.textContent = minesPrice;
}
Eine boolsche Variable kann als Kontrolleur dienen, ob der Nutzer derzeit Minen kaufen kann oder nicht. Folglich muss noch eine Zustandsabfrage in buyMine integriert werden.
Zu guter Letzt tut sich für mich die Frage auf, wozu du einen Timer (setInterval) startest. Für die Zustandsänderungen ist doch der Button zuständig. So lange der nicht betätigt wird, ändert sich auch nichts. Das heißt, die refreshScreen-Funktion könnte genauso gut am Ende von buyMine aufgerufen werden. So muss das DOM nur dann geändert werden, wenn es auch eine tatsächliche Änderung gibt.