Erste Schritte > Einleitung
1.0

Erste Schritte

In diesem Abschnitt erstellen wie das HTML-Dokument und definieren das grobe Layout.

Erstellung des Projekts

Zuerst erstellen wir das grobe Layout so kompakt wie möglich. Für die Konsole brauchen wir drei Abschnitte.

Einen Header für den Titel und eine Leiste aus Informationen wie Sie es von z.B. einem Smartphone gewöhnt sind. Die WiFi und Batterie Icons sind dabei nur für das Design und haben keine wirkliche Funktion. Die Uhr erstellen wir später mit PHP und JavaScript.

Im nächsten Abschnitt, wofür ich Main benutze, soll der eigentliche wichtige Inhalt enthalten sein: Die Auswahl der Spiele, die Anleitung und weiteres.

Im letzten Abschnitt, dem Footer, sind die Buttons die angeben welcher Inhalt ausgewählt ist, sowie die Angaben zur Steuerung. Also welcher Knopf gerade welche Funktion hat. Damit dieses Layout umgesetzt werden kann, brauchen wir noch einige weitere HTML-Tags.

Das erste Layout sieht so aus:

<!DOCTYPE html>
<html>
    <head>
        <meta charset="utf-8">
        <meta name="viewport" content="width=device-width, initial-scale=1">
        <title>Konsole</title>
    </head>
    <body>
        <header>
            <!-- Titel, WiFi, Batterie und Uhr -->
        </header>
        <main>
            <!-- Spiele, Anleitung, Farbmodus, Credits, usw. -->
        </main>
        <footer>
            <!-- Steuerung -->
        </footer>
    </body>
</html>

Gehen wir die Zeilen einzeln durch.

Zuerst lässt <!DOCTYPE html> den Browser wissen, dass es sich bei dem Dokument (der Webseite) um eine HTML5-konforme Datei handelt.

Danach öffnen und schließen wir einen <html></html> Tag. In diesem Tag schreiben wir nur zwei weitere Tags. Den <head></head> und den <body></body>. Im Head befinden sich Informationen über die Seite die nicht direkt auf dieser sichtbar sind. Dort binden wir z.B. Stylesheets und Skripte ein.

Der Tag <meta charset="utf-8"> definiert den Zeichensatz und wird benötigt um auf einer Webseite auch Umlaute anzuzeigen.

Der Tag <meta name="viewport" content="width=device-width, initial-scale=1"> wird genutzt um die größe der Webseite auch auf mobilen Endgeräten gut anzuzeigen.

Im Tag <title>Konsole</title> lässt sich der Titel der Webseite definieren. Da die Konsole Fullscreen genutzt werden sollte, ist der Titel nicht sichtbar.

Im <body></body> Tag befindet sich der sichtbare Inhalt der Seite. Im Body können beliebig viele weitere Tags geschrieben werden. Hier haben wir den Body in drei Abschnitte eingeteilt.

Layout vom Body

Nach der Erstellung des Projekts kümmern wir uns zuerst um das grobe Layout der Konsole. In dieser Phase ist es nicht wichtig wie die Seite aussieht, sondern ob die einzelnen Bereiche richtig angeordnet sind.

Momentan sieht das Layout auf der Seite so aus:

Body
Header
Main
Footer

Die Oberfläche soll den kompletten Umfang des Bildschirms umfassen, ohne dass der Inhalt aus dem Bildschirm überfließt und ein Scrollbalken erscheint. Mit dem CSS min-height: 100vh; lässt sich eine Größe nach den Bildschirm verwenden. Der Wert 100vh steht für 100% der ViewHeight.

body {
    min-height: 100vh;
}
Body
Header
Main
Footer

Jetzt ist der Body so groß wie der Bildschirm. Der Footer klebt jedoch immer noch an der Unterseite von Main. Je nachdem wie groß Main wird, verschiebt es den Footer mehr oder weniger weit nach unten. Hierfür brauchen wir zwei Schritte:

body {
    display: flex;
    flex-direction: column;
}
footer {
    margin-top: auto;
}
Body
Header
Main
Footer

Mit margin: auto versucht das Element soviel Abstand wie möglich zu anderen Elementen zu halten. Das funktioniert aber nur wenn das Element sich in einem Flex-container display: flex befindet. Die Standardausrichtung der Elemente ist flex-direction: row, was die Elemente horizontal in einer Linie ausrichtet. Um das zu überschreiben geben wir flex-direction: column an, damit die Elemente wie gewohnt nach unten gestapelt werden.

Mit margin-top: auto sagen wir der Footer soll soviel Abstand wie möglich nach oben haben und lassen die anderen Richtungen dabei normal. Der Footer springt jetzt immer an das Ende des Body, egal wie groß Main wird.

Damit ist unser grobes Layout auch schon fertig!

Layout vom Header

Zuerst gestalten wird den Header und arbeiten uns von oben nach unten durch.

header {
    padding: 0 10%;
}

#icon-panel {
    display: flex;
}

#icon-panel div:first-child {
    margin-left: auto;
}

#title {
    text-align: center;
}
<header>
    <div id="icon-panel">
        <div></div> <!-- WiFi -->
        <div></div> <!-- Batterie -->
        <div></div> <!-- Uhrzeit -->
    </div>
    <h1 id="title">Titel</h1>
</header>
Titel
Main
Footer

Zuerst geben wir dem Header etwas Padding. Damit kleben die Elemente im Header nicht direkt an den jeweiligen Seitenrändern, sondern haben auf beiden Seiten 10% Abstand. Im Fall von padding: 0 10%; beschreibt die erste Zahl Top und Bottom, die zweite Zahl Left und Right.

Das IconPanel wird auf display: flex; gesetzt, was die Elemente im IconPanel horizontal in einer Linie aufreiht.

Als nächstes setzen wir margin-left: auto; nur auf das erste div-Element im IconPanel. Wie beim Footer versucht es jetzt soviel Abstand zur linken Seite zu haben wie nur irgendwie möglich. Alle Elemente rutschen daher an die rechte Seite.

Der Text des H1 wird mit text-align: center; in die Mitte gesetzt. Das H1 als Element nimmt jedoch den kompletten verfügbaren Platz ein, wie es im Schaubild mit der Hintergrundfarbe des Titels gezeigt wird.

Layout vom Main

Jetzt gestalten wir den Hauptinhalt der Konsole. Hier sollen unterschiedliche Inhalte angezeigt werden, je nachdem welcher Menüpunkt gerade geöffnet ist, ohne dass wir dafür eine neue Seite laden.

Zuerst kümmern wir uns auch hier um das Layout und fügen die Funktion später mit JavaScript hinzu.

.panel {
    display: none;
}
<main>
    <div id="game-panel" class="panel selected"></div>
    <div id="guide-panel" class="panel"></div>
    <div id="color-panel" class="panel"></div>
    <div id="credits-panel" class="panel"></div>
    <div id="exit-panel" class="panel"></div>
</main>
Footer

Wir erstellen in Main fünf Elemente und geben vier davon die Klasse hidden. Damit sind diese Element auf display: none; gestellt. Die Elemente werden dann nicht angezeigt und verbrauchen auch keinen Platz.

Später schalten wir diese CSS-Klassen mit JavaScript um und geben allen Elementen die Klasse hidden, außer dem einen Element welches angezeigt werden soll.

Im Schaubild sehen Sie alle Elemente gestapelt in Main. In Wirklichkeit würde aber nur das erste Element angezeigt werden, da es die hidden Klasse nicht besitzt.

Funktion

Jetzt beginnen wir mit JavaScript und PHP um die Funktion der Konsole zu erstellen.

Menü

<div class="button" onclick="select(this, 0)"></div>
.button.selected { /* Zwischen den Klassen KEIN LEERZEICHEN! */
    background-color: blue;
    transform: translateY(-8px);
    transition: 200ms ease;
}

.panel.selected { /* Zwischen den Klassen KEIN LEERZEICHEN! */
    display: block;   
}
// document.getElementsByClassName() sucht alle Elemente
// mit der jeweiligen Klasse und
// erstellt eine Variable vom Typ HTMLCollection
// welche fast wie ein Array funktionieren
var buttons = document.getElementsByClassName("button");
var panels = document.getElementsByClassName("panel");

// element und index sind Platzhalter und
// sind bei jedem der Buttons unterschiedlich
function select(element, index) {
    removeAllSelection(buttons);
    removeAllSelection(panels);
    element.classList.add("selected");
    panels[i].classList.add("selected");
}

function removeAllSelection(elements) {
    for(var i = 0; i < elements.length; i++) {
        // Prüfe ob das Element an der Stelle in der HTMLCollection
        // die Klasse "selected" besitzt.
        if(elements[i].classList.contains("selected")) {
            // Wenn ja, entferne die Klasse
            elements[i].classList.remove("selected");
        }
    }
}
Spiele
Anleitung
Farbmodus
Credits
Ausschalten

Damit auch etwas passiert, wenn wir auf die Buttons drücken, geben wir den Elementen ein <div onclick="select(this, 0)"></div>, was bei einem Klick auf das Element die JavaScript Funktion select aufruft. Für jeden weiteren Button muss die 0 um Eins hochgesetzt werden.

Zuerst holen wir uns die HTML Elemente und speichern sie in einer Variable in JavaScript ab. Dazu nutzen wir document.getElementsByClassName(), was uns alle Elemente der Seite mit einer bestimmten Klasse als HTMLCollection in einer Variable speichert. Diese Elemente sind jetzt wie ein Array ansprechbar. Um den ersten Button auszuwählen, nutzen wir buttons[0] und für den dritten Button buttons[2], usw. Das gleiche machen wir mit den Panels die sich in Main befinden.

Die Funktion select() nimmt zwei Parameter, welche als Platzhalter dienen. Jeder Button wirft sich selbst mit this in die Funktion und landet dann an der Stelle von element im Code. Die Buttons geben auch jeweils eine Zahl von 0 bis 4 mit in die Funktion, welche die Stelle von index belegt.

Die zweite Funktion removeAllSelection() nimmt ebenfalls einen Platzhalter als Parameter. Diese Funktion wird innerhalb von select() zweimal aufgerufen. Einmal übergeben wir die Buttons und das andere Mal die Panels. Hier werden zuerst von allen Elementen die Klasse selected entfernt.

Danach fügen wir mit element.classList.add("selected"); die Klasse dem jeweiligen gedrückten Button hinzu. Die Panels wählen wir wie ein Array mit dem übergebenen Index panels[index].classList.add("selected"); aus.

Die Klasse selected macht mit dem Button und den Panels unterschiedliche Dinge. Im Stylesheet haben wir .button.selected {} und .panel.selected {} ohne Leerzeichen geschrieben. Das bedeutet das CSS in den geschweiften Klammern soll nur auf Elemente angewandt werden die BEIDE Klassen besitzen. Für einen Button mit Selected ändern wir die Farbe und Position, für ein Panel mit Selected überschreiben wir display: none; mit display: block; und machen es dadurch sichtbar.

Klicke auf die Buttons im Footer des Schaubildes um den Inhalt von Main zu wechseln. Damit deutlicher wird das der komplette Inhalt wechselt und nicht nur der Text, habe ich den einzelnen Panel noch eine unterschiedliche Höhe mitgegeben.

Spiele

Als nächstes kommen die Spiele.

#game-panel {
    display: flex;
    flex-direction: column;
    align-content: flex-start;
    flex-wrap: wrap; /* Wichtig! */
    max-height: 450px; /* Wichtig! */
}

.game {
    height: 100px; /* Kann angepasst werden */
    width: 100px; /* Kann angepasst werden */
    background: grey; /* Beliebige Farbe */
}
<div id="game-panel" class="panel selected">
<?php
    // Speichere den Pfad der Projekte in einer Variable
    $dir = "./projekte/";

    // Scanne den Pfad nach Inhalt
    // Hier bekommen wir die Ordner der Spiele als Array
    $scan = scandir($dir);

    // Entferne "." und ".." aus dem Array
    // Das ist das Root und übergeordente Verzeichnis
    $cut = array_slice($scan, 2);
    
    // Für jeden der gefundenen Ordner einen Schleifendurchlauf
    foreach($cut as $game) {
        // Gibt einen Link mit dem Pfad zum Spiel
        // Echo schreibt einen Tag direkt ins HTML Dokument
        echo "<a class='game' href='projekte/{$game}/index.html'>
            {$game}
        </a>";
    }
?>
</div>
0
1
2
3
Anleitung
Farbmodus
Credits
Ausschalten

Hierzu brauchen wir einen Ordner "projekte" im Verzeichnis der Konsole. In diesem Ordner befinden sich die von Clickteam Fusion erstellten Spiele.

Darkmode

:root {
    --background: #121212;
    --component: #212121;
    --text: #fff;
}

.body {
    background-color: var(--background);
    color: var(--text);
}

.game {
    background-color: var(--component);
}
<div id="color-panel" class="panel">
    <div class="row"> <!-- Klasse "row" beinhaltet nur display: flex; -->
        <div class="color-btn" onclick="changeMode('dark')">Dark</div>
        <div class="color-btn" onclick="changeMode('light')">Light</div>
    </div>
</div>
function changeMode(mode) {
    if(mode == "light") {
        document.documentElement.style.setProperty('--background', '#eee');
        document.documentElement.style.setProperty('--component', '#fff');
        document.documentElement.style.setProperty('--text', '#212121');
    } else if(mode == "dark") {
        document.documentElement.style.setProperty('--background', '#121212');
        document.documentElement.style.setProperty('--component', '#212121');
        document.documentElement.style.setProperty('--text', '#fff');
    }
}
Anleitung
Light
Dark
Credits
Ausschalten

Die Änderung der Textfarbe funktioniert auf die gleiche Weise.

Neben diesen zwei Funktionen werde ich die Anleitung, Credits und das Verlassen nicht mehr erklären.

IFrame

Das <iframe></iframe> werde ich in der nächsten Version erklären. Es gibt da nämlich noch ein großes Problem mit den Spielen. Wenn wir einen Link klicken, werden wir zu der erstellten Seite von Clickteam Fusion weitergeleitet. Von dort aus kommen wir aber nicht mehr zurück zur Konsole. Über die Steuerung im Browser funktioniert das natürlich prima. Die Konsole soll aber nur im Vollbildmodus und per Controller gesteuert werden und in jedem einzelnen erstellten Spiel ein Skript hinzuzufügen, welches uns wieder zur Startseite der Konsole bringt, wäre zu viel Arbeit.

Mit einem IFrame können wir eine andere Webseite innerhalb des IFrame laden. Wir erstellen dabei nur eine einzige game.php in der sich ein IFrame befindet, welches dann die eigentlichen Spiele lädt. In der game.php befindet sich dann das Skript um wieder mit dem Controller zur Startseite zurückzukehren.

Controller

Die Konsole funktioniert bisher gut mit der Maus.

function selectNext(elements, next) {
    for(var i = 0; i < elements.length; i++) {
        if(elements[i].classList.contains("selected")) {
            // Prüfen ob das nächste Element existiert
            if(elements[i + next] !== undefined ) {
                elements[i].classList.remove("selected");
                if(elements[i].classList.contains("game")) {
                    element[i + next].classList.add("selected");
                }
                if(elements[i].classList.contains("button")) {
                    elements[i + next].click(); // Simuliert einen Klick
                }
            }
            return; // Wichtig um die Schleife zu beenden
            // break; würde auch funktionieren
        }
    }
}

// Auf Tastatureingabe reagieren
window.addEventListener("keydown", function(event) {
    switch(event.key) {
        case "r":
            selectMenu(buttons, 1);
            break;
        case "l":
            selectMenu(buttons, -1);
            break;
    }

    // Nur wenn das GamePanel auch ausgewählt ist
    if(panels[0].classList.contains("selected")) {
        switch(event.key) {
            case "w":
                selectNext(games, -1);
                break;
            case "s":
                selectNext(games, 1);
                break;
            case "a":
                selectNext(games, -2);
                break;
            case "d":
                selectNext(games, 2);
                break;
        }
    }
});
Anleitung
Light
Dark
Credits
Ausschalten

Alles was jetzt noch fehlt, ist den Controller zu mappen.

Die Auswahl der Spiele funktioniert ähnlich.