Όταν συνδέετε ένα χειριστήριο, πολτοποιείτε κουμπιά, μετακινείτε τα μπαστούνια, τραβάτε τις σκανδάλες… και ως προγραμματιστής, δεν βλέπετε τίποτα από αυτά. Το πρόγραμμα περιήγησης το παίρνει, σίγουρα, αλλά αν δεν καταγράφετε αριθμούς στην κονσόλα, είναι αόρατο. Αυτός είναι ο πονοκέφαλος με το Gamepad API. Υπάρχει εδώ και χρόνια και είναι πραγματικά πολύ ισχυρό. Μπορείτε να διαβάσετε κουμπιά, μπαστούνια, σκανδάλες, τα έργα. Αλλά οι περισσότεροι άνθρωποι δεν το αγγίζουν. Γιατί; Γιατί δεν υπάρχει ανατροφοδότηση. Δεν υπάρχει πλαίσιο στα εργαλεία προγραμματιστών. Δεν υπάρχει ξεκάθαρος τρόπος να γνωρίζετε αν ο ελεγκτής κάνει αυτό που νομίζετε. Είναι σαν να πετάς στα τυφλά. Αυτό με ενόχλησε αρκετά για να δημιουργήσω ένα μικρό εργαλείο: Gamepad Cascade Debugger. Αντί να κοιτάτε την έξοδο της κονσόλας, έχετε μια ζωντανή, διαδραστική προβολή του χειριστηρίου. Πατήστε κάτι και αντιδρά στην οθόνη. Και με τα CSS Cascade Layers, τα στυλ παραμένουν οργανωμένα, επομένως είναι πιο καθαρό ο εντοπισμός σφαλμάτων. Σε αυτήν την ανάρτηση, θα σας δείξω γιατί ο εντοπισμός σφαλμάτων ελεγκτών είναι τόσο δύσκολος, πώς το CSS βοηθά στην εκκαθάριση και πώς μπορείτε να δημιουργήσετε ένα επαναχρησιμοποιήσιμο οπτικό πρόγραμμα εντοπισμού σφαλμάτων για τα δικά σας έργα.
Ακόμα κι αν μπορείτε να τα καταγράψετε όλα, θα καταλήξετε γρήγορα με δυσανάγνωστα ανεπιθύμητα μηνύματα κονσόλας. Για παράδειγμα: [0,0,1,0,0,0,5,0,...] [0,0,0,0,1,0,0,...] [0,0,1,0,0,0,0,...]
Μπορείτε να πείτε ποιο κουμπί πατήθηκε; Ίσως, αλλά μόνο αφού καταπονήσετε τα μάτια σας και χάσετε μερικές εισροές. Οπότε, όχι, ο εντοπισμός σφαλμάτων δεν γίνεται εύκολα όταν πρόκειται για την ανάγνωση εισόδων. Πρόβλημα 3: Έλλειψη δομής Ακόμα κι αν συνδυάσετε ένα γρήγορο οπτικοποιητή, τα στυλ μπορεί να γίνουν γρήγορα ακατάστατα. Οι προεπιλεγμένες, οι ενεργές και οι καταστάσεις εντοπισμού σφαλμάτων μπορεί να επικαλύπτονται και χωρίς σαφή δομή, το CSS σας γίνεται εύθραυστο και δύσκολο να επεκταθεί. Τα CSS Cascade Layers μπορούν να βοηθήσουν. Ομαδοποιούν τα στυλ σε "επίπεδα" που ταξινομούνται κατά προτεραιότητα, επομένως σταματάτε να παλεύετε με την ιδιαιτερότητα και να μαντεύετε, "Γιατί δεν εμφανίζεται το στυλ εντοπισμού σφαλμάτων μου;" Αντίθετα, διατηρείτε ξεχωριστές ανησυχίες:
Βάση: Η τυπική, αρχική εμφάνιση του ελεγκτή. Ενεργό: Επισημάνσεις για πατημένα κουμπιά και μετακινούμενα μπαστούνια. Εντοπισμός σφαλμάτων: Επικαλύψεις για προγραμματιστές (π.χ. αριθμητικές ενδείξεις, οδηγοί κ.λπ.).
Αν έπρεπε να ορίσουμε επίπεδα στο CSS σύμφωνα με αυτό, θα είχαμε: /* χαμηλότερη προς υψηλότερη προτεραιότητα */ Βάση @layer, ενεργό, εντοπισμός σφαλμάτων.
Βάση @layer { /* ... */ }
@στρώμα ενεργό { /* ... */ }
@layer debug { /* ... */ }
Επειδή κάθε επίπεδο στοιβάζεται προβλέψιμα, γνωρίζετε πάντα ποιοι κανόνες κερδίζουν. Αυτή η προβλεψιμότητα καθιστά τον εντοπισμό σφαλμάτων όχι απλώς ευκολότερο, αλλά ουσιαστικά διαχειρίσιμο. Καλύψαμε το πρόβλημα (αόρατη, ακατάστατη είσοδο) και την προσέγγιση (ένα οπτικό πρόγραμμα εντοπισμού σφαλμάτων που δημιουργήθηκε με Cascade Layers). Τώρα θα ακολουθήσουμε τη διαδικασία βήμα προς βήμα για τη δημιουργία του προγράμματος εντοπισμού σφαλμάτων. Η έννοια του εντοπισμού σφαλμάτων Ο ευκολότερος τρόπος για να κάνετε ορατή την κρυφή είσοδο είναι απλώς να την σχεδιάσετε στην οθόνη. Αυτό κάνει αυτό το πρόγραμμα εντοπισμού σφαλμάτων. Τα κουμπιά, οι σκανδάλες και τα joystick έχουν όλα μια εικόνα.
Πατήστε A: Ένας κύκλος ανάβει. Σπρώξτε το ραβδί: Ο κύκλος γλιστράει γύρω. Τραβήξτε μια σκανδάλη μέχρι τη μέση: Μια μπάρα γεμίζει μέχρι τη μέση.
Τώρα δεν κοιτάτε επίμονα τα 0 και 1, αλλά στην πραγματικότητα παρακολουθείτε τον ελεγκτή να αντιδρά ζωντανά. Φυσικά, μόλις αρχίσετε να συσσωρεύετε καταστάσεις όπως προεπιλογή, πατημένο, πληροφορίες εντοπισμού σφαλμάτων, ίσως ακόμη και λειτουργία εγγραφής, το CSS αρχίζει να γίνεται μεγαλύτερο και πιο περίπλοκο. Εκεί είναι χρήσιμα τα επίπεδα καταρράκτη. Ακολουθεί ένα απογυμνωμένο παράδειγμα: Βάση @layer { .κουμπί { φόντο: #222; ακτίνα συνόρων: 50%; πλάτος: 40 px; ύψος: 40 px; } }
@στρώμα ενεργό { .κουμπί.πατημένο { φόντο: #0f0; /* φωτεινό πράσινο */ } }
@layer debug { .button::after { περιεχόμενο: attr(data-value); μέγεθος γραμματοσειράς: 12 px; χρώμα: #fff; } }
Η σειρά των επιπέδων έχει σημασία: βάση → ενεργό → εντοπισμός σφαλμάτων.
βάση σχεδιάζει τον ελεγκτή. ενεργή χειρίζεται πιεσμένες καταστάσεις. ρίψεις εντοπισμού σφαλμάτων σε επικαλύψεις.
Το να το διαλύσεις έτσι σημαίνει ότι δεν πολεμάς περίεργους πολέμους ιδιαιτεροτήτων. Κάθε στρώμα έχει τη θέση του και πάντα ξέρεις τι κερδίζει. Χτίζοντας το Ας δούμε πρώτα κάτι στην οθόνη. Δεν χρειάζεται να φαίνεται καλό – απλά πρέπει να υπάρχει για να έχουμε κάτι να δουλέψουμε.
Gamepad Cascade Debugger
Αυτό είναι κυριολεκτικά μόνο κουτιά. Δεν είναι ακόμα συναρπαστικό, αλλά μας δίνει λαβές για να το πιάσουμε αργότερα με CSS και JavaScript. Εντάξει, χρησιμοποιώ επίπεδα καταρράκτη εδώ επειδή κρατά τα πράγματα οργανωμένα μόλις προσθέσετε περισσότερες καταστάσεις. Εδώ είναι ένα πρόχειρο πέρασμα:
/* ==================================== ΡΥΘΜΙΣΗ ΣΤΡΩΜΑΤΩΝ ΚΑΣΚΑΔΩΝ Η παραγγελία έχει σημασία: βάση → ενεργό → εντοπισμός σφαλμάτων ==================================== */
/* Ορισμός σειράς επιπέδων εκ των προτέρων */ Βάση @layer, ενεργό, εντοπισμός σφαλμάτων.
/* Επίπεδο 1: Στυλ βάσης - προεπιλεγμένη εμφάνιση */ Βάση @layer { .κουμπί { φόντο: #333; ακτίνα συνόρων: 50%; πλάτος: 70 px; ύψος: 70 px; οθόνη: flex; justify-content: κέντρο; στοίχιση-στοιχεία: κέντρο; }
.pause { πλάτος: 20 px; ύψος: 70 px; φόντο: #333; οθόνη: inline-block; } }
/* Επίπεδο 2: Ενεργές καταστάσεις - χειρίζεται πατημένα κουμπιά */ @στρώμα ενεργό { .button.active { φόντο: #0f0; /* Ανοιχτό πράσινο όταν πατηθεί */ transform: scale(1.1); /* Μεγεθύνει ελαφρώς το κουμπί */ }
.pause.active { φόντο: #0f0; μετασχηματισμός: scaleY(1.1); /* Τεντώνεται κατακόρυφα όταν πατηθεί */ } }
/* Επίπεδο 3: Εντοπισμός σφαλμάτων επικαλύψεων - πληροφορίες προγραμματιστή */ @layer debug { .button::after { περιεχόμενο: attr(data-value); /* Εμφανίζει την αριθμητική τιμή */ μέγεθος γραμματοσειράς: 12 px; χρώμα: #fff; } }
Η ομορφιά αυτής της προσέγγισης είναι ότι κάθε στρώμα έχει έναν ξεκάθαρο σκοπό. Το βασικό επίπεδο δεν μπορεί ποτέ να παρακάμψει το ενεργό και το ενεργό δεν μπορεί ποτέ να παρακάμψει τον εντοπισμό σφαλμάτων, ανεξάρτητα από την ειδικότητα. Αυτό εξαλείφει τους πολέμους ειδικότητας CSS που συνήθως μαστίζουν τα εργαλεία εντοπισμού σφαλμάτων. Τώρα φαίνεται ότι μερικά συμπλέγματα κάθονται σε σκούρο φόντο. Ειλικρινά, όχι και πολύ άσχημα.
Προσθήκη JavaScript Χρόνος JavaScript. Αυτό είναι όπου ο ελεγκτής κάνει πραγματικά κάτι. Θα το φτιάξουμε βήμα-βήμα. Βήμα 1: Ρύθμιση διαχείρισης κατάστασης Πρώτον, χρειαζόμαστε μεταβλητές για την παρακολούθηση της κατάστασης του προγράμματος εντοπισμού σφαλμάτων: // ==================================== // ΔΙΑΧΕΙΡΙΣΗ ΚΡΑΤΟΥΣ // ====================================
ας τρέχει = ψεύτικο; // Παρακολουθεί εάν το πρόγραμμα εντοπισμού σφαλμάτων είναι ενεργό ας rafId? // Αποθηκεύει το αναγνωριστικό requestAnimationFrame για ακύρωση
Αυτές οι μεταβλητές ελέγχουν τον βρόχο κίνησης που διαβάζει συνεχώς την είσοδο του gamepad. Βήμα 2: Πιάστε τις αναφορές DOM Στη συνέχεια, λαμβάνουμε αναφορές σε όλα τα στοιχεία HTML που θα ενημερώσουμε: // ==================================== // ΑΝΑΦΟΡΕΣ ΣΤΟΙΧΕΙΟΥ DOΜ // ====================================
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");
Η αποθήκευση αυτών των αναφορών εκ των προτέρων είναι πιο αποτελεσματική από την επανειλημμένη αναζήτηση στο DOM. Βήμα 3: Προσθήκη εναλλακτικού πληκτρολογίου Για δοκιμές χωρίς φυσικό ελεγκτή, θα αντιστοιχίσουμε τα πλήκτρα του πληκτρολογίου σε κουμπιά: // ==================================== // KEYBOARD FALLBACK (για δοκιμή χωρίς ελεγκτή) // ====================================
const keyMap = { "a": btnA, "b": btnB, "x": btnX, "p": [pause1, pause2] // το πλήκτρο 'p' ελέγχει και τις δύο γραμμές παύσης };
Αυτό μας επιτρέπει να δοκιμάσουμε τη διεπαφή χρήστη πατώντας πλήκτρα σε ένα πληκτρολόγιο. Βήμα 4: Δημιουργήστε τον κύριο βρόχο ενημέρωσης Εδώ συμβαίνει η μαγεία. Αυτή η λειτουργία εκτελείται συνεχώς και διαβάζει την κατάσταση του gamepad: // ==================================== // ΒΡΟΧΟΣ ΕΝΗΜΕΡΩΣΗΣ ΚΥΡΙΟΥ ΠΑΙΧΝΙΔΙΟΥ // ====================================
συνάρτηση updateGamepad() { // Λάβετε όλα τα συνδεδεμένα gamepad const gamepads = navigator.getGamepads(); αν επιστρέψουν (!gamepads).
// Χρησιμοποιήστε το πρώτο συνδεδεμένο gamepad const gp = gamepads[0];
αν (gp) { // Καταστάσεις του κουμπιού ενημέρωση με εναλλαγή της κλάσης "ενεργή". btnA.classList.toggle("active", gp.buttons[0].pressed); btnB.classList.toggle("active", gp.buttons[1].pressed); btnX.classList.toggle("active", gp.buttons[2].pressed);
// Κουμπί παύσης χειρισμού (ευρετήριο κουμπιού 9 στους περισσότερους ελεγκτές) const pausePressed = gp.buttons[9].pressed; pause1.classList.toggle("active", pausePressed); pause2.classList.toggle("active", pausePressed);
// Δημιουργία λίστας κουμπιών που έχουν πατηθεί αυτήν τη στιγμή για εμφάνιση κατάστασης ας πατηθεί = []; gp.buttons.forEach((btn, i) => { εάν (btn.πατηθεί)pressed.push("Button" + i); });
// Ενημέρωση κειμένου κατάστασης εάν πατηθούν κάποια κουμπιά εάν (πατηθεί.μήκος > 0) { status.textContent = "Πατημένο: " + pressed.join(", "); } }
// Συνεχίστε τον βρόχο εάν εκτελείται το πρόγραμμα εντοπισμού σφαλμάτων αν (τρέχει) { rafId = requestAnimationFrame(updateGamepad); } }
Η μέθοδος classList.toggle() προσθέτει ή αφαιρεί την ενεργή κλάση με βάση το αν το κουμπί είναι πατημένο, κάτι που ενεργοποιεί τα στυλ επιπέδου CSS μας. Βήμα 5: Χειριστείτε συμβάντα πληκτρολογίου Αυτοί οι ακροατές συμβάντων κάνουν το εναλλακτικό πληκτρολόγιο να λειτουργεί: // ==================================== // ΧΕΙΡΙΣΤΕΣ ΕΚΔΗΛΩΣΕΩΝ ΠΛΗΚΤΡΟΛΟΓΙΟΥ // ====================================
document.addEventListener("keydown", (e) => { if (keyMap[e.key]) { // Χειριστείτε μεμονωμένα ή πολλαπλά στοιχεία if (Array.isArray(keyMap[e.key])) { keyMap[e.key].forEach(el => el.classList.add("ενεργό")); } αλλο { keyMap[e.key].classList.add("ενεργό"); } status.textContent = "Πατήθηκε το πλήκτρο: " + e.key.toUpperCase(); } });
document.addEventListener("keyup", (e) => { if (keyMap[e.key]) { // Αφαιρέστε την ενεργή κατάσταση όταν απελευθερωθεί το κλειδί if (Array.isArray(keyMap[e.key])) { keyMap[e.key].forEach(el => el.classList.remove("ενεργό")); } αλλο { keyMap[e.key].classList.remove("ενεργό"); } status.textContent = "Το κλειδί κυκλοφόρησε: " + e.key.toUpperCase(); } });
Βήμα 6: Προσθήκη ελέγχου έναρξης/διακοπής Τέλος, χρειαζόμαστε έναν τρόπο για να ενεργοποιήσουμε και να απενεργοποιήσουμε το πρόγραμμα εντοπισμού σφαλμάτων: // ==================================== // ΕΝΕΡΓΟΠΟΙΗΣΗ ΕΝΕΡΓΟΠΟΙΗΣΗΣ ΕΝΤΟΠΙΣΤΗ σφαλμάτων ΕΝΕΡΓΟΠΟΙΗΣΗ/ΑΠΕΝΕΡΓΟΠΟΙΗΣΗ // ====================================
document.getElementById("toggle").addEventListener("κλικ", () => { τρέχω = !τρέχω; // Αναστροφή της κατάστασης εκτέλεσης
αν (τρέχει) { status.textContent = "Το πρόγραμμα εντοπισμού σφαλμάτων εκτελείται..."; updateGamepad(); // Εκκίνηση του βρόχου ενημέρωσης } αλλο { status.textContent = "Το πρόγραμμα εντοπισμού σφαλμάτων είναι ανενεργό"; cancelAnimationFrame(rafId); // Διακοπή του βρόχου } });
Οπότε ναι, πάτα ένα κουμπί και λάμπει. Σπρώξτε το ραβδί και κινείται. Αυτό είναι. Κάτι ακόμα: ακατέργαστες αξίες. Μερικές φορές θέλετε απλώς να δείτε αριθμούς, όχι φώτα.
Σε αυτό το στάδιο, θα πρέπει να δείτε:
Ένα απλό χειριστήριο στην οθόνη, Κουμπιά που αντιδρούν καθώς αλληλεπιδράτε μαζί τους και Μια προαιρετική ανάγνωση εντοπισμού σφαλμάτων που εμφανίζει δείκτες πατημένων κουμπιών.
Για να γίνει αυτό λιγότερο αφηρημένο, ακολουθεί μια γρήγορη επίδειξη του ελεγκτή στην οθόνη που αντιδρά σε πραγματικό χρόνο:
Τώρα, πατώντας Έναρξη εγγραφής καταγράφονται τα πάντα μέχρι να πατήσετε Διακοπή εγγραφής. 2. Εξαγωγή δεδομένων σε CSV/JSON Μόλις έχουμε ένα αρχείο καταγραφής, θα θέλουμε να το αποθηκεύσουμε.
Βήμα 1: Δημιουργήστε το Download Helper Πρώτα, χρειαζόμαστε μια βοηθητική λειτουργία που χειρίζεται τις λήψεις αρχείων στο πρόγραμμα περιήγησης: // ==================================== // ΒΟΗΘΟΣ ΛΗΨΗΣ ΑΡΧΕΙΟΥ // ====================================
συνάρτηση λήψηΑρχείου (όνομα αρχείου, περιεχόμενο, τύπος = "κείμενο/απλό") { // Δημιουργήστε ένα blob από το περιεχόμενο const blob = new Blob([content], { type }); const url = URL.createObjectURL(blob);
// Δημιουργήστε έναν προσωρινό σύνδεσμο λήψης και κάντε κλικ σε αυτόν const a = document.createElement("a"); a.href = url; a.download = όνομα αρχείου; a.click();
// Καθαρίστε τη διεύθυνση URL του αντικειμένου μετά τη λήψη setTimeout(() => URL.revokeObjectURL(url), 100); }
Αυτή η συνάρτηση λειτουργεί δημιουργώντας ένα Blob (δυαδικό μεγάλο αντικείμενο) από τα δεδομένα σας, δημιουργώντας μια προσωρινή διεύθυνση URL για αυτό και κάνοντας κλικ μέσω προγραμματισμού σε έναν σύνδεσμο λήψης. Η εκκαθάριση διασφαλίζει ότι δεν υπάρχει διαρροή μνήμης. Βήμα 2: Χειριστείτε την εξαγωγή JSON Το JSON είναι τέλειο για τη διατήρηση της πλήρους δομής δεδομένων:
// ==================================== // ΕΞΑΓΩΓΗ ΩΣ JSON // ====================================
document.getElementById("export-json").addEventListener("κλικ", () => { // Ελέγξτε αν υπάρχει κάτι για εξαγωγή if (!frames.length) { console.warn("Δεν υπάρχει διαθέσιμη εγγραφή για εξαγωγή."); επιστροφή? }
// Δημιουργία ωφέλιμου φορτίου με μεταδεδομένα και πλαίσια const ωφέλιμο φορτίο = { createAt: new Date().toISOSstring(), πλαίσια };
// Λήψη ως μορφοποιημένο JSON λήψηαρχείου( "gamepad-log.json", JSON.stringify(payload, null, 2), "application/json" ) });
Η μορφή JSON διατηρεί τα πάντα δομημένα και εύκολα αναλύσιμα, καθιστώντας την ιδανική για επαναφόρτωση σε εργαλεία προγραμματισμού ή για κοινή χρήση με συμπαίκτες. Βήμα 3: Χειριστείτε την Εξαγωγή CSV Για εξαγωγές CSV, πρέπει να ισοπεδώσουμε τα ιεραρχικά δεδομένα σε σειρές και στήλες:
//==================================== // ΕΞΑΓΩΓΗ ΩΣ CSV // ====================================
document.getElementById("export-csv").addEventListener("κλικ", () => { // Ελέγξτε αν υπάρχει κάτι για εξαγωγή if (!frames.length) { console.warn("Δεν υπάρχει διαθέσιμη εγγραφή για εξαγωγή."); επιστροφή? }
// Δημιουργία σειράς κεφαλίδας CSV (στήλες για χρονική σήμανση, όλα τα κουμπιά, όλους τους άξονες) 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 const rows = frames.map(f => { const btnVals = f.buttons.map(b => b.value); return [f.t, ...btnVals, ...f.axes].join(","); }).join("\n");
// Λήψη ως CSV downloadFile("gamepad-log.csv", κεφαλίδα + σειρές, "κείμενο/csv"); });
Το CSV είναι εξαιρετικό για ανάλυση δεδομένων, επειδή ανοίγει απευθείας στο Excel ή τα Φύλλα Google, επιτρέποντάς σας να δημιουργείτε γραφήματα, να φιλτράρετε δεδομένα ή να εντοπίζετε μοτίβα οπτικά. Τώρα που είναι μέσα τα κουμπιά εξαγωγής, θα δείτε δύο νέες επιλογές στον πίνακα: Εξαγωγή JSON και Εξαγωγή CSV. Το JSON είναι ωραίο αν θέλετε να επαναφέρετε το ακατέργαστο αρχείο καταγραφής στα εργαλεία προγραμματιστή σας ή να περιηγηθείτε στη δομή. Το CSV, από την άλλη πλευρά, ανοίγει απευθείας στο Excel ή τα Φύλλα Google, ώστε να μπορείτε να γράφετε, να φιλτράρετε ή να συγκρίνετε εισόδους. Το παρακάτω σχήμα δείχνει πώς φαίνεται ο πίνακας με αυτά τα επιπλέον χειριστήρια.
3. Σύστημα Στιγμιότυπων Μερικές φορές δεν χρειάζεστε πλήρη εγγραφή, απλώς ένα γρήγορο «στιγμιότυπο οθόνης» των καταστάσεων εισαγωγής. Εκεί βοηθά ένα κουμπί Λήψη στιγμιότυπου.
Και το JavaScript:
// ==================================== // TAKE SNAPSHOT // ====================================
document.getElementById("snapshot").addEventListener("κλικ", () => { // Λάβετε όλα τα συνδεδεμένα gamepad const pads = navigator.getGamepads(); const activePads = [];
// Κάντε βρόχο και καταγράψτε την κατάσταση κάθε συνδεδεμένου gamepad για (const gp of pads) { αν (!gp) συνεχίσει? // Παράλειψη κενών υποδοχών
activePads.push({ id: gp.id, // Όνομα/μοντέλο ελεγκτή timestamp: performance.now(), κουμπιά: gp.buttons.map(b => ({ πατημένο: β.πατημένο, αξία: β.αξία })), άξονες: [...gp.axes] }); }
// Ελέγξτε αν εντοπίστηκαν παιχνίδια if (!activePads.length) { console.warn("Δεν έχουν συνδεθεί gamepads για στιγμιότυπο."); alert ("Δεν εντοπίστηκε ελεγκτής!"); επιστροφή? }
// Συνδεθείτε και ειδοποιήστε τον χρήστη console.log("Snapshot:", activePads); alert(Λήψη στιγμιότυπου! Έγινε λήψη ελεγκτών ${activePads.length}). });
Τα στιγμιότυπα παγώνουν την ακριβή κατάσταση του ελεγκτή σας σε μια στιγμή. 4. Επανάληψη εισαγωγής φάντασμα Τώρα για το διασκεδαστικό: επανάληψη εισόδου φαντασμάτων. Αυτό παίρνει ένα αρχείο καταγραφής και το αναπαράγει οπτικά σαν να χρησιμοποιούσε το χειριστήριο ένα πρόγραμμα αναπαραγωγής φάντασμα.
JavaScript για επανάληψη: // ==================================== // GHOST REPLAY // ====================================
document.getElementById("replay").addEventListener("κλικ", () => { // Βεβαιωθείτε ότι έχουμε μια εγγραφή για επανάληψη if (!frames.length) { alert ("Δεν υπάρχει εγγραφή για επανάληψη!"); επιστροφή? }
console.log("Έναρξη επανάληψης φαντασμάτων...");
// Παρακολούθηση χρονισμού για συγχρονισμένη αναπαραγωγή ας startTime = performance.now(); έστω frameIndex = 0;
// Επανάληψη βρόχου κινουμένων σχεδίων βήμα συνάρτησης() { const now = performance.now(); const elapsed = τώρα - start Time;
// Επεξεργαστείτε όλα τα πλαίσια που θα έπρεπε να έχουν προκύψει μέχρι τώρα ενώ (frameIndex < frames.length && frames[frameIndex].t <= παρήλθε) { const frame = frames[frameIndex];
// Ενημέρωση διεπαφής χρήστη με τις καταγεγραμμένες καταστάσεις κουμπιών btnA.classList.toggle("active", frame.buttons[0].pressed); btnB.classList.toggle("active", frame.buttons[1].pressed); btnX.classList.toggle("active", frame.buttons[2].pressed);
// Ενημέρωση εμφάνισης κατάστασης ας πατηθεί = []; frame.buttons.forEach((btn, i) => { if (btn.pressed) pressed.push("Button" + i); }); εάν (πατηθεί.μήκος > 0) { status.textContent = "Ghost: " + pressed.join(", "); }
frameIndex++; }
// Συνεχίστε τον βρόχο εάν υπάρχουν περισσότερα καρέ if (frameIndex < frames.length) { requestAnimationFrame(βήμα); } αλλο { console.log("Επανάληψητελειωμένο."); status.textContent = "Η επανάληψη ολοκληρώθηκε"; } }
// Έναρξη επανάληψης step(); });
Για να κάνω τον εντοπισμό σφαλμάτων λίγο πιο πρακτικό, πρόσθεσα μια επανάληψη φαντασμάτων. Μόλις ηχογραφήσετε μια περίοδο λειτουργίας, μπορείτε να πατήσετε επανάληψη και να παρακολουθήσετε τη διεπαφή χρήστη να την εκτελεί, σχεδόν σαν ένα πρόγραμμα αναπαραγωγής φάντασμα να τρέχει το pad. Ένα νέο κουμπί Replay Ghost εμφανίζεται στον πίνακα για αυτό.
Πατήστε Εγγραφή, μπλέξτε λίγο με το χειριστήριο, σταματήστε και μετά επαναλάβετε. Η διεπαφή χρήστη απλώς απηχεί όλα όσα κάνατε, σαν ένα φάντασμα που ακολουθεί τις εισαγωγές σας. Γιατί να ασχοληθείτε με αυτά τα πρόσθετα;
Η εγγραφή/εξαγωγή διευκολύνει τους δοκιμαστές να δείξουν ακριβώς τι συνέβη. Τα στιγμιότυπα παγώνουν μια στιγμή στο χρόνο, εξαιρετικά χρήσιμα όταν κυνηγάτε περίεργα σφάλματα. Η επανάληψη Ghost είναι ιδανική για σεμινάρια, ελέγχους προσβασιμότητας ή απλώς σύγκριση ρυθμίσεων ελέγχου δίπλα-δίπλα.
Σε αυτό το σημείο, δεν είναι πια απλώς μια προσεγμένη επίδειξη, αλλά κάτι που θα μπορούσατε πραγματικά να δουλέψετε. Περιπτώσεις χρήσης πραγματικού κόσμου Τώρα έχουμε αυτό το πρόγραμμα εντοπισμού σφαλμάτων που μπορεί να κάνει πολλά. Εμφανίζει ζωντανή είσοδο, καταγράφει αρχεία καταγραφής, τα εξάγει, ακόμη και αναπαράγει πράγματα. Αλλά το πραγματικό ερώτημα είναι: ποιος ενδιαφέρεται πραγματικά; Σε ποιον είναι χρήσιμο αυτό; Προγραμματιστές παιχνιδιών Οι ελεγκτές είναι μέρος της δουλειάς, αλλά η αποσφαλμάτωση τους; Συνήθως ένας πόνος. Φανταστείτε ότι δοκιμάζετε ένα συνδυασμό μάχης, όπως ↓ → + punch. Αντί να προσευχηθείς, το πάτησες με τον ίδιο τρόπο δύο φορές, το ηχογραφείς μία φορά και το ξαναπαίζεις. Έγινε. Εναλλακτικά, αλλάζετε αρχεία καταγραφής JSON με έναν συμπαίκτη σας για να ελέγξετε αν ο κωδικός σας για πολλούς παίκτες αντιδρά το ίδιο στον υπολογιστή του. Αυτό είναι τεράστιο. Προσβασιμότητα Practitioners Αυτό είναι κοντά στην καρδιά μου. Δεν παίζουν όλοι με ένα «τυπικό» χειριστήριο. Οι προσαρμοστικοί ελεγκτές εκπέμπουν περίεργα σήματα μερικές φορές. Με αυτό το εργαλείο, μπορείτε να δείτε ακριβώς τι συμβαίνει. Δάσκαλοι, ερευνητές, όποιος κι αν είναι. Μπορούν να αρπάξουν αρχεία καταγραφής, να τα συγκρίνουν ή να αναπαράγουν τις εισόδους δίπλα-δίπλα. Ξαφνικά, αόρατα πράγματα γίνονται προφανή. Δοκιμές Διασφάλισης Ποιότητας Οι δοκιμαστές συνήθως γράφουν σημειώσεις όπως "Έκαψα κουμπιά εδώ και έσπασε". Όχι πολύ χρήσιμο. Τώρα; Μπορούν να συλλάβουν τα ακριβή πατήματα, να εξάγουν το αρχείο καταγραφής και να το στείλουν. Χωρίς εικασίες. Παιδαγωγοί Αν φτιάχνετε σεμινάρια ή βίντεο YouTube, η επανάληψη φαντασμάτων είναι χρυσή. Μπορείτε να πείτε κυριολεκτικά, "Να τι έκανα με τον ελεγκτή", ενώ το UI δείχνει ότι συμβαίνει. Κάνει τις εξηγήσεις πολύ πιο ξεκάθαρες. Πέρα από τα παιχνίδια Και ναι, αυτό δεν είναι μόνο για παιχνίδια. Οι άνθρωποι έχουν χρησιμοποιήσει ελεγκτές για ρομπότ, έργα τέχνης και διεπαφές προσβασιμότητας. Το ίδιο θέμα κάθε φορά: τι βλέπει πραγματικά το πρόγραμμα περιήγησης; Με αυτό, δεν χρειάζεται να μαντέψετε. Συμπέρασμα Ο εντοπισμός σφαλμάτων μιας εισόδου ελεγκτή ήταν πάντα σαν να πετάγομαι στα τυφλά. Σε αντίθεση με το DOM ή το CSS, δεν υπάρχει ενσωματωμένος επιθεωρητής για gamepad. είναι απλώς ακατέργαστοι αριθμοί στην κονσόλα, που χάνονται εύκολα στο θόρυβο. Με μερικές εκατοντάδες γραμμές HTML, CSS και JavaScript, δημιουργήσαμε κάτι διαφορετικό:
Ένα οπτικό πρόγραμμα εντοπισμού σφαλμάτων που κάνει ορατές τις αόρατες εισόδους. Ένα πολυεπίπεδο σύστημα CSS που διατηρεί τη διεπαφή χρήστη καθαρή και με δυνατότητα εντοπισμού σφαλμάτων. Ένα σύνολο βελτιώσεων (εγγραφή, εξαγωγή, στιγμιότυπα, επανάληψη φαντασμάτων) που το ανεβάζουν από το demo στο εργαλείο προγραμματιστή.
Αυτό το έργο δείχνει πόσο μακριά μπορείτε να φτάσετε αναμειγνύοντας τη δύναμη της πλατφόρμας Ιστού με λίγη δημιουργικότητα στα επίπεδα CSS Cascade Layers. Το εργαλείο που μόλις εξήγησα στο σύνολό του είναι ανοιχτού κώδικα. Μπορείτε να κλωνοποιήσετε το αποθετήριο GitHub και να το δοκιμάσετε μόνοι σας. Αλλά το πιο σημαντικό, μπορείτε να το κάνετε δικό σας. Προσθέστε τα δικά σας επίπεδα. Δημιουργήστε τη δική σας λογική επανάληψης. Ενσωματώστε το με το πρωτότυπο του παιχνιδιού σας. Ή ακόμα και να το χρησιμοποιήσω με τρόπους που δεν έχω φανταστεί. Για διδασκαλία, προσβασιμότητα ή ανάλυση δεδομένων. Στο τέλος της ημέρας, αυτό δεν αφορά μόνο τον εντοπισμό σφαλμάτων των gamepads. Έχει να κάνει με το να ρίξουμε φως σε κρυφές εισόδους και να δώσουμε στους προγραμματιστές την αυτοπεποίθηση να εργαστούν με υλικό που ο ιστός εξακολουθεί να μην αγκαλιάζει πλήρως. Έτσι, συνδέστε τον ελεγκτή σας, ανοίξτε τον επεξεργαστή σας και ξεκινήστε να πειραματίζεστε. Μπορεί να εκπλαγείτε με το τι μπορούν πραγματικά να επιτύχουν το πρόγραμμα περιήγησής σας και το CSS σας.