Tworzenie prostej gry 2D - gdzie zaimplementować podwójne buforowanie?

0

Witam. Pisze sobie małą gierke i natrafiłem na problem z podwójnym buforowaniem. Otóż nie wiem gdzie je wcisnąć. Na razie wygląda to tak: mam obiekt Manager który "zarządza" całą grą, oraz obiekt dziedziczący po JFrame (w trybie pełnoekranowym). Rysuje w Managerze poprzez:

private void draw(){
		Graphics g = frame.getGraphics();
		g.setColor(Color.white);
		g.fillRect(0, 0, frame.getWidth(), frame.getHeight());
		g.setColor(Color.red);
		g.fillRect(111, 111,222, 222);
	}

Petla w managerze wyglada:

private void gameLoop(){
		do {
			checkInput();
			draw();
		} while (frame.isVisible());
	}

I teraz pytanie jak do tego "wsadzić" podwójne buforowanie? Próbowałem jakoś w managerze ale zawsze dostaje " java.lang.IllegalStateException: Component must have a valid peer"

0

Po skonstruowaniu okna typu JFrame:

okno.getRootPane().setDoubleBuffered(true);

okno to zmienna typu JFrame, nie znam Twojego kodu, może wystarczy

 
getRootPane().setDoubleBuffered(true);

w konstruktorze klasy okna.

0
public class MyFrame extends JFrame{

	private GraphicsDevice device;

	public MyFrame(){
		setUndecorated(true);
		setResizable(false);
		setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		GraphicsEnvironment environment = GraphicsEnvironment.getLocalGraphicsEnvironment();
		device = environment.getDefaultScreenDevice();
		getRootPane().setDoubleBuffered(true);
	}
	
	
}
private void createFarme(){
		frame = new MyFrame();
		
		DisplayMode displayMode = new DisplayMode(frame.getWidth(), frame.getHeight(), 16, 75);
		GraphicsEnvironment environment = GraphicsEnvironment.getLocalGraphicsEnvironment();
		GraphicsDevice device = environment.getDefaultScreenDevice();
		device.setFullScreenWindow(frame);
	}
private void draw(){
		Graphics g = frame.getGraphics();
		g.setColor(Color.white);
		g.fillRect(0, 0, frame.getWidth(), frame.getHeight());
		g.setColor(Color.red);
		g.fillRect(x, y,222, 222);
		g.drawString("Speed"+speed, 10, 10);
	}

Mam cos takiego. I nie wiem co dalej z tym ponieważ jak sam próbuje coś zmienić to albo wypluwa błędy albo po prostu nie działa. Za każdą pomoc bede wdzięczny ponieważ wszystkie przykłady jakie znalazłem odnosiły sie do rysowania w tej samej klasie

0

Zamieszczasz fragmenty kodu, nie wiadomo z jednej klasy czy z kilku. Piszesz

wypluwa błędy
bez informacji jakie błędy i w jakim miejscu programu. Proponuję kontakt z wróżką.

0

okej to kolejno. kod:

package pl.danek.gra;

import java.awt.Color;
import java.awt.DisplayMode;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.GraphicsDevice;
import java.awt.GraphicsEnvironment;
import java.awt.image.BufferStrategy;

import pl.danek.grafika.MyFrame;
import pl.danek.input.InputManager;


public class Main{

	private MyFrame frame;
	private InputManager input;
	private int x=100,y=100;
	
	BufferStrategy strategy;
	
	private int key_exit=27;
	private int key_up=87;
	private int key_down=83;
	private int key_left=65;
	private int key_right=68;
	private int key_space=32;
	
	private int speed=2;

	public static void main(String[] args) {
		new Main().init();
	}



	private void init() {
		createFarme();
		input = new InputManager(frame);
		gameLoop();
	}

	private void createFarme(){
		frame = new MyFrame();
		
		DisplayMode displayMode = new DisplayMode(frame.getWidth(), frame.getHeight(), 16, 75);
		GraphicsEnvironment environment = GraphicsEnvironment.getLocalGraphicsEnvironment();
		GraphicsDevice device = environment.getDefaultScreenDevice();
		device.setFullScreenWindow(frame);
	}

	private void draw(){
		Graphics g = frame.getGraphics();
		g.setColor(Color.white);
		g.fillRect(0, 0, frame.getWidth(), frame.getHeight());
		g.setColor(Color.red);
		g.fillRect(x, y,222, 222);
		g.drawString("Speed"+speed, 10, 10);
	}
	
	private void checkInput(){
		if(input.isPress(key_exit)){
			System.exit(0);
		}
		if(input.isPress(key_right)){
			x+=speed;
		}
		if(input.isPress(key_left)){
			x-=speed;
		}
		if(input.isPress(key_up)){
			y-=speed;
		}
		if(input.isPress(key_down)){
			y+=speed;
		}
		if(input.isPress(key_space)){
			speed++;
			input.clear(key_space);
		}
		
	}

	private void gameLoop(){
		do {
			checkInput();
			draw();
		} while (frame.isVisible());
	}
}
package pl.danek.grafika;

import java.awt.GraphicsDevice;
import java.awt.GraphicsEnvironment;

import javax.swing.JFrame;

public class MyFrame extends JFrame{

	private GraphicsDevice device;

	public MyFrame(){
		setUndecorated(true);
		setResizable(false);
		setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		GraphicsEnvironment environment = GraphicsEnvironment.getLocalGraphicsEnvironment();
		device = environment.getDefaultScreenDevice();
		getRootPane().setDoubleBuffered(true);
		
	}
	
	
}

Myśle że nie potrzeba wklejać klasy InputManager ponieważ nie jest ona tu ważna.

Jeśli próbuje dodać do konstruktora klasy MyFrame

createBufferStrategy(2);

wywala

Exception in thread "main" java.lang.IllegalStateException: Component must have a valid peer

w tej dodanej linijce

0
        private void createFrame(){
                frame = new MyFrame();
 
                DisplayMode displayMode = new DisplayMode(frame.getWidth(), frame.getHeight(), 16, 75);
                GraphicsEnvironment environment = GraphicsEnvironment.getLocalGraphicsEnvironment();
                GraphicsDevice device = environment.getDefaultScreenDevice();
                device.setFullScreenWindow(frame);
                frame.createBufferStrategy(2); //to ma być tu
        }

(zmieniłem nazwę metody!).
Kod, który jest w konstruktorze klasy MyFrame jest całkowicie zbyteczny (poza wierszem setDefaultClose....).

0

Zastosowałem rozwiązanie z książki java Tworzenie gier. Mianowicie do klasy MyFrame dopisałem dwie metody:

package pl.danek.grafika;

import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.GraphicsDevice;
import java.awt.GraphicsEnvironment;
import java.awt.Toolkit;
import java.awt.Window;
import java.awt.image.BufferStrategy;

import javax.swing.JFrame;

public class MyFrame extends JFrame{

	private GraphicsDevice device;

	public MyFrame(){
		setUndecorated(true);
		setResizable(false);
		setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		GraphicsEnvironment environment = GraphicsEnvironment.getLocalGraphicsEnvironment();
		device = environment.getDefaultScreenDevice();
		getRootPane().setDoubleBuffered(true);
	}

	public void update() {
		Window window = device.getFullScreenWindow();
		if (window != null) {
			BufferStrategy strategy = window.getBufferStrategy();
			if (!strategy.contentsLost()) {
				strategy.show();
			}
		}
		Toolkit.getDefaultToolkit().sync();
	}
	
	@Override
	public Graphics getGraphics() {
        try {
			Window window = device.getFullScreenWindow();
			if (window != null) {
				BufferStrategy strategy = window.getBufferStrategy();
				return (Graphics2D) strategy.getDrawGraphics();
			} else {
				return null;
			}
		} catch (Exception e) {
			return null;
		}
    }
}

Pochodza one z ksiażki.

Rysowanie realizuje tak(Klasa Manager, wyciąłem to co nie istotne):

private void draw(Graphics g){
		g.setColor(Color.white);
		g.fillRect(0, 0, frame.getWidth(), frame.getHeight());
		g.setColor(Color.red);
		g.fillRect(x, y,20, 20);
		g.drawString("Speed"+speed, 10, 10);
	}

private void gameLoop(){
		do {
			checkInput();

			Graphics g = frame.getGraphics();
			draw(g);
			g.dispose();
			frame.update();

		} while (frame.isVisible());
	}

Jest to po częsci z tej książki. Działa tak jak powinno, nie ma tego efetku "szarpania" Dzieki wielkie za pomoc ;)

1 użytkowników online, w tym zalogowanych: 0, gości: 1