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

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

[code]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();
			}
		}[/code]

cria a tela do jogo

[code]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();
}[/code]

Obrigada pela atenção!

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

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

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.

[code]

@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();
}[/code]

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.

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?

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

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)

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?

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?