Problema de integração entre dois JFrames (game)

8 respostas
elithin

Olá a todos!
bem, estou desenvolvendo um game para a faculdade, mas estou encontrando problemas...

O jogo em si está pronto,e agora fiz um menu inicial para ele mas na hora de integrar, o jogo não funciona.
Inicialmente fiz o menu em um JFrame e o jogo em outro, e quando o usuário apertasse Start Game o Frame do jogo apareceria e o do menu desapareceria. Até aí tudo bem, mas o jogo fica descentralizado no frame novo, e não responde aos comandos do teclado nem nada. Até o X para fechar para de funcionar. Tenho que fechar o programa pelo gerenciador de tarefas....

Então tentei fazer tudo em um frame só e o problema da descentralização diminuiu, mas não foi resolvido, e o jogo continua sem responder...

aqui estão os códigos que criam os frames:

cria a tela com o menu
Initial(){
		
		setTitle("Chicken Killer");
		setSize(new Dimension(800,600));
		setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		back = SpriteStore.get().getSprite("sprites/front.jpg");
		menuShown = false;
		
		addKeyListener(new KeyListener() {
			public void keyTyped(KeyEvent e) {}
			public void keyPressed(KeyEvent e) {
				if (menuShown){
					if (e.getKeyCode() == KeyEvent.VK_UP) {
						menu.selectPreviousOption();
						paintScreen();
					}
					if (e.getKeyCode() == KeyEvent.VK_DOWN) {
						menu.selectNextOption();
						paintScreen();
					}
					if (e.getKeyCode() == KeyEvent.VK_ENTER) {
						enterPressed();
					}
				}
				else {
					menu = new Menu();
					menuShown = true;
					paintScreen();
				}
			}
cria a tela do jogo
public Game(Initial menuScreen) {
		menuScreen.dispose();
		// create a frame to contain our game
		JFrame container = new JFrame("ChickenKiller");

		// get hold the content of the frame and set up the resolution of the game
		JPanel panel = (JPanel) container.getContentPane();
		panel.setPreferredSize(new Dimension(800,600));
		panel.setLayout(null);
		
		// setup canvas size and put it into the content of the frame
		setBounds(0,0,800,600);
		panel.add(this);
		
		// Tell AWT not to bother repainting our canvas since we're
		// going to do that our self in accelerated mode
		setIgnoreRepaint(true);
		
		// make the window visible 
		container.pack();
		container.setResizable(false);
		container.setVisible(true);
		
		// add a listener to respond to the user closing the window. 
		container.addWindowListener(new WindowAdapter() {
			public void windowClosing(WindowEvent e) {
				System.exit(0);
			}
		});
		
		// add a key input system (defined below) to canvas
		// so it can respond to key pressed
		addKeyListener(new KeyInputHandler());
		
		// request the focus so key events come to us
		requestFocus();

		// create the buffering strategy which will allow AWT
		// to manage the accelerated graphics
		createBufferStrategy(2);
		strategy = getBufferStrategy();
		
		//initializes the game entities
		initEntities();
	}

Obrigada pela atenção!

8 Respostas

ViniGodoy

Só com a informação que você passou fica bem difícil saber o que está havendo.

elithin

bem, então vou tentar ser um pouco mais específica…
o menu está funcionado corretamente. Quando dou ENTER na opção Start Game o programa cria uma instância da classe Game, cujo construtor está no primeiro post. Esta classe cria outro frame, (onde vai rodar o jogo) e some com o frame do menu.

Até aí ok.
Na hora de pintar os componentes, tudo é deenhado corretamente, mas deslocado digamos dez unidades para cima e para a esquerda, o que some com um pedaço da imagem, e deixa faixas pretas embaixo e à direita.
Além disso o jogo não funciona. O KeyListener que este frame possui não captura nenhuma tecla pressionada, então o jogo não começa (fica escrito “Pressione qualquer tecla para iniciar o jogo”. Já tentei usar o requestFocus() mas não adianta.

Ah! E a classe Game extende Canvas. sinceramente não sei direito como usar esta classe. Para escrever o jogo me baseei em um exemplo que encontrei na internet.

Sem colocar o menu inicial, criando a classe Game direto de uma main nesta classe o jogo funciona perfeitamente.

Espero que tenha ficado um pouco mais claro. Se necessário posso colocar mais algum trecho de código.
Obrigada pela disposição em ajudar! =D

ViniGodoy

Oi Elithin.

O seu problema é o seguinte:

No StartOpt você cria um novo game, e chama o método gameLoop().

Quando você faz isso a partir do main, é a main thread que dispara o game loop. Por isso, o game loop fica numa thread (a main thread) e o controle de eventos em outra (a AWT thread), e o jogo funciona.

Quando você faz isso a partir do menu, quem reage ao keypress é a AWT Thread. Essa é a thread que trata eventos. E é ela quem roda o método gameLoop(). Como sua própria documentação ressalta, o método gameloop() não termina até que o jogo termine. Agora, se o método não termina, ele também não libera a AWT thread, que fica impedida de tratar eventos.

A solução para seu problema é disparar o método gameLoop() a partir de uma nova thread.
@Override
    public void doAction(Initial menuScreen) {
        final Game g = new Game(menuScreen);

        // Start the main game loop, note: this method will not
        // return until the game has finished running.
        Thread gameThread = new Thread(new Runnable() {

            @Override
            public void run() {
                g.gameLoop();
            }
        }, "Game Thread");
        gameThread.start();
    }

Fiz ainda alguns ajustes em suas classes para simplificar. Você usava muito o iterator e for normal, numa sintaxe típica do Java 4. Alterei para for each. O código completo vou enviar no seu e-mail.

Também transformei o Canvas num JFrame. Afinal, não é uma boa prática misturar AWT e Swing.

elithin

hmmmn, só por curiosidade, a chamada public void run() cria uma nova thread ? ainda não estou muito à vontade com todos estes conceitos, e vou aprendendo com o que encontro na net. obrigada pelas dicas do for vou ver como esse novo meio funciona =)

Além disso, qual a diferença de JFrame e Canvas (fora que o frame cria a janela)? Quando uso o Canvas?
Muitíssimo obrigada pela ajuda. Você realmentesabe muuito de Java né? :shock: Tem algum lugar que você indique para aprender essas novas sintaxes e não ficar aprendendo coisas defasadas?

ViniGodoy

O Canvas é uma classe que só representa a área de pintura. Ele é da AWT (pode ver que não começa com o J na frente).
É uma boa prática não misturar componentes de tela da AWT e do Swing.

A classe Thread é um disparador de threads. Ela recebe como parâmetro no construtor um Runnable (que é uma interface, como os “listeners” o são), que tem um método run. Você usa então o método start(). Esse método cria uma nova thread, que começa a rodar no run() do Runnable que foi passado como parâmetro.

Só a presença do run() não garante a execução de uma nova thread.

Eu trabalhei por 6 anos com o Java, no desenvolvimento de sistemas industriais, na Siemens. O java não é minha primeira linguagem (e nem foi a última), pois antes já programava com C++, VB e Delphi.

E, nesse tempo, dá sim pra aprender uma coisa ou outra. :wink:

O local para aprender os recursos “novos” do Java é essa página aqui (não são tão novos pois surgiram no Java 5):
http://download.oracle.com/javase/1.5.0/docs/guide/language/index.html

elithin

Brigada pelos esclarecimentos! Vou olhar mais a fundo a página que me recomendou.
O próximo passo no jogo, já que tenho tempo até a data de entrega vai ser colocar alguns sons. Espero não ser muito difícil.
Obrigada de novo e até mais (quem sabe num futuro próximo =S)

ViniGodoy

Tocar sons em java não é muito trivial. Tenho algumas classes prontas para esse trabalho, se quiser, eu te passo. Na verdade, você pode baixa-las do Vikanoid, aqui na página dos meus jogos. Você vai ver que além do jogo tem uns pacotes da “JGF”, que é a sigla de “Java Game Framework”. Lá tem classes para tocar som e música em formato midi. Para formato mp3, você precisa baixar um pacote externo, fácil de usar, chamado javazoom.

Quem sabe vc não gosta dessa brincadeira de fazer jogo e vem ser minha aluna na pós de jogos aqui da PUC?

elithin

se é pra gostar de jogos, já gostei.=P é muito legal ver uma idéia se materializar :slight_smile:

hmn vou olhar essas classes do vikanoid. os sons que eu queria tocar são midi mesmo, então deve ser mais simples.
quem sabe um dia não vou mesmo hein?

Criado 2 de novembro de 2010
Ultima resposta 4 de nov. de 2010
Respostas 8
Participantes 2