LIBGDX Cambiando de pantalla

De MediaWiki
Ir a la navegación Ir a la búsqueda

UNIDADE 2: Cambiando de pantalla

Cambiando de pantalla

Tal como comentamos anteriormente neste punto a forma de proceder para cambiar de pantalla é chamando ó método setScreen da clase Game.


Nota: Lembrar que no exemplo que estamos a seguir, mandamos o obxecto que deriva da clase Game como parámetro na chamada ó método setScreen, para que a outra pantalla poda ter referencia ó mesmo e poida volver a chamar ó método setScreen.


No noso exemplo....

Imos cambiar a pantalla inicial para que en vez de ir ó xogo directamente pase pola pantalla principal.


Preparación:

  • Subide o seguinte gráfico ó cartafol GRAFICOS dentro do cartafol assets no proxecto Android.


LIBGDX itin1 pantallapresentacion.png
  • Agora imos modificar a clase PantallaPresentacion para crear unha cámara e visualizar o gráfico anterior.

Código da clase PantallaPresentacion
Obxectivo: visualizar a pantalla de presentación.

  1 public class PantallaPresentacion implements Screen, InputProcessor{
  2 	private MeuXogoGame meuxogogame;
  3 
  4     private OrthographicCamera camara2d;
  5     private SpriteBatch spritebatch;
  6     private static Texture fondo;
  7 	
  8 	public PantallaPresentacion(MeuXogoGame meuxogogame){
  9 		this.meuxogogame=meuxogogame;
 10 
 11 		camara2d = new OrthographicCamera();
 12 		spritebatch = new SpriteBatch();
 13 		fondo = new Texture(Gdx.files.internal("GRAFICOS/LIBGDX_itin1_pantallapresentacion.png"));
 14 		
 15 	}
 16 
 17 	@Override
 18 	public void render(float delta) {
 19 		// TODO Auto-generated method stub
 20 		
 21 		spritebatch.begin();
 22 		
 23 		spritebatch.draw(fondo,0,0,Mundo.TAMANO_MUNDO_ANCHO,Mundo.TAMANO_MUNDO_ALTO);
 24 		
 25 		spritebatch.end();
 26 		
 27 		
 28 	}
 29 
 30 	@Override
 31 	public void resize(int width, int height) {
 32 		// TODO Auto-generated method stub
 33 		
 34 		camara2d.setToOrtho(false, Mundo.TAMANO_MUNDO_ANCHO, Mundo.TAMANO_MUNDO_ALTO);
 35 		camara2d.update();
 36 		
 37 		spritebatch.setProjectionMatrix(camara2d.combined);
 38 		spritebatch.disableBlending();
 39 		
 40 	}
 41 
 42 	@Override
 43 	public void show() {
 44 		// TODO Auto-generated method stub
 45 		Gdx.input.setInputProcessor(this);
 46 		
 47 	}
 48 
 49 	@Override
 50 	public void hide() {
 51 		// TODO Auto-generated method stub
 52                 // Neste caso non fai falta poñelo xa que imos ser nos o que chamemos a dispose cando cambiemos de pantalla.
 53 		//dispose();
 54 		
 55 	}
 56 
 57 	@Override
 58 	public void pause() {
 59 		// TODO Auto-generated method stub
 60 		Gdx.input.setInputProcessor(null);
 61 		
 62 	}
 63 
 64 	@Override
 65 	public void resume() {
 66 		// TODO Auto-generated method stub
 67 		Gdx.input.setInputProcessor(this);
 68 		
 69 	}
 70 
 71 	@Override
 72 	public void dispose() {
 73 		// TODO Auto-generated method stub
 74 		Gdx.input.setInputProcessor(null);
 75 	
 76 		spritebatch.dispose();
 77 		fondo.dispose();
 78 		
 79 	}
 80 
 81 	@Override
 82 	public boolean keyDown(int keycode) {
 83 		// TODO Auto-generated method stub
 84 		return false;
 85 	}
 86 
 87 	@Override
 88 	public boolean keyUp(int keycode) {
 89 		// TODO Auto-generated method stub
 90 		return false;
 91 	}
 92 
 93 	@Override
 94 	public boolean keyTyped(char character) {
 95 		// TODO Auto-generated method stub
 96 		return false;
 97 	}
 98 
 99 	@Override
100 	public boolean touchDown(int screenX, int screenY, int pointer, int button) {
101 		// TODO Auto-generated method stub
102 		return false;
103 	}
104 
105 	@Override
106 	public boolean touchUp(int screenX, int screenY, int pointer, int button) {
107 		// TODO Auto-generated method stub
108 		return false;
109 	}
110 
111 	@Override
112 	public boolean touchDragged(int screenX, int screenY, int pointer) {
113 		// TODO Auto-generated method stub
114 		return false;
115 	}
116 
117 	@Override
118 	public boolean mouseMoved(int screenX, int screenY) {
119 		// TODO Auto-generated method stub
120 		return false;
121 	}
122 
123 	@Override
124 	public boolean scrolled(int amount) {
125 		// TODO Auto-generated method stub
126 		return false;
127 	}
128 
129 
130 }
  • Liña 38:

Atención:: Na liña 38 temos a seguinte instrución:

1 spritebatch.disableBlending();

O que fai dita liña é deshabilitar o uso de transparencias. Isto o facemos nesta pantalla xa que o fondo da mesma ocupa todo e non imos engadir novos gráficos que teñan transparencias.

No resto de pantallas (como a de Marcadores) imos escribir texto que vai ter transperencias polo que dita orde non se debe poñer ou se a poñemos (por ter un fondo por exemplo) deberemos chamar a orde contraria (spritebatch.enableBlending()) antes de debuxar o gráfico con transparencias.


Modificamos agora a clase principal MeuXogoGame para que chame á nova pantalla...

Código da clase MeuXogoGame
Obxectivo: chama á pantalla principal.

 1 public class MeuXogoGame extends Game {
 2 
 3 	
 4 	@Override
 5 	public void create() {
 6 		// TODO Auto-generated method stub
 7 		
 8 		AssetsXogo.cargarTexturas();
 9 		setScreen(new PantallaPresentacion(this));
10 	}
11 
12 	@Override
13 	public void dispose(){
14 		super.dispose();
15 
16 		AssetsXogo.liberarTexturas();
17 	}
18 }


Agora temos que comprobar se pulsamos cada unha das opcións (botóns) e obrar en consecuencia. Debemos crear un rectángulo por cada unha das opcións (xa visto na sección das colisións) e comprobar se o dedo toca cada unha delas.



TAREFA 2.10 A FACER: Esta parte está asociada á realización dunha tarefa.


Facendo pause

En case todos os xogos podemos facer un pause do xogo para seguir posteriormente así como a opción de saír.

No caso do pause temos dúas opcións:

  • Quedarnos na mesma pantalla e no caso de que o xogo pase ó estado de pause debuxar un gráfico no centro da pantalla que indique que está en pause.

Para esta opción só teríamos que non chamar ó método controladorXogo.update(delta) dentro do método render da clase PantallaXogo. Desta forma ningún personaxe se moverá. Teríamos que cambiar a variable booleana pause a true e facela static e public para que dende a clase RendererXogo poidamos verificar o seu valor e no caso de que valga true poñer o gráfico de pause no centro da pantalla. Teríamos que controlar o método touchdown para que no caso de estar en pause e tocar a pantalla volver a poñer o valor a false.

  • Cambiar de pantalla e que ó premer volvamos ó xogo no punto onde o deixamos.

Para esta segunda opción imos modificar a clase PantallaPause para cargar o seguinte gráfico:

LIBGDX itin1 pantallapause.jpg

Levade este gráfico ó cartafol assets/GRAFICOS da versión Android e dádelle de nome LIBGDX_itin1_pantallapause.jpg.

Modificade o código da clase PantallaPause para que cargue o gráfico anterior.

Lembrar incluír a interface InputProcessor como xa vimos anteriormente.

Tamén deberedes liberar os recursos cando pase polo método hide (chamar ó método dispose nese intre e liberade a textura e o spritebach).


Preparando a clase PantallaXogo e RendererXogo:

Modificamos agora o código da RendererXogo para que visualice dúas iconas na parte inferior esquerda.

Aquí temos os gráficos a engadir no cartafol assets/GRAFICOS/CONTROIS da versión Android:

Como sempre os cargarmos na clase AssetsXogo cos nome indicados entre parénteses.

Despois modificamos a clase RendererXogo para que debuxe os novos controis. Como imos ter que indicar onde debuxalos podemos definir a súa posición e tamaño na clase Controis.


Código da clase Controis
Obxectivo: definir posición e tamaño das iconas pausa e saír.

 1 public class Controis {
 2 
 3 	public final static Rectangle FONDO_NEGRO = new Rectangle(0, 0,
 4 			Mundo.TAMANO_MUNDO_ANCHO, 12);
 5 	public final static Rectangle CONTROL = new Rectangle(10, 40, 50, 70);	
 6 	public final static int POSVIDAS = 60;
 7 
 8 	public final static Rectangle CONTROL_PAUSE = new Rectangle(30,0,10,10);
 9 	public final static Rectangle CONTROL_SAIR = new Rectangle(45,0,10,10);
10 
11 	
12 }


Código da clase RendererXogo
Obxectivo: visualiza as iconas pausa e saír.

 1 	private void debuxarControis(){
 2 		
 3 		// Fondo negro
 4 		spritebatch.draw(AssetsXogo.texturePuntoNegro, Controis.FONDO_NEGRO.x,Controis.FONDO_NEGRO.y,Controis.FONDO_NEGRO.width,Controis.FONDO_NEGRO.height);
 5 
 6 		spritebatch.draw(AssetsXogo.control, Controis.CONTROL.x,Controis.CONTROL.y,
 7 		         Controis.CONTROL.width,Controis.CONTROL.height);
 8 
 9 		spritebatch.draw(AssetsXogo.texturePausa, Controis.CONTROL_PAUSE.x,Controis.CONTROL_PAUSE.y,Controis.CONTROL_PAUSE.width,Controis.CONTROL_PAUSE.height);
10 		spritebatch.draw(AssetsXogo.textureSair, Controis.CONTROL_SAIR.x,Controis.CONTROL_SAIR.y,Controis.CONTROL_SAIR.width,Controis.CONTROL_SAIR.height);
11 	}


Agora controlamos se prememos a opción de pausa e saír.

Código da clase PantallaXogo
Obxectivo: xestionamos a opción de premer pausa e saír.

 1 	@Override
 2 	public boolean touchDown(int screenX, int screenY, int pointer, int button) {
 3 		
 4 //		if (Gdx.app.getType()!=ApplicationType.Android) return false;
 5 		
 6 		// TODO Auto-generated method stub
 7 		Vector3 vecTemporal = new Vector3(screenX,screenY,0);
 8 		rendererXogo.getCamara2d().unproject(vecTemporal);
 9 		
10                 Rectangle recTemporal = new Rectangle();
11 
12                 ...........................
13                 // Falta o código feito na tarefa 2.8.B no que se controla cando prememos no control do alien
14 
15 
16 		recTemporal.set(Controis.CONTROL_PAUSE.x,Controis.CONTROL_PAUSE.y,Controis.CONTROL_PAUSE.width,Controis.CONTROL_PAUSE.height);
17 		if (Intersector.overlaps(dedo, recTemporal)){
18 			pause = true;
19 		}
20 		
21 		recTemporal.set(Controis.CONTROL_SAIR.x,Controis.CONTROL_SAIR.y,Controis.CONTROL_SAIR.width,Controis.CONTROL_SAIR.height);
22 		if (Intersector.overlaps(dedo, recTemporal)){
23 			dispose();
24 			meuXogoGame.setScreen(new PantallaPresentacion(meuXogoGame));
25 		}
26 
27 		
28 		
29 		return false;
30 	}


Como podemos comprobar a opción de saír non ten complicación, xa a temos vista na tarefa 2.10. A chamada ó método dispose non se atopa no método hide xa que cando vaiamos á pantalla de pausa non queremos 'borrar' nada do xogo. Queremos ir con todo o estado do xogo e recuperalo ó volver.

Como facemos isto ? Como sempre temos varias opcións...Algunha delas:

  • Poderíamos gardar o estado do xogo a disco e recuperalo ó volver. Esta opción non é aconsellable nunha pantalla de pausa e si no caso de querer gardar a partida para continuar outro día (neste xogo non ten moito sentido).
  • Mandar como parámetro ó constructor da clase PantallaPause o obxecto da clase PantallaXogo desta forma:

Código da clase PantallaPause
Obxectivo: modifcamos o constructor para obter unha referencia á PantallaXogo.

 1 public class PantallaPause implements Screen, InputProcessor{
 2         ..............
 3         private PantallaXogo pantallaXogo;
 4     
 5 	public PantallaPause(MeuXogoGame meuXogoGame, PantallaXogo pantallaXogo){
 6 		
 7 		this.meuxogogame=meuxogogame;
 8 		this.pantallaXogo = pantallaXogo;
 9 
10 		camara2d = new OrthographicCamera();
11 		spritebatch = new SpriteBatch();
12 		fondo = new Texture(Gdx.files.internal("GRAFICOS/LIBGDX_itin1_pantallapause.png"));
13 		
14 	}
15         ..............
16 }

Agora no método render da clase PantallaXogo controlamos cando estamos en pause para mandar o control á PantallaPause:

Código da clase PantallaXogo
Obxectivo: controlamos se estamos en pause para ir á PantallaPause.

 1 	@Override
 2 	public void render(float delta) {
 3 		// TODO Auto-generated method stub
 4 
 5 		rendererXogo.render(delta);
 6 		controladorXogo.update(delta);
 7 		
 8 		if (pause){
 9 			meuXogoGame.setScreen(new PantallaPause(meuXogoGame, this));
10 			return;
11 		}
12 	}

Nota importante: Debemos facer return despois de chamar a setScreen, xa que a pesar que o control pasa a nova pantalla, se sigue executando o código do método render ata finalizar. Se temos código a continuación podemos ter un erro de execución.

Fixarse como no método setScreen enviamos non só a referencia a clase MeuXogoGame (para poder facer o setScreen) se non tamén unha referencia á propia clase PantallaXogo.

Agora só temos que controlar se se preme na pantalla PantallaPause volver ó control á PantallaXogo, pero usando a referencia pasada.


Código da clase PantallaPause
Obxectivo: devolvemos o control á PantallaXogo se prememos na pantalla.

1 	@Override
2 	public boolean touchDown(int screenX, int screenY, int pointer, int button) {
3 		// TODO Auto-generated method stub
4 		meuxogogame.setScreen(pantallaXogo);
5 		return false;
6 	}

Se executades o código podedes comprobar que xa accedemos á pantalla de pausa cando prememos sobre o control, pero ó intentar continuar o xogo volve á pantalla de pausa. Isto é debido a que a variable pause segue valendo true cando regresamos e polo tanto volve a facer o setScreen da pantalla de pause.

Imos modificar isto para que o xogo cando entre en estado de pause (ó premer o botón de pause ou cando minimizamos (en desktop) ou cambiamos de aplicación (en móbil) ) poñamos a variable a true e cando volvamos (maximicemos ou volvamos nun móbil) cambie a false.


Código da clase PantallaXogo
Obxectivo: modificar a propiedade pause.

 1         ................
 2 
 3 	@Override
 4 	public void pause() {
 5 		// TODO Auto-generated method stub
 6 		Gdx.input.setInputProcessor(null);
 7 		if (!finXogo) {
 8 			pause = true;
 9 		}
10 		
11 	}
12 
13 	@Override
14 	public void resume() {
15 		// TODO Auto-generated method stub
16 		Gdx.input.setInputProcessor(this);
17 		pause=false;
18 		
19 	}
20 	@Override
21 	public void show() {
22 		// TODO Auto-generated method stub
23 		Gdx.input.setInputProcessor(this);
24 		pause=false;
25 	}
26 
27         ................


Nota: Fixarse como cando facemos a pausa do xogo minimizando a aplicación na versión desktop, pasamos polo evento pause, pero cando restauramos, non pasamos polo evento resume xa que cambiamos de pantalla (estamos na pantalla de pausa). Cando dende a pantalla de pausa chamamos ó método setScreen volvemos a pasar polo evento show.

Saíndo do xogo

Ó premer a icona de saír debemos ir á pantalla de presentación. Tamén imos engadir outra condición e é que se utilizamos máis de 15 vidas o xogo acaba.

Lembrar que temos que liberar os recursos.

Código da clase PantallaXogo
Obxectivo: Xestionar o fin do xogo.

 1 	@Override
 2 	public void render(float delta) {
 3 		// TODO Auto-generated method stub
 4 
 5 		rendererXogo.render(delta);
 6 		controladorXogo.update(delta);
 7 		
 8 		if (meuMundo.getAlien().getNumVidas().size>=15)
 9 			finXogo=true;
10 
11 
12 		if (pause){
13 			Audio.stopMusica();
14 			meuXogoGame.setScreen(new PantallaPause(meuXogoGame, this));
15 			return;
16 		}
17 		if (finXogo){
18 			meuXogoGame.setScreen(new PantallaMarcadores(meuXogoGame));
19 			// Facemos o return xa que continua a execución ata que remate o render.
20 			return;
21 		}
22 		
23 	}
24 
25 	@Override
26 	public boolean touchDown(int screenX, int screenY, int pointer, int button) {
27 		
28 		vecTemporal.set(screenX,screenY,0);
29 		rendererXogo.getCamara2d().unproject(vecTemporal);
30 		
31 		dedo.set(vecTemporal.x,vecTemporal.y,2);
32                 ..................
33 
34 				recTemporal.set(Controis.CONTROL_SAIR.x,Controis.CONTROL_SAIR.y,Controis.CONTROL_SAIR.width,Controis.CONTROL_SAIR.height);
35 		if (Intersector.overlaps(dedo, recTemporal)){
36 			sair=true;
37 			meuXogoGame.setScreen(new PantallaPresentacion(meuXogoGame));
38 		}
39 
40 		
41 		
42 		return false;
43 	}
44 	@Override
45 	public void hide() {
46 		// TODO Auto-generated method stub
47 		if ((finXogo) || (sair)) dispose();
48 		
49 	}




-- Ángel D. Fernández González -- (2015).