Kleiner JavaScript Kurs

Spiel: Mondlandung

Die Computersimulation einer Mondlandung ist ein sehr altes Spiel, dass es schon auf den ersten Homecomputern gab. Wir wollen das Spiel zunächst als Textsimulation programmieren und später noch eine Grafik mit einem Canvas hinzufügen. Diese Anleitung wurde in Anlehnung an den entsprechenden Artikel im Buch "Programmieren lernen mit JavaScript" von Stephan Elter erstellt.
Wir befinden uns mit unserem Raumsciff im Landeanflug Richtung Mond. Wir befinden uns 500 m über dem Mond, wir nähern uns dem Mond mit einer Geschwindigkeit von -50 m pro Zeiteinheit (z.B. Sekunde bei uns pro Spielrunde ...). Zum Abbremsen können wir ein Triebwerk verwenden, haben aber nur noch 200 Einheiten Treibstoff. Durch die Anziehungskraft des Mondes steigt unsere Geschwindigkeit um g = 5 (m/s). Unsere html - Seite könnte so aussehen:

Wir haben eine h1 - Überschrift und ein Ausgabefeld, in dem wir in jeder Spielrunde die Geschwindigkeit, die Höhe und den Treibstoffvorrat ausgeben.

<!DOCTYPE html>
<html lang="de">
    <head>
        <meta charset="utf-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>Mondlandung</title> 
    </head>
    <body>
        <h1>Mondlandung</h1>
        <p id="ausgabefeld"></p>

        <script>
            
        </script>

    </body>
</html>

Jetzt beginnen wir mit der Programmierung. Zunähst werden die globalen Variablen mit ihren Startwerten definiert. Außerdem wird das Ausgabefeld - Objekt angelegt und die Funktion ausgabe() aufgerufen (damit wir die Startwerte sehen).
<script>
    var speed = -50;
    var treibstoff = 200;
    var hoehe = 500;
    var g = 5;
    var ausgabefeld = document.getElementById("ausgabefeld");
    ausgabe();
</script>

Die Funktion ausgabe() könnte folgendermaßen aussehen:
function ausgabe() {
    var info = "Geschwindigkeit: " + speed;
    info += "
Treibstoff: " + treibstoff; info += "
Höhe: " + hoehe; ausgabefeld.innerHTML = info; }

Die nächste Funktion soll alle Parameter (Geschwindigkeit, Höhe, Treibstoff) bei jeder Spielrunde neu berechnen. Die Höhe nimmt, je nach Geschwindigkeit, von Runde zu Runde ab (wir nähern uns dem Mond und sollten bei 0 m / Landung nicht mehr zu schnell sein). Die Geschwindigkeit wird von Runde zu Runde höher ( + 5 m/s = g). Durch die Zündung der Bremstriebwerke (mit Treibstoffverbrauch) - wir geben dazu bei jeder Spielrunde den Treibstoff ein, den wir zum Bremsen nutzen wollen - können wir die Geschwindigkeit (und den Treibstoff) reduzieren.
function neuberechnung(schub) {
    hoehe = hoehe + speed + schub / 2;
    treibstoff = treibstoff - schub;
    speed = speed -g + schub;
}

Die Eingabefunktion für den Schub der Bremsraketen realisieren wir mit einem prompt() Dialog (die Eingabe in ein input - Feld auf der html - Seite wäre ebenfalls möglich).
function eingabe() {
    var schub = parseInt(prompt("Treibstoff", 0));
    return schub;
}
Du soltest den eingegebenen Wert noch überprüfen. Texte werden durch die parseInt - Funktion verhindert. Es dürfen aber auch keine negativen Werte eingegeben werden und der Wert darf auch nicht größer sein, als der Treibstoffvorrat.


Zum Abschluss fehlt noch eine Funktion zur Flugkontrolle (sind wir noch in der Luft?, wie war die Landung?, mit welcher Geschwindigkeit sind wir auf dem Boden aufgekommen?, ...) und das "Hauptprogramm", eine Spielschleife (gameLoop()) in der alle Funktionen nacheinander aufgerufen werden. Die Funktion gameLoop() rufen wir mit 1/2 Sekunde (500 ms) Verzögerung auf, damit wir uns den aktuellen Stand (Höhe, Geschw., Treibstoff) in Ruhe ansehen können.
function gameLoop() {
    var eingegebenerSchub = eingabe();
    neuberechnung(eingegebenerSchub);
    ausgabe();
    flugKontrolle();
}
function flugKontrolle() {
    if (hoehe > 1) {
        setTimeout(gameLoop, 500);
    } else {
        if (hoehe > -5 && Math.abs(speed) < 10) {
            ausgabe();
            ausgabefeld.innerHTML += "<br>Geschafft!";
        } else {
            ausgabe();
            ausgabefeld.innerHTML += "<br>*Bruchlandung*";
        }
    }
}
Eine Landung mit einem kleinen Krater (kleiner 5 m bei einer Geschwindigkeit kleiner 10 m/s wird von den Stoßdämpfern abgefangen. Sind wir schneller oder ist der Krater tiefer war's eine Bruchlandung.


So könnte es aussehen: Mondlandung_02.html

Hier die HTML-Seite mit dem kompletten Programm


<!DOCTYPE html>
<html lang="de">
    <head>
        <meta charset="utf-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>Mondlandung</title> 
    </head>
    <body>
        <h1>Mondlandung</h1>
        <p id="ausgabefeld"></p>

        <script>
            var speed = -50;
            var treibstoff = 200;
            var hoehe = 500;
            var g = 5;
			var ausgabefeld = document.getElementById("ausgabefeld");
            ausgabe();
            setTimeout(gameLoop, 500);
            
            function gameLoop() {
                var eingegebenerSchub = eingabe();
                neuberechnung(eingegebenerSchub);
                ausgabe();
                flugKontrolle();
            }
            
            function ausgabe() {
                var info = "Geschwindigkeit: " + speed;
                info += "<br>Treibstoff: " + treibstoff;
                info += "<br>Höhe: " + hoehe;
                ausgabefeld.innerHTML = info;
            }

            function flugKontrolle() {
                if (hoehe > 1) {
                    setTimeout(gameLoop, 500);
                } else {
                    if (hoehe > -5 && Math.abs(speed) < 10) {
                        ausgabe();
                        ausgabefeld.innerHTML += "<br>Geschafft!";
                    } else {
                        ausgabe();
                        ausgabefeld.innerHTML += "<br>*Bruchlandung*";
                    }
                }
            }
            
            function eingabe() {
                var schub = prompt("Treibstoff", 0);
                schub = Math.abs(schub);
                if (isNaN(schub)) {
                    schub = 0;
                }
                if (schub > treibstoff)
                {
                    schub = treibstoff;
                }
                return schub;
            }
            
            function neuberechnung(schub) {
                hoehe = hoehe + speed + schub / 2;
                treibstoff = treibstoff - schub;
                speed = speed -g + schub;
            }
        </script>

    </body>
</html> 

Als Erweiterung könnte man die Landung in einem Canvas grafisch darstellen. Ein Bild für die Landefähre liegt im Ordner "images/lander.gif" (128 x 96 px)


Mit der folgenden Funktion kann man das Canvas löschen und den Lander an der Position x/y anzeigen.

function lander_anzeigen(x, y){
  var lander = new Image();
  lander.src = "images/lander.gif";
  var landerBreite=128;
  var landerHoehe=96;
  lander.onload = function() {
      ctx.fillRect(0, 0, cbreite, choehe);
      ctx.drawImage(lander, x-landerBreite, y-landerHoehe, landerBreite/2, landerHoehe/2);
              }
}