Vianoce v ITnetwork sú tu! Dobí si teraz kredity a získaj až 80 % extra kreditov na e-learningové kurzy ZADARMO. Zisti viac.
Hľadáme nové posily do ITnetwork tímu. Pozri sa na voľné pozície a pridaj sa k najagilnejšej firme na trhu - Viac informácií.

9. diel - Programovanie jednoduchých Java GUI hier - Detekcia kolízií

V nasledujúcich dvoch dieloch si ukážeme, ako detekovať kolízie objektov.

Detekcia kolízií

V predchádzajúcej kapitole sme vytvorili obdĺžnik, ktorý sa pri stlačení šípok pohyboval po paneli. Všetok tento kód sme natlačili do triedy, ktorá vytvárala panel a začalo to byť trošku neprehľadné.

Vezmeme teda predchádzajúci príklad a trošku ho upravíme. Najskôr vytvoríme triedu predstavujúce obdĺžnik (stíhača), potom triedu s panelom a nakoniec triedu s hlavným oknom.

Detekcia kolízií v Jave - Tvorba hier v Java Swing

Trieda predstavujúce náš obdĺžnik.

import java.awt.Color;
import java.awt.Graphics;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;

public class Chytac implements KeyListener {

    private Color barva = Color.white;
    private final int SIRKA = 50;
    private final int VYSKA = 10;
    private int x, y, smerX, smerY, rychlost;
    private MujPanel panel;

    public Chytac(MujPanel panel) {

        this.rychlost = 3;
        this.panel = panel;
        this.x = (panel.getSIRKA_PANELU() - SIRKA) / 2;
        this.y = (panel.getVYSKA_PANELU() - VYSKA) / 2;
    }

    public void vykresliSe(Graphics g) {
        g.setColor(barva);
        g.drawRect(x, y, SIRKA, VYSKA);
    }

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

        if (x >= panel.getSIRKA_PANELU() - (SIRKA + 1)) {
            x = panel.getSIRKA_PANELU() - (SIRKA + 1);
        }
        if (x <= 0) {
            x = 0;
        }
        if (y >= panel.getVYSKA_PANELU() - (VYSKA + 1)) {
            y = panel.getVYSKA_PANELU() - (VYSKA + 1);
        }
        if (y <= 0) {
            y = 0;
        }
    }

    @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) {
    }
}
public class Chytac implements KeyListener

Trieda implementuje rozhranie KeyListener, čo znamená, že má schopnosť reagovať na udalosti generované stlačením kláves. Nemusíme teda vytvárať špeciálne triedu poslucháča klávesnice, ale ako poslucháča zaregistrujeme objekt typu stíhača.

private MujPanel panel;

Do tejto premennej uložíme odkaz na panel, v ktorom bol vytvorený stíhača. Budeme tak mať prístup k metódam objektu MujPanel (napríklad metódy getSIRKA_PANELU () a getVYSKA_PANELU () pre zistenie rozmerov panelu).

this.x = (panel.getSIRKA_PANELU() - SIRKA) / 2;
this.y = (panel.getVYSKA_PANELU() - VYSKA) / 2;

Tu pozor. Chceme umiestniť chytač od stredu panelu. Chytač sa ale vykreslí na súradnice x = 0, y = 0. Ako je toto možné?

Síce sme nastavili preferovanú veľkosť JPanelu, ale panel ešte nebol vytvorený, preto je jeho šírka a výška nula. Vyššie uvedeným kódom chytač dokonca prvotne umiestnime mimo panel (0 - šírka, 0 - výšky), ale pretože je každý cyklus volaná metóda chytac.move () (v MujPanel.java), pozícia je upravená na [0, 0]. Zatiaľ to takto necháme.

public void vykresliSe(Graphics g) {
    g.setColor(barva);
    g.drawRect(x, y, SIRKA, VYSKA);
}

Táto metóda dostane ako parameter grafický kontext (grafický kontext si môžete predstaviť ako podložku, ktorá sa postupne odovzdáva kresliacim metódam, každá metóda na ňu nakreslí to svoje - odovzdáva sa plocha panelu a na ňu sa postupne kreslí) a vykreslí objekt chytača na súradnice x, y.

Metódy public void move (), public void keyPressed (KeyEvent e) a public void keyReleased (KeyEvent e) sú nám už známe z predchádzajúcich príkladov. Metódu public void keyTyped (KeyEvent e) nebudeme používať.

Trieda s hlavným panelom.

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

public class MujPanel extends JPanel {

    private Chytac chytac;

    public MujPanel() {

        this.chytac = new Chytac(this);

        this.setPreferredSize(new Dimension(400, 300));
        this.setBackground(Color.black);
        this.addKeyListener(chytac);
        this.setFocusable(true);

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

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

        chytac.vykresliSe(g);
    }

    private class PosluchacCasovace implements ActionListener {

        @Override
        public void actionPerformed(ActionEvent e) {

            chytac.move();
            repaint();
        }
    }

    public int getSIRKA_PANELU() {
        return this.getWidth();
    }

    public int getVYSKA_PANELU() {
        return this.getHeight();
    }
}
this.chytac = new Chytac(this);

Vytvoríme nový objekt typu chytača a odkaz na neho uložíme do privátnej premennej stíhača, ktorú sme deklarovali skôr.

this.addKeyListener(chytac);

Správy budú zasielané objektu typu stíhača. Je to logické, pretože stíhača reaguje na klávesové šípky.

this.setFocusable(true);

Nezabudnite na zameranie (focus) panelu. Bez neho by nám ovládanie z klávesnice nefungovalo.

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

    chytac.vykresliSe(g);
}

Vykreslí pozadia a zavolá kresliaci metódu stíhača, ktoré odovzdá grafický kontext (plochu na kreslenie).

private class PosluchacCasovace implements ActionListener {

    public void actionPerformed(ActionEvent e) {

        chytac.move();
        repaint();
    }
}

V prípade vygenerovania udalosti ActionEvent objektom Timer (ako poslucháč je zaregistrovaný objekt typu PosluchacCasovace) je zavolaná metóda actionPerformed (ActionEvent e). Podľa nastavenia Timeru v tomto programe, je táto metóda volaná približne každých desať milisekúnd. Táto metóda následne volá metódu move () objektu stíhača, ktorá (v prípade že je stlačená klávesa nečíselný šípka) vykoná zmenu súradníc stíhača. Potom je volaná metóda prekreslenie (), ktorá volá metódu paintComponent (). Vďaka tomu sa plocha panelu prekresľuje (každých desať milisekúnd).

public int getSIRKA_PANELU() {
    return SIRKA_PANELU;
}

public int getVYSKA_PANELU() {
    return VYSKA_PANELU;
}

Pridali sme dve metódy, ktoré vracia rozmer panelu.

Trieda vytvárajúce hlavné okno a obsahujúce metódu main (vstupný bod programu)

import javax.swing.JFrame;

public class DetekceKolizi extends JFrame {

    public DetekceKolizi() {
        this.setTitle("Detekce kolizí");
        this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        MujPanel panel = new MujPanel();
        this.add(panel);

        this.pack();
        this.setResizable(false);
    }

    public static void main(String[] args) {
        new DetekceKolizi().setVisible(true);
    }
}

Posledná dôležitú vec, ktorú si ešte musíme ukázať, je ako zistiť zrážku objektov (detekovať kolízie). Zrážka objektov je situácia, keď sa jeden objekt pretne s druhým. V našom programe chceme túto zrážku zistiť v prípade, že objekt stíhača narazí do objektu štvorec. Ako chytač tak štvorec sú obdĺžniky (štvorec je obdĺžnik s rovnakou dĺžkou strán) a určite by sme si mohli napísať metódu, ktorá by zisťovala, kedy došlo k pretnutia obdĺžnikov. Java ale túto prácu urobila za nás a ponúka nám hotovú metódu. Je to metóda pretína objektu Rectangle. Aby sme ju mohli použiť, potrebujeme dva objekty Rectangle, ktoré porovnáme a zistíme, či sa prekrývajú. Pokračovanie v ďalšom diele.


 

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é 316x (2.06 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č 2
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í 2
Článok pre vás napísal vita
Avatar
Užívateľské hodnotenie:
Ešte nikto nehodnotil, buď prvý!
vita
Aktivity