Jak powinienem wprowadzić klucz / mysz w zaawansowanej grze Java?

9

Jestem programistą-samoukiem, więc nie znam właściwych sposobów robienia rzeczy. Stworzyłem proste gry, takie jak asteroidy i wąż, ale w tych grach można łatwo modyfikować zmienne w ramach kluczowych funkcji. Oto jak to zrobiłem w mojej prostej grze Asteroids:

/*
* key listener events
*/
public void keyReleased(KeyEvent k){
    int keyCode = k.getKeyCode();

    switch(keyCode){

        case KeyEvent.VK_LEFT:
            turnLeft = false;
            break;

        case KeyEvent.VK_RIGHT:
            turnRight = false;
            break;

        case KeyEvent.VK_UP:
            accel = false;
            break;

        case KeyEvent.VK_1:
            cls = true;
            break;
        case KeyEvent.VK_ENTER:
            break;
        case KeyEvent.VK_SPACE:
            fire = false;
    }
}
public void keyTyped(KeyEvent K){}
public void keyPressed(KeyEvent k){
    int keyCode = k.getKeyCode();

    switch(keyCode){

        case KeyEvent.VK_LEFT:
            turnLeft = true;
            break;

        case KeyEvent.VK_RIGHT:
            turnRight = true;
            break;

        case KeyEvent.VK_UP:
            accel = true;
            break;

        case KeyEvent.VK_1:
            cls = false;
            break;
        case KeyEvent.VK_ENTER:
            clearAllBullets();
            break;
        case KeyEvent.VK_SPACE:
            fire = true;
    }
}

Jeśli miałbym stworzyć bardziej zaawansowaną grę (z menu głównym, opcjami, grą główną itp.), Jak powinienem wprowadzić dane za pomocą klawiszy / myszy?

Ponadto, jeśli miałbym przejść do trybu dla jednego gracza, czy powinienem umieścić cały kod rozgrywki w jednej klasie? Czy istnieje sposób na umieszczenie kodu dla pojedynczego gracza w osobnej klasie i jakoś wprowadzenie klucza nadal modyfikuje zmienne i tym podobne?

Steven Rogers
źródło
+1 Twoja odpowiedź pozwoliła mi nauczyć się czegoś nowego z odpowiedzi bearcdp. Dzięki, że pytasz! =)
Czy Marcouiller

Odpowiedzi:

3

Nie jestem ekspertem, a jednak sugeruję oddzielenie zarówno elementów sterujących, jak i logiki biznesowej / gry / menu (nazwij ją).

Odpowiedziałem już na podobne pytanie dotyczące udzielania wskazówek wężowi w grze zaprojektowanej z klasami. Java jest językiem zorientowanym obiektowo. Sądzę, że potrafisz pisać odpowiednie klasy i inne rzeczy. Następnie, gdy napisałeś klasę obiektu, jeśli jest tak, że twój obiekt musi reagować na niektóre klawisze i kliknięcia myszą, wybrałbym klasę Controller, która wie, co jest aktualnie wyświetlane na ekranie, a następnie powiedziałbym temu obiektowi, co powinien zrobić w zależności od naciśniętego klawisza lub regionu, który został kliknięty.

Oto link do pytania, które ci powiedziałem, na które odpowiedziałem na temat oddzielenia kontrolek od logiki obiektowej. Zawiera także przykładowy kod ilustrujący moją myśl.

Przenoszenie mojego duszka w XNA za pomocą klas

( Niestety, żadna z odpowiedzi nie została jeszcze zaakceptowana przez PO, więc nie wiemy na pewno, czy to rozwiązało jego obawy. Poza tym, zawsze projektuję w ten sposób i nie miałem z tym problemu. )

Teraz wiem, że jest oznaczony jako XNA. Pomysł lub projekt to wyższy poziom architektury niż stosowana technologia, więc projekt ten można po prostu dostosować do składni Java. Ogólna idea pozostaje taka sama. =)

Mam nadzieję, że to pomoże! Z przyjemnością pomogę, kiedy będę mógł, po prostu zapytaj! =)

Will Marcouiller
źródło
5

Odpowiedź Willa pokazuje, co jest prawdopodobnie najbardziej elastyczne i proste, i poleciłbym to, jeśli potrzebujesz bezpośredniego sondowania danych wejściowych.

Ale jeśli potrzebujesz łatwego sposobu sprawdzenia różnych kombinacji naciśnięć przycisków, unikając przy tym ogromnej ilości przełączników i instrukcji if, możesz użyć wyliczeń flag bitowych.

Nie wiem, co wiesz o wektorach bitowych, więc oto przegląd: Zasadniczo masz klasę wyliczającą, która reprezentuje wszystkie możliwe klucze. Każde wyliczenie powinno mieć wartość, która odpowiada bitowi w liczbie całkowitej. (tj .: 0x0001, 0x0002, 0x0004, 0x0008, 0x0010, 0x0011, 0x0012, 0x0014 itp.). ( Link do robienia tego w Javie).

Teraz, ponieważ możesz przekazywać informacje o maksymalnie 32 (lub 64, jeśli używasz długich) kluczach, możesz mieć tablicę skrótów, która kojarzy wektory bitowe (int lub long) z obiektami objętymi pewnego rodzaju interfejsem KeyComboCallback, który zawiera tylko pojedyncze wywołanie metody, Do (), które jest wywoływane po naciśnięciu skojarzonej kombinacji klawiszy.

Teraz, kiedy tworzysz / inicjujesz obiekt odtwarzacza lub obiekt menu, możesz zadzwonić do jakiegoś menedżera wprowadzania i przekazać mu wszystkie potrzebne wektory bitów kombinacji klawiszy i powiązać je z anonimowymi klasami wewnętrznymi.

// ... in your init code for Player

InputManager.map(
    KeyMap.A.val() | KeyMap.B.val() | KeyMap.C.val(), 
    new KeyComboCallback(KeyMap keys) {
        public void Do() {
           this.DoCrazyAwesomeComboAttack();
        }
    });

// ...  continue init

Jest to naprawdę szybkie i wygodne w C ++ i C #, ale wyliczenia Java są wyjątkowe, więc może okazać się wygodniejsze utworzenie klasy KeyCombination lub czegoś, co będzie przechowywać wszystkie te informacje bez martwienia się o wyliczenia. Ale pomysł jest nadal ten sam. Używam tego w grze XNA i bardzo lubię ten obiekt. Można go również użyć do oddzielenia obszarów wejściowych, co jest przydatne do niezależnego porównywania różnych części klawiatury lub gamepada (może być przydatne dla dwóch graczy na jednej klawiaturze).

michael.bartnett
źródło
Podoba mi się twój post, szczególnie „this.DoCrazyAwesomeComboAttack ();” XD. Twoja ścieżka wydaje się lepszym sposobem na skomplikowane rzeczy, więc będę trzymać się łatwiejszych rzeczy. Dziękuję za pomoc!
Steven Rogers
+1 Bardzo interesująca odpowiedź! Nauczyłem się z tej odpowiedzi i wypróbuję ją, gdy będę miał więcej czasu na rozwój gry hobby. I dziękuję, że powiedziałem, że moja odpowiedź jest dobra, chociaż dotyczy prostszych rzeczy, o których nie będę się kłócił, ponieważ jestem początkującym w GD. =) Dzięki!
Will Marcouiller,