Wenn Sie einen Controller anschließen, drücken Sie Tasten, bewegen die Steuerknüppel, betätigen die Auslöser … und als Entwickler sehen Sie nichts davon. Der Browser erkennt es zwar, aber solange Sie die Zahlen nicht in der Konsole protokollieren, ist es unsichtbar. Das ist das Problem mit der Gamepad-API. Es gibt es schon seit Jahren und es ist tatsächlich ziemlich mächtig. Sie können Knöpfe, Stöcke, Auslöser und die Funktionsweise lesen. Aber die meisten Leute fassen es nicht an. Warum? Weil es kein Feedback gibt. Kein Panel in den Entwicklertools. Es gibt keine klare Möglichkeit herauszufinden, ob der Controller überhaupt das tut, was Sie denken. Es fühlt sich an wie ein Blindflug. Das hat mich so sehr genervt, dass ich ein kleines Tool entwickelt habe: den Gamepad Cascade Debugger. Anstatt auf die Konsolenausgabe zu starren, erhalten Sie eine interaktive Live-Ansicht des Controllers. Drücken Sie etwas und es reagiert auf dem Bildschirm. Und mit CSS Cascade Layers bleiben die Stile organisiert, sodass das Debuggen einfacher ist. In diesem Beitrag zeige ich Ihnen, warum das Debuggen von Controllern so mühsam ist, wie CSS dabei hilft, es zu bereinigen, und wie Sie einen wiederverwendbaren visuellen Debugger für Ihre eigenen Projekte erstellen können.

Selbst wenn Sie alle protokollieren können, erhalten Sie schnell unlesbaren Konsolen-Spam. Zum Beispiel: [0,0,1,0,0,0,5,0,...] [0,0,0,0,1,0,0,...] [0,0,1,0,0,0,0,...]

Können Sie erkennen, welcher Knopf gedrückt wurde? Vielleicht, aber nur, nachdem Sie Ihre Augen angestrengt und ein paar Eingaben verpasst haben. Nein, das Debuggen ist nicht einfach, wenn es um das Lesen von Eingaben geht. Problem 3: Mangelnde Struktur Selbst wenn Sie eine schnelle Visualisierung zusammenstellen, können Stile schnell unübersichtlich werden. Standard-, Aktiv- und Debug-Zustände können sich überschneiden, und ohne eine klare Struktur wird Ihr CSS brüchig und lässt sich nur schwer erweitern. CSS-Kaskadenebenen können helfen. Sie gruppieren Stile in „Ebenen“, die nach Priorität geordnet sind, sodass Sie nicht mehr gegen Spezifität kämpfen und raten müssen: „Warum wird mein Debug-Stil nicht angezeigt?“ Stattdessen vertreten Sie separate Bedenken:

Basis: Das standardmäßige, anfängliche Erscheinungsbild des Controllers. Aktiv: Hervorhebungen für gedrückte Tasten und bewegte Sticks. Debug: Overlays für Entwickler (z. B. numerische Anzeigen, Anleitungen usw.).

Wenn wir Ebenen in CSS entsprechend definieren würden, hätten wir: /* niedrigste bis höchste Priorität */ @layer base, aktiv, debuggen;

@layer base { /* ... */ }

@layer aktiv { /* ... */ }

@layer debug { /* ... */ }

Da jede Schicht vorhersehbar stapelbar ist, wissen Sie immer, welche Regeln gewinnen. Diese Vorhersehbarkeit macht das Debuggen nicht nur einfacher, sondern auch überschaubar. Wir haben das Problem (unsichtbare, unordentliche Eingabe) und den Ansatz (ein mit Cascade Layers erstellter visueller Debugger) behandelt. Jetzt gehen wir Schritt für Schritt durch den Prozess zum Erstellen des Debuggers. Das Debugger-Konzept Der einfachste Weg, versteckte Eingaben sichtbar zu machen, besteht darin, sie einfach auf dem Bildschirm zu zeichnen. Genau das macht dieser Debugger. Alle Tasten, Auslöser und Joysticks werden visuell dargestellt.

Drücken Sie A: Ein Kreis leuchtet auf. Stupse den Stock an: Der Kreis gleitet herum. Drücken Sie einen Abzug zur Hälfte: Ein Balken füllt sich zur Hälfte.

Jetzt starren Sie nicht mehr auf Nullen und Einsen, sondern beobachten tatsächlich, wie der Controller live reagiert. Sobald Sie anfangen, Zustände wie „Standard“, „Gedrückt“, „Debug-Info“ und vielleicht sogar einen Aufnahmemodus anzuhäufen, wird das CSS natürlich größer und komplexer. Hier kommen Kaskadenschichten zum Einsatz. Hier ist ein vereinfachtes Beispiel: @layer base { .button { Hintergrund: #222; Randradius: 50 %; Breite: 40px; Höhe: 40px; } }

@layer aktiv { .button.pressed { Hintergrund: #0f0; /* leuchtendes Grün */ } }

@layer debug { .button::after { Inhalt: attr(Datenwert); Schriftgröße: 12px; Farbe: #fff; } }

Die Ebenenreihenfolge ist wichtig: Basis → Aktiv → Debug.

Base zeichnet den Controller. active behandelt gedrückte Zustände. Debug löst Overlays aus.

Eine solche Aufteilung bedeutet, dass Sie keine seltsamen Spezifitätskriege führen. Jede Ebene hat ihren Platz und Sie wissen immer, was gewinnt. Es ausbauen Lassen Sie uns zuerst etwas auf den Bildschirm bringen. Es muss nicht gut aussehen – es muss nur existieren, damit wir etwas haben, mit dem wir arbeiten können.

Gamepad Cascade Debugger

A
B
X

Debugger inaktiv

Das sind im wahrsten Sinne des Wortes nur Kisten. Noch nicht aufregend, aber es gibt uns Griffe, die wir später mit CSS und JavaScript erlernen können. Okay, ich verwende hier Kaskadenebenen, weil sie für Ordnung sorgen, sobald Sie weitere Zustände hinzufügen. Hier ist ein grober Überblick:

/* ================================== Kaskadenebenen-Setup Die Reihenfolge ist wichtig: Basis → Aktiv → Debug ================================== */

/* Ebenenreihenfolge im Voraus definieren */ @layer base, aktiv, debuggen;

/* Ebene 1: Basisstile – Standardaussehen */ @layer base { .button { Hintergrund: #333; Randradius: 50 %; Breite: 70px; Höhe: 70px; Anzeige: Flex; rechtfertigen-Inhalt: Mitte; align-items: center; }

.pause { Breite: 20px; Höhe: 70px; Hintergrund: #333; Anzeige: Inline-Block; } }

/* Schicht 2: Aktive Zustände – verarbeitet gedrückte Tasten */ @layer aktiv { .button.active { Hintergrund: #0f0; /* Hellgrün, wenn gedrückt */ transformieren: Skala(1.1); /* Vergrößert die Schaltfläche leicht */ }

.pause.active { Hintergrund: #0f0; transform: scaleY(1.1); /* Wird beim Drücken vertikal gedehnt */ } }

/* Schicht 3: Debug-Overlays – Entwicklerinformationen */ @layer debug { .button::after { Inhalt: attr(Datenwert); /* Zeigt den numerischen Wert */ Schriftgröße: 12px; Farbe: #fff; } }

Das Schöne an diesem Ansatz ist, dass jede Ebene einen klaren Zweck hat. Die Basisschicht kann niemals „aktiv“ überschreiben, und „aktiv“ kann niemals das Debuggen überschreiben, unabhängig von der Spezifität. Dies eliminiert die CSS-Spezifitätskriege, die normalerweise Debugging-Tools plagen. Jetzt sieht es so aus, als ob einige Cluster auf einem dunklen Hintergrund sitzen würden. Ehrlich gesagt, nicht so schlimm.

Hinzufügen des JavaScript JavaScript-Zeit. Hier tut der Controller tatsächlich etwas. Wir werden dies Schritt für Schritt aufbauen. Schritt 1: Statusverwaltung einrichten Zunächst benötigen wir Variablen, um den Status des Debuggers zu verfolgen: // ================================== // STAATLICHE VERWALTUNG // ==================================

let run = false; // Verfolgt, ob der Debugger aktiv ist lass RafId; // Speichert die requestAnimationFrame-ID für den Abbruch

Diese Variablen steuern die Animationsschleife, die kontinuierlich die Gamepad-Eingaben liest. Schritt 2: Besorgen Sie sich DOM-Referenzen Als Nächstes erhalten wir Verweise auf alle HTML-Elemente, die wir aktualisieren werden: // ================================== // DOM-ELEMENT-REFERENZEN // ==================================

const btnA = document.getElementById("btn-a"); const btnB = document.getElementById("btn-b"); const btnX = document.getElementById("btn-x"); const pause1 = document.getElementById("pause1"); const pause2 = document.getElementById("pause2"); const status = document.getElementById("status");

Das Speichern dieser Referenzen im Voraus ist effizienter als das wiederholte Abfragen des DOM. Schritt 3: Tastatur-Fallback hinzufügen Zum Testen ohne physischen Controller ordnen wir Tastaturtasten den Tasten zu: // ================================== // KEYBOARD FALLBACK (zum Testen ohne Controller) // ==================================

const keyMap = { „a“: btnA, „b“: btnB, „x“: btnX, „p“: [pause1, pause2] // Die Taste „p“ steuert beide Pausenleisten };

Dadurch können wir die Benutzeroberfläche testen, indem wir Tasten auf einer Tastatur drücken. Schritt 4: Erstellen Sie die Hauptaktualisierungsschleife Hier passiert die Magie. Diese Funktion läuft kontinuierlich und liest den Gamepad-Status: // ================================== // Haupt-Gamepad-Update-Schleife // ==================================

Funktion updateGamepad() { // Alle angeschlossenen Gamepads abrufen const gamepads = navigator.getGamepads(); if (!gamepads) return;

// Benutze das erste verbundene Gamepad const gp = Gamepads[0];

if (gp) { // Schaltflächenzustände durch Umschalten der „aktiven“ Klasse aktualisieren btnA.classList.toggle("active", gp.buttons[0].pressed); btnB.classList.toggle("active", gp.buttons[1].pressed); btnX.classList.toggle("active", gp.buttons[2].pressed);

// Behandeln Sie die Pause-Taste (Tastenindex 9 auf den meisten Controllern) const pausePressed = gp.buttons[9].pressed; pause1.classList.toggle("active", pausePressed); pause2.classList.toggle("active", pausePressed);

// Erstellen Sie eine Liste der aktuell gedrückten Tasten zur Statusanzeige gedrückt halten = []; gp.buttons.forEach((btn, i) => { if (btn.pressed)pressed.push("Button " + i); });

// Statustext aktualisieren, wenn irgendwelche Tasten gedrückt werden if (pressed.length > 0) { status.textContent = "Gedrückt: " + gedrückt.join(", "); } }

// Schleife fortsetzen, wenn der Debugger läuft if (running) { rafId = requestAnimationFrame(updateGamepad); } }

Die Methode classList.toggle() fügt die aktive Klasse hinzu oder entfernt sie, je nachdem, ob die Schaltfläche gedrückt wird, wodurch unsere CSS-Ebenenstile ausgelöst werden. Schritt 5: Behandeln Sie Tastaturereignisse Diese Ereignis-Listener sorgen dafür, dass der Tastatur-Fallback funktioniert: // ================================== // TASTATUR-EVENT-HANDLER // ==================================

document.addEventListener("keydown", (e) => { if (keyMap[e.key]) { // Einzelne oder mehrere Elemente verarbeiten if (Array.isArray(keyMap[e.key])) { keyMap[e.key].forEach(el => el.classList.add("active")); } sonst { keyMap[e.key].classList.add("active"); } status.textContent = "Taste gedrückt: " + e.key.toUpperCase(); } });

document.addEventListener("keyup", (e) => { if (keyMap[e.key]) { // Aktiven Zustand entfernen, wenn die Taste losgelassen wird if (Array.isArray(keyMap[e.key])) { keyMap[e.key].forEach(el => el.classList.remove("active")); } sonst { keyMap[e.key].classList.remove("active"); } status.textContent = "Schlüssel freigegeben: " + e.key.toUpperCase(); } });

Schritt 6: Start/Stopp-Steuerung hinzufügen Schließlich benötigen wir eine Möglichkeit, den Debugger ein- und auszuschalten: // ================================== // Debugger ein-/ausschalten // ==================================

document.getElementById("toggle").addEventListener("click", () => { running = !running; // Den laufenden Zustand umdrehen

if (running) { status.textContent = „Debugger läuft …“; updateGamepad(); // Update-Schleife starten } sonst { status.textContent = „Debugger inaktiv“; cancelAnimationFrame(rafId); // Stoppen Sie die Schleife } });

Also ja, drücken Sie einen Knopf und es leuchtet. Drücken Sie den Stick und er bewegt sich. Das ist es. Noch etwas: Rohwerte. Manchmal möchte man einfach nur Zahlen sehen, keine Lichter.

Zu diesem Zeitpunkt sollten Sie Folgendes sehen:

Ein einfacher On-Screen-Controller, Schaltflächen, die reagieren, wenn Sie mit ihnen interagieren, und Eine optionale Debug-Anzeige, die die Indizes der gedrückten Tasten anzeigt.

Um dies weniger abstrakt zu gestalten, finden Sie hier eine kurze Demo der Reaktion des Bildschirmcontrollers in Echtzeit:

Wenn Sie nun auf „Aufzeichnung starten“ klicken, wird alles protokolliert, bis Sie auf „Aufzeichnung beenden“ klicken. 2. Exportieren von Daten nach CSV/JSON Sobald wir ein Protokoll haben, möchten wir es speichern.

Schritt 1: Erstellen Sie den Download-Helper Zunächst benötigen wir eine Hilfsfunktion, die das Herunterladen von Dateien im Browser verwaltet: // ================================== // DATEI-DOWNLOAD-HELFER // ==================================

Funktion downloadFile(filename, content, type = "text/plain") { // Erstelle einen Blob aus dem Inhalt const blob = new Blob([content], { type }); const url = URL.createObjectURL(blob);

// Einen temporären Download-Link erstellen und darauf klicken const a = document.createElement("a"); a.href = url; a.download = Dateiname; a.click();

// Bereinigen Sie die Objekt-URL nach dem Download setTimeout(() => URL.revokeObjectURL(url), 100); }

Diese Funktion funktioniert, indem sie aus Ihren Daten einen Blob (binäres großes Objekt) erstellt, eine temporäre URL dafür generiert und programmgesteuert auf einen Download-Link klickt. Durch die Bereinigung wird sichergestellt, dass kein Speicher verloren geht. Schritt 2: JSON-Export durchführen JSON eignet sich perfekt zum Erhalt der kompletten Datenstruktur:

// ================================== // ALS JSON EXPORTIEREN // ==================================

document.getElementById("export-json").addEventListener("click", () => { // Überprüfen Sie, ob etwas zum Exportieren vorhanden ist if (!frames.length) { console.warn("Keine Aufnahme zum Exportieren verfügbar."); Rückkehr; }

// Eine Nutzlast mit Metadaten und Frames erstellen const Nutzlast = { createdAt: new Date().toISOString(), Rahmen };

// Als formatiertes JSON herunterladen downloadFile( „gamepad-log.json“, JSON.stringify(Nutzlast, null, 2), „application/json“ ); });

Das JSON-Format sorgt dafür, dass alles strukturiert und leicht zu analysieren ist, sodass es sich ideal zum Zurückladen in Entwicklungstools oder zum Teilen mit Teamkollegen eignet. Schritt 3: CSV-Export durchführen Für CSV-Exporte müssen wir die hierarchischen Daten in Zeilen und Spalten reduzieren:

//================================== // ALS CSV EXPORTIEREN // ==================================

document.getElementById("export-csv").addEventListener("click", () => { // Überprüfen Sie, ob etwas zum Exportieren vorhanden ist if (!frames.length) { console.warn("Keine Aufnahme zum Exportieren verfügbar."); Rückkehr; }

// CSV-Kopfzeile erstellen (Spalten für Zeitstempel, alle Schaltflächen, alle Achsen) const headerButtons = frames[0].buttons.map((_, i) => btn${i}); const headerAxes = frames[0].axes.map((_, i) => axis${i}); const header = ["t", ...headerButtons, ...headerAxes].join(",") + "\n";

// CSV-Datenzeilen erstellen const rows = frames.map(f => { const btnVals = f.buttons.map(b => b.value); return [f.t, ...btnVals, ...f.axes].join(","); }).join("\n");

// Als CSV herunterladen downloadFile("gamepad-log.csv", header + rows, "text/csv"); });

CSV eignet sich hervorragend für die Datenanalyse, da es direkt in Excel oder Google Sheets geöffnet wird und Sie Diagramme erstellen, Daten filtern oder Muster visuell erkennen können. Da nun die Schaltflächen zum Exportieren aktiviert sind, werden im Bedienfeld zwei neue Optionen angezeigt: „JSON exportieren“ und „CSV exportieren“. JSON ist nützlich, wenn Sie das Rohprotokoll zurück in Ihre Entwicklungstools werfen oder in der Struktur herumstöbern möchten. CSV hingegen wird direkt in Excel oder Google Sheets geöffnet, sodass Sie Eingaben grafisch darstellen, filtern oder vergleichen können. Die folgende Abbildung zeigt, wie das Bedienfeld mit diesen zusätzlichen Steuerelementen aussieht.

3. Snapshot-System Manchmal benötigen Sie keine vollständige Aufzeichnung, sondern nur einen kurzen „Screenshot“ des Eingabestatus. Hier hilft die Schaltfläche „Schnappschuss erstellen“.

Und das JavaScript:

// ================================== // SCHNAPPSCHUSS MACHEN // ==================================

document.getElementById("snapshot").addEventListener("click", () => { // Alle angeschlossenen Gamepads abrufen const pads = navigator.getGamepads(); const activePads = [];

// Durchlaufen und Erfassen des Status jedes angeschlossenen Gamepads for (const gp of Pads) { if (!gp) continue; // Leere Slots überspringen

activePads.push({ id: gp.id, // Controller-Name/Modell Zeitstempel: performance.now(), Schaltflächen: gp.buttons.map(b => ({ gedrückt: b.gepresst, Wert: b.value })), Achsen: [...gp.axes] }); }

// Überprüfen Sie, ob Gamepads gefunden wurden if (!activePads.length) { console.warn("Keine Gamepads für Snapshot angeschlossen."); alarm("Kein Controller erkannt!"); Rückkehr; }

// Benutzer protokollieren und benachrichtigen console.log("Snapshot:", activePads); Alert(Schnappschuss gemacht! ${activePads.length} Controller erfasst.); });

Snapshots frieren den genauen Zustand Ihres Controllers zu einem bestimmten Zeitpunkt ein. 4. Ghost-Eingabewiederholung Nun zum Spaß: Wiederholung der Ghost-Eingabe. Dadurch wird ein Protokoll erstellt und visuell wiedergegeben, als ob ein Phantomspieler den Controller verwenden würde.

JavaScript zur Wiedergabe: // ================================== // GHOST REPLAY // ==================================

document.getElementById("replay").addEventListener("click", () => { // Stellen Sie sicher, dass wir eine Aufnahme zur Wiedergabe haben if (!frames.length) { alarm("Keine Aufnahme zum Wiedergeben!"); Rückkehr; }

console.log("Ghost Replay wird gestartet...");

// Track-Timing für synchronisierte Wiedergabe let startTime = performance.now(); sei FrameIndex = 0;

// Animationsschleife wiedergeben Funktion step() { const now = performance.now(); const elapsed = now - startTime;

// Alle Frames verarbeiten, die inzwischen aufgetreten sein sollten while (frameIndex < Frames.Length && Frames[FrameIndex].t <= Elapsed) { const Frame = Frames[FrameIndex];

// Benutzeroberfläche mit den aufgezeichneten Schaltflächenzuständen aktualisieren btnA.classList.toggle("active", frame.buttons[0].pressed); btnB.classList.toggle("active", frame.buttons[1].pressed); btnX.classList.toggle("active", frame.buttons[2].pressed);

// Statusanzeige aktualisieren gedrückt halten = []; frame.buttons.forEach((btn, i) => { if (btn.pressed) pressed.push("Button " + i); }); if (pressed.length > 0) { status.textContent = "Ghost: " +pressed.join(", "); }

FrameIndex++; }

// Schleife fortsetzen, wenn mehr Frames vorhanden sind if (frameIndex

// Wiedergabe starten Schritt(); });

Um das Debuggen etwas praktischer zu gestalten, habe ich eine Geisterwiedergabe hinzugefügt. Sobald Sie eine Sitzung aufgezeichnet haben, können Sie auf „Wiederholen“ klicken und zusehen, wie die Benutzeroberfläche sie ausführt, fast so, als würde ein Phantomspieler das Pad bedienen. Hierfür wird im Bedienfeld eine neue Schaltfläche „Replay Ghost“ angezeigt.

Klicken Sie auf „Aufnahme“, experimentieren Sie ein wenig mit dem Controller, halten Sie an und wiederholen Sie die Wiedergabe. Die Benutzeroberfläche spiegelt einfach alles wider, was Sie getan haben, wie ein Geist, der Ihren Eingaben folgt. Warum sich mit diesen Extras beschäftigen?

Durch die Aufzeichnung/Exportierung können Tester ganz einfach genau zeigen, was passiert ist. Snapshots frieren einen Moment ein, was besonders nützlich ist, wenn Sie seltsame Fehler jagen. Ghost Replay eignet sich hervorragend für Tutorials, Barrierefreiheitsprüfungen oder einfach zum Vergleichen von Steuerungseinstellungen nebeneinander.

An diesem Punkt handelt es sich nicht mehr nur um eine nette Demo, sondern um etwas, das Sie tatsächlich umsetzen können. Anwendungsfälle aus der Praxis Jetzt haben wir diesen Debugger, der viel kann. Es zeigt Live-Eingaben an, zeichnet Protokolle auf, exportiert sie und spielt sogar Dinge ab. Aber die eigentliche Frage ist: Wen interessiert das eigentlich? Für wen ist das nützlich? Spieleentwickler Controller gehören zum Job, aber sie zu debuggen? Normalerweise ein Schmerz. Stellen Sie sich vor, Sie testen eine Kampfspielkombination wie ↓ → + Schlag. Anstatt zu beten, drücken Sie zweimal auf die gleiche Weise, nehmen es einmal auf und spielen es erneut ab. Fertig. Oder Sie tauschen JSON-Protokolle mit einem Teamkollegen aus, um zu überprüfen, ob Ihr Multiplayer-Code auf dessen Computer gleich reagiert. Das ist riesig. Praktiker für Barrierefreiheit Das hier liegt mir am Herzen. Nicht jeder spielt mit einem „Standard“-Controller. Adaptive Controller geben manchmal seltsame Signale aus. Mit diesem Tool können Sie genau sehen, was passiert. Lehrer, Forscher, wer auch immer. Sie können Protokolle abrufen, vergleichen oder Eingaben nebeneinander wiedergeben. Plötzlich werden unsichtbare Dinge offensichtlich. Qualitätssicherungstests Tester schreiben normalerweise Notizen wie „Ich habe hier einen Knopf zerdrückt und er ist kaputt gegangen.“ Nicht sehr hilfreich. Jetzt? Sie können die genauen Druckvorgänge erfassen, das Protokoll exportieren und versenden. Kein Raten. Pädagogen Wenn Sie Tutorials oder YouTube-Videos erstellen, ist Ghost Replay Gold wert. Sie können buchstäblich sagen: „Das habe ich mit dem Controller gemacht“, während die Benutzeroberfläche anzeigt, dass es passiert. Macht Erklärungen viel klarer. Jenseits von Spielen Und ja, hier geht es nicht nur um Spiele. Menschen haben Controller für Roboter, Kunstprojekte und Barrierefreiheitsschnittstellen verwendet. Jedes Mal das gleiche Problem: Was sieht der Browser tatsächlich? Damit müssen Sie nicht raten. Fazit Das Debuggen einer Controller-Eingabe fühlte sich schon immer wie ein Blindflug an. Im Gegensatz zu DOM oder CSS gibt es für Gamepads keinen integrierten Inspektor. Es sind nur rohe Zahlen in der Konsole, die leicht im Rauschen untergehen. Mit ein paar hundert Zeilen HTML, CSS und JavaScript haben wir etwas anderes erstellt:

Ein visueller Debugger, der unsichtbare Eingaben sichtbar macht. Ein mehrschichtiges CSS-System, das die Benutzeroberfläche sauber und debuggbar hält. Eine Reihe von Verbesserungen (Aufzeichnung, Export, Snapshots, Ghost Replay), die es von der Demo zum Entwicklertool machen.

Dieses Projekt zeigt, wie weit Sie kommen können, wenn Sie die Leistungsfähigkeit der Webplattform mit ein wenig Kreativität in CSS Cascade Layers kombinieren. Das Tool, das ich gerade vollständig erklärt habe, ist Open Source. Sie können das GitHub-Repo klonen und es selbst ausprobieren. Aber was noch wichtiger ist: Sie können es zu Ihrem eigenen machen. Fügen Sie Ihre eigenen Ebenen hinzu. Erstellen Sie Ihre eigene Wiedergabelogik. Integrieren Sie es in Ihren Spielprototyp. Oder es sogar auf eine Weise nutzen, die ich mir nicht vorgestellt habe. Für Unterricht, Barrierefreiheit oder Datenanalyse. Letztlich geht es hier nicht nur um das Debuggen von Gamepads. Es geht darum, versteckte Eingaben ans Licht zu bringen und Entwicklern das Vertrauen zu geben, mit Hardware zu arbeiten, die das Web noch nicht vollständig akzeptiert. Schließen Sie also Ihren Controller an, öffnen Sie Ihren Editor und beginnen Sie mit dem Experimentieren. Sie werden überrascht sein, was Ihr Browser und Ihr CSS wirklich leisten können.

You May Also Like

Enjoyed This Article?

Get weekly tips on growing your audience and monetizing your content — straight to your inbox.

No spam. Join 138,000+ creators. Unsubscribe anytime.

Create Your Free Bio Page

Join 138,000+ creators on Seemless.

Get Started Free