IT rekvalifikácia. Seniorní programátori zarábajú až 6 000 €/mesiac a rekvalifikácia je prvým krokom. Zisti, ako na to!

8. diel - Programovanie jednoduchých Java GUI hier - Časovač 2

V tomto diele budeme pokračovať v tom, čo sme začali minule - pohyb objektov po JPanelu.

Vytvoríme program, v ktorom budeme pohybovať objektom (v tomto prípade obdĺžnikom) pomocou klávesnice.

import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Rectangle;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import javax.swing.JPanel;
import javax.swing.Timer;

public class MujPanel extends JPanel {
    private final int SIRKA_OBDELNIKA = 80;
    private final int VYSKA_OBDELNIKA = 50;
    private int x, y;
    private int smerX, smerY;
    private int rychlost;
    private Rectangle obdelnik;

    public MujPanel() {

        this.x = 0;
        this.y = 0;
        this.smerX = 0;
        this.smerY = 0;
        this.rychlost = 2;
        this.obdelnik = new Rectangle(x, y, SIRKA_OBDELNIKA, VYSKA_OBDELNIKA);

        this.setPreferredSize(new Dimension(400, 300));
        this.setBackground(Color.blue);
        this.setFocusable(true);

        this.addKeyListener(new PosluchacKlavesnice());

        Timer casovac = new Timer(10, new PosluchacCasovace());
        casovac.start();
    }

    @Override
    public void paintComponent(Graphics g) {
        super.paintComponent(g);

        g.setColor(Color.red);
        g.drawRect(x, y, SIRKA_OBDELNIKA, VYSKA_OBDELNIKA);
    }

    private void move() {
        x += smerX;
        y += smerY;

        if (x >= this.getWidth() - (SIRKA_OBDELNIKA + 1)) {
            x = this.getWidth() - (SIRKA_OBDELNIKA + 1);
        }
        if (x <= 0) {
            x = 0;
        }
        if (y >= this.getHeight() - (VYSKA_OBDELNIKA + 1)) {
            y = this.getHeight() - (VYSKA_OBDELNIKA + 1);
        }
        if (y <= 0) {
            y = 0;
        }
    }

    private class PosluchacCasovace implements ActionListener {

        @Override
        public void actionPerformed(ActionEvent e) {
            move();
            repaint();
        }
    }

    private class PosluchacKlavesnice implements KeyListener {

        @Override
        public void keyPressed(KeyEvent e) {
            int klavesa = e.getKeyCode();
            if (klavesa == KeyEvent.VK_LEFT) {
                smerX = -rychlost;
            }
            else if (klavesa == KeyEvent.VK_UP) {
                smerY = -rychlost;
            }
            else if (klavesa == KeyEvent.VK_RIGHT) {
                smerX = rychlost;
            }
            else if (klavesa == KeyEvent.VK_DOWN) {
                smerY = rychlost;
            }
        }

        @Override
        public void keyReleased(KeyEvent e) {
            int klavesa = e.getKeyCode();
            if (klavesa == KeyEvent.VK_LEFT) {
                smerX = 0;
            }
            else if (klavesa == KeyEvent.VK_UP) {
                smerY = 0;
            }
            else if (klavesa == KeyEvent.VK_RIGHT) {
                smerX = 0;
            }
            else if (klavesa == KeyEvent.VK_DOWN) {
                smerY = 0;
            }
        }

        @Override
        public void keyTyped(KeyEvent e) {

        }
    }
}
Pohyb pomocou klávesnice v Java Swing - Tvorba hier v Java Swing
private final int SIRKA_OBDELNIKA = 80;
private final int VYSKA_OBDELNIKA = 50;

Deklarujeme dve premenné typu int a inicializujeme je na zadané hodnoty. Kľúčové slovo final znamená, že tieto premenné sú konštanty (nebude sa meniť ich hodnota). Takýmto spôsobom deklarujeme premenné, u ktorých vieme, že ich hodnota je konečná.

Tento spôsob deklarácie je výhodný z toho dôvodu, že v prípade, že sa v programe omylom pokúsime zmeniť hodnoty tejto premennej, prekladač nám to neumožní.

private int x, y;

X-ová a y-nová súradnice ľavého horného rohu obdĺžnika.

private int smerX, smerY;

Premenné uchovávajúci posun v smere. Ak sú nula obdĺžnik sa nepohybuje.

private int rychlost;

Premenná uchovávajúce rýchlosť, akou sa bude obdĺžnik pohybovať.

this.obdelnik = new Rectangle(x, y, SIRKA_OBDELNIKA, VYSKA_OBDELNIKA);

Premenná obdĺžnikov je typu Rectangle. Do konstruktoru zadávame súradnice ľavého horného rohu (x, y), šírku a výšku obdĺžnika.

this.addKeyListener(new PosluchacKlavesnice());

JPanel (this) si registruje ako poslucháča udalostí KeyEvent objekt typu PosluchacKlaves­nice.

Inak povedané, objektu PosluchacKlaves­nice, ktorý bol práve vytvorený pomocou new, sa budú posielať udalosti (správy) typu KeyEvent. Je to to isté, ako by ste napísali:

PosluchacKlavesnice posKla = new PosluchacKlavesnice();
this.addKeyListener(posKla);

Ušetrí sa tým ale trocha písania.

Timer casovac = new Timer(10, new PosluchacCasovace());
casovac.start();

Nič nové, ale opakovanie je matka múdrosti. Vytvoríme nový Timer, ktorý bude generovať udalosti čo desať milisekúnd a poslucháčom týchto udalostí bude práve vytvorený objekt typu PosluchacCasovace.

public void paintComponent(Graphics g) {
    super.paintComponent(g);

    g.setColor(Color.red);
    g.drawRect(x, y, SIRKA_OBDELNIKA, VYSKA_OBDELNIKA);
}

Vykreslenie pozadie, nastaví farbu popredia na červenú a vykreslí obdĺžnik (Rectangle). Obdĺžnik rozhýbe tak, že mu budeme meniť súradnice xaya opätovne ho kresliť na JPanel.

x += smerX;
y += smerY;

V metóde move (), keď je zavolaná, sa xay zmení podľa hodnoty v premenných smerX, smer. Tieto dve premenné sú v kostruktoru inicializované na nulu, takže obdĺžnik sa nepohybuje. Pomocou zmien týchto premenných ovplyvňujeme pohyb obdĺžnika. Meniť ich budeme pri stlačení klávesov.

Následne v metóde move () kontrolujeme, či je obdĺžnik (celá jeho plocha) viditeľný. Možno vám nie je jasné, prečo pričítame ešte jedničku (x> = this.getWidth () - (SIRKA_OBDELNIKA + 1)). X-ová súradnice začína nulou a pri nastavení veľkosti panelu na 400 bodov je viditeľné x od 0 do 399. Výsledkom operácie je 320 (x-ová súradnice ľavého horného rohu obdĺžnika) a keď 320 sčítame s 80 (šírkou obdĺžnika) dostaneme 400, čo je pravý okraj obdĺžnika, ktorý je však už nie je viditeľný. Ak to budete chcieť skúsiť a odmazať jedničku, napriek tomu sa obdĺžnik môže zobrazovať správne. Je to preto, že veľkosť nastavená metódou setPreferredSize () nie je úplne záväzná a JPanel môže mať veľkosť inú. Aktuálnu veľkosť JPanelu získate metódou getWidth () a getHeight ().

public void keyPressed(KeyEvent e) {
    int klavesa = e.getKeyCode();
    if (klavesa == KeyEvent.VK_LEFT) {
        smerX = -rychlost;
    }
    else if (klavesa == KeyEvent.VK_UP) {
        smerY = -rychlost;
    }
    else if (klavesa == KeyEvent.VK_RIGHT) {
        smerX = rychlost;
    }
    else if (klavesa == KeyEvent.VK_DOWN) {
        smerY = rychlost;
    }
}

V prípade stlačenia klávesy na klávesnici je vygenerovaná udalosť KeyEvent, ktorá je zaslaná zaregistrovanému poslucháči (je zavolaná posluchačova metóda keyPressed () a ako parameter je ňou odovzdaný objekt typu KeyEvent).

int klavesa = e.getKeyCode();
if (klavesa == KeyEvent.VK_LEFT) {
    smerX = -rychlost;
}

Získame číslo reprezentujúce kláves. Následne toto číslo porovnávame s konštantou. Ak sa napríklad premenná klávesa rovná 37, jedná sa o kláves nečíselný šípka vľavo (37 je hodnota konštanty KeyEvent.VK_LEFT). V tomto prípade premenná smerX bude -rýchlosť.

Premenná rýchlosť je dva, tým pádom pri zavolaní metódy move (), ktoré sa deje pri každom vygenerovaní udalostí objektom Timer (podľa nášho nastavenia každých 10 milisekúnd), sa bude hodnota súradnice x znižovať o dva a obdĺžnik sa bude pohybovať doľava.

V metóde keyPressed (KeyEvent e) ošetrujeme stav, kedy je stlačený nejaký z nenumerických šípok. Obdobné je to s metódou keyReleased (KeyEvent e). Ak by sme túto metódu nechali prázdnu, obdĺžnik by sa pohyboval aj po pustení šípky.

//super.paintComponent(g);

Ak ste to ešte neskúsili, tak Zdokumentujte (alebo vymažte) volanie rodičovskej metódy paintComponent. Tak najlepšie zistíte, k čomu to vlastne je.


 

Mal si s čímkoľvek problém? Stiahni si vzorovú aplikáciu nižšie a porovnaj ju so svojím projektom, chybu tak ľahko nájdeš.

Stiahnuť

Stiahnutím nasledujúceho súboru súhlasíš s licenčnými podmienkami

Stiahnuté 331x (1.61 kB)
Aplikácia je vrátane zdrojových kódov v jazyku Java

 

Predchádzajúci článok
Programovanie jednoduchých Java GUI hier - Časovač
Všetky články v sekcii
Tvorba hier v Java Swing
Preskočiť článok
(neodporúčame)
Programovanie jednoduchých Java GUI hier - Detekcia kolízií
Článok pre vás napísal vita
Avatar
Užívateľské hodnotenie:
Ešte nikto nehodnotil, buď prvý!
vita
Aktivity