IT rekvalifikace s garancí práce. Seniorní programátoři vydělávají až 160 000 Kč/měsíc a rekvalifikace je prvním krokem. Zjisti, jak na to!
Hledáme nové posily do ITnetwork týmu. Podívej se na volné pozice a přidej se do nejagilnější firmy na trhu - Více informací.

Diskuze: Hra

Aktivity
Avatar
dinokino
Člen
Avatar
dinokino:8.6.2016 0:06

Dobrý den, mám takový problém. Učím se programovat hry a řekl jsem si, že zkusím nějakou naprogramovat sám (po předchozích tutoriálech). Jenže jsem se zasekl hned na začátku. Mám 2 třídy. Hlavní třída slouží pouze jako základní okno:

public class Frame extends JFrame{
        /**
         *
         */
        private static final long serialVersionUID = 1L;
        Game game;
        public Frame() {
                this.setDefaultCloseOperation(EXIT_ON_CLOSE);


                game = new Game();
                this.add(game.canvas);
                this.pack();
                this.setResizable(false);
        }
        public static void main(String[] args) {
                SwingUtilities.invokeLater(new Runnable() {

                        @Override
                        public void run() {
                                new Frame().setVisible(true);;
                        }
                });
        }

}

V tom by problém nebyl. Problém byl až jsem vytvořil druhou třídu, která měla zajistit běh hry:

public class Game implements Runnable{
        public Canvas canvas;
        Thread thread;
        BufferStrategy bs;
        Graphics g;


        //Variables for game loop
        private int fps, timePerTick;
        double now, lastTime;
        private double delta;

        Game(){
                initVariables();
                canvas = new Canvas();
                canvas.setPreferredSize(new Dimension(300, 300));
        }
        private void initVariables(){

                //create and start thread
                thread = new Thread(this);
                thread.start();
        }
        private void tick(){
        }
        private void render(){
                bs = canvas.getBufferStrategy();
                if (bs == null){
                        canvas.createBufferStrategy(3);
                        return;
                }
                g = bs.getDrawGraphics();
                g.drawRect(0, 0, 50, 50);
                bs.show();
                g.dispose();

        }
        private void initRun(){
                delta = 0;
                lastTime = System.nanoTime();
                fps = 30;
                timePerTick = 1000000000/fps;
        }
        @Override
        public void run() {
                initRun();
                int timer=0;
                int ticks=0;
                while(true){

                        now = System.nanoTime();
                        delta += (now - lastTime) / timePerTick;
                        timer += (now - lastTime);
                        lastTime = now;
                        if(delta>=1){
                                tick();
                                render();
                                delta--;
                                ticks++;
                        }
                        if (timer>1000000000){
                                System.out.println("FPS: "+ticks);
                                timer = ticks = 0;
                        }
                }
        }
}

problém byl konkrétně v hodnotě proměnné FPS...Když jsem ji v metodě private void initRun() nastavil na 10, tak vše šlo jak mělo (prostě se jen díky metodě run() každou vteřinu do konzole vypsalo "FPS: 10" a vykreslil se čtverec do JFrame). Když jsem ale tuto hodnotu (FPS) nastavil na 30, nastal problém. Objevilo se okno, viz. přiložený obr. a aplikace nefungovala). Dále se hned otevřelo (v Eclipse) okno debug a "něco" se tam rozbalilo (opět viz. obr.1). Dále se ještě otevřela "nová záložka" (viz. obr.2), ve které se akorát napsalo "source not found".(viz. obr. 2).
Dokáže někdo poradit v čem je vlastně problém?? Děkuji

 
Odpovědět
8.6.2016 0:06
Avatar
dinokino
Člen
Avatar
dinokino:8.6.2016 0:10

(obrázky se prohodily...ten druhý zobrazený (ten víc "červený") je míněn jako obr.1)

 
Nahoru Odpovědět
8.6.2016 0:10
Avatar
Odpovídá na dinokino
Milan Suchomel:8.6.2016 14:42

Změň v run() metodě volání metody render(). Překreslování GUI nemůžeš volat ve vláknech obyčejným způsobem. Ve swingu jsem z vlákny nepracoval, ale takhle by to mělo funguje. Já jsem to dělal v JavaFX a tam je Aplication.Run­Later(...)

SwingUtilities.invokeLater(new Runnable() {
    @Override
    public void run() {
        render();
    }
});

Více zde: Threading with swing

 
Nahoru Odpovědět
8.6.2016 14:42
Avatar
dinokino
Člen
Avatar
Odpovídá na Milan Suchomel
dinokino:8.6.2016 15:41

Skutečně to nyní funguje jak má. Díky.
Jen nechápu proč to nefunguje, protože ve hře, co jsem dělal podle návodu byli metody run() i render() naprosto stejné, a žádné SwingUtilities­.invokeLater() tam nebylo.
Tím, že jsem si do programu vložil na různá místa postupně metody println() jsem zjistil, že problém je v metodě render konkrétně v příkazu canvas.create­BufferStrategy(3). To jsem spouštěl přes "debug". Když jsem to spustil přes "run", tak došlo k vyjímce "xception in thread "Thread-1" java.lang.Ille­galStateExcep­tion: Component must have a valid peer" na tom samém příkazu. Nejde to vyřešit ještě jinak? Neví někdo?? Jak říkám, u jednoho návodu vůbec žádná metoda invokeLater() použitá nebyla a přesto to fungovalo...

 
Nahoru Odpovědět
8.6.2016 15:41
Děláme co je v našich silách, aby byly zdejší diskuze co nejkvalitnější. Proto do nich také mohou přispívat pouze registrovaní členové. Pro zapojení do diskuze se přihlas. Pokud ještě nemáš účet, zaregistruj se, je to zdarma.

Zobrazeno 4 zpráv z 4.