Posts Tagged ‘double buffering’

Java pong

Napsat hru Pong v Javě by mě nyní ani nenapadlo. Chtěl jsem původně napsat Pong pro OS Android, ale asi v půlce vývoje mi odešel telefon, takže je nyní na reklamaci. Jen mimo řeč bych rád zmínil, že program Kies od Samsungu opravdu stojí za to. Je tak dobře napsaný, že mu nedělá problémy spadnout při aktivitě, jako je například upgrade firmwaru telefonu. Ano, přesně z tohoto důvodu putuje můj telefon po servisním oddělení společnosti Samsung. Samozřejmě existovala možnost nahrát nějakou neoficiální ROM, ale pomyšlení na ztrátu záruky v případě poruchy telefonu mi to nedovolilo. Nyní zase k věci. Telefon není doma, provádět všechny testy v AVD se mi nechtělo, tak jsem se rozhodl, že dopíši Pong prozatím v Java SE. Hra není úplně dolazena a má nedostatky, víceméně jsem její tvorbou jen zabíjel čas.

Nebudu v tomto příspěvku rozvádět každý kousek kódu. Celý zdrojový kód včetně výsledné aplikace si můžete stahnout z odkazů umístěných na konci příspěvku. Hlavní logika hry, vykreslování, ovládání klávesnicí se nachází ve třídě Pong.java, která obsahuje asi 150 řádků kódu. Nejedná se tedy o nic složitého. Dále se pokusím poukázat na pár detailů, které by se mohli programátorům začátečníkům hodit – aby měl tento příspěvěk alespoň nějaký význam :) .

Double buffering

Předpokládám, že není třeba termín vysvětlovat. Pokud někdo přeci jen neví oč jde, může se podívat například sem. Jak v Javě řešit tento problém existuje více způsobů. Jeden způsob je zmíněn v odkazu, který je umístěn  na začátku odstavce. Já použil trošku jiný styl řešení. Kreslím vše do obrázku. Pokud je vše vykresleno, tak tento obrázek vykreslím na obrazovku. To bohatě stačí k zamezení protivného problikávání obrazu způsobeného neustálým překreslováním při kreslení dalších a dalších tvarů.

Image bufferImage = createImage(getWidth(), getHeight());
Graphics buffer = bufferImage.getGraphics();

Tímto kódem se vytvoří obrázek – instance třídy Image, který poté bude vykreslován na obrazovku (v tomto případě do panelu JPanel) a instance třídy Graphics, pomocí níž jsme schopni do obrázku kreslit základní tvary atd.

@Override
public void paint(Graphics g) {
    buffer.drawString("Ahoj :]", 20, 20);
    g.drawImage(bufferImage, 0, 0, this);
}

Zde je už jen příklad přetížené metody paint, ve které do “bufferovaného” obrázku zakreslíme řetězec a následně je vykreslen “bufferovaný” obrázek.

Stisk více klávec najednou

Tento problém jsem vyřešil tak, že jsem ho vlastně moc neřešil. Na nějakém fóru jsem zahlédl jedno řešení a to použil. Nejedná se ovšem o moc použitelnou variantu, což si každý může v aplikaci vyzkoušet. Nicméně to funguje o level lépe, než kdyby se to neřešilo vůbec.

private Set pressedKeys = new HashSet();
@Override
public void keyPressed(KeyEvent e) {
    pressedKeys.add(e.getKeyCode());
    if (pressedKeys.size() > 0) {
            for (int i : pressedKeys) {
                switch (i) {
                    case KeyEvent.VK_UP:
                    //do something
                    .
                    .
                    .
                }
            }
     }
}

@Override
public void keyReleased(KeyEvent e) {
    pressedKeys.remove(e.getKeyCode());
}

Jde jen o registraci instance třídy HashSet, přičemž se do ní ukládá kód stishnuté klávesy. Jestliže je vyvolána událost keyReleased, která nastane pokud pustíme stiknutou klávesu, tak se z kolekce její kód odebere. Pokud jsou nějaké klávesy stishnuny, je volána obslužná metoda keyPressed a v ní je možno iterovat stisknuté klávesy, které jsou uloženy v kolekci typu HashSet.

Náhodná hodnota z výčtu (enum)

Pro směr míčku jsem si udělal výčet směrů. Když jsem poté řešil, jak elegantně vyřešit návrat náhodného směru, tak jsem došel k následujícímu řešení.

public enum Direction {

    RIGHT_DOWN,
    RIGHT_UP,
    LEFT_DOWN,
    LEFT_UP;

    private static final List VALUES = Arrays.asList(values());
    private static final int SIZE = VALUES.size();
    private static final Random RANDOM = new Random();

    public static Direction randomDirection() {
        return VALUES.get(RANDOM.nextInt(SIZE));
    }
}

Zdrojové kódy hry Pong – PongSE.zip
Hra Pong – PongSE-jar.zip


Hledat


Menu

Archiv

Odkazy